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()));
}
}
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(
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);
}
}
+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);
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