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 "securec.h"
22 #include "ble_hs_priv.h"
23 #include "host/ble_hs_id.h"
24
25 static uint8_t ble_hs_id_pub[6];
26 static uint8_t ble_hs_id_rnd[6];
27
ble_hs_id_set_pub(const uint8_t * pub_addr)28 void ble_hs_id_set_pub(const uint8_t *pub_addr)
29 {
30 ble_hs_lock();
31 memcpy_s(ble_hs_id_pub, sizeof(ble_hs_id_pub), pub_addr, 6); // 6:size
32 ble_hs_unlock();
33 }
34
ble_hs_id_gen_rnd(int nrpa,ble_addr_t * out_addr)35 int ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr)
36 {
37 int rc;
38 out_addr->type = BLE_ADDR_RANDOM;
39 rc = ble_hs_hci_util_rand(out_addr->val, 6); // 6:size
40 if (rc != 0) {
41 return rc;
42 }
43
44 if (nrpa) {
45 out_addr->val[5] &= ~0xc0;
46 } else {
47 out_addr->val[5] |= 0xc0;
48 }
49
50 return 0;
51 }
52
ble_hs_id_set_rnd(const uint8_t * rnd_addr)53 int ble_hs_id_set_rnd(const uint8_t *rnd_addr)
54 {
55 uint8_t addr_type_byte;
56 int rc;
57 int ones;
58 ble_hs_lock();
59 /* Make sure random part of rnd_addr is not all ones or zeros. Reference:
60 * Core v5.0, Vol 6, Part B, section 1.3.2.1 */
61 addr_type_byte = rnd_addr[5] & 0xc0; // 5:array element
62 /* count bits set to 1 in random part of address */
63 ones = __builtin_popcount(rnd_addr[0]);
64 ones += __builtin_popcount(rnd_addr[1]);
65 ones += __builtin_popcount(rnd_addr[2]); // 2:array element
66 ones += __builtin_popcount(rnd_addr[3]); // 3:array element
67 ones += __builtin_popcount(rnd_addr[4]); // 4:array element
68 ones += __builtin_popcount(rnd_addr[5] & 0x3f); // 5:array element
69 if ((addr_type_byte != 0x00 && addr_type_byte != 0xc0) ||
70 (ones == 0 || ones == 46)) { // 6:Analyzing conditions
71 rc = BLE_HS_EINVAL;
72 goto done;
73 }
74
75 rc = ble_hs_hci_util_set_random_addr(rnd_addr);
76 if (rc != 0) {
77 goto done;
78 }
79
80 memcpy_s(ble_hs_id_rnd, sizeof(ble_hs_id_rnd), rnd_addr, 6);
81 done:
82 ble_hs_unlock();
83 return rc;
84 }
85
86 /**
87 * Retrieves one of the device's identity addresses. The device can have two
88 * identity addresses: one public and one random. The id_addr_type argument
89 * specifies which of these two addresses to retrieve.
90 *
91 * @param id_addr_type The type of identity address to retrieve.
92 * Valid values are:
93 * o BLE_ADDR_PUBLIC
94 * o BLE_ADDR_RANDOM
95 * @param out_id_addr On success, this is reseated to point to the
96 * retrieved 6-byte identity address. Pass
97 * NULL if you do not require this
98 * information.
99
100 * @param out_is_nrpa On success, the pointed-to value indicates
101 * whether the retrieved address is a
102 * non-resolvable private address. Pass NULL
103 * if you do not require this information.
104 *
105 * @return 0 on success;
106 * BLE_HS_EINVAL if an invalid address type was
107 * specified;
108 * BLE_HS_ENOADDR if the device does not have an
109 * identity address of the requested type;
110 * Other BLE host core code on error.
111 */
ble_hs_id_addr(uint8_t id_addr_type,const uint8_t ** out_id_addr,int * out_is_nrpa)112 int ble_hs_id_addr(uint8_t id_addr_type, const uint8_t **out_id_addr, int *out_is_nrpa)
113 {
114 const uint8_t *id_addr;
115 int nrpa;
116 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
117
118 switch (id_addr_type) {
119 case BLE_ADDR_PUBLIC:
120 id_addr = ble_hs_id_pub;
121 nrpa = 0;
122 break;
123
124 case BLE_ADDR_RANDOM:
125 id_addr = ble_hs_id_rnd;
126 nrpa = (ble_hs_id_rnd[5] & 0xc0) == 0;
127 break;
128
129 default:
130 return BLE_HS_EINVAL;
131 }
132
133 if (memcmp(id_addr, ble_hs_misc_null_addr, 6) == 0) {
134 return BLE_HS_ENOADDR;
135 }
136
137 if (out_id_addr != NULL) {
138 *out_id_addr = id_addr;
139 }
140
141 if (out_is_nrpa != NULL) {
142 *out_is_nrpa = nrpa;
143 }
144
145 return 0;
146 }
147
ble_hs_id_copy_addr(uint8_t id_addr_type,uint8_t * out_id_addr,int * out_is_nrpa)148 int ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr, int *out_is_nrpa)
149 {
150 const uint8_t *addr;
151 int rc;
152 ble_hs_lock();
153 rc = ble_hs_id_addr(id_addr_type, &addr, out_is_nrpa);
154 if (rc == 0 && out_id_addr != NULL) {
155 memcpy_s(out_id_addr, sizeof(out_id_addr), addr, 6);
156 }
157
158 ble_hs_unlock();
159 return rc;
160 }
161
ble_hs_id_addr_type_usable(uint8_t own_addr_type)162 static int ble_hs_id_addr_type_usable(uint8_t own_addr_type)
163 {
164 uint8_t id_addr_type;
165 int nrpa;
166 int rc;
167
168 switch (own_addr_type) {
169 case BLE_OWN_ADDR_PUBLIC:
170 case BLE_OWN_ADDR_RANDOM:
171 rc = ble_hs_id_addr(own_addr_type, NULL, NULL);
172 if (rc != 0) {
173 return rc;
174 }
175
176 break;
177
178 case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT:
179 case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT:
180 id_addr_type = ble_hs_misc_own_addr_type_to_id(own_addr_type);
181 rc = ble_hs_id_addr(id_addr_type, NULL, &nrpa);
182 if (rc != 0) {
183 return rc;
184 }
185
186 if (nrpa) {
187 return BLE_HS_ENOADDR;
188 }
189
190 break;
191
192 default:
193 return BLE_HS_EINVAL;
194 }
195
196 return 0;
197 }
198
ble_hs_id_use_addr(uint8_t own_addr_type)199 int ble_hs_id_use_addr(uint8_t own_addr_type)
200 {
201 int rc;
202 rc = ble_hs_id_addr_type_usable(own_addr_type);
203 if (rc != 0) {
204 return rc;
205 }
206
207 /* If privacy is being used, make sure RPA rotation is in effect. */
208 if (own_addr_type == BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT ||
209 own_addr_type == BLE_OWN_ADDR_RPA_RANDOM_DEFAULT) {
210 rc = ble_hs_pvcy_ensure_started();
211 if (rc != 0) {
212 return rc;
213 }
214 }
215
216 return 0;
217 }
218
ble_hs_id_infer_auto(int privacy,uint8_t * out_addr_type)219 int ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type)
220 {
221 static const uint8_t pub_addr_types[] = {
222 BLE_OWN_ADDR_RANDOM,
223 BLE_OWN_ADDR_PUBLIC,
224 };
225 static const uint8_t priv_addr_types[] = {
226 BLE_OWN_ADDR_RPA_RANDOM_DEFAULT,
227 BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT,
228 };
229 const uint8_t *addr_types;
230 uint8_t addr_type;
231 int num_addr_types;
232 int rc;
233 int i;
234 ble_hs_lock();
235
236 if (privacy) {
237 addr_types = priv_addr_types;
238 num_addr_types = sizeof priv_addr_types / sizeof priv_addr_types[0];
239 } else {
240 addr_types = pub_addr_types;
241 num_addr_types = sizeof pub_addr_types / sizeof pub_addr_types[0];
242 }
243
244 for (i = 0; i < num_addr_types; i++) {
245 addr_type = addr_types[i];
246 rc = ble_hs_id_addr_type_usable(addr_type);
247 switch (rc) {
248 case 0:
249 *out_addr_type = addr_type;
250 goto done;
251
252 case BLE_HS_ENOADDR:
253 break;
254
255 default:
256 goto done;
257 }
258 }
259
260 rc = BLE_HS_ENOADDR;
261 done:
262 ble_hs_unlock();
263 return rc;
264 }
265
266 /**
267 * Clears both the public and random addresses. This function is necessary
268 * when the controller loses its random address (e.g., on a stack reset).
269 */
ble_hs_id_reset(void)270 void ble_hs_id_reset(void)
271 {
272 memset_s(ble_hs_id_pub, sizeof ble_hs_id_pub, 0, sizeof ble_hs_id_pub);
273 memset_s(ble_hs_id_rnd, sizeof ble_hs_id_rnd, 0, sizeof ble_hs_id_pub);
274 }
275
276 /**
277 * Clears random address. This function is necessary when the host wants to
278 * clear random address.
279 */
ble_hs_id_rnd_reset(void)280 void ble_hs_id_rnd_reset(void)
281 {
282 memset_s(ble_hs_id_rnd, sizeof ble_hs_id_rnd, 0, sizeof ble_hs_id_rnd);
283 }