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 /**
21 * L2CAP Security Manager (channel ID = 6).
22 *
23 * Design overview:
24 *
25 * L2CAP sm procedures are initiated by the application via function calls.
26 * Such functions return when either of the following happens:
27 *
28 * (1) The procedure completes (success or failure).
29 * (2) The procedure cannot proceed until a BLE peer responds.
30 *
31 * For (1), the result of the procedure if fully indicated by the function
32 * return code.
33 * For (2), the procedure result is indicated by an application-configured
34 * callback. The callback is executed when the procedure completes.
35 *
36 * Notes on thread-safety:
37 * 1. The ble_hs mutex must never be locked when an application callback is
38 * executed. A callback is free to initiate additional host procedures.
39 * 2. Keep the host mutex locked whenever:
40 * o A proc entry is read from or written to.
41 * o The proc list is read or modified.
42 */
43
44 #include <string.h>
45 #include <errno.h>
46 #include "nimble/ble.h"
47 #include "nimble/nimble_opt.h"
48 #include "host/ble_sm.h"
49 #include "ble_hs_priv.h"
50
51 #if NIMBLE_BLE_SM
52
53 /** Procedure timeout; 30 seconds. */
54 #define BLE_SM_TIMEOUT_MS (30000)
55
56 STAILQ_HEAD(ble_sm_proc_list, ble_sm_proc);
57
58 typedef void ble_sm_rx_fn(uint16_t conn_handle, struct os_mbuf **om,
59 struct ble_sm_result *res);
60
61 static ble_sm_rx_fn ble_sm_rx_noop;
62 static ble_sm_rx_fn ble_sm_pair_req_rx;
63 static ble_sm_rx_fn ble_sm_pair_rsp_rx;
64 static ble_sm_rx_fn ble_sm_confirm_rx;
65 static ble_sm_rx_fn ble_sm_random_rx;
66 static ble_sm_rx_fn ble_sm_fail_rx;
67 static ble_sm_rx_fn ble_sm_enc_info_rx;
68 static ble_sm_rx_fn ble_sm_master_id_rx;
69 static ble_sm_rx_fn ble_sm_id_info_rx;
70 static ble_sm_rx_fn ble_sm_id_addr_info_rx;
71 static ble_sm_rx_fn ble_sm_sign_info_rx;
72 static ble_sm_rx_fn ble_sm_sec_req_rx;
73
74 static ble_sm_rx_fn * const ble_sm_dispatch[] = {
75 [BLE_SM_OP_PAIR_REQ] = ble_sm_pair_req_rx,
76 [BLE_SM_OP_PAIR_RSP] = ble_sm_pair_rsp_rx,
77 [BLE_SM_OP_PAIR_CONFIRM] = ble_sm_confirm_rx,
78 [BLE_SM_OP_PAIR_RANDOM] = ble_sm_random_rx,
79 [BLE_SM_OP_PAIR_FAIL] = ble_sm_fail_rx,
80 [BLE_SM_OP_ENC_INFO] = ble_sm_enc_info_rx,
81 [BLE_SM_OP_MASTER_ID] = ble_sm_master_id_rx,
82 [BLE_SM_OP_IDENTITY_INFO] = ble_sm_id_info_rx,
83 [BLE_SM_OP_IDENTITY_ADDR_INFO] = ble_sm_id_addr_info_rx,
84 [BLE_SM_OP_SIGN_INFO] = ble_sm_sign_info_rx,
85 [BLE_SM_OP_SEC_REQ] = ble_sm_sec_req_rx,
86 [BLE_SM_OP_PAIR_KEYPRESS_NOTIFY] = ble_sm_rx_noop,
87 #if MYNEWT_VAL(BLE_SM_SC)
88 [BLE_SM_OP_PAIR_PUBLIC_KEY] = ble_sm_sc_public_key_rx,
89 [BLE_SM_OP_PAIR_DHKEY_CHECK] = ble_sm_sc_dhkey_check_rx,
90 #else
91 [BLE_SM_OP_PAIR_PUBLIC_KEY] = ble_sm_rx_noop,
92 [BLE_SM_OP_PAIR_DHKEY_CHECK] = ble_sm_rx_noop,
93 #endif
94 };
95
96 typedef void ble_sm_state_fn(struct ble_sm_proc *proc,
97 struct ble_sm_result *res, void *arg);
98
99 static ble_sm_state_fn ble_sm_pair_exec;
100 static ble_sm_state_fn ble_sm_confirm_exec;
101 static ble_sm_state_fn ble_sm_random_exec;
102 static ble_sm_state_fn ble_sm_ltk_start_exec;
103 static ble_sm_state_fn ble_sm_ltk_restore_exec;
104 static ble_sm_state_fn ble_sm_enc_start_exec;
105 static ble_sm_state_fn ble_sm_enc_restore_exec;
106 static ble_sm_state_fn ble_sm_key_exch_exec;
107 static ble_sm_state_fn ble_sm_sec_req_exec;
108
109 static ble_sm_state_fn * const
110 ble_sm_state_dispatch[BLE_SM_PROC_STATE_CNT] = {
111 [BLE_SM_PROC_STATE_PAIR] = ble_sm_pair_exec,
112 [BLE_SM_PROC_STATE_CONFIRM] = ble_sm_confirm_exec,
113 [BLE_SM_PROC_STATE_RANDOM] = ble_sm_random_exec,
114 [BLE_SM_PROC_STATE_LTK_START] = ble_sm_ltk_start_exec,
115 [BLE_SM_PROC_STATE_LTK_RESTORE] = ble_sm_ltk_restore_exec,
116 [BLE_SM_PROC_STATE_ENC_START] = ble_sm_enc_start_exec,
117 [BLE_SM_PROC_STATE_ENC_RESTORE] = ble_sm_enc_restore_exec,
118 [BLE_SM_PROC_STATE_KEY_EXCH] = ble_sm_key_exch_exec,
119 [BLE_SM_PROC_STATE_SEC_REQ] = ble_sm_sec_req_exec,
120 #if MYNEWT_VAL(BLE_SM_SC)
121 [BLE_SM_PROC_STATE_PUBLIC_KEY] = ble_sm_sc_public_key_exec,
122 [BLE_SM_PROC_STATE_DHKEY_CHECK] = ble_sm_sc_dhkey_check_exec,
123 #else
124 [BLE_SM_PROC_STATE_PUBLIC_KEY] = NULL,
125 [BLE_SM_PROC_STATE_DHKEY_CHECK] = NULL,
126 #endif
127 };
128
129 static os_membuf_t ble_sm_proc_mem[
130 OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_SM_MAX_PROCS),
131 sizeof (struct ble_sm_proc))
132 ];
133
134 static struct os_mempool ble_sm_proc_pool;
135
136 /* Maintains the list of active security manager procedures. */
137 static struct ble_sm_proc_list ble_sm_procs;
138
139 static void ble_sm_pair_cfg(struct ble_sm_proc *proc);
140
141
142 /*****************************************************************************
143 * $debug *
144 *****************************************************************************/
145
146 #if MYNEWT_VAL(BLE_HS_DEBUG)
147
148 static uint8_t ble_sm_dbg_next_pair_rand[16];
149 static uint8_t ble_sm_dbg_next_pair_rand_set;
150 static uint16_t ble_sm_dbg_next_ediv;
151 static uint8_t ble_sm_dbg_next_ediv_set;
152 static uint64_t ble_sm_dbg_next_master_id_rand;
153 static uint8_t ble_sm_dbg_next_master_id_rand_set;
154 static uint8_t ble_sm_dbg_next_ltk[16];
155 static uint8_t ble_sm_dbg_next_ltk_set;
156 static uint8_t ble_sm_dbg_next_csrk[16];
157 static uint8_t ble_sm_dbg_next_csrk_set;
158
159 void
ble_sm_dbg_set_next_pair_rand(uint8_t * next_pair_rand)160 ble_sm_dbg_set_next_pair_rand(uint8_t *next_pair_rand)
161 {
162 memcpy(ble_sm_dbg_next_pair_rand, next_pair_rand,
163 sizeof ble_sm_dbg_next_pair_rand);
164 ble_sm_dbg_next_pair_rand_set = 1;
165 }
166
167 void
ble_sm_dbg_set_next_ediv(uint16_t next_ediv)168 ble_sm_dbg_set_next_ediv(uint16_t next_ediv)
169 {
170 ble_sm_dbg_next_ediv = next_ediv;
171 ble_sm_dbg_next_ediv_set = 1;
172 }
173
174 void
ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand)175 ble_sm_dbg_set_next_master_id_rand(uint64_t next_master_id_rand)
176 {
177 ble_sm_dbg_next_master_id_rand = next_master_id_rand;
178 ble_sm_dbg_next_master_id_rand_set = 1;
179 }
180
181 void
ble_sm_dbg_set_next_ltk(uint8_t * next_ltk)182 ble_sm_dbg_set_next_ltk(uint8_t *next_ltk)
183 {
184 memcpy(ble_sm_dbg_next_ltk, next_ltk,
185 sizeof ble_sm_dbg_next_ltk);
186 ble_sm_dbg_next_ltk_set = 1;
187 }
188
189 void
ble_sm_dbg_set_next_csrk(uint8_t * next_csrk)190 ble_sm_dbg_set_next_csrk(uint8_t *next_csrk)
191 {
192 memcpy(ble_sm_dbg_next_csrk, next_csrk,
193 sizeof ble_sm_dbg_next_csrk);
194 ble_sm_dbg_next_csrk_set = 1;
195 }
196
197 #endif
198
199 static void
ble_sm_dbg_assert_no_cycles(void)200 ble_sm_dbg_assert_no_cycles(void)
201 {
202 #if MYNEWT_VAL(BLE_HS_DEBUG)
203 ble_sm_num_procs();
204 #endif
205 }
206
207 static void
ble_sm_dbg_assert_not_inserted(struct ble_sm_proc * proc)208 ble_sm_dbg_assert_not_inserted(struct ble_sm_proc *proc)
209 {
210 #if MYNEWT_VAL(BLE_HS_DEBUG)
211 struct ble_sm_proc *cur;
212
213 STAILQ_FOREACH(cur, &ble_sm_procs, next) {
214 BLE_HS_DBG_ASSERT(cur != proc);
215 }
216 #endif
217 }
218
219 /*****************************************************************************
220 * $misc *
221 *****************************************************************************/
222
223 /**
224 * Calculates the number of active SM procedures.
225 */
226 int
ble_sm_num_procs(void)227 ble_sm_num_procs(void)
228 {
229 struct ble_sm_proc *proc;
230 int cnt;
231
232 cnt = 0;
233 STAILQ_FOREACH(proc, &ble_sm_procs, next) {
234 BLE_HS_DBG_ASSERT(cnt < MYNEWT_VAL(BLE_SM_MAX_PROCS));
235 cnt++;
236 }
237
238 return cnt;
239 }
240
241 int
ble_sm_gen_pair_rand(uint8_t * pair_rand)242 ble_sm_gen_pair_rand(uint8_t *pair_rand)
243 {
244 int rc;
245
246 #if MYNEWT_VAL(BLE_HS_DEBUG)
247 if (ble_sm_dbg_next_pair_rand_set) {
248 ble_sm_dbg_next_pair_rand_set = 0;
249 memcpy(pair_rand, ble_sm_dbg_next_pair_rand,
250 sizeof ble_sm_dbg_next_pair_rand);
251 return 0;
252 }
253 #endif
254
255 rc = ble_hs_hci_util_rand(pair_rand, 16);
256 if (rc != 0) {
257 return rc;
258 }
259
260 return 0;
261 }
262
263 static int
ble_sm_gen_ediv(struct ble_sm_master_id * master_id)264 ble_sm_gen_ediv(struct ble_sm_master_id *master_id)
265 {
266 int rc;
267
268 #if MYNEWT_VAL(BLE_HS_DEBUG)
269 if (ble_sm_dbg_next_ediv_set) {
270 ble_sm_dbg_next_ediv_set = 0;
271 master_id->ediv = ble_sm_dbg_next_ediv;
272 return 0;
273 }
274 #endif
275
276 rc = ble_hs_hci_util_rand(&master_id->ediv, sizeof master_id->ediv);
277 if (rc != 0) {
278 return rc;
279 }
280
281 return 0;
282 }
283
284 static int
ble_sm_gen_master_id_rand(struct ble_sm_master_id * master_id)285 ble_sm_gen_master_id_rand(struct ble_sm_master_id *master_id)
286 {
287 int rc;
288
289 #if MYNEWT_VAL(BLE_HS_DEBUG)
290 if (ble_sm_dbg_next_master_id_rand_set) {
291 ble_sm_dbg_next_master_id_rand_set = 0;
292 master_id->rand_val = ble_sm_dbg_next_master_id_rand;
293 return 0;
294 }
295 #endif
296
297 rc = ble_hs_hci_util_rand(&master_id->rand_val, sizeof master_id->rand_val);
298 if (rc != 0) {
299 return rc;
300 }
301
302 return 0;
303 }
304
305 static int
ble_sm_gen_ltk(struct ble_sm_proc * proc,uint8_t * ltk)306 ble_sm_gen_ltk(struct ble_sm_proc *proc, uint8_t *ltk)
307 {
308 int rc;
309
310 #if MYNEWT_VAL(BLE_HS_DEBUG)
311 if (ble_sm_dbg_next_ltk_set) {
312 ble_sm_dbg_next_ltk_set = 0;
313 memcpy(ltk, ble_sm_dbg_next_ltk,
314 sizeof ble_sm_dbg_next_ltk);
315 return 0;
316 }
317 #endif
318
319 rc = ble_hs_hci_util_rand(ltk, proc->key_size);
320 if (rc != 0) {
321 return rc;
322 }
323
324 /* Ensure proper key size */
325 memset(ltk + proc->key_size, 0, sizeof proc->ltk - proc->key_size);
326
327 return 0;
328 }
329
330 static int
ble_sm_gen_csrk(struct ble_sm_proc * proc,uint8_t * csrk)331 ble_sm_gen_csrk(struct ble_sm_proc *proc, uint8_t *csrk)
332 {
333 int rc;
334
335 #if MYNEWT_VAL(BLE_HS_DEBUG)
336 if (ble_sm_dbg_next_csrk_set) {
337 ble_sm_dbg_next_csrk_set = 0;
338 memcpy(csrk, ble_sm_dbg_next_csrk,
339 sizeof ble_sm_dbg_next_csrk);
340 return 0;
341 }
342 #endif
343
344 rc = ble_hs_hci_util_rand(csrk, 16);
345 if (rc != 0) {
346 return rc;
347 }
348
349 return 0;
350 }
351
352 static void
ble_sm_proc_set_timer(struct ble_sm_proc * proc)353 ble_sm_proc_set_timer(struct ble_sm_proc *proc)
354 {
355 proc->exp_os_ticks = ble_npl_time_get() +
356 ble_npl_time_ms_to_ticks32(BLE_SM_TIMEOUT_MS);
357 ble_hs_timer_resched();
358 }
359
360 static ble_sm_rx_fn *
ble_sm_dispatch_get(uint8_t op)361 ble_sm_dispatch_get(uint8_t op)
362 {
363 if (op >= sizeof ble_sm_dispatch / sizeof ble_sm_dispatch[0]) {
364 return NULL;
365 }
366
367 return ble_sm_dispatch[op];
368 }
369
370 /**
371 * Allocates a proc entry.
372 *
373 * @return An entry on success; null on failure.
374 */
375 static struct ble_sm_proc *
ble_sm_proc_alloc(void)376 ble_sm_proc_alloc(void)
377 {
378 struct ble_sm_proc *proc;
379
380 proc = os_memblock_get(&ble_sm_proc_pool);
381 if (proc != NULL) {
382 memset(proc, 0, sizeof *proc);
383 }
384
385 return proc;
386 }
387
388 /**
389 * Frees the specified proc entry. No-state if passed a null pointer.
390 */
391 static void
ble_sm_proc_free(struct ble_sm_proc * proc)392 ble_sm_proc_free(struct ble_sm_proc *proc)
393 {
394 int rc;
395
396 if (proc != NULL) {
397 ble_sm_dbg_assert_not_inserted(proc);
398 #if MYNEWT_VAL(BLE_HS_DEBUG)
399 memset(proc, 0xff, sizeof *proc);
400 #endif
401 rc = os_memblock_put(&ble_sm_proc_pool, proc);
402 BLE_HS_DBG_ASSERT_EVAL(rc == 0);
403 }
404 }
405
406 static void
ble_sm_proc_remove(struct ble_sm_proc * proc,struct ble_sm_proc * prev)407 ble_sm_proc_remove(struct ble_sm_proc *proc,
408 struct ble_sm_proc *prev)
409 {
410 if (prev == NULL) {
411 BLE_HS_DBG_ASSERT(STAILQ_FIRST(&ble_sm_procs) == proc);
412 STAILQ_REMOVE_HEAD(&ble_sm_procs, next);
413 } else {
414 BLE_HS_DBG_ASSERT(STAILQ_NEXT(prev, next) == proc);
415 STAILQ_REMOVE_AFTER(&ble_sm_procs, prev, next);
416 }
417
418 ble_sm_dbg_assert_no_cycles();
419 }
420
421 static void
ble_sm_update_sec_state(uint16_t conn_handle,int encrypted,int authenticated,int bonded,int key_size)422 ble_sm_update_sec_state(uint16_t conn_handle, int encrypted,
423 int authenticated, int bonded, int key_size)
424 {
425 struct ble_hs_conn *conn;
426
427 conn = ble_hs_conn_find(conn_handle);
428 if (conn != NULL) {
429 conn->bhc_sec_state.encrypted = encrypted;
430
431 /* Authentication and bonding are never revoked from a secure link */
432 if (authenticated) {
433 conn->bhc_sec_state.authenticated = 1;
434 }
435 if (bonded) {
436 conn->bhc_sec_state.bonded = 1;
437 }
438
439 if (key_size) {
440 conn->bhc_sec_state.key_size = key_size;
441 }
442 }
443 }
444
445 static void
ble_sm_fill_store_value(const ble_addr_t * peer_addr,int authenticated,int sc,struct ble_sm_keys * keys,struct ble_store_value_sec * value_sec)446 ble_sm_fill_store_value(const ble_addr_t *peer_addr,
447 int authenticated,
448 int sc,
449 struct ble_sm_keys *keys,
450 struct ble_store_value_sec *value_sec)
451 {
452 memset(value_sec, 0, sizeof *value_sec);
453
454 value_sec->peer_addr = *peer_addr;
455
456 if (keys->ediv_rand_valid && keys->ltk_valid) {
457 value_sec->key_size = keys->key_size;
458 value_sec->ediv = keys->ediv;
459 value_sec->rand_num = keys->rand_val;
460
461 memcpy(value_sec->ltk, keys->ltk, sizeof value_sec->ltk);
462 value_sec->ltk_present = 1;
463
464 value_sec->authenticated = !!authenticated;
465 value_sec->sc = !!sc;
466 }
467
468 if (keys->irk_valid) {
469 memcpy(value_sec->irk, keys->irk, sizeof value_sec->irk);
470 value_sec->irk_present = 1;
471 }
472
473 if (keys->csrk_valid) {
474 memcpy(value_sec->csrk, keys->csrk, sizeof value_sec->csrk);
475 value_sec->csrk_present = 1;
476 }
477 }
478
479 void
ble_sm_ia_ra(struct ble_sm_proc * proc,uint8_t * out_iat,uint8_t * out_ia,uint8_t * out_rat,uint8_t * out_ra)480 ble_sm_ia_ra(struct ble_sm_proc *proc,
481 uint8_t *out_iat, uint8_t *out_ia,
482 uint8_t *out_rat, uint8_t *out_ra)
483 {
484 struct ble_hs_conn_addrs addrs;
485 struct ble_hs_conn *conn;
486
487 conn = ble_hs_conn_find_assert(proc->conn_handle);
488
489 ble_hs_conn_addrs(conn, &addrs);
490
491 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
492 *out_iat = addrs.our_ota_addr.type;
493 memcpy(out_ia, addrs.our_ota_addr.val, 6);
494
495 *out_rat = addrs.peer_ota_addr.type;
496 memcpy(out_ra, addrs.peer_ota_addr.val, 6);
497 } else {
498 *out_iat = addrs.peer_ota_addr.type;
499 memcpy(out_ia, addrs.peer_ota_addr.val, 6);
500
501 *out_rat = addrs.our_ota_addr.type;
502 memcpy(out_ra, addrs.our_ota_addr.val, 6);
503 }
504 }
505
506 static void
ble_sm_persist_keys(struct ble_sm_proc * proc)507 ble_sm_persist_keys(struct ble_sm_proc *proc)
508 {
509 struct ble_store_value_sec value_sec;
510 struct ble_hs_conn *conn;
511 ble_addr_t peer_addr;
512 int authenticated;
513 int identity_ev = 0;
514 int sc;
515
516 ble_hs_lock();
517
518 conn = ble_hs_conn_find(proc->conn_handle);
519 BLE_HS_DBG_ASSERT(conn != NULL);
520
521 /* If we got an identity address, use that for key storage. */
522 if (proc->peer_keys.addr_valid) {
523 peer_addr.type = proc->peer_keys.addr_type;
524 memcpy(peer_addr.val, proc->peer_keys.addr, sizeof peer_addr.val);
525
526 conn->bhc_peer_addr = peer_addr;
527 /* Update identity address in conn.
528 * If peer's address was an RPA, we store it as RPA since peer's address
529 * will not be an identity address. The peer's address type has to be
530 * set as 'ID' to allow resolve 'id' and 'ota' addresses properly in
531 * conn info.
532 */
533 if (BLE_ADDR_IS_RPA(&conn->bhc_peer_addr)) {
534 conn->bhc_peer_rpa_addr = conn->bhc_peer_addr;
535
536 switch (peer_addr.type) {
537 case BLE_ADDR_PUBLIC:
538 case BLE_ADDR_PUBLIC_ID:
539 conn->bhc_peer_addr.type = BLE_ADDR_PUBLIC_ID;
540 break;
541
542 case BLE_ADDR_RANDOM:
543 case BLE_ADDR_RANDOM_ID:
544 conn->bhc_peer_addr.type = BLE_ADDR_RANDOM_ID;
545 break;
546 }
547 }
548
549 identity_ev = 1;
550 } else {
551 peer_addr = conn->bhc_peer_addr;
552 peer_addr.type = ble_hs_misc_addr_type_to_id(conn->bhc_peer_addr.type);
553 }
554
555 ble_hs_unlock();
556
557 if (identity_ev) {
558 ble_gap_identity_event(proc->conn_handle);
559 }
560
561 authenticated = proc->flags & BLE_SM_PROC_F_AUTHENTICATED;
562 sc = proc->flags & BLE_SM_PROC_F_SC;
563
564 ble_sm_fill_store_value(&peer_addr, authenticated, sc, &proc->our_keys,
565 &value_sec);
566 ble_store_write_our_sec(&value_sec);
567
568 ble_sm_fill_store_value(&peer_addr, authenticated, sc, &proc->peer_keys,
569 &value_sec);
570 ble_store_write_peer_sec(&value_sec);
571 }
572
573 static int
ble_sm_proc_matches(struct ble_sm_proc * proc,uint16_t conn_handle,uint8_t state,int is_initiator)574 ble_sm_proc_matches(struct ble_sm_proc *proc, uint16_t conn_handle,
575 uint8_t state, int is_initiator)
576 {
577 int proc_is_initiator;
578
579 if (conn_handle != proc->conn_handle) {
580 return 0;
581 }
582
583 if (state != BLE_SM_PROC_STATE_NONE && state != proc->state) {
584 return 0;
585 }
586
587 proc_is_initiator = !!(proc->flags & BLE_SM_PROC_F_INITIATOR);
588 if (is_initiator != -1 && is_initiator != proc_is_initiator) {
589 return 0;
590 }
591
592 return 1;
593 }
594
595 /**
596 * Searches the main proc list for an entry whose connection handle and state
597 * code match those specified.
598 *
599 * @param conn_handle The connection handle to match against.
600 * @param state The state code to match against.
601 * @param is_initiator Matches on the proc's initiator flag:
602 * 0=non-initiator only
603 * 1=initiator only
604 * -1=don't care
605 * @param out_prev On success, the entry previous to the result is
606 * written here.
607 *
608 * @return The matching proc entry on success;
609 * null on failure.
610 */
611 struct ble_sm_proc *
ble_sm_proc_find(uint16_t conn_handle,uint8_t state,int is_initiator,struct ble_sm_proc ** out_prev)612 ble_sm_proc_find(uint16_t conn_handle, uint8_t state, int is_initiator,
613 struct ble_sm_proc **out_prev)
614 {
615 struct ble_sm_proc *proc;
616 struct ble_sm_proc *prev;
617
618 BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
619
620 prev = NULL;
621 STAILQ_FOREACH(proc, &ble_sm_procs, next) {
622 if (ble_sm_proc_matches(proc, conn_handle, state, is_initiator)) {
623 if (out_prev != NULL) {
624 *out_prev = prev;
625 }
626 break;
627 }
628
629 prev = proc;
630 }
631
632 return proc;
633 }
634
635 static void
ble_sm_insert(struct ble_sm_proc * proc)636 ble_sm_insert(struct ble_sm_proc *proc)
637 {
638 #if MYNEWT_VAL(BLE_HS_DEBUG)
639 struct ble_sm_proc *cur;
640
641 STAILQ_FOREACH(cur, &ble_sm_procs, next) {
642 BLE_HS_DBG_ASSERT(cur != proc);
643 }
644 #endif
645
646 STAILQ_INSERT_HEAD(&ble_sm_procs, proc, next);
647 }
648
649 static int32_t
ble_sm_extract_expired(struct ble_sm_proc_list * dst_list)650 ble_sm_extract_expired(struct ble_sm_proc_list *dst_list)
651 {
652 struct ble_sm_proc *proc;
653 struct ble_sm_proc *prev;
654 struct ble_sm_proc *next;
655 ble_npl_time_t now;
656 ble_npl_stime_t next_exp_in;
657 ble_npl_stime_t time_diff;
658
659 now = ble_npl_time_get();
660 STAILQ_INIT(dst_list);
661
662 /* Assume each event is either expired or has infinite duration. */
663 next_exp_in = BLE_HS_FOREVER;
664
665 ble_hs_lock();
666
667 prev = NULL;
668 proc = STAILQ_FIRST(&ble_sm_procs);
669 while (proc != NULL) {
670 next = STAILQ_NEXT(proc, next);
671
672 time_diff = proc->exp_os_ticks - now;
673 if (time_diff <= 0) {
674 /* Procedure has expired; move it to the destination list. */
675 if (prev == NULL) {
676 STAILQ_REMOVE_HEAD(&ble_sm_procs, next);
677 } else {
678 STAILQ_REMOVE_AFTER(&ble_sm_procs, prev, next);
679 }
680 STAILQ_INSERT_HEAD(dst_list, proc, next);
681 } else {
682 if (time_diff < next_exp_in) {
683 next_exp_in = time_diff;
684 }
685 }
686
687 prev = proc;
688 proc = next;
689 }
690
691 ble_sm_dbg_assert_no_cycles();
692
693 ble_hs_unlock();
694
695 return next_exp_in;
696 }
697
698 static void
ble_sm_rx_noop(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)699 ble_sm_rx_noop(uint16_t conn_handle, struct os_mbuf **om,
700 struct ble_sm_result *res)
701 {
702 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
703 res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
704 }
705
706 static uint8_t
ble_sm_build_authreq(void)707 ble_sm_build_authreq(void)
708 {
709 return ble_hs_cfg.sm_bonding << 0 |
710 ble_hs_cfg.sm_mitm << 2 |
711 ble_hs_cfg.sm_sc << 3 |
712 ble_hs_cfg.sm_keypress << 4;
713 }
714
715 static int
ble_sm_io_action(struct ble_sm_proc * proc,uint8_t * action)716 ble_sm_io_action(struct ble_sm_proc *proc, uint8_t *action)
717 {
718 if (proc->flags & BLE_SM_PROC_F_SC) {
719 return ble_sm_sc_io_action(proc, action);
720 } else {
721 return ble_sm_lgcy_io_action(proc, action);
722 }
723 }
724
725 int
ble_sm_ioact_state(uint8_t action)726 ble_sm_ioact_state(uint8_t action)
727 {
728 switch (action) {
729 case BLE_SM_IOACT_NONE:
730 return BLE_SM_PROC_STATE_NONE;
731
732 case BLE_SM_IOACT_NUMCMP:
733 return BLE_SM_PROC_STATE_DHKEY_CHECK;
734
735 case BLE_SM_IOACT_OOB:
736 case BLE_SM_IOACT_INPUT:
737 case BLE_SM_IOACT_DISP:
738 return BLE_SM_PROC_STATE_CONFIRM;
739
740 default:
741 BLE_HS_DBG_ASSERT(0);
742 return BLE_SM_PROC_STATE_NONE;
743 }
744 }
745
746 int
ble_sm_proc_can_advance(struct ble_sm_proc * proc)747 ble_sm_proc_can_advance(struct ble_sm_proc *proc)
748 {
749 uint8_t ioact;
750 int rc;
751
752 rc = ble_sm_io_action(proc, &ioact);
753 if (rc != 0) {
754 BLE_HS_DBG_ASSERT(0);
755 }
756
757 if (ble_sm_ioact_state(ioact) != proc->state) {
758 return 1;
759 }
760
761 if (proc->flags & BLE_SM_PROC_F_IO_INJECTED &&
762 proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO) {
763
764 return 1;
765 }
766
767 return 0;
768 }
769
770 static void
ble_sm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)771 ble_sm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, void *arg)
772 {
773 ble_sm_state_fn *cb;
774
775 memset(res, 0, sizeof *res);
776
777 if (!ble_hs_conn_exists(proc->conn_handle)) {
778 res->app_status = BLE_HS_ENOTCONN;
779 } else {
780 BLE_HS_DBG_ASSERT(proc->state < BLE_SM_PROC_STATE_CNT);
781 cb = ble_sm_state_dispatch[proc->state];
782 BLE_HS_DBG_ASSERT(cb != NULL);
783 cb(proc, res, arg);
784 }
785 }
786
787 static void
ble_sm_pair_fail_tx(uint16_t conn_handle,uint8_t reason)788 ble_sm_pair_fail_tx(uint16_t conn_handle, uint8_t reason)
789 {
790 struct ble_sm_pair_fail *cmd;
791 struct os_mbuf *txom;
792
793 BLE_HS_DBG_ASSERT(reason > 0 && reason < BLE_SM_ERR_MAX_PLUS_1);
794
795 cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_FAIL, sizeof(*cmd), &txom);
796 if (cmd) {
797 cmd->reason = reason;
798 ble_sm_tx(conn_handle, txom);
799 }
800 }
801
802 /**
803 * Reads a bond from storage.
804 */
805 static int
ble_sm_read_bond(uint16_t conn_handle,struct ble_store_value_sec * out_bond)806 ble_sm_read_bond(uint16_t conn_handle, struct ble_store_value_sec *out_bond)
807 {
808 struct ble_store_key_sec key_sec;
809 struct ble_gap_conn_desc desc;
810 int rc;
811
812 rc = ble_gap_conn_find(conn_handle, &desc);
813 if (rc != 0) {
814 return rc;
815 }
816
817 memset(&key_sec, 0, sizeof key_sec);
818 key_sec.peer_addr = desc.peer_id_addr;
819
820 rc = ble_store_read_peer_sec(&key_sec, out_bond);
821 return rc;
822 }
823
824 /**
825 * Checks if the specified peer is already bonded. If it is, the application
826 * is queried about how to proceed: retry or ignore. The application should
827 * only indicate a retry if it deleted the old bond.
828 *
829 * @param conn_handle The handle of the connection over which the
830 * pairing request was received.
831 * @param proc_flags The security flags associated with the
832 * conflicting SM procedure.
833 * @param key_size The key size of the conflicting SM procedure.
834 *
835 * @return 0 if the procedure should continue;
836 * nonzero if the request should be ignored.
837 */
838 static int
ble_sm_chk_repeat_pairing(uint16_t conn_handle,ble_sm_proc_flags proc_flags,uint8_t key_size)839 ble_sm_chk_repeat_pairing(uint16_t conn_handle,
840 ble_sm_proc_flags proc_flags,
841 uint8_t key_size)
842 {
843 struct ble_gap_repeat_pairing rp;
844 struct ble_store_value_sec bond;
845 int rc;
846
847 do {
848 /* If the peer isn't bonded, indicate that the pairing procedure should
849 * continue.
850 */
851 rc = ble_sm_read_bond(conn_handle, &bond);
852 switch (rc) {
853 case 0:
854 break;
855 case BLE_HS_ENOENT:
856 return 0;
857 default:
858 return rc;
859 }
860
861 /* Peer is already bonded. Ask the application what to do about it. */
862 rp.conn_handle = conn_handle;
863 rp.cur_key_size = bond.key_size;
864 rp.cur_authenticated = bond.authenticated;
865 rp.cur_sc = bond.sc;
866
867 rp.new_key_size = key_size;
868 rp.new_authenticated = !!(proc_flags & BLE_SM_PROC_F_AUTHENTICATED);
869 rp.new_sc = !!(proc_flags & BLE_SM_PROC_F_SC);
870 rp.new_bonding = !!(proc_flags & BLE_SM_PROC_F_BONDING);
871
872 rc = ble_gap_repeat_pairing_event(&rp);
873 } while (rc == BLE_GAP_REPEAT_PAIRING_RETRY);
874
875 BLE_HS_LOG(DEBUG, "silently ignoring pair request from bonded peer");
876
877 return BLE_HS_EALREADY;
878 }
879
880 void
ble_sm_process_result(uint16_t conn_handle,struct ble_sm_result * res)881 ble_sm_process_result(uint16_t conn_handle, struct ble_sm_result *res)
882 {
883 struct ble_sm_proc *prev;
884 struct ble_sm_proc *proc;
885 int rm;
886
887 rm = 0;
888
889 while (1) {
890 ble_hs_lock();
891 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1,
892 &prev);
893
894 if (proc != NULL) {
895 if (res->execute) {
896 ble_sm_exec(proc, res, res->state_arg);
897 }
898
899 if (res->app_status != 0) {
900 rm = 1;
901 }
902
903 if (proc->state == BLE_SM_PROC_STATE_NONE) {
904 rm = 1;
905 }
906
907 if (rm) {
908 ble_sm_proc_remove(proc, prev);
909 } else {
910 ble_sm_proc_set_timer(proc);
911 }
912 }
913
914 if (res->sm_err != 0) {
915 ble_sm_pair_fail_tx(conn_handle, res->sm_err);
916 }
917
918 ble_hs_unlock();
919
920 if (proc == NULL) {
921 break;
922 }
923
924 if (res->enc_cb) {
925 BLE_HS_DBG_ASSERT(proc == NULL || rm);
926 ble_gap_enc_event(conn_handle, res->app_status, res->restore);
927 }
928
929 if (res->app_status == 0 &&
930 res->passkey_params.action != BLE_SM_IOACT_NONE) {
931
932 ble_gap_passkey_event(conn_handle, &res->passkey_params);
933 }
934
935 /* Persist keys if bonding has successfully completed. */
936 if (res->app_status == 0 &&
937 rm &&
938 proc->flags & BLE_SM_PROC_F_BONDING) {
939
940 ble_sm_persist_keys(proc);
941 }
942
943 if (rm) {
944 ble_sm_proc_free(proc);
945 break;
946 }
947
948 if (!res->execute) {
949 break;
950 }
951
952 memset(res, 0, sizeof *res);
953 res->execute = 1;
954 }
955 }
956
957 static void
ble_sm_key_dist(struct ble_sm_proc * proc,uint8_t * out_init_key_dist,uint8_t * out_resp_key_dist)958 ble_sm_key_dist(struct ble_sm_proc *proc,
959 uint8_t *out_init_key_dist, uint8_t *out_resp_key_dist)
960 {
961 struct ble_sm_pair_cmd *pair_rsp;
962
963 pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
964
965 *out_init_key_dist = pair_rsp->init_key_dist;
966 *out_resp_key_dist = pair_rsp->resp_key_dist;
967
968 /* Encryption info and master ID are only sent in legacy pairing. */
969 if (proc->flags & BLE_SM_PROC_F_SC) {
970 *out_init_key_dist &= ~BLE_SM_PAIR_KEY_DIST_ENC;
971 *out_resp_key_dist &= ~BLE_SM_PAIR_KEY_DIST_ENC;
972 }
973 }
974
975 static int
ble_sm_chk_store_overflow_by_type(int obj_type,uint16_t conn_handle)976 ble_sm_chk_store_overflow_by_type(int obj_type, uint16_t conn_handle)
977 {
978 #if !MYNEWT_VAL(BLE_SM_BONDING)
979 return 0;
980 #endif
981
982 int count;
983 int rc;
984
985 rc = ble_store_util_count(obj_type, &count);
986 if (rc != 0) {
987 return rc;
988 }
989
990 /* Pessimistically assume all active procs will persist bonds. */
991 ble_hs_lock();
992 count += ble_sm_num_procs();
993 ble_hs_unlock();
994
995 if (count < MYNEWT_VAL(BLE_STORE_MAX_BONDS)) {
996 /* There is sufficient capacity for another bond. */
997 return 0;
998 }
999
1000 /* No capacity for an additional bond. Tell the application to make
1001 * room.
1002 */
1003 rc = ble_store_full_event(obj_type, conn_handle);
1004 if (rc != 0) {
1005 return rc;
1006 }
1007
1008 return 0;
1009 }
1010
1011 static int
ble_sm_chk_store_overflow(uint16_t conn_handle)1012 ble_sm_chk_store_overflow(uint16_t conn_handle)
1013 {
1014 int rc;
1015
1016 rc = ble_sm_chk_store_overflow_by_type(BLE_STORE_OBJ_TYPE_PEER_SEC,
1017 conn_handle);
1018 if (rc != 0) {
1019 return rc;
1020 }
1021
1022 rc = ble_sm_chk_store_overflow_by_type(BLE_STORE_OBJ_TYPE_OUR_SEC,
1023 conn_handle);
1024 if (rc != 0) {
1025 return rc;
1026 }
1027
1028 return 0;
1029 }
1030
1031 /*****************************************************************************
1032 * $enc *
1033 *****************************************************************************/
1034
1035 static int
ble_sm_start_encrypt_tx(struct hci_start_encrypt * cmd)1036 ble_sm_start_encrypt_tx(struct hci_start_encrypt *cmd)
1037 {
1038 uint8_t buf[BLE_HCI_LE_START_ENCRYPT_LEN];
1039 int rc;
1040
1041 ble_hs_hci_cmd_build_le_start_encrypt(cmd, buf, sizeof buf);
1042 rc = ble_hs_hci_cmd_tx_empty_ack(BLE_HCI_OP(BLE_HCI_OGF_LE,
1043 BLE_HCI_OCF_LE_START_ENCRYPT),
1044 buf, sizeof(buf));
1045 if (rc != 0) {
1046 return rc;
1047 }
1048
1049 return 0;
1050 }
1051
1052 static void
ble_sm_enc_start_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1053 ble_sm_enc_start_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1054 void *arg)
1055 {
1056 struct hci_start_encrypt cmd;
1057 int rc;
1058
1059 BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_INITIATOR);
1060
1061 cmd.connection_handle = proc->conn_handle;
1062 cmd.encrypted_diversifier = 0;
1063 cmd.random_number = 0;
1064 memcpy(cmd.long_term_key, proc->ltk, sizeof cmd.long_term_key);
1065
1066 rc = ble_sm_start_encrypt_tx(&cmd);
1067 if (rc != 0) {
1068 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1069 res->app_status = rc;
1070 res->enc_cb = 1;
1071 }
1072 }
1073
1074 static void
ble_sm_enc_restore_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1075 ble_sm_enc_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1076 void *arg)
1077 {
1078 struct hci_start_encrypt *cmd;
1079
1080 BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_INITIATOR);
1081
1082 cmd = arg;
1083 BLE_HS_DBG_ASSERT(cmd != NULL);
1084
1085 res->app_status = ble_sm_start_encrypt_tx(cmd);
1086 }
1087
1088 static void
ble_sm_enc_event_rx(uint16_t conn_handle,uint8_t evt_status,int encrypted)1089 ble_sm_enc_event_rx(uint16_t conn_handle, uint8_t evt_status, int encrypted)
1090 {
1091 struct ble_sm_result res;
1092 struct ble_sm_proc *proc;
1093 int authenticated;
1094 int bonded;
1095 int key_size;
1096
1097 memset(&res, 0, sizeof res);
1098
1099 /* Assume no change in authenticated and bonded statuses. */
1100 authenticated = 0;
1101 bonded = 0;
1102 key_size = 0;
1103
1104 ble_hs_lock();
1105
1106 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
1107 if (proc != NULL) {
1108 switch (proc->state) {
1109 case BLE_SM_PROC_STATE_ENC_START:
1110 /* We are completing a pairing procedure; keys may need to be
1111 * exchanged.
1112 */
1113 if (evt_status == 0) {
1114 /* If the responder has any keys to send, it sends them
1115 * first.
1116 */
1117 proc->state = BLE_SM_PROC_STATE_KEY_EXCH;
1118 if (!(proc->flags & BLE_SM_PROC_F_INITIATOR) ||
1119 proc->rx_key_flags == 0) {
1120
1121 res.execute = 1;
1122 }
1123
1124 key_size = proc->key_size;
1125 } else {
1126 /* Failure or no keys to exchange; procedure is complete. */
1127 proc->state = BLE_SM_PROC_STATE_NONE;
1128 }
1129 if (proc->flags & BLE_SM_PROC_F_AUTHENTICATED) {
1130 authenticated = 1;
1131 }
1132 break;
1133
1134 case BLE_SM_PROC_STATE_ENC_RESTORE:
1135 /* A secure link is being restored via the encryption
1136 * procedure. Keys were exchanged during pairing; they don't
1137 * get exchanged again now. Procedure is complete.
1138 */
1139 BLE_HS_DBG_ASSERT(proc->rx_key_flags == 0);
1140 proc->state = BLE_SM_PROC_STATE_NONE;
1141 if (proc->flags & BLE_SM_PROC_F_AUTHENTICATED) {
1142 authenticated = 1;
1143 }
1144 bonded = 1;
1145 res.restore = 1;
1146
1147 key_size = proc->key_size;
1148 break;
1149
1150 default:
1151 /* The encryption change event is unexpected. We take the
1152 * controller at its word that the state has changed and we
1153 * terminate the procedure.
1154 */
1155 proc->state = BLE_SM_PROC_STATE_NONE;
1156 res.sm_err = BLE_SM_ERR_UNSPECIFIED;
1157 break;
1158 }
1159 }
1160
1161 if (evt_status == 0) {
1162 /* Set the encrypted state of the connection as indicated in the
1163 * event.
1164 */
1165 ble_sm_update_sec_state(conn_handle, encrypted, authenticated, bonded,
1166 key_size);
1167 }
1168
1169 /* Unless keys need to be exchanged, notify the application of the security
1170 * change. If key exchange is pending, the application callback is
1171 * triggered after exchange completes.
1172 */
1173 if (proc == NULL || proc->state == BLE_SM_PROC_STATE_NONE) {
1174 res.enc_cb = 1;
1175 res.app_status = BLE_HS_HCI_ERR(evt_status);
1176 }
1177
1178 ble_hs_unlock();
1179
1180 ble_sm_process_result(conn_handle, &res);
1181 }
1182
1183 void
ble_sm_enc_change_rx(struct hci_encrypt_change * evt)1184 ble_sm_enc_change_rx(struct hci_encrypt_change *evt)
1185 {
1186 /* For encrypted state: read LE-encryption bit; ignore BR/EDR and reserved
1187 * bits.
1188 */
1189 ble_sm_enc_event_rx(evt->connection_handle, evt->status,
1190 evt->encryption_enabled & 0x01);
1191 }
1192
1193 void
ble_sm_enc_key_refresh_rx(struct hci_encrypt_key_refresh * evt)1194 ble_sm_enc_key_refresh_rx(struct hci_encrypt_key_refresh *evt)
1195 {
1196 ble_sm_enc_event_rx(evt->connection_handle, evt->status, 1);
1197 }
1198
1199 /*****************************************************************************
1200 * $ltk *
1201 *****************************************************************************/
1202
1203 static int
ble_sm_retrieve_ltk(struct hci_le_lt_key_req * evt,uint8_t peer_addr_type,uint8_t * peer_addr,struct ble_store_value_sec * value_sec)1204 ble_sm_retrieve_ltk(struct hci_le_lt_key_req *evt, uint8_t peer_addr_type,
1205 uint8_t *peer_addr, struct ble_store_value_sec *value_sec)
1206 {
1207 struct ble_store_key_sec key_sec;
1208 int rc;
1209
1210 /* Tell applicaiton to look up LTK by peer address and ediv/rand pair. */
1211 memset(&key_sec, 0, sizeof key_sec);
1212 key_sec.peer_addr.type = peer_addr_type;
1213 memcpy(key_sec.peer_addr.val, peer_addr, 6);
1214 key_sec.ediv = evt->encrypted_diversifier;
1215 key_sec.rand_num = evt->random_number;
1216 key_sec.ediv_rand_present = 1;
1217
1218 rc = ble_store_read_our_sec(&key_sec, value_sec);
1219 return rc;
1220 }
1221
1222 static int
ble_sm_ltk_req_reply_tx(uint16_t conn_handle,uint8_t * ltk)1223 ble_sm_ltk_req_reply_tx(uint16_t conn_handle, uint8_t *ltk)
1224 {
1225 struct hci_lt_key_req_reply cmd;
1226 uint16_t ack_conn_handle;
1227 uint8_t buf[BLE_HCI_LT_KEY_REQ_REPLY_LEN];
1228 uint8_t ack_params_len;
1229 int rc;
1230
1231 cmd.conn_handle = conn_handle;
1232 memcpy(cmd.long_term_key, ltk, 16);
1233
1234 ble_hs_hci_cmd_build_le_lt_key_req_reply(&cmd, buf, sizeof buf);
1235 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1236 BLE_HCI_OCF_LE_LT_KEY_REQ_REPLY),
1237 buf, sizeof(buf), &ack_conn_handle,
1238 sizeof(ack_conn_handle), &ack_params_len);
1239 if (rc != 0) {
1240 return rc;
1241 }
1242 if (ack_params_len != BLE_HCI_LT_KEY_REQ_REPLY_ACK_PARAM_LEN) {
1243 return BLE_HS_ECONTROLLER;
1244 }
1245
1246 if (le16toh(ack_conn_handle) != conn_handle) {
1247 return BLE_HS_ECONTROLLER;
1248 }
1249
1250 return 0;
1251 }
1252
1253 static int
ble_sm_ltk_req_neg_reply_tx(uint16_t conn_handle)1254 ble_sm_ltk_req_neg_reply_tx(uint16_t conn_handle)
1255 {
1256 uint16_t ack_conn_handle;
1257 uint8_t buf[BLE_HCI_LT_KEY_REQ_NEG_REPLY_LEN];
1258 uint8_t ack_params_len;
1259 int rc;
1260
1261 ble_hs_hci_cmd_build_le_lt_key_req_neg_reply(conn_handle, buf, sizeof buf);
1262 rc = ble_hs_hci_cmd_tx(BLE_HCI_OP(BLE_HCI_OGF_LE,
1263 BLE_HCI_OCF_LE_LT_KEY_REQ_NEG_REPLY),
1264 buf, sizeof(buf), &ack_conn_handle,
1265 sizeof(ack_conn_handle), &ack_params_len);
1266 if (rc != 0) {
1267 return rc;
1268 }
1269 if (ack_params_len != BLE_HCI_LT_KEY_REQ_NEG_REPLY_ACK_PARAM_LEN) {
1270 return BLE_HS_ECONTROLLER;
1271 }
1272
1273 if (le16toh(ack_conn_handle) != conn_handle) {
1274 return BLE_HS_ECONTROLLER;
1275 }
1276
1277 return 0;
1278 }
1279
1280 static void
ble_sm_ltk_start_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1281 ble_sm_ltk_start_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1282 void *arg)
1283 {
1284 BLE_HS_DBG_ASSERT(!(proc->flags & BLE_SM_PROC_F_INITIATOR));
1285
1286 res->app_status = ble_sm_ltk_req_reply_tx(proc->conn_handle, proc->ltk);
1287 if (res->app_status == 0) {
1288 proc->state = BLE_SM_PROC_STATE_ENC_START;
1289 } else {
1290 res->enc_cb = 1;
1291 }
1292 }
1293
1294 static void
ble_sm_ltk_restore_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1295 ble_sm_ltk_restore_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1296 void *arg)
1297 {
1298 struct ble_store_value_sec *value_sec;
1299
1300 BLE_HS_DBG_ASSERT(!(proc->flags & BLE_SM_PROC_F_INITIATOR));
1301
1302 value_sec = arg;
1303
1304 if (value_sec != NULL) {
1305 /* Store provided a key; send it to the controller. */
1306 res->app_status = ble_sm_ltk_req_reply_tx(
1307 proc->conn_handle, value_sec->ltk);
1308
1309 if (res->app_status == 0) {
1310 if (value_sec->authenticated) {
1311 proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
1312 }
1313 } else {
1314 /* Notify the app if it provided a key and the procedure failed. */
1315 res->enc_cb = 1;
1316 }
1317 } else {
1318 /* Application does not have the requested key in its database. Send a
1319 * negative reply to the controller.
1320 */
1321 ble_sm_ltk_req_neg_reply_tx(proc->conn_handle);
1322 res->app_status = BLE_HS_ENOENT;
1323 }
1324
1325 if (res->app_status == 0) {
1326 proc->state = BLE_SM_PROC_STATE_ENC_RESTORE;
1327 }
1328 }
1329
1330 int
ble_sm_ltk_req_rx(struct hci_le_lt_key_req * evt)1331 ble_sm_ltk_req_rx(struct hci_le_lt_key_req *evt)
1332 {
1333 struct ble_store_value_sec value_sec;
1334 struct ble_hs_conn_addrs addrs;
1335 struct ble_sm_result res;
1336 struct ble_sm_proc *proc;
1337 struct ble_hs_conn *conn;
1338 uint8_t peer_id_addr[6];
1339 int store_rc;
1340 int restore;
1341
1342 memset(&res, 0, sizeof res);
1343
1344 ble_hs_lock();
1345 proc = ble_sm_proc_find(evt->connection_handle, BLE_SM_PROC_STATE_NONE,
1346 0, NULL);
1347 if (proc == NULL) {
1348 /* The peer is attempting to restore a encrypted connection via the
1349 * encryption procedure. Create a proc entry to indicate that security
1350 * establishment is in progress and execute the procedure after the
1351 * mutex gets unlocked.
1352 */
1353 restore = 1;
1354 proc = ble_sm_proc_alloc();
1355 if (proc == NULL) {
1356 res.app_status = BLE_HS_ENOMEM;
1357 } else {
1358 proc->conn_handle = evt->connection_handle;
1359 proc->state = BLE_SM_PROC_STATE_LTK_RESTORE;
1360 ble_sm_insert(proc);
1361
1362 res.execute = 1;
1363 }
1364 } else if (proc->state == BLE_SM_PROC_STATE_SEC_REQ) {
1365 /* Same as above, except we solicited the encryption procedure by
1366 * sending a security request.
1367 */
1368 restore = 1;
1369 proc->state = BLE_SM_PROC_STATE_LTK_RESTORE;
1370 res.execute = 1;
1371 } else if (proc->state == BLE_SM_PROC_STATE_LTK_START) {
1372 /* Legacy pairing just completed. Send the short term key to the
1373 * controller.
1374 */
1375 restore = 0;
1376 res.execute = 1;
1377 } else {
1378 /* The request is unexpected; nack and forget. */
1379 restore = 0;
1380 ble_sm_ltk_req_neg_reply_tx(evt->connection_handle);
1381 proc = NULL;
1382 }
1383
1384 if (restore) {
1385 conn = ble_hs_conn_find_assert(evt->connection_handle);
1386 ble_hs_conn_addrs(conn, &addrs);
1387 memcpy(peer_id_addr, addrs.peer_id_addr.val, 6);
1388 }
1389
1390 ble_hs_unlock();
1391
1392 if (proc == NULL) {
1393 return res.app_status;
1394 }
1395
1396 if (res.app_status == 0) {
1397 if (restore) {
1398 store_rc = ble_sm_retrieve_ltk(evt, addrs.peer_id_addr.type,
1399 peer_id_addr, &value_sec);
1400 if (store_rc == 0) {
1401 /* Send the key to the controller. */
1402 res.state_arg = &value_sec;
1403 } else {
1404 /* Send a nack to the controller. */
1405 res.state_arg = NULL;
1406 }
1407 }
1408 }
1409
1410 ble_sm_process_result(evt->connection_handle, &res);
1411
1412 return 0;
1413 }
1414
1415 /*****************************************************************************
1416 * $random *
1417 *****************************************************************************/
1418
1419 uint8_t *
ble_sm_our_pair_rand(struct ble_sm_proc * proc)1420 ble_sm_our_pair_rand(struct ble_sm_proc *proc)
1421 {
1422 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
1423 return proc->randm;
1424 } else {
1425 return proc->rands;
1426 }
1427 }
1428
1429 uint8_t *
ble_sm_peer_pair_rand(struct ble_sm_proc * proc)1430 ble_sm_peer_pair_rand(struct ble_sm_proc *proc)
1431 {
1432 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
1433 return proc->rands;
1434 } else {
1435 return proc->randm;
1436 }
1437 }
1438
1439 static void
ble_sm_random_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1440 ble_sm_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1441 void *arg)
1442 {
1443 if (proc->flags & BLE_SM_PROC_F_SC) {
1444 ble_sm_sc_random_exec(proc, res);
1445 } else {
1446 ble_sm_lgcy_random_exec(proc, res);
1447 }
1448 }
1449
1450 static void
ble_sm_random_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)1451 ble_sm_random_rx(uint16_t conn_handle, struct os_mbuf **om,
1452 struct ble_sm_result *res)
1453 {
1454 struct ble_sm_pair_random *cmd;
1455 struct ble_sm_proc *proc;
1456
1457 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
1458 if (res->app_status != 0) {
1459 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1460 res->enc_cb = 1;
1461 return;
1462 }
1463
1464 cmd = (struct ble_sm_pair_random *)(*om)->om_data;
1465
1466 BLE_SM_LOG_CMD(0, "random", conn_handle, ble_sm_pair_random_log, cmd);
1467
1468 ble_hs_lock();
1469 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_RANDOM, -1, NULL);
1470 if (proc == NULL) {
1471 res->app_status = BLE_HS_ENOENT;
1472 } else {
1473 memcpy(ble_sm_peer_pair_rand(proc), cmd->value, 16);
1474
1475 if (proc->flags & BLE_SM_PROC_F_SC) {
1476 ble_sm_sc_random_rx(proc, res);
1477 } else {
1478 ble_sm_lgcy_random_rx(proc, res);
1479 }
1480 }
1481 ble_hs_unlock();
1482 }
1483
1484 /*****************************************************************************
1485 * $confirm *
1486 *****************************************************************************/
1487
1488 static void
ble_sm_confirm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1489 ble_sm_confirm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1490 void *arg)
1491 {
1492 if (!(proc->flags & BLE_SM_PROC_F_SC)) {
1493 ble_sm_lgcy_confirm_exec(proc, res);
1494 } else {
1495 ble_sm_sc_confirm_exec(proc, res);
1496 }
1497 }
1498
1499 static void
ble_sm_confirm_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)1500 ble_sm_confirm_rx(uint16_t conn_handle, struct os_mbuf **om,
1501 struct ble_sm_result *res)
1502 {
1503 struct ble_sm_pair_confirm *cmd;
1504 struct ble_sm_proc *proc;
1505 uint8_t ioact;
1506
1507 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
1508 if (res->app_status != 0) {
1509 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1510 res->enc_cb = 1;
1511 return;
1512 }
1513
1514 cmd = (struct ble_sm_pair_confirm *)(*om)->om_data;
1515
1516 BLE_SM_LOG_CMD(0, "confirm", conn_handle, ble_sm_pair_confirm_log, cmd);
1517
1518 ble_hs_lock();
1519 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_CONFIRM, -1, NULL);
1520 if (proc == NULL) {
1521 res->app_status = BLE_HS_ENOENT;
1522 } else {
1523 memcpy(proc->confirm_peer, cmd->value, 16);
1524
1525 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
1526 proc->state = BLE_SM_PROC_STATE_RANDOM;
1527 res->execute = 1;
1528 } else {
1529 int rc;
1530
1531 rc = ble_sm_io_action(proc, &ioact);
1532 if (rc != 0) {
1533 BLE_HS_DBG_ASSERT(0);
1534 }
1535
1536 if (ble_sm_ioact_state(ioact) == proc->state) {
1537 proc->flags |= BLE_SM_PROC_F_ADVANCE_ON_IO;
1538 }
1539 if (ble_sm_proc_can_advance(proc)) {
1540 res->execute = 1;
1541 }
1542 }
1543 }
1544 ble_hs_unlock();
1545 }
1546
1547 /*****************************************************************************
1548 * $pair *
1549 *****************************************************************************/
1550
1551 static uint8_t
ble_sm_state_after_pair(struct ble_sm_proc * proc)1552 ble_sm_state_after_pair(struct ble_sm_proc *proc)
1553 {
1554 if (proc->flags & BLE_SM_PROC_F_SC) {
1555 return BLE_SM_PROC_STATE_PUBLIC_KEY;
1556 } else {
1557 return BLE_SM_PROC_STATE_CONFIRM;
1558 }
1559 }
1560
1561 static void
ble_sm_pair_cfg(struct ble_sm_proc * proc)1562 ble_sm_pair_cfg(struct ble_sm_proc *proc)
1563 {
1564 struct ble_sm_pair_cmd *pair_req, *pair_rsp;
1565 uint8_t init_key_dist;
1566 uint8_t resp_key_dist;
1567 uint8_t rx_key_dist;
1568 uint8_t ioact;
1569 int rc;
1570
1571 pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
1572 pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
1573
1574 if (pair_req->authreq & BLE_SM_PAIR_AUTHREQ_SC &&
1575 pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_SC) {
1576
1577 proc->flags |= BLE_SM_PROC_F_SC;
1578 }
1579
1580 ble_sm_key_dist(proc, &init_key_dist, &resp_key_dist);
1581 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
1582 rx_key_dist = resp_key_dist;
1583 } else {
1584 rx_key_dist = init_key_dist;
1585 }
1586
1587 if (pair_req->authreq & BLE_SM_PAIR_AUTHREQ_BOND &&
1588 pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_BOND) {
1589
1590 proc->flags |= BLE_SM_PROC_F_BONDING;
1591 }
1592
1593 /* In legacy mode, bonding requires the exchange of keys. If no key
1594 * exchange was specified, pretend bonding is not enabled.
1595 */
1596 if (!(proc->flags & BLE_SM_PROC_F_SC) &&
1597 (init_key_dist == 0 || resp_key_dist == 0)) {
1598
1599 proc->flags &= ~BLE_SM_PROC_F_BONDING;
1600 }
1601
1602 proc->rx_key_flags = 0;
1603 if (rx_key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
1604 proc->rx_key_flags |= BLE_SM_KE_F_ENC_INFO |
1605 BLE_SM_KE_F_MASTER_ID;
1606 }
1607 if (rx_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
1608 proc->rx_key_flags |= BLE_SM_KE_F_ID_INFO |
1609 BLE_SM_KE_F_ADDR_INFO;
1610 }
1611 if (rx_key_dist & BLE_SM_PAIR_KEY_DIST_SIGN) {
1612 proc->rx_key_flags |= BLE_SM_KE_F_SIGN_INFO;
1613 }
1614
1615 proc->key_size = min(pair_req->max_enc_key_size,
1616 pair_rsp->max_enc_key_size);
1617
1618 rc = ble_sm_io_action(proc, &ioact);
1619 BLE_HS_DBG_ASSERT_EVAL(rc == 0);
1620 }
1621
1622 static void
ble_sm_pair_base_fill(struct ble_sm_pair_cmd * cmd)1623 ble_sm_pair_base_fill(struct ble_sm_pair_cmd *cmd)
1624 {
1625 cmd->io_cap = ble_hs_cfg.sm_io_cap;
1626 cmd->oob_data_flag = ble_hs_cfg.sm_oob_data_flag;
1627 cmd->authreq = ble_sm_build_authreq();
1628 cmd->max_enc_key_size = BLE_SM_PAIR_KEY_SZ_MAX;
1629 }
1630
1631 static void
ble_sm_pair_req_fill(struct ble_sm_proc * proc)1632 ble_sm_pair_req_fill(struct ble_sm_proc *proc)
1633 {
1634 struct ble_sm_pair_cmd *req;
1635
1636 req = (void *)(proc->pair_req + 1);
1637
1638 proc->pair_req[0] = BLE_SM_OP_PAIR_REQ;
1639 ble_sm_pair_base_fill(req);
1640 req->init_key_dist = ble_hs_cfg.sm_our_key_dist;
1641 req->resp_key_dist = ble_hs_cfg.sm_their_key_dist;
1642 }
1643
1644 static void
ble_sm_pair_rsp_fill(struct ble_sm_proc * proc)1645 ble_sm_pair_rsp_fill(struct ble_sm_proc *proc)
1646 {
1647 const struct ble_sm_pair_cmd *req;
1648 struct ble_sm_pair_cmd *rsp;
1649
1650 req = (void *)(proc->pair_req + 1);
1651 rsp = (void *)(proc->pair_rsp + 1);
1652
1653 proc->pair_rsp[0] = BLE_SM_OP_PAIR_RSP;
1654 ble_sm_pair_base_fill(rsp);
1655
1656 /* The response's key distribution flags field is the intersection of
1657 * the peer's preferences and our capabilities.
1658 */
1659 rsp->init_key_dist = req->init_key_dist &
1660 ble_hs_cfg.sm_their_key_dist;
1661 rsp->resp_key_dist = req->resp_key_dist &
1662 ble_hs_cfg.sm_our_key_dist;
1663 }
1664
1665 static void
ble_sm_pair_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1666 ble_sm_pair_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1667 void *arg)
1668 {
1669 struct ble_sm_pair_cmd *cmd;
1670 struct os_mbuf *txom;
1671 uint8_t ioact;
1672 int is_req;
1673 int rc;
1674
1675 is_req = proc->flags & BLE_SM_PROC_F_INITIATOR;
1676
1677 cmd = ble_sm_cmd_get(is_req ? BLE_SM_OP_PAIR_REQ : BLE_SM_OP_PAIR_RSP,
1678 sizeof(*cmd), &txom);
1679 if (cmd == NULL) {
1680 rc = BLE_HS_ENOMEM;
1681 goto err;
1682 }
1683
1684 if (is_req) {
1685 ble_sm_pair_req_fill(proc);
1686 memcpy(cmd, proc->pair_req + 1, sizeof(*cmd));
1687 } else {
1688 /* The response was already generated when we processed the incoming
1689 * request.
1690 */
1691 memcpy(cmd, proc->pair_rsp + 1, sizeof(*cmd));
1692
1693 proc->state = ble_sm_state_after_pair(proc);
1694
1695 rc = ble_sm_io_action(proc, &ioact);
1696 BLE_HS_DBG_ASSERT(rc == 0);
1697
1698 if (ble_sm_ioact_state(ioact) == proc->state) {
1699 res->passkey_params.action = ioact;
1700 }
1701 }
1702
1703 rc = ble_sm_tx(proc->conn_handle, txom);
1704 if (rc != 0) {
1705 goto err;
1706 }
1707
1708 res->app_status = ble_sm_gen_pair_rand(ble_sm_our_pair_rand(proc));
1709 if (res->app_status != 0) {
1710 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1711 res->enc_cb = 1;
1712 return;
1713 }
1714
1715 return;
1716
1717 err:
1718 res->app_status = rc;
1719
1720 if (!is_req) {
1721 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1722 }
1723 }
1724
1725 static void
ble_sm_pair_req_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)1726 ble_sm_pair_req_rx(uint16_t conn_handle, struct os_mbuf **om,
1727 struct ble_sm_result *res)
1728 {
1729 struct ble_sm_pair_cmd *req;
1730 struct ble_sm_proc *proc;
1731 struct ble_sm_proc *prev;
1732 struct ble_hs_conn *conn;
1733 ble_sm_proc_flags proc_flags;
1734 uint8_t key_size;
1735 int rc;
1736
1737 /* Silence spurious unused-variable warnings. */
1738 proc_flags = 0;
1739 key_size = 0;
1740
1741 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*req));
1742 if (res->app_status != 0) {
1743 return;
1744 }
1745
1746 req = (struct ble_sm_pair_cmd *)(*om)->om_data;
1747
1748 BLE_SM_LOG_CMD(0, "pair req", conn_handle, ble_sm_pair_cmd_log, req);
1749
1750 ble_hs_lock();
1751
1752 /* XXX: Check connection state; reject if not appropriate. */
1753 /* XXX: Ensure enough time has passed since the previous failed pairing
1754 * attempt.
1755 */
1756 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, &prev);
1757 if (proc != NULL) {
1758 /* Pairing already in progress; abort old procedure and start new. */
1759 /* XXX: Check the spec on this. */
1760 ble_sm_proc_remove(proc, prev);
1761 ble_sm_proc_free(proc);
1762 }
1763
1764 ble_hs_unlock();
1765
1766 /* Check if there is storage capacity for a new bond. If there isn't, ask
1767 * the application to make room.
1768 */
1769 rc = ble_sm_chk_store_overflow(conn_handle);
1770 if (rc != 0) {
1771 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
1772 res->app_status = rc;
1773 return;
1774 }
1775
1776 ble_hs_lock();
1777
1778 proc = ble_sm_proc_alloc();
1779 if (proc != NULL) {
1780 proc->conn_handle = conn_handle;
1781 proc->state = BLE_SM_PROC_STATE_PAIR;
1782 ble_sm_insert(proc);
1783
1784 proc->pair_req[0] = BLE_SM_OP_PAIR_REQ;
1785 memcpy(proc->pair_req + 1, req, sizeof(*req));
1786
1787 conn = ble_hs_conn_find_assert(proc->conn_handle);
1788 if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
1789 res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
1790 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
1791 } else if (req->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) {
1792 res->sm_err = BLE_SM_ERR_ENC_KEY_SZ;
1793 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ);
1794 } else if (req->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) {
1795 res->sm_err = BLE_SM_ERR_INVAL;
1796 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL);
1797 } else {
1798 /* The request looks good. Precalculate our pairing response and
1799 * determine some properties of the imminent link. We need this
1800 * information in case this is a repeated pairing attempt (i.e., we
1801 * are already bonded to this peer). In that case, we include the
1802 * information in a notification to the app.
1803 */
1804 ble_sm_pair_rsp_fill(proc);
1805 ble_sm_pair_cfg(proc);
1806
1807 proc_flags = proc->flags;
1808 key_size = proc->key_size;
1809 res->execute = 1;
1810 }
1811 }
1812
1813 ble_hs_unlock();
1814
1815 /* Check if we are already bonded to this peer. If so, give the
1816 * application an opportunity to delete the old bond.
1817 */
1818 if (res->app_status == 0) {
1819 rc = ble_sm_chk_repeat_pairing(conn_handle, proc_flags, key_size);
1820 if (rc != 0) {
1821 /* The app indicated that the pairing request should be ignored. */
1822 res->app_status = rc;
1823 res->execute = 0;
1824 }
1825 }
1826 }
1827
1828 static void
ble_sm_pair_rsp_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)1829 ble_sm_pair_rsp_rx(uint16_t conn_handle, struct os_mbuf **om,
1830 struct ble_sm_result *res)
1831 {
1832 struct ble_sm_pair_cmd *rsp;
1833 struct ble_sm_proc *proc;
1834 uint8_t ioact;
1835 int rc;
1836
1837 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*rsp));
1838 if (res->app_status != 0) {
1839 res->enc_cb = 1;
1840 return;
1841 }
1842
1843 rsp = (struct ble_sm_pair_cmd *)(*om)->om_data;
1844
1845 BLE_SM_LOG_CMD(0, "pair rsp", conn_handle, ble_sm_pair_cmd_log, rsp);
1846
1847 ble_hs_lock();
1848 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PAIR, 1, NULL);
1849 if (proc != NULL) {
1850 proc->pair_rsp[0] = BLE_SM_OP_PAIR_RSP;
1851 memcpy(proc->pair_rsp + 1, rsp, sizeof(*rsp));
1852
1853 if (rsp->max_enc_key_size < BLE_SM_PAIR_KEY_SZ_MIN) {
1854 res->sm_err = BLE_SM_ERR_ENC_KEY_SZ;
1855 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_ENC_KEY_SZ);
1856 } else if (rsp->max_enc_key_size > BLE_SM_PAIR_KEY_SZ_MAX) {
1857 res->sm_err = BLE_SM_ERR_INVAL;
1858 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_INVAL);
1859 } else {
1860 ble_sm_pair_cfg(proc);
1861
1862 rc = ble_sm_io_action(proc, &ioact);
1863 if (rc != 0) {
1864 res->sm_err = BLE_SM_ERR_AUTHREQ;
1865 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_AUTHREQ);
1866 res->enc_cb = 1;
1867 } else {
1868 proc->state = ble_sm_state_after_pair(proc);
1869 if (ble_sm_ioact_state(ioact) == proc->state) {
1870 res->passkey_params.action = ioact;
1871 }
1872 if (ble_sm_proc_can_advance(proc)) {
1873 res->execute = 1;
1874 }
1875 }
1876 }
1877 }
1878
1879 ble_hs_unlock();
1880 }
1881
1882 /*****************************************************************************
1883 * $security request *
1884 *****************************************************************************/
1885
1886 static void
ble_sm_sec_req_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1887 ble_sm_sec_req_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
1888 void *arg)
1889 {
1890 struct ble_sm_sec_req *cmd;
1891 struct os_mbuf *txom;
1892 int rc;
1893
1894 cmd = ble_sm_cmd_get(BLE_SM_OP_SEC_REQ, sizeof(*cmd), &txom);
1895 if (!cmd) {
1896 res->app_status = BLE_HS_ENOMEM;
1897 return;
1898 }
1899
1900 cmd->authreq = ble_sm_build_authreq();
1901 rc = ble_sm_tx(proc->conn_handle, txom);
1902 if (rc != 0) {
1903 res->app_status = rc;
1904 return;
1905 }
1906 }
1907
1908 static void
ble_sm_sec_req_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)1909 ble_sm_sec_req_rx(uint16_t conn_handle, struct os_mbuf **om,
1910 struct ble_sm_result *res)
1911 {
1912 struct ble_store_value_sec value_sec;
1913 struct ble_store_key_sec key_sec;
1914 struct ble_hs_conn_addrs addrs;
1915 struct ble_sm_sec_req *cmd;
1916 struct ble_hs_conn *conn;
1917 int authreq_mitm;
1918
1919 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
1920 if (res->app_status != 0) {
1921 return;
1922 }
1923
1924 cmd = (struct ble_sm_sec_req *)(*om)->om_data;
1925 BLE_SM_LOG_CMD(0, "sec req", conn_handle, ble_sm_sec_req_log, cmd);
1926
1927 /* XXX: Reject if:
1928 * o authreq-reserved flags set?
1929 */
1930
1931 ble_hs_lock();
1932
1933 conn = ble_hs_conn_find_assert(conn_handle);
1934 if (!(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
1935 res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CMD_NOT_SUPP);
1936 res->sm_err = BLE_SM_ERR_CMD_NOT_SUPP;
1937 } else {
1938 /* We will be querying the SM database for a key corresponding to the
1939 * sender; remember the sender's address while the connection list is
1940 * locked.
1941 */
1942 ble_hs_conn_addrs(conn, &addrs);
1943 memset(&key_sec, 0, sizeof key_sec);
1944 key_sec.peer_addr = addrs.peer_id_addr;
1945 }
1946
1947 ble_hs_unlock();
1948
1949 if (res->app_status == 0) {
1950 /* If the peer is requesting a bonded connection, query database for an
1951 * LTK corresponding to the sender.
1952 */
1953 if (cmd->authreq & BLE_SM_PAIR_AUTHREQ_BOND) {
1954 res->app_status = ble_store_read_peer_sec(&key_sec, &value_sec);
1955 } else {
1956 res->app_status = BLE_HS_ENOENT;
1957 }
1958 if (res->app_status == 0) {
1959 /* Found a key corresponding to this peer. Make sure it meets the
1960 * requested minimum authreq.
1961 */
1962 authreq_mitm = cmd->authreq & BLE_SM_PAIR_AUTHREQ_MITM;
1963 if ((!authreq_mitm && value_sec.authenticated) ||
1964 (authreq_mitm && !value_sec.authenticated)) {
1965
1966 res->app_status = BLE_HS_EREJECT;
1967 }
1968 }
1969
1970 if (res->app_status == 0) {
1971 res->app_status = ble_sm_enc_initiate(conn_handle, value_sec.ltk,
1972 value_sec.ediv,
1973 value_sec.rand_num,
1974 value_sec.authenticated);
1975 } else {
1976 res->app_status = ble_sm_pair_initiate(conn_handle);
1977 }
1978 }
1979 }
1980
1981 /*****************************************************************************
1982 * $key exchange *
1983 *****************************************************************************/
1984
1985 static void
ble_sm_key_exch_success(struct ble_sm_proc * proc,struct ble_sm_result * res)1986 ble_sm_key_exch_success(struct ble_sm_proc *proc, struct ble_sm_result *res)
1987 {
1988 /* The procedure is now complete. Update connection bonded state and
1989 * terminate procedure.
1990 */
1991 ble_sm_update_sec_state(proc->conn_handle, 1, 0, 1, proc->key_size);
1992 proc->state = BLE_SM_PROC_STATE_NONE;
1993
1994 res->app_status = 0;
1995 res->enc_cb = 1;
1996 }
1997
1998 static void
ble_sm_key_exch_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)1999 ble_sm_key_exch_exec(struct ble_sm_proc *proc, struct ble_sm_result *res,
2000 void *arg)
2001 {
2002 struct ble_sm_id_addr_info *addr_info;
2003 struct ble_hs_conn_addrs addrs;
2004 struct ble_sm_sign_info *sign_info;
2005 struct ble_sm_master_id *master_id;
2006 struct ble_sm_enc_info *enc_info;
2007 struct ble_sm_id_info *id_info;
2008 struct ble_hs_conn *conn;
2009 uint8_t init_key_dist;
2010 uint8_t resp_key_dist;
2011 uint8_t our_key_dist;
2012 struct os_mbuf *txom;
2013 const uint8_t *irk;
2014 int rc;
2015
2016 ble_sm_key_dist(proc, &init_key_dist, &resp_key_dist);
2017 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
2018 our_key_dist = init_key_dist;
2019 } else {
2020 our_key_dist = resp_key_dist;
2021 }
2022
2023 if (our_key_dist & BLE_SM_PAIR_KEY_DIST_ENC) {
2024 /* Send encryption information. */
2025 enc_info = ble_sm_cmd_get(BLE_SM_OP_ENC_INFO, sizeof(*enc_info), &txom);
2026 if (!enc_info) {
2027 rc = BLE_HS_ENOMEM;
2028 goto err;
2029 }
2030
2031 rc = ble_sm_gen_ltk(proc, enc_info->ltk);
2032 if (rc != 0) {
2033 os_mbuf_free_chain(txom);
2034 goto err;
2035 }
2036
2037 /* store LTK before sending since ble_sm_tx consumes tx mbuf */
2038 memcpy(proc->our_keys.ltk, enc_info->ltk, 16);
2039 proc->our_keys.ltk_valid = 1;
2040
2041 rc = ble_sm_tx(proc->conn_handle, txom);
2042 if (rc != 0) {
2043 goto err;
2044 }
2045
2046 /* Send master identification. */
2047 master_id = ble_sm_cmd_get(BLE_SM_OP_MASTER_ID, sizeof(*master_id),
2048 &txom);
2049 if (!master_id) {
2050 rc = BLE_HS_ENOMEM;
2051 goto err;
2052 }
2053
2054 rc = ble_sm_gen_ediv(master_id);
2055 if (rc != 0) {
2056 os_mbuf_free_chain(txom);
2057 goto err;
2058 }
2059 rc = ble_sm_gen_master_id_rand(master_id);
2060 if (rc != 0) {
2061 os_mbuf_free_chain(txom);
2062 goto err;
2063 }
2064
2065 proc->our_keys.ediv_rand_valid = 1;
2066 proc->our_keys.rand_val = master_id->rand_val;
2067 proc->our_keys.ediv = master_id->ediv;
2068
2069 rc = ble_sm_tx(proc->conn_handle, txom);
2070 if (rc != 0) {
2071 goto err;
2072 }
2073 }
2074
2075 if (our_key_dist & BLE_SM_PAIR_KEY_DIST_ID) {
2076 /* Send identity information. */
2077 id_info = ble_sm_cmd_get(BLE_SM_OP_IDENTITY_INFO, sizeof(*id_info),
2078 &txom);
2079 if (!id_info) {
2080 rc = BLE_HS_ENOMEM;
2081 goto err;
2082 }
2083
2084 rc = ble_hs_pvcy_our_irk(&irk);
2085 if (rc != 0) {
2086 os_mbuf_free_chain(txom);
2087 goto err;
2088 }
2089
2090 memcpy(id_info->irk, irk, 16);
2091 proc->our_keys.irk_valid = 1;
2092
2093 rc = ble_sm_tx(proc->conn_handle, txom);
2094 if (rc != 0) {
2095 goto err;
2096 }
2097
2098 /* Send identity address information. */
2099 addr_info = ble_sm_cmd_get(BLE_SM_OP_IDENTITY_ADDR_INFO,
2100 sizeof(*addr_info), &txom);
2101 if (!addr_info) {
2102 rc = BLE_HS_ENOMEM;
2103 goto err;
2104 }
2105
2106 conn = ble_hs_conn_find_assert(proc->conn_handle);
2107 ble_hs_conn_addrs(conn, &addrs);
2108
2109 addr_info->addr_type = addrs.our_id_addr.type;
2110 memcpy(addr_info->bd_addr, addrs.our_id_addr.val, 6);
2111
2112 proc->our_keys.addr_valid = 1;
2113 memcpy(proc->our_keys.irk, irk, 16);
2114 proc->our_keys.addr_type = addr_info->addr_type;
2115 memcpy(proc->our_keys.addr, addr_info->bd_addr, 6);
2116
2117 rc = ble_sm_tx(proc->conn_handle, txom);
2118 if (rc != 0) {
2119 goto err;
2120 }
2121 }
2122
2123 if (our_key_dist & BLE_SM_PAIR_KEY_DIST_SIGN) {
2124 /* Send signing information. */
2125 sign_info = ble_sm_cmd_get(BLE_SM_OP_SIGN_INFO, sizeof(*sign_info),
2126 &txom);
2127 if (!sign_info) {
2128 rc = BLE_HS_ENOMEM;
2129 goto err;
2130 }
2131
2132 rc = ble_sm_gen_csrk(proc, sign_info->sig_key);
2133 if (rc != 0) {
2134 os_mbuf_free_chain(txom);
2135 goto err;
2136 }
2137
2138 proc->our_keys.csrk_valid = 1;
2139 memcpy(proc->our_keys.csrk, sign_info->sig_key, 16);
2140
2141 rc = ble_sm_tx(proc->conn_handle, txom);
2142 if (rc != 0) {
2143 goto err;
2144 }
2145 }
2146
2147 if (proc->flags & BLE_SM_PROC_F_INITIATOR || proc->rx_key_flags == 0) {
2148 /* The procedure is now complete. */
2149 ble_sm_key_exch_success(proc, res);
2150 }
2151
2152 return;
2153
2154 err:
2155 res->app_status = rc;
2156 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2157 res->enc_cb = 1;
2158 }
2159
2160 static void
ble_sm_key_rxed(struct ble_sm_proc * proc,struct ble_sm_result * res)2161 ble_sm_key_rxed(struct ble_sm_proc *proc, struct ble_sm_result *res)
2162 {
2163 BLE_HS_LOG(DEBUG, "rx_key_flags=0x%02x\n", proc->rx_key_flags);
2164
2165 if (proc->rx_key_flags == 0) {
2166 /* The peer is done sending keys. If we are the initiator, we need to
2167 * send ours. If we are the responder, the procedure is complete.
2168 */
2169 if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
2170 res->execute = 1;
2171 } else {
2172 ble_sm_key_exch_success(proc, res);
2173 }
2174 }
2175 }
2176
2177 static void
ble_sm_enc_info_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2178 ble_sm_enc_info_rx(uint16_t conn_handle, struct os_mbuf **om,
2179 struct ble_sm_result *res)
2180 {
2181 struct ble_sm_enc_info *cmd;
2182 struct ble_sm_proc *proc;
2183
2184 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2185 if (res->app_status != 0) {
2186 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2187 res->enc_cb = 1;
2188 return;
2189 }
2190
2191 cmd = (struct ble_sm_enc_info *)(*om)->om_data;
2192 BLE_SM_LOG_CMD(0, "enc info", conn_handle, ble_sm_enc_info_log, cmd);
2193
2194 ble_hs_lock();
2195
2196 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
2197 if (proc == NULL) {
2198 res->app_status = BLE_HS_ENOENT;
2199 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2200 } else {
2201 proc->rx_key_flags &= ~BLE_SM_KE_F_ENC_INFO;
2202 proc->peer_keys.ltk_valid = 1;
2203 memcpy(proc->peer_keys.ltk, cmd->ltk, 16);
2204
2205 ble_sm_key_rxed(proc, res);
2206 }
2207
2208 ble_hs_unlock();
2209 }
2210
2211 static void
ble_sm_master_id_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2212 ble_sm_master_id_rx(uint16_t conn_handle, struct os_mbuf **om,
2213 struct ble_sm_result *res)
2214 {
2215 struct ble_sm_master_id *cmd;
2216 struct ble_sm_proc *proc;
2217
2218 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2219 if (res->app_status != 0) {
2220 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2221 res->enc_cb = 1;
2222 return;
2223 }
2224
2225 cmd = (struct ble_sm_master_id *)(*om)->om_data;
2226 BLE_SM_LOG_CMD(0, "master id", conn_handle, ble_sm_master_id_log, cmd);
2227
2228 ble_hs_lock();
2229
2230 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
2231 if (proc == NULL) {
2232 res->app_status = BLE_HS_ENOENT;
2233 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2234 } else {
2235 proc->rx_key_flags &= ~BLE_SM_KE_F_MASTER_ID;
2236 proc->peer_keys.ediv_rand_valid = 1;
2237
2238 proc->peer_keys.ediv = le16toh(cmd->ediv);
2239 proc->peer_keys.rand_val = le64toh(cmd->rand_val);
2240
2241 ble_sm_key_rxed(proc, res);
2242 }
2243
2244 ble_hs_unlock();
2245 }
2246
2247 static void
ble_sm_id_info_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2248 ble_sm_id_info_rx(uint16_t conn_handle, struct os_mbuf **om,
2249 struct ble_sm_result *res)
2250 {
2251 struct ble_sm_id_info *cmd;
2252 struct ble_sm_proc *proc;
2253
2254 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2255 if (res->app_status != 0) {
2256 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2257 res->enc_cb = 1;
2258 return;
2259 }
2260
2261 cmd = (struct ble_sm_id_info *)(*om)->om_data;
2262 BLE_SM_LOG_CMD(0, "id info", conn_handle, ble_sm_id_info_log, cmd);
2263
2264 ble_hs_lock();
2265
2266 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
2267 if (proc == NULL) {
2268 res->app_status = BLE_HS_ENOENT;
2269 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2270 } else {
2271 proc->rx_key_flags &= ~BLE_SM_KE_F_ID_INFO;
2272
2273 memcpy(proc->peer_keys.irk, cmd->irk, 16);
2274 proc->peer_keys.irk_valid = 1;
2275
2276 ble_sm_key_rxed(proc, res);
2277 }
2278
2279 ble_hs_unlock();
2280 }
2281
2282 static void
ble_sm_id_addr_info_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2283 ble_sm_id_addr_info_rx(uint16_t conn_handle, struct os_mbuf **om,
2284 struct ble_sm_result *res)
2285 {
2286 struct ble_sm_id_addr_info *cmd;
2287 struct ble_sm_proc *proc;
2288
2289 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2290 if (res->app_status != 0) {
2291 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2292 res->enc_cb = 1;
2293 return;
2294 }
2295
2296 cmd = (struct ble_sm_id_addr_info *)(*om)->om_data;
2297 BLE_SM_LOG_CMD(0, "id addr info", conn_handle, ble_sm_id_addr_info_log,
2298 cmd);
2299
2300 ble_hs_lock();
2301
2302 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
2303 if (proc == NULL) {
2304 res->app_status = BLE_HS_ENOENT;
2305 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2306 } else {
2307 proc->rx_key_flags &= ~BLE_SM_KE_F_ADDR_INFO;
2308 proc->peer_keys.addr_valid = 1;
2309 proc->peer_keys.addr_type = cmd->addr_type;
2310 memcpy(proc->peer_keys.addr, cmd->bd_addr, 6);
2311
2312 ble_sm_key_rxed(proc, res);
2313 }
2314
2315 ble_hs_unlock();
2316 }
2317
2318 static void
ble_sm_sign_info_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2319 ble_sm_sign_info_rx(uint16_t conn_handle, struct os_mbuf **om,
2320 struct ble_sm_result *res)
2321 {
2322 struct ble_sm_sign_info *cmd;
2323 struct ble_sm_proc *proc;
2324
2325 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2326 if (res->app_status != 0) {
2327 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2328 res->enc_cb = 1;
2329 return;
2330 }
2331
2332 cmd = (struct ble_sm_sign_info *)(*om)->om_data;
2333 BLE_SM_LOG_CMD(0, "sign info", conn_handle, ble_sm_sign_info_log, cmd);
2334
2335 ble_hs_lock();
2336
2337 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_KEY_EXCH, -1, NULL);
2338 if (proc == NULL) {
2339 res->app_status = BLE_HS_ENOENT;
2340 res->sm_err = BLE_SM_ERR_UNSPECIFIED;
2341 } else {
2342 proc->rx_key_flags &= ~BLE_SM_KE_F_SIGN_INFO;
2343
2344 memcpy(proc->peer_keys.csrk, cmd->sig_key, 16);
2345 proc->peer_keys.csrk_valid = 1;
2346
2347 ble_sm_key_rxed(proc, res);
2348 }
2349
2350 ble_hs_unlock();
2351 }
2352
2353 /*****************************************************************************
2354 * $fail *
2355 *****************************************************************************/
2356
2357 static void
ble_sm_fail_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)2358 ble_sm_fail_rx(uint16_t conn_handle, struct os_mbuf **om,
2359 struct ble_sm_result *res)
2360 {
2361 struct ble_sm_pair_fail *cmd;
2362
2363 res->enc_cb = 1;
2364
2365 res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
2366 if (res->app_status == 0) {
2367 cmd = (struct ble_sm_pair_fail *)(*om)->om_data;
2368 BLE_SM_LOG_CMD(0, "fail", conn_handle, ble_sm_pair_fail_log, cmd);
2369
2370 res->app_status = BLE_HS_SM_PEER_ERR(cmd->reason);
2371 }
2372 }
2373
2374 /*****************************************************************************
2375 * $api *
2376 *****************************************************************************/
2377
2378 /**
2379 * Times out expired SM procedures.
2380 *
2381 * @return The number of ticks until this function should
2382 * be called again.
2383 */
2384 int32_t
ble_sm_timer(void)2385 ble_sm_timer(void)
2386 {
2387 struct ble_sm_proc_list exp_list;
2388 struct ble_sm_proc *proc;
2389 int32_t ticks_until_exp;
2390
2391 /* Remove timed-out procedures from the main list and insert them into a
2392 * temporary list. This function also calculates the number of ticks until
2393 * the next expiration will occur.
2394 */
2395 ticks_until_exp = ble_sm_extract_expired(&exp_list);
2396
2397 /* Notify application of each failure and free the corresponding procedure
2398 * object.
2399 * XXX: Mark connection as tainted; don't allow any subsequent SMP
2400 * procedures without reconnect.
2401 */
2402 while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
2403 ble_gap_enc_event(proc->conn_handle, BLE_HS_ETIMEOUT, 0);
2404
2405 STAILQ_REMOVE_HEAD(&exp_list, next);
2406 ble_sm_proc_free(proc);
2407 }
2408
2409 return ticks_until_exp;
2410 }
2411
2412 /**
2413 * Initiates the pairing procedure for the specified connection.
2414 */
2415 int
ble_sm_pair_initiate(uint16_t conn_handle)2416 ble_sm_pair_initiate(uint16_t conn_handle)
2417 {
2418 struct ble_sm_result res;
2419 struct ble_sm_proc *proc;
2420 int rc;
2421
2422 memset(&res, 0, sizeof(res));
2423
2424 /* Make sure a procedure isn't already in progress for this connection. */
2425 ble_hs_lock();
2426 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
2427 ble_hs_unlock();
2428
2429 if (proc != NULL) {
2430 res.app_status = BLE_HS_EALREADY;
2431 return BLE_HS_EALREADY;
2432 }
2433
2434 /* Check if there is storage capacity for a new bond. If there isn't, ask
2435 * the application to make room.
2436 */
2437 rc = ble_sm_chk_store_overflow(conn_handle);
2438 if (rc != 0) {
2439 return rc;
2440 }
2441
2442 proc = ble_sm_proc_alloc();
2443 if (proc == NULL) {
2444 res.app_status = BLE_HS_ENOMEM;
2445 } else {
2446 proc->conn_handle = conn_handle;
2447 proc->state = BLE_SM_PROC_STATE_PAIR;
2448 proc->flags |= BLE_SM_PROC_F_INITIATOR;
2449
2450 ble_hs_lock();
2451 ble_sm_insert(proc);
2452 ble_hs_unlock();
2453
2454 res.execute = 1;
2455 }
2456
2457 if (proc != NULL) {
2458 ble_sm_process_result(conn_handle, &res);
2459 }
2460
2461 return res.app_status;
2462 }
2463
2464 int
ble_sm_slave_initiate(uint16_t conn_handle)2465 ble_sm_slave_initiate(uint16_t conn_handle)
2466 {
2467 struct ble_sm_result res;
2468 struct ble_sm_proc *proc;
2469
2470 memset(&res, 0, sizeof(res));
2471
2472 ble_hs_lock();
2473
2474 /* Make sure a procedure isn't already in progress for this connection. */
2475 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
2476 if (proc != NULL) {
2477 res.app_status = BLE_HS_EALREADY;
2478
2479 /* Set pointer to null so that existing entry doesn't get freed. */
2480 proc = NULL;
2481 } else {
2482 proc = ble_sm_proc_alloc();
2483 if (proc == NULL) {
2484 res.app_status = BLE_HS_ENOMEM;
2485 } else {
2486 proc->conn_handle = conn_handle;
2487 proc->state = BLE_SM_PROC_STATE_SEC_REQ;
2488 ble_sm_insert(proc);
2489
2490 res.execute = 1;
2491 }
2492 }
2493
2494 ble_hs_unlock();
2495
2496 if (proc != NULL) {
2497 ble_sm_process_result(conn_handle, &res);
2498 }
2499
2500 return res.app_status;
2501 }
2502
2503 /**
2504 * Initiates the encryption procedure for the specified connection.
2505 */
2506 int
ble_sm_enc_initiate(uint16_t conn_handle,const uint8_t * ltk,uint16_t ediv,uint64_t rand_val,int auth)2507 ble_sm_enc_initiate(uint16_t conn_handle, const uint8_t *ltk, uint16_t ediv,
2508 uint64_t rand_val, int auth)
2509 {
2510 struct ble_sm_result res;
2511 struct ble_sm_proc *proc;
2512 struct hci_start_encrypt cmd;
2513
2514 memset(&res, 0, sizeof res);
2515
2516 /* Make sure a procedure isn't already in progress for this connection. */
2517 ble_hs_lock();
2518 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
2519 if (proc != NULL) {
2520 res.app_status = BLE_HS_EALREADY;
2521
2522 /* Set pointer to null so that existing entry doesn't get freed. */
2523 proc = NULL;
2524 } else {
2525 proc = ble_sm_proc_alloc();
2526 if (proc == NULL) {
2527 res.app_status = BLE_HS_ENOMEM;
2528 } else {
2529 proc->conn_handle = conn_handle;
2530 proc->state = BLE_SM_PROC_STATE_ENC_RESTORE;
2531 proc->flags |= BLE_SM_PROC_F_INITIATOR;
2532 if (auth) {
2533 proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
2534 }
2535 ble_sm_insert(proc);
2536
2537 cmd.connection_handle = conn_handle;
2538 cmd.encrypted_diversifier = ediv;
2539 cmd.random_number = rand_val;
2540 memcpy(cmd.long_term_key, ltk, sizeof cmd.long_term_key);
2541
2542 res.execute = 1;
2543 res.state_arg = &cmd;
2544 }
2545 }
2546
2547 ble_hs_unlock();
2548
2549 ble_sm_process_result(conn_handle, &res);
2550
2551 return res.app_status;
2552 }
2553
2554 static int
ble_sm_rx(struct ble_l2cap_chan * chan)2555 ble_sm_rx(struct ble_l2cap_chan *chan)
2556 {
2557 struct ble_sm_result res;
2558 ble_sm_rx_fn *rx_cb;
2559 uint8_t op;
2560 uint16_t conn_handle;
2561 struct os_mbuf **om;
2562 int rc;
2563
2564 STATS_INC(ble_l2cap_stats, sm_rx);
2565
2566 conn_handle = ble_l2cap_get_conn_handle(chan);
2567 if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
2568 return BLE_HS_ENOTCONN;
2569 }
2570
2571 om = &chan->rx_buf;
2572 BLE_HS_DBG_ASSERT(*om != NULL);
2573
2574 rc = os_mbuf_copydata(*om, 0, 1, &op);
2575 if (rc != 0) {
2576 return BLE_HS_EBADDATA;
2577 }
2578
2579 /* Strip L2CAP SM header from the front of the mbuf. */
2580 os_mbuf_adj(*om, 1);
2581
2582 rx_cb = ble_sm_dispatch_get(op);
2583 if (rx_cb != NULL) {
2584 memset(&res, 0, sizeof res);
2585
2586 rx_cb(conn_handle, om, &res);
2587 ble_sm_process_result(conn_handle, &res);
2588 rc = res.app_status;
2589 } else {
2590 rc = BLE_HS_ENOTSUP;
2591 }
2592
2593 return rc;
2594 }
2595
2596 int
ble_sm_inject_io(uint16_t conn_handle,struct ble_sm_io * pkey)2597 ble_sm_inject_io(uint16_t conn_handle, struct ble_sm_io *pkey)
2598 {
2599 struct ble_sm_result res;
2600 struct ble_sm_proc *proc;
2601 int rc;
2602 uint8_t action;
2603
2604 memset(&res, 0, sizeof res);
2605
2606 ble_hs_lock();
2607
2608 proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
2609 if (proc == NULL) {
2610 rc = BLE_HS_ENOENT;
2611 } else if (proc->flags & BLE_SM_PROC_F_IO_INJECTED) {
2612 rc = BLE_HS_EALREADY;
2613 } else if ((ble_sm_io_action(proc, &action) == 0) && pkey->action != action) {
2614 /* Application provided incorrect IO type. */
2615 rc = BLE_HS_EINVAL;
2616 } else if (ble_sm_ioact_state(pkey->action) != proc->state) {
2617 /* Procedure is not ready for user input. */
2618 rc = BLE_HS_EINVAL;
2619 } else {
2620 /* Assume valid input. */
2621 rc = 0;
2622
2623 switch (pkey->action) {
2624 case BLE_SM_IOACT_OOB:
2625 proc->flags |= BLE_SM_PROC_F_IO_INJECTED;
2626 memcpy(proc->tk, pkey->oob, 16);
2627 if ((proc->flags & BLE_SM_PROC_F_INITIATOR) ||
2628 (proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO)) {
2629
2630 res.execute = 1;
2631 }
2632 break;
2633
2634 case BLE_SM_IOACT_INPUT:
2635 case BLE_SM_IOACT_DISP:
2636 if (pkey->passkey > 999999) {
2637 rc = BLE_HS_EINVAL;
2638 } else {
2639 proc->flags |= BLE_SM_PROC_F_IO_INJECTED;
2640 memset(proc->tk, 0, 16);
2641 proc->tk[0] = (pkey->passkey >> 0) & 0xff;
2642 proc->tk[1] = (pkey->passkey >> 8) & 0xff;
2643 proc->tk[2] = (pkey->passkey >> 16) & 0xff;
2644 proc->tk[3] = (pkey->passkey >> 24) & 0xff;
2645 if ((proc->flags & BLE_SM_PROC_F_INITIATOR) ||
2646 (proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO)) {
2647
2648 res.execute = 1;
2649 }
2650 }
2651 break;
2652
2653 case BLE_SM_IOACT_NUMCMP:
2654 if (!pkey->numcmp_accept) {
2655 res.app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_NUMCMP);
2656 res.sm_err = BLE_SM_ERR_NUMCMP;
2657 } else {
2658 proc->flags |= BLE_SM_PROC_F_IO_INJECTED;
2659 if (proc->flags & BLE_SM_PROC_F_INITIATOR ||
2660 proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO) {
2661
2662 res.execute = 1;
2663 }
2664 }
2665 break;
2666
2667 default:
2668 BLE_HS_DBG_ASSERT(0);
2669 rc = BLE_HS_EINVAL;
2670 break;
2671 }
2672 }
2673
2674 ble_hs_unlock();
2675
2676 /* If application provided invalid input, return error without modifying
2677 * SMP state.
2678 */
2679 if (rc != 0) {
2680 return rc;
2681 }
2682
2683 ble_sm_process_result(conn_handle, &res);
2684 return res.app_status;
2685 }
2686
2687 void
ble_sm_connection_broken(uint16_t conn_handle)2688 ble_sm_connection_broken(uint16_t conn_handle)
2689 {
2690 struct ble_sm_result res;
2691
2692 memset(&res, 0, sizeof res);
2693 res.app_status = BLE_HS_ENOTCONN;
2694 res.enc_cb = 1;
2695
2696 ble_sm_process_result(conn_handle, &res);
2697 }
2698
2699 int
ble_sm_init(void)2700 ble_sm_init(void)
2701 {
2702 int rc;
2703
2704 STAILQ_INIT(&ble_sm_procs);
2705
2706 rc = os_mempool_init(&ble_sm_proc_pool,
2707 MYNEWT_VAL(BLE_SM_MAX_PROCS),
2708 sizeof (struct ble_sm_proc),
2709 ble_sm_proc_mem,
2710 "ble_sm_proc_pool");
2711 if (rc != 0) {
2712 return rc;
2713 }
2714
2715 ble_sm_sc_init();
2716
2717 return 0;
2718 }
2719 #else
2720 /* if pairing is not supported it is only needed to reply with Pairing
2721 * Failed with 'Pairing not Supported' reason so this function can be very
2722 * simple
2723 */
2724 static int
ble_sm_rx(struct ble_l2cap_chan * chan)2725 ble_sm_rx(struct ble_l2cap_chan *chan)
2726 {
2727 struct ble_sm_pair_fail *cmd;
2728 struct os_mbuf *txom;
2729 uint16_t handle;
2730
2731 handle = ble_l2cap_get_conn_handle(chan);
2732 if (!handle) {
2733 return BLE_HS_ENOTCONN;
2734 }
2735
2736 cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_FAIL, sizeof(*cmd), &txom);
2737 if (cmd == NULL) {
2738 return BLE_HS_ENOMEM;
2739 }
2740
2741 cmd->reason = BLE_SM_ERR_PAIR_NOT_SUPP;
2742
2743 return ble_sm_tx(handle, txom);
2744 }
2745 #endif
2746
2747 struct ble_l2cap_chan *
ble_sm_create_chan(uint16_t conn_handle)2748 ble_sm_create_chan(uint16_t conn_handle)
2749 {
2750 struct ble_l2cap_chan *chan;
2751
2752 chan = ble_l2cap_chan_alloc(conn_handle);
2753 if (chan == NULL) {
2754 return NULL;
2755 }
2756
2757 chan->scid = BLE_L2CAP_CID_SM;
2758 chan->dcid = BLE_L2CAP_CID_SM;
2759 chan->my_mtu = BLE_SM_MTU;
2760 chan->rx_fn = ble_sm_rx;
2761
2762 return chan;
2763 }
2764