1 /****************************************************************************** 2 * 3 * Copyright 2019 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at: 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 * 17 ******************************************************************************/ 18 19 #pragma once 20 21 #include <sstream> 22 #include <string> 23 #include <utility> 24 25 #include "crypto_toolbox/crypto_toolbox.h" 26 #include "hci/address.h" 27 #include "hci/hci_packets.h" 28 29 namespace bluetooth { 30 namespace hci { 31 32 class AddressWithType final { 33 public: AddressWithType(Address address,AddressType address_type)34 AddressWithType(Address address, AddressType address_type) 35 : address_(std::move(address)), address_type_(address_type) {} 36 AddressWithType()37 explicit AddressWithType() : address_(Address::kEmpty), address_type_(AddressType::PUBLIC_DEVICE_ADDRESS) {} 38 GetAddress()39 inline Address GetAddress() const { 40 return address_; 41 } 42 GetAddressType()43 inline AddressType GetAddressType() const { 44 return address_type_; 45 } 46 47 /* Is this an Resolvable Private Address ? */ IsRpa()48 inline bool IsRpa() const { 49 return address_type_ == hci::AddressType::RANDOM_DEVICE_ADDRESS && ((address_.data())[0] & 0xc0) == 0x40; 50 } 51 52 /* Is this an Resolvable Private Address, that was generated from given irk ? */ IsRpaThatMatchesIrk(const crypto_toolbox::Octet16 & irk)53 bool IsRpaThatMatchesIrk(const crypto_toolbox::Octet16& irk) const { 54 if (!IsRpa()) return false; 55 56 /* use the 3 MSB of bd address as prand */ 57 uint8_t prand[3]; 58 prand[0] = address_.address[2]; 59 prand[1] = address_.address[1]; 60 prand[2] = address_.address[0]; 61 /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ 62 crypto_toolbox::Octet16 computed_hash = crypto_toolbox::aes_128(irk, &prand[0], 3); 63 uint8_t hash[3]; 64 hash[0] = address_.address[5]; 65 hash[1] = address_.address[4]; 66 hash[2] = address_.address[3]; 67 if (memcmp(computed_hash.data(), &hash[0], 3) == 0) { 68 // match 69 return true; 70 } 71 // not a match 72 return false; 73 } 74 75 bool operator<(const AddressWithType& rhs) const { 76 return address_ < rhs.address_ && address_type_ < rhs.address_type_; 77 } 78 bool operator==(const AddressWithType& rhs) const { 79 return address_ == rhs.address_ && address_type_ == rhs.address_type_; 80 } 81 bool operator>(const AddressWithType& rhs) const { 82 return (rhs < *this); 83 } 84 bool operator<=(const AddressWithType& rhs) const { 85 return !(*this > rhs); 86 } 87 bool operator>=(const AddressWithType& rhs) const { 88 return !(*this < rhs); 89 } 90 bool operator!=(const AddressWithType& rhs) const { 91 return !(*this == rhs); 92 } 93 ToString()94 std::string ToString() const { 95 std::stringstream ss; 96 ss << address_ << "[" << AddressTypeText(address_type_) << "]"; 97 return ss.str(); 98 } 99 100 private: 101 Address address_; 102 AddressType address_type_; 103 }; 104 105 inline std::ostream& operator<<(std::ostream& os, const AddressWithType& a) { 106 os << a.ToString(); 107 return os; 108 } 109 110 } // namespace hci 111 } // namespace bluetooth 112 113 namespace std { 114 template <> 115 struct hash<bluetooth::hci::AddressWithType> { 116 std::size_t operator()(const bluetooth::hci::AddressWithType& val) const { 117 static_assert(sizeof(uint64_t) >= (bluetooth::hci::Address::kLength + sizeof(bluetooth::hci::AddressType))); 118 uint64_t int_addr = 0; 119 memcpy(reinterpret_cast<uint8_t*>(&int_addr), val.GetAddress().data(), bluetooth::hci::Address::kLength); 120 bluetooth::hci::AddressType address_type = val.GetAddressType(); 121 memcpy( 122 reinterpret_cast<uint8_t*>(&int_addr) + bluetooth::hci::Address::kLength, &address_type, sizeof(address_type)); 123 return std::hash<uint64_t>{}(int_addr); 124 } 125 }; 126 } // namespace std