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