xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/controller/src/ble_ll_resolv.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 #include <stdint.h>
20 #include <assert.h>
21 #include <string.h>
22 #include "syscfg/syscfg.h"
23 #include "os/os.h"
24 #include "nimble/ble.h"
25 #include "nimble/nimble_opt.h"
26 #include "controller/ble_ll.h"
27 #include "controller/ble_ll_resolv.h"
28 #include "controller/ble_ll_hci.h"
29 #include "controller/ble_ll_scan.h"
30 #include "controller/ble_ll_adv.h"
31 #include "controller/ble_hw.h"
32 #include "ble_ll_conn_priv.h"
33 
34 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
35 struct ble_ll_resolv_data
36 {
37     uint8_t addr_res_enabled;
38     uint8_t rl_size;
39     uint8_t rl_cnt;
40     uint32_t rpa_tmo;
41     struct ble_npl_callout rpa_timer;
42 };
43 struct ble_ll_resolv_data g_ble_ll_resolv_data;
44 
45 struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)];
46 
47 static int
ble_ll_is_controller_busy(void)48 ble_ll_is_controller_busy(void)
49 {
50     return ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
51            g_ble_ll_conn_create_sm;
52 }
53 /**
54  * Called to determine if a change is allowed to the resolving list at this
55  * time. We are not allowed to modify the resolving list if address translation
56  * is enabled and we are either scanning, advertising, or attempting to create
57  * a connection.
58  *
59  * @return int 0: not allowed. 1: allowed.
60  */
61 static int
ble_ll_resolv_list_chg_allowed(void)62 ble_ll_resolv_list_chg_allowed(void)
63 {
64     int rc;
65 
66     if (g_ble_ll_resolv_data.addr_res_enabled &&
67        ble_ll_is_controller_busy()) {
68         rc = 0;
69     } else {
70         rc = 1;
71     }
72     return rc;
73 }
74 
75 
76 /**
77  * Called to generate a resolvable private address in rl structure
78  *
79  * @param rl
80  * @param local
81  */
82 static void
ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry * rl,int local)83 ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local)
84 {
85     uint8_t *irk;
86     uint8_t *prand;
87     struct ble_encryption_block ecb;
88     uint8_t *addr;
89 
90     BLE_LL_ASSERT(rl != NULL);
91 
92     if (local) {
93         addr = rl->rl_local_rpa;
94         irk = rl->rl_local_irk;
95     } else {
96         addr = rl->rl_peer_rpa;
97         irk = rl->rl_peer_irk;
98     }
99 
100     /* Get prand */
101     prand = addr + 3;
102     ble_ll_rand_prand_get(prand);
103 
104     /* Calculate hash, hash = ah(local IRK, prand) */
105     memcpy(ecb.key, irk, 16);
106     memset(ecb.plain_text, 0, 13);
107     ecb.plain_text[13] = prand[2];
108     ecb.plain_text[14] = prand[1];
109     ecb.plain_text[15] = prand[0];
110 
111     /* Calculate hash */
112     ble_hw_encrypt_block(&ecb);
113 
114     addr[0] = ecb.cipher_text[15];
115     addr[1] = ecb.cipher_text[14];
116     addr[2] = ecb.cipher_text[13];
117 }
118 
119 /**
120  * Called when the Resolvable private address timer expires. This timer
121  * is used to regenerate local and peers RPA's in the resolving list.
122  */
123 static void
ble_ll_resolv_rpa_timer_cb(struct ble_npl_event * ev)124 ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
125 {
126     int i;
127     os_sr_t sr;
128     struct ble_ll_resolv_entry *rl;
129 
130     rl = &g_ble_ll_resolv_list[0];
131     for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
132         OS_ENTER_CRITICAL(sr);
133         ble_ll_resolv_gen_priv_addr(rl, 1);
134         OS_EXIT_CRITICAL(sr);
135 
136         OS_ENTER_CRITICAL(sr);
137         ble_ll_resolv_gen_priv_addr(rl, 0);
138         OS_EXIT_CRITICAL(sr);
139         ++rl;
140     }
141     ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
142                      (int32_t)g_ble_ll_resolv_data.rpa_tmo);
143 
144     ble_ll_adv_rpa_timeout();
145 }
146 
147 /**
148  * Called to determine if the IRK is all zero.
149  *
150  * @param irk
151  *
152  * @return int 0: IRK is zero . 1: IRK has non-zero value.
153  */
154 int
ble_ll_resolv_irk_nonzero(uint8_t * irk)155 ble_ll_resolv_irk_nonzero(uint8_t *irk)
156 {
157     int i;
158     int rc;
159 
160     rc = 0;
161     for (i = 0; i < 16; ++i) {
162         if (*irk != 0) {
163             rc = 1;
164             break;
165         }
166         ++irk;
167     }
168 
169     return rc;
170 }
171 
172 /**
173  * Clear the resolving list
174  *
175  * @return int 0: success, BLE error code otherwise
176  */
177 int
ble_ll_resolv_list_clr(void)178 ble_ll_resolv_list_clr(void)
179 {
180     /* Check proper state */
181     if (!ble_ll_resolv_list_chg_allowed()) {
182         return BLE_ERR_CMD_DISALLOWED;
183     }
184 
185     /* Sets total on list to 0. Clears HW resolve list */
186     g_ble_ll_resolv_data.rl_cnt = 0;
187     ble_hw_resolv_list_clear();
188 
189     return BLE_ERR_SUCCESS;
190 }
191 
192 /**
193  * Read the size of the resolving list. This is the total number of resolving
194  * list entries allowed by the controller.
195  *
196  * @param rspbuf Pointer to response buffer
197  *
198  * @return int 0: success.
199  */
200 int
ble_ll_resolv_list_read_size(uint8_t * rspbuf,uint8_t * rsplen)201 ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen)
202 {
203     rspbuf[0] = g_ble_ll_resolv_data.rl_size;
204     *rsplen = 1;
205     return BLE_ERR_SUCCESS;
206 }
207 
208 /**
209  * Used to determine if the device is on the resolving list.
210  *
211  * @param addr
212  * @param addr_type Public address (0) or random address (1)
213  *
214  * @return int 0: device is not on resolving list; otherwise the return value
215  * is the 'position' of the device in the resolving list (the index of the
216  * element plus 1).
217  */
218 static int
ble_ll_is_on_resolv_list(uint8_t * addr,uint8_t addr_type)219 ble_ll_is_on_resolv_list(uint8_t *addr, uint8_t addr_type)
220 {
221     int i;
222     struct ble_ll_resolv_entry *rl;
223 
224     rl = &g_ble_ll_resolv_list[0];
225     for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
226         if ((rl->rl_addr_type == addr_type) &&
227             (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
228             return i + 1;
229         }
230         ++rl;
231     }
232 
233     return 0;
234 }
235 
236 /**
237  * Used to determine if the device is on the resolving list.
238  *
239  * @param addr
240  * @param addr_type Public address (0) or random address (1)
241  *
242  * @return Pointer to resolving list entry or NULL if no entry found.
243  */
244 struct ble_ll_resolv_entry *
ble_ll_resolv_list_find(uint8_t * addr,uint8_t addr_type)245 ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type)
246 {
247     int i;
248     struct ble_ll_resolv_entry *rl;
249 
250     rl = &g_ble_ll_resolv_list[0];
251     for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
252         if ((rl->rl_addr_type == addr_type) &&
253             (!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
254             return rl;
255         }
256         ++rl;
257     }
258 
259     return NULL;
260 }
261 
262 /**
263  * Add a device to the resolving list
264  *
265  * @return int
266  */
267 int
ble_ll_resolv_list_add(uint8_t * cmdbuf)268 ble_ll_resolv_list_add(uint8_t *cmdbuf)
269 {
270     int rc;
271     uint8_t addr_type;
272     uint8_t *ident_addr;
273     struct ble_ll_resolv_entry *rl;
274 
275     /* Must be in proper state */
276     if (!ble_ll_resolv_list_chg_allowed()) {
277         return BLE_ERR_CMD_DISALLOWED;
278     }
279 
280     /* Check if we have any open entries */
281     if (g_ble_ll_resolv_data.rl_cnt >= g_ble_ll_resolv_data.rl_size) {
282         return BLE_ERR_MEM_CAPACITY;
283     }
284 
285     addr_type = cmdbuf[0];
286     ident_addr = cmdbuf + 1;
287 
288     /* spec is not clear on how to handle this but make sure host is aware
289      * that new keys are not used in that case
290      */
291     if (ble_ll_is_on_resolv_list(ident_addr, addr_type)) {
292         return BLE_ERR_INV_HCI_CMD_PARMS;
293     }
294 
295     rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
296     memset (rl, 0, sizeof(*rl));
297 
298     rl->rl_addr_type = addr_type;
299     memcpy(&rl->rl_identity_addr[0], ident_addr, BLE_DEV_ADDR_LEN);
300     swap_buf(rl->rl_peer_irk, cmdbuf + 7, 16);
301     swap_buf(rl->rl_local_irk, cmdbuf + 23, 16);
302 
303     /* By default use privacy network mode */
304     rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK;
305 
306     /* Add peer IRK to HW resolving list. Should always succeed since we
307      * already checked if there is room for it.
308      */
309     rc = ble_hw_resolv_list_add(rl->rl_peer_irk);
310     BLE_LL_ASSERT (rc == BLE_ERR_SUCCESS);
311 
312     /* generate a local and peer RPAs now, those will be updated by timer
313      * when resolution is enabled
314      */
315     ble_ll_resolv_gen_priv_addr(rl, 1);
316     ble_ll_resolv_gen_priv_addr(rl, 0);
317     ++g_ble_ll_resolv_data.rl_cnt;
318 
319     return rc;
320 }
321 
322 /**
323  * Remove a device from the resolving list
324  *
325  * @param cmdbuf
326  *
327  * @return int 0: success, BLE error code otherwise
328  */
329 int
ble_ll_resolv_list_rmv(uint8_t * cmdbuf)330 ble_ll_resolv_list_rmv(uint8_t *cmdbuf)
331 {
332     int position;
333     uint8_t addr_type;
334     uint8_t *ident_addr;
335 
336     /* Must be in proper state */
337     if (!ble_ll_resolv_list_chg_allowed()) {
338         return BLE_ERR_CMD_DISALLOWED;
339     }
340 
341     addr_type = cmdbuf[0];
342     ident_addr = cmdbuf + 1;
343 
344     /* Remove from IRK records */
345     position = ble_ll_is_on_resolv_list(ident_addr, addr_type);
346     if (position) {
347         BLE_LL_ASSERT(position <= g_ble_ll_resolv_data.rl_cnt);
348 
349         memmove(&g_ble_ll_resolv_list[position - 1],
350                 &g_ble_ll_resolv_list[position],
351                 g_ble_ll_resolv_data.rl_cnt - position);
352         --g_ble_ll_resolv_data.rl_cnt;
353 
354         /* Remove from HW list */
355         ble_hw_resolv_list_rmv(position - 1);
356         return BLE_ERR_SUCCESS;
357     }
358 
359     return BLE_ERR_UNK_CONN_ID;
360 }
361 
362 /**
363  * Called to enable or disable address resolution in the controller
364  *
365  * @param cmdbuf
366  *
367  * @return int
368  */
369 int
ble_ll_resolv_enable_cmd(uint8_t * cmdbuf)370 ble_ll_resolv_enable_cmd(uint8_t *cmdbuf)
371 {
372     int rc;
373     int32_t tmo;
374     uint8_t enabled;
375 
376     if (ble_ll_is_controller_busy()) {
377         rc = BLE_ERR_CMD_DISALLOWED;
378     } else {
379         enabled = cmdbuf[0];
380         if (enabled <= 1) {
381             /* If we change state, we need to disable/enable the RPA timer */
382             if ((enabled ^ g_ble_ll_resolv_data.addr_res_enabled) != 0) {
383                 if (enabled) {
384                     tmo = (int32_t)g_ble_ll_resolv_data.rpa_tmo;
385                     ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer, tmo);
386                 } else {
387                     ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
388                 }
389                 g_ble_ll_resolv_data.addr_res_enabled = enabled;
390             }
391             rc = BLE_ERR_SUCCESS;
392         } else {
393             rc = BLE_ERR_INV_HCI_CMD_PARMS;
394         }
395     }
396 
397     return rc;
398 }
399 
400 int
ble_ll_resolv_peer_addr_rd(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)401 ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
402 {
403     struct ble_ll_resolv_entry *rl;
404     uint8_t addr_type;
405     uint8_t *ident_addr;
406     int rc;
407 
408     addr_type = cmdbuf[0];
409     ident_addr = cmdbuf + 1;
410 
411     rl = ble_ll_resolv_list_find(ident_addr, addr_type);
412     if (rl) {
413         memcpy(rspbuf, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
414         rc = BLE_ERR_SUCCESS;
415     } else {
416         memset(rspbuf, 0, BLE_DEV_ADDR_LEN);
417         rc = BLE_ERR_UNK_CONN_ID;
418     }
419 
420     *rsplen = BLE_DEV_ADDR_LEN;
421     return rc;
422 }
423 
424 int
ble_ll_resolv_local_addr_rd(uint8_t * cmdbuf,uint8_t * rspbuf,uint8_t * rsplen)425 ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf, uint8_t *rspbuf, uint8_t *rsplen)
426 {
427     struct ble_ll_resolv_entry *rl;
428     uint8_t addr_type;
429     uint8_t *ident_addr;
430     int rc;
431 
432     addr_type = cmdbuf[0];
433     ident_addr = cmdbuf + 1;
434 
435     rl = ble_ll_resolv_list_find(ident_addr, addr_type);
436     if (rl) {
437         memcpy(rspbuf, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
438         rc = BLE_ERR_SUCCESS;
439     } else {
440         memset(rspbuf, 0, BLE_DEV_ADDR_LEN);
441         rc = BLE_ERR_UNK_CONN_ID;
442     }
443 
444     *rsplen = BLE_DEV_ADDR_LEN;
445     return rc;
446 }
447 
448 /**
449  * Set the resolvable private address timeout.
450  *
451  * @param cmdbuf
452  *
453  * @return int
454  */
455 int
ble_ll_resolv_set_rpa_tmo(uint8_t * cmdbuf)456 ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
457 {
458     uint16_t tmo_secs;
459 
460     tmo_secs = get_le16(cmdbuf);
461     if (!((tmo_secs > 0) && (tmo_secs <= 0xA1B8))) {
462         return BLE_ERR_INV_HCI_CMD_PARMS;
463     }
464 
465     g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(tmo_secs * 1000);
466 
467     /* If resolving is not enabled, we are done here. */
468     if (!ble_ll_resolv_enabled()) {
469         return BLE_ERR_SUCCESS;
470     }
471 
472     /* Reset timeout if resolving is enabled */
473     ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
474                      (int32_t)g_ble_ll_resolv_data.rpa_tmo);
475 
476     return BLE_ERR_SUCCESS;
477 }
478 
479 int
ble_ll_resolve_set_priv_mode(uint8_t * cmdbuf)480 ble_ll_resolve_set_priv_mode(uint8_t *cmdbuf)
481 {
482     struct ble_ll_resolv_entry *rl;
483 
484     if (ble_ll_is_controller_busy()) {
485         return BLE_ERR_CMD_DISALLOWED;
486     }
487 
488     /* cmdbuf = addr_type(0) | addr(6) | priv_mode(1) */
489     rl = ble_ll_resolv_list_find(&cmdbuf[1], cmdbuf[0]);
490     if (!rl) {
491         return BLE_ERR_UNK_CONN_ID;
492     }
493 
494     if (cmdbuf[7] > BLE_HCI_PRIVACY_DEVICE) {
495         return BLE_ERR_INV_HCI_CMD_PARMS;
496     }
497 
498     rl->rl_priv_mode = cmdbuf[7];
499     return 0;
500 }
501 
502 /**
503  * Returns the Resolvable Private address timeout, in os ticks
504  *
505  *
506  * @return uint32_t
507  */
508 uint32_t
ble_ll_resolv_get_rpa_tmo(void)509 ble_ll_resolv_get_rpa_tmo(void)
510 {
511     return g_ble_ll_resolv_data.rpa_tmo;
512 }
513 
514 void
ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry * rl,int local,uint8_t * addr)515 ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local,
516                             uint8_t *addr)
517 {
518     os_sr_t sr;
519 
520     BLE_LL_ASSERT(rl != NULL);
521     BLE_LL_ASSERT(addr != NULL);
522 
523     OS_ENTER_CRITICAL(sr);
524     if (local) {
525         memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
526     } else {
527         memcpy(addr, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
528     }
529 
530     OS_EXIT_CRITICAL(sr);
531 }
532 
533 void
ble_ll_resolv_set_peer_rpa(int index,uint8_t * rpa)534 ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa)
535 {
536     os_sr_t sr;
537     struct ble_ll_resolv_entry *rl;
538 
539     OS_ENTER_CRITICAL(sr);
540     rl = &g_ble_ll_resolv_list[index];
541     memcpy(rl->rl_peer_rpa, rpa, BLE_DEV_ADDR_LEN);
542     OS_EXIT_CRITICAL(sr);
543 }
544 
545 /**
546  * Generate a resolvable private address.
547  *
548  * @param addr
549  * @param addr_type
550  * @param rpa
551  *
552  * @return int
553  */
554 int
ble_ll_resolv_gen_rpa(uint8_t * addr,uint8_t addr_type,uint8_t * rpa,int local)555 ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local)
556 {
557     int rc;
558     uint8_t *irk;
559     struct ble_ll_resolv_entry *rl;
560 
561     rc = 0;
562     rl = ble_ll_resolv_list_find(addr, addr_type);
563     if (rl) {
564         if (local) {
565             irk = rl->rl_local_irk;
566         } else {
567             irk = rl->rl_peer_irk;
568         }
569         if (ble_ll_resolv_irk_nonzero(irk)) {
570             ble_ll_resolv_get_priv_addr(rl, local, rpa);
571             rc = 1;
572         }
573     }
574 
575     return rc;
576 }
577 
578 /**
579  * Resolve a Resolvable Private Address
580  *
581  * @param rpa
582  * @param index
583  *
584  * @return int
585  */
586 int
ble_ll_resolv_rpa(uint8_t * rpa,uint8_t * irk)587 ble_ll_resolv_rpa(uint8_t *rpa, uint8_t *irk)
588 {
589     int rc;
590     uint32_t *irk32;
591     uint32_t *key32;
592     uint32_t *pt32;
593     struct ble_encryption_block ecb;
594 
595     irk32 = (uint32_t *)irk;
596     key32 = (uint32_t *)&ecb.key[0];
597 
598     key32[0] = irk32[0];
599     key32[1] = irk32[1];
600     key32[2] = irk32[2];
601     key32[3] = irk32[3];
602 
603     pt32 = (uint32_t *)&ecb.plain_text[0];
604     pt32[0] = 0;
605     pt32[1] = 0;
606     pt32[2] = 0;
607     pt32[3] = 0;
608 
609     ecb.plain_text[15] = rpa[3];
610     ecb.plain_text[14] = rpa[4];
611     ecb.plain_text[13] = rpa[5];
612 
613     ble_hw_encrypt_block(&ecb);
614     if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) &&
615         (ecb.cipher_text[13] == rpa[2])) {
616         rc = 1;
617     } else {
618         rc = 0;
619     }
620 
621     return rc;
622 }
623 
624 /**
625  * Returns whether or not address resolution is enabled.
626  *
627  * @return uint8_t
628  */
629 uint8_t
ble_ll_resolv_enabled(void)630 ble_ll_resolv_enabled(void)
631 {
632     return g_ble_ll_resolv_data.addr_res_enabled;
633 }
634 
635 /**
636  * Called to reset private address resolution module.
637  */
638 void
ble_ll_resolv_list_reset(void)639 ble_ll_resolv_list_reset(void)
640 {
641     g_ble_ll_resolv_data.addr_res_enabled = 0;
642     ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
643     ble_ll_resolv_list_clr();
644     ble_ll_resolv_init();
645 }
646 
647 void
ble_ll_resolv_init(void)648 ble_ll_resolv_init(void)
649 {
650     uint8_t hw_size;
651 
652     /* Default is 15 minutes */
653     g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(15 * 60 * 1000);
654 
655     hw_size = ble_hw_resolv_list_size();
656     if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) {
657         hw_size = MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE);
658     }
659     g_ble_ll_resolv_data.rl_size = hw_size;
660 
661     ble_npl_callout_init(&g_ble_ll_resolv_data.rpa_timer,
662                          &g_ble_ll_data.ll_evq,
663                          ble_ll_resolv_rpa_timer_cb,
664                          NULL);
665 }
666 
667 #endif  /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1 */
668 
669