xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_hs_id.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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