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