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