xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_sm.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 /**
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