OSDN Git Service

GD: Store peer keys in legacy format
authorJakub Pawlowski <jpawlowski@google.com>
Thu, 1 Oct 2020 13:12:25 +0000 (15:12 +0200)
committerJakub Pawlowski <jpawlowski@google.com>
Wed, 7 Oct 2020 06:16:21 +0000 (06:16 +0000)
Bug: 142341141
Tag: #gd-refactor
Test: cert/run --host SecurityRecordStorageTest
Change-Id: I94d270da66977fef6356f011b649bb405d0c4324

gd/security/initial_informations.h
gd/security/internal/security_manager_impl.cc
gd/security/record/security_record.h
gd/security/record/security_record_storage.cc
gd/security/record/security_record_storage_test.cc
gd/storage/device.cc
gd/storage/device.h
gd/storage/le_device.h

index 56a6bce..5a707e4 100644 (file)
@@ -54,6 +54,8 @@ struct DistributedKeys {
 struct PairingResult {
   hci::AddressWithType connection_address;
   DistributedKeys distributed_keys;
+  uint8_t key_size;
+  uint8_t security_level;
 };
 
 using PairingResultOrFailure = std::variant<PairingResult, PairingFailure>;
index 2d06734..835e5a5 100644 (file)
@@ -670,6 +670,8 @@ void SecurityManagerImpl::OnPairingFinished(security::PairingResultOrFailure pai
   auto record = this->security_database_.FindOrCreate(result.connection_address);
   record->identity_address_ = result.distributed_keys.identity_address;
   record->ltk = result.distributed_keys.ltk;
+  record->key_size = result.key_size;
+  record->security_level = result.security_level;
   record->ediv = result.distributed_keys.ediv;
   record->rand = result.distributed_keys.rand;
   record->irk = result.distributed_keys.irk;
index 00cd784..0f476d0 100644 (file)
@@ -136,6 +136,8 @@ class SecurityRecord {
   std::optional<hci::AddressWithType> identity_address_;
 
   std::optional<crypto_toolbox::Octet16> ltk;
+  uint8_t key_size;
+  uint8_t security_level;
   std::optional<uint16_t> ediv;
   std::optional<std::array<uint8_t, 8>> rand;
   std::optional<crypto_toolbox::Octet16> irk;
index b7ac8aa..238b6a1 100644 (file)
@@ -40,32 +40,54 @@ void SetLeData(storage::Mutation& mutation, std::shared_ptr<record::SecurityReco
   if (*device.GetDeviceType() == hci::DeviceType::BR_EDR) {
     return;
   }
+
+  auto le_device = device.Le();
+
   if (record->identity_address_) {
-    mutation.Add(device.Le().SetIdentityAddress(record->identity_address_->GetAddress()));
+    mutation.Add(le_device.SetAddressType(record->identity_address_->GetAddressType()));
+  }
+
+  if (record->irk) {
+    std::array<uint8_t, 23> peerid;
+    std::copy_n(record->irk->data(), record->irk->size(), peerid.data());
+    peerid[16] = static_cast<uint8_t>(record->identity_address_->GetAddressType());
+    std::copy_n(record->identity_address_->GetAddress().data(), 6, peerid.data() + 17);
+
+    common::ByteArray<23> byte_array(peerid);
+    mutation.Add(le_device.SetPeerId(byte_array.ToString()));
   }
+
   if (record->pseudo_address_) {
-    mutation.Add(device.Le().SetLegacyPseudoAddress(record->pseudo_address_->GetAddress()));
+    mutation.Add(le_device.SetLegacyPseudoAddress(record->pseudo_address_->GetAddress()));
   }
+
   if (record->ltk) {
-    common::ByteArray<16> byte_array(*record->ltk);
-    mutation.Add(device.Le().SetLtk(byte_array.ToString()));
-  }
-  if (record->ediv) {
-    mutation.Add(device.Le().SetEdiv(*record->ediv));
-  }
-  if (record->rand) {
-    common::ByteArray<8> byte_array(*record->rand);
-    mutation.Add(device.Le().SetRand(byte_array.ToString()));
-  }
+    std::array<uint8_t, 28> penc_keys;
 
-  if (record->irk) {
-    common::ByteArray<16> byte_array(*record->irk);
-    mutation.Add(device.Le().SetIrk(byte_array.ToString()));
+    std::copy_n(record->ltk->data(), record->ltk->size(), penc_keys.data());
+    std::copy_n(record->rand->data(), record->rand->size(), penc_keys.data() + 16);
+    uint16_t* ediv_location = (uint16_t*)(penc_keys.data() + 24);
+    *ediv_location = *record->ediv;
+    penc_keys[26] = record->security_level;
+    penc_keys[27] = record->key_size;
+
+    common::ByteArray<28> byte_array(penc_keys);
+    mutation.Add(le_device.SetPeerEncryptionKeys(byte_array.ToString()));
   }
 
   if (record->signature_key) {
-    common::ByteArray<16> byte_array(*record->signature_key);
-    mutation.Add(device.Le().SetSignatureKey(byte_array.ToString()));
+    std::array<uint8_t, 21> psrk_keys;
+
+    // four bytes counter, all zeros
+    *psrk_keys.data() = 0;
+    *(psrk_keys.data() + 1) = 0;
+    *(psrk_keys.data() + 2) = 0;
+    *(psrk_keys.data() + 3) = 0;
+    std::copy_n(record->signature_key->data(), record->signature_key->size(), psrk_keys.data() + 4);
+    *(psrk_keys.data() + 20) = record->security_level;
+
+    common::ByteArray<21> byte_array(psrk_keys);
+    mutation.Add(le_device.SetPeerSignatureResolvingKeys(byte_array.ToString()));
   }
 }
 
@@ -84,12 +106,12 @@ void SecurityRecordStorage::SaveSecurityRecords(std::set<std::shared_ptr<record:
     if (record->IsTemporary()) continue;
     storage::Device device = storage_module_->GetDeviceByClassicMacAddress(record->GetPseudoAddress()->GetAddress());
     auto mutation = storage_module_->Modify();
-    mutation.Add(device.SetDeviceType(hci::DeviceType::BR_EDR));
+
     if (record->IsClassicLinkKeyValid() && !record->identity_address_) {
       mutation.Add(device.SetDeviceType(hci::DeviceType::BR_EDR));
-    } else if (record->IsClassicLinkKeyValid() && record->identity_address_) {
+    } else if (record->IsClassicLinkKeyValid() && record->ltk) {
       mutation.Add(device.SetDeviceType(hci::DeviceType::DUAL));
-    } else if (!record->IsClassicLinkKeyValid() && record->identity_address_) {
+    } else if (!record->IsClassicLinkKeyValid() && record->ltk) {
       mutation.Add(device.SetDeviceType(hci::DeviceType::LE));
     } else {
       LOG_ERROR(
@@ -109,26 +131,52 @@ void SecurityRecordStorage::LoadSecurityRecords(std::set<std::shared_ptr<record:
   for (auto device : storage_module_->GetBondedDevices()) {
     auto address_type = (device.GetDeviceType() == hci::DeviceType::BR_EDR) ? hci::AddressType::PUBLIC_DEVICE_ADDRESS
                                                                             : device.Le().GetAddressType();
-    auto address_with_type = hci::AddressWithType(device.Classic().GetAddress(), *address_type);
+    auto address_with_type = hci::AddressWithType(device.GetAddress(), *address_type);
+
     auto record = std::make_shared<record::SecurityRecord>(address_with_type);
     if (device.GetDeviceType() != hci::DeviceType::LE) {
       record->SetLinkKey(device.Classic().GetLinkKey()->bytes, *device.Classic().GetLinkKeyType());
     }
     if (device.GetDeviceType() != hci::DeviceType::BR_EDR) {
-      record->identity_address_ =
-          std::make_optional<hci::AddressWithType>(*device.Le().GetIdentityAddress(), *device.Le().GetAddressType());
       record->pseudo_address_ = std::make_optional<hci::AddressWithType>(
           *device.Le().GetLegacyPseudoAddress(), *device.Le().GetAddressType());
-      auto byte_array = common::ByteArray<16>::FromString(*device.Le().GetLtk());
-      record->ltk = std::make_optional<std::array<uint8_t, 16>>(byte_array->bytes);
-      record->ediv = device.Le().GetEdiv();
-      auto byte_array2 = common::ByteArray<8>::FromString(*device.Le().GetRand());
-      record->rand = std::make_optional<std::array<uint8_t, 8>>(byte_array2->bytes);
-      byte_array = common::ByteArray<16>::FromString(*device.Le().GetIrk());
-      record->irk = std::make_optional<std::array<uint8_t, 16>>(byte_array->bytes);
-      byte_array = common::ByteArray<16>::FromString(*device.Le().GetSignatureKey());
-      record->signature_key = std::make_optional<std::array<uint8_t, 16>>(byte_array->bytes);
+
+      if (device.Le().GetPeerId()) {
+        auto peerid = common::ByteArray<23>::FromString(*device.Le().GetPeerId());
+        record->irk = std::make_optional<std::array<uint8_t, 16>>();
+        std::copy_n(peerid->data(), record->irk->size(), record->irk->data());
+
+        uint8_t idaddress_type;
+        hci::Address idaddress;
+        std::copy_n(peerid->data() + 16, 1, &idaddress_type);
+        std::copy_n(peerid->data() + 17, 6, idaddress.data());
+        record->identity_address_ =
+            std::make_optional<hci::AddressWithType>(idaddress, static_cast<hci::AddressType>(idaddress_type));
+      }
+
+      if (device.Le().GetPeerEncryptionKeys()) {
+        auto peer_encryption_keys = common::ByteArray<28>::FromString(*device.Le().GetPeerEncryptionKeys());
+        record->ltk = std::make_optional<std::array<uint8_t, 16>>();
+        record->rand = std::make_optional<std::array<uint8_t, 8>>();
+        record->ediv = std::make_optional(0);
+
+        std::copy_n(peer_encryption_keys->data(), 16, record->ltk->data());
+        std::copy_n(peer_encryption_keys->data() + 16, 8, record->rand->data());
+        std::copy_n(peer_encryption_keys->data() + 24, 2, &(*record->ediv));
+        record->security_level = peer_encryption_keys->data()[26];
+        record->key_size = peer_encryption_keys->data()[27];
+      }
+
+      if (device.Le().GetPeerSignatureResolvingKeys()) {
+        auto peer_signature_resolving_keys =
+            common::ByteArray<21>::FromString(*device.Le().GetPeerSignatureResolvingKeys());
+        record->signature_key = std::make_optional<std::array<uint8_t, 16>>();
+
+        std::copy_n(peer_signature_resolving_keys->data() + 4, 16, record->signature_key->data());
+        record->security_level = peer_signature_resolving_keys->data()[20];
+      }
     }
+
     record->SetIsEncrypted(false);
     record->SetIsEncryptionRequired(device.GetIsEncryptionRequired() == 1 ? true : false);
     record->SetAuthenticated(device.GetIsAuthenticated() == 1 ? true : false);
index 08520ae..3d4247d 100644 (file)
@@ -78,6 +78,46 @@ TEST_F(SecurityRecordStorageTest, store_security_record) {
   }
 }
 
+TEST_F(SecurityRecordStorageTest, store_le_security_record) {
+  hci::AddressWithType identity_address(
+      hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), hci::AddressType::RANDOM_DEVICE_ADDRESS);
+  std::array<uint8_t, 16> ltk{
+      0x07, 0x0c, 0x0e, 0x16, 0x18, 0x55, 0xc6, 0x72, 0x64, 0x5a, 0xd8, 0xb1, 0xf6, 0x93, 0x94, 0xa7};
+  uint16_t ediv = 0x28;
+  std::array<uint8_t, 8> rand{0x48, 0xac, 0x91, 0xf4, 0xef, 0x6d, 0x41, 0x10};
+  std::array<uint8_t, 16> irk{
+      0x66, 0x90, 0x40, 0x76, 0x27, 0x69, 0x57, 0x71, 0x0d, 0x39, 0xf7, 0x80, 0x9e, 0x2f, 0x49, 0xcf};
+  std::array<uint8_t, 16> signature_key{
+      0x08, 0x83, 0xae, 0x44, 0xd6, 0x77, 0x9e, 0x90, 0x1d, 0x25, 0xcd, 0xd7, 0xb6, 0xf4, 0x57, 0x85};
+  std::shared_ptr<record::SecurityRecord> record = std::make_shared<record::SecurityRecord>(identity_address);
+
+  record->identity_address_ = identity_address;
+  record->ltk = ltk;
+  record->key_size = 16;
+  record->security_level = 2;
+  record->ediv = ediv;
+  record->rand = rand;
+  record->irk = irk;
+  record->signature_key = signature_key;
+
+  std::set<std::shared_ptr<record::SecurityRecord>> record_set;
+  record_set.insert(record);
+  record_storage_->SaveSecurityRecords(&record_set);
+
+  auto device = storage_module_->GetDeviceByClassicMacAddress(identity_address.GetAddress());
+  ASSERT_EQ(hci::DeviceType::LE, device.GetDeviceType());
+  ASSERT_EQ(device.Le().GetAddressType(), identity_address.GetAddressType());
+
+  // IRK, address type, and address glued together
+  ASSERT_EQ(*device.Le().GetPeerId(), "66904076276957710d39f7809e2f49cf01010203040506");
+
+  // LTK, RAND, EDIV and sec level glued together
+  ASSERT_EQ(*device.Le().GetPeerEncryptionKeys(), "070c0e161855c672645ad8b1f69394a748ac91f4ef6d411028000210");
+
+  // Counter, signature key, and security level glued together
+  ASSERT_EQ(device.Le().GetPeerSignatureResolvingKeys(), "000000000883ae44d6779e901d25cdd7b6f4578502");
+}
+
 TEST_F(SecurityRecordStorageTest, load_security_record) {
   hci::AddressWithType remote(
       hci::Address({0x01, 0x02, 0x03, 0x04, 0x05, 0x06}), hci::AddressType::PUBLIC_DEVICE_ADDRESS);
index 153881f..7afb30f 100644 (file)
@@ -106,6 +106,13 @@ ClassicDevice Device::Classic() {
   return ClassicDevice(config_, memory_only_config_, section_);
 }
 
+hci::Address Device::GetAddress() const {
+  // section name of a device is its address
+  auto addr = hci::Address::FromString(section_);
+  ASSERT(addr.has_value());
+  return addr.value();
+}
+
 std::string Device::ToLogString() const {
   return section_;
 }
index 49c6b66..7aba3df 100644 (file)
@@ -164,6 +164,8 @@ class Device {
   // For logging purpose only, you can't get a Device object from parsing a std::string
   std::string ToLogString() const;
 
+  hci::Address GetAddress() const;
+
   // Property names that correspond to a link key used in Bluetooth Classic and LE device
   static const std::unordered_set<std::string_view> kLinkKeyProperties;
 
index faa5ce8..79e3045 100644 (file)
@@ -81,13 +81,14 @@ class LeDevice {
  public:
   // Get LE address type of the key address
   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(AddressType, hci::AddressType, "AddrType");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(IdentityAddress, hci::Address, "LeIdentityAddr");
+  // IRK + Identity Address Type + Identity Address
+  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerId, std::string, "LE_KEY_PID");
+  // LTK + RAND + EDIV + Security Level + Key Length
+  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerEncryptionKeys, std::string, "LE_KEY_PENC");
+  // counter + CSRK (connection signature resolving key) + security level
+  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(PeerSignatureResolvingKeys, std::string, "LE_KEY_PCSRK");
+
   GENERATE_PROPERTY_GETTER_SETTER_REMOVER(LegacyPseudoAddress, hci::Address, "LeLegacyPseudoAddr");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(Ltk, std::string, "Ltk");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(Ediv, uint16_t, "Ediv");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(Irk, std::string, "Irk");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(Rand, std::string, "Rand");
-  GENERATE_PROPERTY_GETTER_SETTER_REMOVER(SignatureKey, std::string, "SignatureKey");
 };
 
 }  // namespace storage