From 7c1847ad0d12534262c4032faac27a4b63db5d6f Mon Sep 17 00:00:00 2001 From: Jakub Pawlowski Date: Thu, 1 Oct 2020 15:12:25 +0200 Subject: [PATCH] GD: Store peer keys in legacy format Bug: 142341141 Tag: #gd-refactor Test: cert/run --host SecurityRecordStorageTest Change-Id: I94d270da66977fef6356f011b649bb405d0c4324 --- gd/security/initial_informations.h | 2 + gd/security/internal/security_manager_impl.cc | 2 + gd/security/record/security_record.h | 2 + gd/security/record/security_record_storage.cc | 112 +++++++++++++++------ gd/security/record/security_record_storage_test.cc | 40 ++++++++ gd/storage/device.cc | 7 ++ gd/storage/device.h | 2 + gd/storage/le_device.h | 13 +-- 8 files changed, 142 insertions(+), 38 deletions(-) diff --git a/gd/security/initial_informations.h b/gd/security/initial_informations.h index 56a6bce19..5a707e484 100644 --- a/gd/security/initial_informations.h +++ b/gd/security/initial_informations.h @@ -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; diff --git a/gd/security/internal/security_manager_impl.cc b/gd/security/internal/security_manager_impl.cc index 2d06734ed..835e5a5f1 100644 --- a/gd/security/internal/security_manager_impl.cc +++ b/gd/security/internal/security_manager_impl.cc @@ -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; diff --git a/gd/security/record/security_record.h b/gd/security/record/security_record.h index 00cd784e3..0f476d0ff 100644 --- a/gd/security/record/security_record.h +++ b/gd/security/record/security_record.h @@ -136,6 +136,8 @@ class SecurityRecord { std::optional identity_address_; std::optional ltk; + uint8_t key_size; + uint8_t security_level; std::optional ediv; std::optional> rand; std::optional irk; diff --git a/gd/security/record/security_record_storage.cc b/gd/security/record/security_record_storage.cc index b7ac8aad3..238b6a1e5 100644 --- a/gd/security/record/security_record_storage.cc +++ b/gd/security/record/security_record_storage.cc @@ -40,32 +40,54 @@ void SetLeData(storage::Mutation& mutation, std::shared_ptridentity_address_) { - mutation.Add(device.Le().SetIdentityAddress(record->identity_address_->GetAddress())); + mutation.Add(le_device.SetAddressType(record->identity_address_->GetAddressType())); + } + + if (record->irk) { + std::array peerid; + std::copy_n(record->irk->data(), record->irk->size(), peerid.data()); + peerid[16] = static_cast(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 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 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::setIsTemporary()) 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::setGetBondedDevices()) { 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(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(*device.Le().GetIdentityAddress(), *device.Le().GetAddressType()); record->pseudo_address_ = std::make_optional( *device.Le().GetLegacyPseudoAddress(), *device.Le().GetAddressType()); - auto byte_array = common::ByteArray<16>::FromString(*device.Le().GetLtk()); - record->ltk = std::make_optional>(byte_array->bytes); - record->ediv = device.Le().GetEdiv(); - auto byte_array2 = common::ByteArray<8>::FromString(*device.Le().GetRand()); - record->rand = std::make_optional>(byte_array2->bytes); - byte_array = common::ByteArray<16>::FromString(*device.Le().GetIrk()); - record->irk = std::make_optional>(byte_array->bytes); - byte_array = common::ByteArray<16>::FromString(*device.Le().GetSignatureKey()); - record->signature_key = std::make_optional>(byte_array->bytes); + + if (device.Le().GetPeerId()) { + auto peerid = common::ByteArray<23>::FromString(*device.Le().GetPeerId()); + record->irk = std::make_optional>(); + 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(idaddress, static_cast(idaddress_type)); + } + + if (device.Le().GetPeerEncryptionKeys()) { + auto peer_encryption_keys = common::ByteArray<28>::FromString(*device.Le().GetPeerEncryptionKeys()); + record->ltk = std::make_optional>(); + record->rand = std::make_optional>(); + 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::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); diff --git a/gd/security/record/security_record_storage_test.cc b/gd/security/record/security_record_storage_test.cc index 08520aeba..3d4247da6 100644 --- a/gd/security/record/security_record_storage_test.cc +++ b/gd/security/record/security_record_storage_test.cc @@ -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 ltk{ + 0x07, 0x0c, 0x0e, 0x16, 0x18, 0x55, 0xc6, 0x72, 0x64, 0x5a, 0xd8, 0xb1, 0xf6, 0x93, 0x94, 0xa7}; + uint16_t ediv = 0x28; + std::array rand{0x48, 0xac, 0x91, 0xf4, 0xef, 0x6d, 0x41, 0x10}; + std::array irk{ + 0x66, 0x90, 0x40, 0x76, 0x27, 0x69, 0x57, 0x71, 0x0d, 0x39, 0xf7, 0x80, 0x9e, 0x2f, 0x49, 0xcf}; + std::array signature_key{ + 0x08, 0x83, 0xae, 0x44, 0xd6, 0x77, 0x9e, 0x90, 0x1d, 0x25, 0xcd, 0xd7, 0xb6, 0xf4, 0x57, 0x85}; + std::shared_ptr record = std::make_shared(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> 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); diff --git a/gd/storage/device.cc b/gd/storage/device.cc index 153881f4d..7afb30f36 100644 --- a/gd/storage/device.cc +++ b/gd/storage/device.cc @@ -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_; } diff --git a/gd/storage/device.h b/gd/storage/device.h index 49c6b66e2..7aba3dfe5 100644 --- a/gd/storage/device.h +++ b/gd/storage/device.h @@ -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 kLinkKeyProperties; diff --git a/gd/storage/le_device.h b/gd/storage/le_device.h index faa5ce811..79e3045c5 100644 --- a/gd/storage/le_device.h +++ b/gd/storage/le_device.h @@ -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 -- 2.11.0