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

Commit a497114a authored by Henri Chataing's avatar Henri Chataing Committed by Gerrit Code Review
Browse files

Merge changes Ide5f90fa,I6540ae6d,Ia2cb58b5,Ie6ffe0a3,I8dfca687

* changes:
  pdl: Define exhaustive array tests
  RootCanal: Implement additional LL tests
  RootCanal: Implement additional LL tests
  RootCanal: Implement additional LL tests
  RootCanal/Gd: Fix RPA address check
parents 67a4fcc0 81c0b910
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};

+12 −0
Original line number Diff line number Diff line
@@ -3171,6 +3171,12 @@ packet LeSetAdvertisingData : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetAdvertisingDataRaw : LeAdvertisingCommand (op_code = LE_SET_ADVERTISING_DATA) {
  _size_(advertising_data) : 8,
  advertising_data : 8[],
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetAdvertisingDataComplete : CommandComplete (command_op_code = LE_SET_ADVERTISING_DATA) {
  status : ErrorCode,
}
@@ -3181,6 +3187,12 @@ packet LeSetScanResponseData : LeAdvertisingCommand (op_code = LE_SET_SCAN_RESPO
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetScanResponseDataRaw : LeAdvertisingCommand (op_code = LE_SET_SCAN_RESPONSE_DATA) {
  _size_(advertising_data) : 8,
  advertising_data : 8[],
  _padding_[31], // Zero padding to 31 bytes of advertising_data
}

packet LeSetScanResponseDataComplete : CommandComplete (command_op_code = LE_SET_SCAN_RESPONSE_DATA) {
  status : ErrorCode,
}
+51 −7
Original line number Diff line number Diff line
@@ -177,6 +177,41 @@ class FieldParser:
            element = f"{field.type_id}.parse_all({span})"
            self.append_(f"    {field.id}.append({element})")

    def parse_byte_array_field_(self, field: ast.ArrayField):
        """Parse the selected u8 array field."""
        array_size = core.get_array_field_size(field)
        padded_size = field.padded_size

        # Shift the span to reset the offset to 0.
        self.consume_span_()

        # Derive the array size.
        if isinstance(array_size, int):
            size = array_size
        elif isinstance(array_size, ast.SizeField):
            size = f'{field.id}_size - {field.size_modifier}' if field.size_modifier else f'{field.id}_size'
        elif isinstance(array_size, ast.CountField):
            size = f'{field.id}_count'
        else:
            size = None

        # Parse from the padded array if padding is present.
        if padded_size and size is not None:
            self.check_size_(padded_size)
            self.append_(f"if {size} > {padded_size}:")
            self.append_("    raise Exception('Array size is larger than the padding size')")
            self.append_(f"fields['{field.id}'] = list(span[:{size}])")
            self.append_(f"span = span[{padded_size}:]")

        elif size is not None:
            self.check_size_(size)
            self.append_(f"fields['{field.id}'] = list(span[:{size}])")
            self.append_(f"span = span[{size}:]")

        else:
            self.append_(f"fields['{field.id}'] = list(span)")
            self.append_(f"span = bytes()")

    def parse_array_field_(self, field: ast.ArrayField):
        """Parse the selected array field."""
        array_size = core.get_array_field_size(field)
@@ -261,12 +296,13 @@ class FieldParser:
            if size is not None:
                self.check_size_(size)
            array_size = size or 'len(span)'
            array_count = size
            if element_width != 1:
                self.append_(f"if {array_size} % {element_width} != 0:")
                self.append_("    raise Exception('Array size is not a multiple of the element size')")
                self.append_(f"{field.id}_count = int({array_size} / {element_width})")
                array_count = f'{field.id}_count'
            else:
                array_count = array_size
            self.append_(f"{field.id} = []")
            self.append_(f"for n in range({array_count}):")
            span = ('span[n:n + 1]' if element_width == 1 else f'span[n * {element_width}:(n + 1) * {element_width}]')
@@ -274,6 +310,8 @@ class FieldParser:
            self.append_(f"fields['{field.id}'] = {field.id}")
            if size is not None:
                self.append_(f"span = span[{size}:]")
            else:
                self.append_(f"span = bytes()")

        # Drop the padding
        if padded_size:
@@ -483,6 +521,9 @@ class FieldParser:
            pass

        # Array fields.
        elif isinstance(field, ast.ArrayField) and field.width == 8:
            self.parse_byte_array_field_(field)

        elif isinstance(field, ast.ArrayField):
            self.parse_array_field_(field)

@@ -592,17 +633,20 @@ class FieldSerializer:
                size_modifier = f' + {value_field.size_modifier}'

            if isinstance(value_field, (ast.PayloadField, ast.BodyField)):
                self.append_(f"_size = len(payload or self.payload or []){size_modifier}")
                self.append_(f"if _size > {max_size}:")
                self.append_(f"_payload_size = len(payload or self.payload or []){size_modifier}")
                self.append_(f"if _payload_size > {max_size}:")
                self.append_(f"    print(f\"Invalid length for payload field:" +
                             f"  {{_size}} > {max_size}; the packet cannot be generated\")")
                             f"  {{_payload_size}} > {max_size}; the packet cannot be generated\")")
                self.append_(f"    raise Exception(\"Invalid payload length\")")
                array_size = "_size"
                array_size = "_payload_size"
            elif isinstance(value_field, ast.ArrayField) and value_field.width:
                array_size = f"(len(self.{value_field.id}) * {int(value_field.width / 8)}{size_modifier})"
            elif isinstance(value_field, ast.ArrayField) and isinstance(value_field.type, ast.EnumDeclaration):
                array_size = f"(len(self.{value_field.id}) * {int(value_field.type.width / 8)}{size_modifier})"
            elif isinstance(value_field, ast.ArrayField):
                self.append_(f"_size = sum([elt.size for elt in self.{value_field.id}]){size_modifier}")
                array_size = "_size"
                self.append_(
                    f"_{value_field.id}_size = sum([elt.size for elt in self.{value_field.id}]){size_modifier}")
                array_size = f"_{value_field.id}_size"
            else:
                raise Exception("Unsupported field type")
            self.value.append(f"({array_size} << {shift})")
Loading