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 "common/interfaces/ILoggable.h" 26 #include "crypto_toolbox/crypto_toolbox.h" 27 #include "hci/address.h" 28 #include "hci/hci_packets.h" 29 30 namespace bluetooth { 31 namespace hci { 32 33 class AddressWithType final : public bluetooth::common::IRedactableLoggable { 34 public: AddressWithType(Address address,AddressType address_type)35 AddressWithType(Address address, AddressType address_type) 36 : address_(std::move(address)), address_type_(address_type) {} 37 AddressWithType()38 explicit AddressWithType() : address_(Address::kEmpty), address_type_(AddressType::PUBLIC_DEVICE_ADDRESS) {} 39 GetAddress()40 inline Address GetAddress() const { 41 return address_; 42 } 43 GetAddressType()44 inline AddressType GetAddressType() const { 45 return address_type_; 46 } 47 48 /* Is this an Resolvable Private Address ? */ IsRpa()49 inline bool IsRpa() const { 50 return address_type_ == hci::AddressType::RANDOM_DEVICE_ADDRESS && ((address_.data())[0] & 0xc0) == 0x40; 51 } 52 53 /* Is this an Resolvable Private Address, that was generated from given irk ? */ IsRpaThatMatchesIrk(const crypto_toolbox::Octet16 & irk)54 bool IsRpaThatMatchesIrk(const crypto_toolbox::Octet16& irk) const { 55 if (!IsRpa()) return false; 56 57 /* use the 3 MSB of bd address as prand */ 58 uint8_t prand[3]; 59 prand[0] = address_.address[2]; 60 prand[1] = address_.address[1]; 61 prand[2] = address_.address[0]; 62 /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */ 63 crypto_toolbox::Octet16 computed_hash = crypto_toolbox::aes_128(irk, &prand[0], 3); 64 uint8_t hash[3]; 65 hash[0] = address_.address[5]; 66 hash[1] = address_.address[4]; 67 hash[2] = address_.address[3]; 68 if (memcmp(computed_hash.data(), &hash[0], 3) == 0) { 69 // match 70 return true; 71 } 72 // not a match 73 return false; 74 } 75 76 bool operator<(const AddressWithType& rhs) const { 77 return (address_ != rhs.address_) ? address_ < rhs.address_ : address_type_ < rhs.address_type_; 78 } 79 bool operator==(const AddressWithType& rhs) const { 80 return address_ == rhs.address_ && address_type_ == rhs.address_type_; 81 } 82 bool operator>(const AddressWithType& rhs) const { 83 return (rhs < *this); 84 } 85 bool operator<=(const AddressWithType& rhs) const { 86 return !(*this > rhs); 87 } 88 bool operator>=(const AddressWithType& rhs) const { 89 return !(*this < rhs); 90 } 91 bool operator!=(const AddressWithType& rhs) const { 92 return !(*this == rhs); 93 } 94 ToFilterAcceptListAddressType()95 FilterAcceptListAddressType ToFilterAcceptListAddressType() const { 96 switch (address_type_) { 97 case AddressType::PUBLIC_DEVICE_ADDRESS: 98 case AddressType::PUBLIC_IDENTITY_ADDRESS: 99 return FilterAcceptListAddressType::PUBLIC; 100 case AddressType::RANDOM_DEVICE_ADDRESS: 101 case AddressType::RANDOM_IDENTITY_ADDRESS: 102 return FilterAcceptListAddressType::RANDOM; 103 } 104 } 105 ToPeerAddressType()106 PeerAddressType ToPeerAddressType() const { 107 switch (address_type_) { 108 case AddressType::PUBLIC_DEVICE_ADDRESS: 109 case AddressType::PUBLIC_IDENTITY_ADDRESS: 110 return PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS; 111 case AddressType::RANDOM_DEVICE_ADDRESS: 112 case AddressType::RANDOM_IDENTITY_ADDRESS: 113 return PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS; 114 } 115 } 116 ToString()117 std::string ToString() const { 118 std::stringstream ss; 119 ss << address_ << "[" << AddressTypeText(address_type_) << "]"; 120 return ss.str(); 121 } 122 ToStringForLogging()123 std::string ToStringForLogging() const override { 124 return address_.ToStringForLogging() + "[" + AddressTypeText(address_type_) + "]"; 125 } 126 ToRedactedStringForLogging()127 std::string ToRedactedStringForLogging() const override { 128 return address_.ToStringForLogging() + "[" + AddressTypeText(address_type_) + "]"; 129 } 130 131 private: 132 Address address_; 133 AddressType address_type_; 134 }; 135 136 inline std::ostream& operator<<(std::ostream& os, const AddressWithType& a) { 137 os << a.ToString(); 138 return os; 139 } 140 141 } // namespace hci 142 } // namespace bluetooth 143 144 namespace std { 145 template <> 146 struct hash<bluetooth::hci::AddressWithType> { 147 std::size_t operator()(const bluetooth::hci::AddressWithType& val) const { 148 static_assert(sizeof(uint64_t) >= (bluetooth::hci::Address::kLength + sizeof(bluetooth::hci::AddressType))); 149 uint64_t int_addr = 0; 150 memcpy(reinterpret_cast<uint8_t*>(&int_addr), val.GetAddress().data(), bluetooth::hci::Address::kLength); 151 bluetooth::hci::AddressType address_type = val.GetAddressType(); 152 memcpy( 153 reinterpret_cast<uint8_t*>(&int_addr) + bluetooth::hci::Address::kLength, &address_type, sizeof(address_type)); 154 return std::hash<uint64_t>{}(int_addr); 155 } 156 }; 157 } // namespace std 158