• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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