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