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