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

Commit 357b2fbd authored by Henri Chataing's avatar Henri Chataing
Browse files

RootCanal/Gd: Fix RPA address check

The check was implemented with the wrong byte order in mind.
This change fixes and documents the byte order, and corrects
the associated unit tests.

Test: atest --host bluetooth_test_gd_unit AddressWithTypeTest
Change-Id: I8dfca68756e5037b86fb6682b4bd869b0649ec8a
parent 8600bef8
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@ class Address final : public packet::CustomFieldFixedSizeInterface<Address>,
 public:
  static constexpr size_t kLength = 6;

  // Bluetooth MAC address bytes saved in little endian format.
  // The address MSB is address[5], the address LSB is address[0].
  // Note that the textual representation follows the big endian format,
  // ie. Address{0, 1, 2, 3, 4, 5} is represented as 05:04:03:02:01:00.
  std::array<uint8_t, kLength> address = {};

  Address() = default;
+7 −7
Original line number Diff line number Diff line
@@ -47,7 +47,7 @@ class AddressWithType final : public bluetooth::common::IRedactableLoggable {

  /* Is this an Resolvable Private Address ? */
  inline bool IsRpa() const {
    return address_type_ == hci::AddressType::RANDOM_DEVICE_ADDRESS && ((address_.data())[0] & 0xc0) == 0x40;
    return address_type_ == hci::AddressType::RANDOM_DEVICE_ADDRESS && ((address_.data())[5] & 0xc0) == 0x40;
  }

  /* Is this an Resolvable Private Address, that was generated from given irk ? */
@@ -56,15 +56,15 @@ class AddressWithType final : public bluetooth::common::IRedactableLoggable {

    /* use the 3 MSB of bd address as prand */
    uint8_t prand[3];
    prand[0] = address_.address[2];
    prand[1] = address_.address[1];
    prand[2] = address_.address[0];
    prand[0] = address_.address[3];
    prand[1] = address_.address[4];
    prand[2] = address_.address[5];
    /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
    crypto_toolbox::Octet16 computed_hash = crypto_toolbox::aes_128(irk, &prand[0], 3);
    uint8_t hash[3];
    hash[0] = address_.address[5];
    hash[1] = address_.address[4];
    hash[2] = address_.address[3];
    hash[0] = address_.address[0];
    hash[1] = address_.address[1];
    hash[2] = address_.address[2];
    if (memcmp(computed_hash.data(), &hash[0], 3) == 0) {
      // match
      return true;
+8 −9
Original line number Diff line number Diff line
@@ -73,25 +73,24 @@ TEST(AddressWithTypeTest, IsRpa) {

  // Must have proper Most Significant Bit configuration
  EXPECT_FALSE(
      AddressWithType(Address{{0x30, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
  EXPECT_TRUE(
      AddressWithType(Address{{0x40, 0x02, 0x03, 0x04, 0x05, 0x03}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x40}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
  EXPECT_TRUE(
      AddressWithType(Address{{0x50, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x50}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
  EXPECT_TRUE(
      AddressWithType(Address{{0x60, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x60}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
  EXPECT_TRUE(
      AddressWithType(Address{{0x70, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x70}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
  EXPECT_FALSE(
      AddressWithType(Address{{0x80, 0x02, 0x03, 0x04, 0x05, 0x06}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
      AddressWithType(Address{{0x01, 0x02, 0x03, 0x04, 0x05, 0x80}}, AddressType::RANDOM_DEVICE_ADDRESS).IsRpa());
}

TEST(AddressWithTypeTest, IsRpaThatMatchesIrk) {
  // Public address can't be RPA
  AddressWithType address_1 =
      AddressWithType(Address{{0x50, 0x02, 0x03, 0xC9, 0x12, 0xDE}}, AddressType::RANDOM_DEVICE_ADDRESS);
      AddressWithType(Address{{0xDE, 0x12, 0xC9, 0x03, 0x02, 0x50}}, AddressType::RANDOM_DEVICE_ADDRESS);
  AddressWithType address_2 =
      AddressWithType(Address{{0x50, 0x02, 0x03, 0xC9, 0x12, 0xDD}}, AddressType::RANDOM_DEVICE_ADDRESS);
      AddressWithType(Address{{0xDD, 0x12, 0xC9, 0x03, 0x02, 0x50}}, AddressType::RANDOM_DEVICE_ADDRESS);
  crypto_toolbox::Octet16 irk_1{0x90, 0x5e, 0x60, 0x59, 0xc9, 0x11, 0x43, 0x7b,
                                0x04, 0x09, 0x6a, 0x53, 0x28, 0xe6, 0x59, 0x6d};

+5 −1
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *  Copyright 2022 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
@@ -34,6 +34,10 @@ class Address final : public packet::CustomFieldFixedSizeInterface<Address> {
 public:
  static constexpr size_t kLength = 6;

  // Bluetooth MAC address bytes saved in little endian format.
  // The address MSB is address[5], the address LSB is address[0].
  // Note that the textual representation follows the big endian format,
  // ie. Address{0, 1, 2, 3, 4, 5} is represented as 05:04:03:02:01:00.
  std::array<uint8_t, kLength> address = {};

  constexpr Address() = default;
+9 −14
Original line number Diff line number Diff line
/******************************************************************************
 *
 *  Copyright 2019 The Android Open Source Project
 *  Copyright 2022 The Android Open Source Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
@@ -45,7 +45,7 @@ class AddressWithType final {
  /* Is this an Resolvable Private Address ? */
  inline bool IsRpa() const {
    return address_type_ == hci::AddressType::RANDOM_DEVICE_ADDRESS &&
           ((address_.data())[0] & 0xc0) == 0x40;
           ((address_.data())[5] & 0xc0) == 0x40;
  }

  /* Is this an Resolvable Private Address, that was generated from given irk ?
@@ -55,22 +55,17 @@ class AddressWithType final {

    /* use the 3 MSB of bd address as prand */
    uint8_t prand[3];
    prand[0] = address_.address[2];
    prand[1] = address_.address[1];
    prand[2] = address_.address[0];
    prand[0] = address_.address[3];
    prand[1] = address_.address[4];
    prand[2] = address_.address[5];
    /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
    rootcanal::crypto::Octet16 computed_hash =
        rootcanal::crypto::aes_128(irk, &prand[0], 3);
    uint8_t hash[3];
    hash[0] = address_.address[5];
    hash[1] = address_.address[4];
    hash[2] = address_.address[3];
    if (memcmp(computed_hash.data(), &hash[0], 3) == 0) {
      // match
      return true;
    }
    // not a match
    return false;
    hash[0] = address_.address[0];
    hash[1] = address_.address[1];
    hash[2] = address_.address[2];
    return memcmp(computed_hash.data(), &hash[0], 3) == 0;
  }

  bool operator<(const AddressWithType& rhs) const {
Loading