Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f9da3e1b authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

GD: Store peer keys in legacy format

Bug: 142341141
Tag: #gd-refactor
Test: cert/run --host SecurityRecordStorageTest
Change-Id: I94d270da66977fef6356f011b649bb405d0c4324
parent dede761e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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>;
+2 −0
Original line number Diff line number Diff line
@@ -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;
+2 −0
Original line number Diff line number Diff line
@@ -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;
+80 −32
Original line number Diff line number Diff line
@@ -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);
+40 −0
Original line number Diff line number Diff line
@@ -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);
Loading