1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <string.h>
21 #include "host/ble_hs_id.h"
22 #include "ble_hs_priv.h"
23
24 static uint8_t ble_hs_id_pub[6];
25 static uint8_t ble_hs_id_rnd[6];
26
27 void
ble_hs_id_set_pub(const uint8_t * pub_addr)28 ble_hs_id_set_pub(const uint8_t *pub_addr)
29 {
30 ble_hs_lock();
31 memcpy(ble_hs_id_pub, pub_addr, 6);
32 ble_hs_unlock();
33 }
34
35 int
ble_hs_id_gen_rnd(int nrpa,ble_addr_t * out_addr)36 ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr)
37 {
38 int rc;
39
40 out_addr->type = BLE_ADDR_RANDOM;
41
42 rc = ble_hs_hci_util_rand(out_addr->val, 6);
43 if (rc != 0) {
44 return rc;
45 }
46
47 if (nrpa) {
48 out_addr->val[5] &= ~0xc0;
49 } else {
50 out_addr->val[5] |= 0xc0;
51 }
52
53 return 0;
54 }
55
56 int
ble_hs_id_set_rnd(const uint8_t * rnd_addr)57 ble_hs_id_set_rnd(const uint8_t *rnd_addr)
58 {
59 uint8_t addr_type_byte;
60 int rc;
61
62 ble_hs_lock();
63
64 addr_type_byte = rnd_addr[5] & 0xc0;
65 if (addr_type_byte != 0x00 && addr_type_byte != 0xc0) {
66 rc = BLE_HS_EINVAL;
67 goto done;
68 }
69
70 rc = ble_hs_hci_util_set_random_addr(rnd_addr);
71 if (rc != 0) {
72 goto done;
73 }
74
75 memcpy(ble_hs_id_rnd, rnd_addr, 6);
76
77 rc = 0;
78
79 done:
80 ble_hs_unlock();
81 return rc;
82 }
83
84 /**
85 * Retrieves one of the device's identity addresses. The device can have two
86 * identity addresses: one public and one random. The id_addr_type argument
87 * specifies which of these two addresses to retrieve.
88 *
89 * @param id_addr_type The type of identity address to retrieve.
90 * Valid values are:
91 * o BLE_ADDR_PUBLIC
92 * o BLE_ADDR_RANDOM
93 * @param out_id_addr On success, this is reseated to point to the
94 * retrieved 6-byte identity address. Pass
95 * NULL if you do not require this
96 * information.
97
98 * @param out_is_nrpa On success, the pointed-to value indicates
99 * whether the retrieved address is a
100 * non-resolvable private address. Pass NULL
101 * if you do not require this information.
102 *
103 * @return 0 on success;
104 * BLE_HS_EINVAL if an invalid address type was
105 * specified;
106 * BLE_HS_ENOADDR if the device does not have an
107 * identity address of the requested type;
108 * Other BLE host core code on error.
109 */
110 int
ble_hs_id_addr(uint8_t id_addr_type,const uint8_t ** out_id_addr,int * out_is_nrpa)111 ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr,
112 int *out_is_nrpa)
113 {
114 const uint8_t *id_addr;
115 int nrpa;
116
117 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
118
119 switch (id_addr_type) {
120 case BLE_ADDR_PUBLIC:
121 id_addr = ble_hs_id_pub;
122 nrpa = 0;
123 break;
124
125 case BLE_ADDR_RANDOM:
126 id_addr = ble_hs_id_rnd;
127 nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0;
128 break;
129
130 default:
131 return BLE_HS_EINVAL;
132 }
133
134 if (memcmp(id_addr, ble_hs_misc_null_addr, 6) == 0) {
135 return BLE_HS_ENOADDR;
136 }
137
138 if (out_id_addr != NULL) {
139 *out_id_addr = id_addr;
140 }
141 if (out_is_nrpa != NULL) {
142 *out_is_nrpa = nrpa;
143 }
144
145 return 0;
146 }
147
148 int
ble_hs_id_copy_addr(uint8_t id_addr_type,uint8_t * out_id_addr,int * out_is_nrpa)149 ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr,
150 int *out_is_nrpa)
151 {
152 const uint8_t *addr;
153 int rc;
154
155 ble_hs_lock();
156
157 rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa);
158 if (rc == 0 && out_id_addr != NULL) {
159 memcpy(out_id_addr, addr, 6);
160 }
161
162 ble_hs_unlock();
163
164 return rc;
165 }
166
167 static int
ble_hs_id_addr_type_usable(uint8_t own_addr_type)168 ble_hs_id_addr_type_usable(uint8_t own_addr_type)
169 {
170 uint8_t id_addr_type;
171 int nrpa;
172 int rc;
173
174 switch (own_addr_type) {
175 case BLE_OWN_ADDR_PUBLIC:
176 case BLE_OWN_ADDR_RANDOM:
177 rc = ble_hs_id_addr(own_addr_type, NULL, NULL);
178 if (rc != 0) {
179 return rc;
180 }
181 break;
182
183 case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
184 case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
185 id_addr_type = ble_hs_misc_addr_type_to_id(own_addr_type);
186 rc = ble_hs_id_addr(id_addr_type, NULL, &nrpa);
187 if (rc != 0) {
188 return rc;
189 }
190 if (nrpa) {
191 return BLE_HS_ENOADDR;
192 }
193 break;
194
195 default:
196 return BLE_HS_EINVAL;
197 }
198
199 return 0;
200 }
201
202 int
ble_hs_id_use_addr(uint8_t own_addr_type)203 ble_hs_id_use_addr(uint8_t own_addr_type)
204 {
205 int rc;
206
207 rc = ble_hs_id_addr_type_usable(own_addr_type);
208 if (rc != 0) {
209 return rc;
210 }
211
212 /* If privacy is being used, make sure RPA rotation is in effect. */
213 if (own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT ||
214 own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) {
215
216 rc = ble_hs_pvcy_ensure_started();
217 if (rc != 0) {
218 return rc;
219 }
220 }
221
222 return 0;
223 }
224
225 int
ble_hs_id_infer_auto(int privacy,uint8_t * out_addr_type)226 ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type)
227 {
228 static const uint8_t pub_addr_types[] = {
229 BLE_OWN_ADDR_RANDOM,
230 BLE_OWN_ADDR_PUBLIC,
231 };
232 static const uint8_t priv_addr_types[] = {
233 BLE_OWN_ADDR_RPA_RANDOM_DEFAULT,
234 BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
235 };
236 const uint8_t *addr_types;
237 uint8_t addr_type;
238 int num_addr_types;
239 int rc;
240 int i;
241
242 ble_hs_lock();
243
244 if (privacy) {
245 addr_types = priv_addr_types;
246 num_addr_types = sizeof priv_addr_types / sizeof priv_addr_types[0];
247 } else {
248 addr_types = pub_addr_types;
249 num_addr_types = sizeof pub_addr_types / sizeof pub_addr_types[0];
250 }
251
252 for (i = 0; i < num_addr_types; i++) {
253 addr_type = addr_types[i];
254
255 rc = ble_hs_id_addr_type_usable(addr_type);
256 switch (rc) {
257 case 0:
258 *out_addr_type = addr_type;
259 goto done;
260
261 case BLE_HS_ENOADDR:
262 break;
263
264 default:
265 goto done;
266 }
267 }
268
269 rc = BLE_HS_ENOADDR;
270
271 done:
272 ble_hs_unlock();
273 return rc;
274 }
275
276 /**
277 * Clears both the public and random addresses. This function is necessary
278 * when the controller loses its random address (e.g., on a stack reset).
279 */
280 void
ble_hs_id_reset(void)281 ble_hs_id_reset(void)
282 {
283 memset(ble_hs_id_pub, 0, sizeof ble_hs_id_pub);
284 memset(ble_hs_id_rnd, 0, sizeof ble_hs_id_pub);
285 }
286