• 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 #include "securec.h"
21 #include "nimble/nimble_opt.h"
22 #include "host/ble_sm.h"
23 #include "ble_hs_priv.h"
24 
25 #if MYNEWT_VAL(BLE_SM_SC)
26 
27 #define BLE_SM_SC_PASSKEY_BYTES     4
28 #define BLE_SM_SC_PASSKEY_BITS      20
29 
30 static uint8_t ble_sm_sc_pub_key[64];
31 static uint8_t ble_sm_sc_priv_key[32];
32 
33 /**
34  * Whether our public-private key pair has been generated.  We generate it on
35  * startup for now until we have a non-volatile storage mechanism.
36  */
37 static uint8_t ble_sm_sc_keys_generated;
38 
39 /**
40  * Create some shortened names for the passkey actions so that the table is
41  * easier to read.
42  */
43 #define IOACT_NONE      BLE_SM_IOACT_NONE
44 #define IOACT_OOB       BLE_SM_IOACT_OOB
45 #define IOACT_INPUT     BLE_SM_IOACT_INPUT
46 #define IOACT_DISP      BLE_SM_IOACT_DISP
47 #define IOACT_NUMCMP    BLE_SM_IOACT_NUMCMP
48 
49 /**
50  * This table expresses the required initiator IO action.  Inputs are:
51  *     o Responder IO capabilities (from pair response).
52  *     o Initiator IO capabilities (from pair request).
53  */
54 static const uint8_t ble_sm_sc_init_ioa[5][5] = {
55     /* init */
56     {IOACT_NONE,    IOACT_NONE,   IOACT_INPUT, IOACT_NONE, IOACT_INPUT}, /* r */
57     {IOACT_NONE,    IOACT_NUMCMP, IOACT_INPUT, IOACT_NONE, IOACT_NUMCMP}, /* e */
58     {IOACT_DISP,    IOACT_DISP,   IOACT_INPUT, IOACT_NONE, IOACT_DISP}, /* s */
59     {IOACT_NONE,    IOACT_NONE,   IOACT_NONE,  IOACT_NONE, IOACT_NONE}, /* p */
60     {IOACT_DISP,    IOACT_NUMCMP, IOACT_INPUT, IOACT_NONE, IOACT_NUMCMP},
61 };
62 
63 /**
64  * This table expresses the required responder IO action.  Inputs are:
65  *     o Responder IO capabilities (from pair response).
66  *     o Initiator IO capabilities (from pair request).
67  */
68 static const uint8_t ble_sm_sc_resp_ioa[5][5] = {
69     /* init */
70     {IOACT_NONE,    IOACT_NONE,   IOACT_DISP,  IOACT_NONE, IOACT_DISP}, /* r */
71     {IOACT_NONE,    IOACT_NUMCMP, IOACT_DISP,  IOACT_NONE, IOACT_NUMCMP}, /* e */
72     {IOACT_INPUT,   IOACT_INPUT,  IOACT_INPUT, IOACT_NONE, IOACT_INPUT}, /* s */
73     {IOACT_NONE,    IOACT_NONE,   IOACT_NONE,  IOACT_NONE, IOACT_NONE}, /* p */
74     {IOACT_INPUT,   IOACT_NUMCMP, IOACT_DISP,  IOACT_NONE, IOACT_NUMCMP},
75 };
76 
77 #if MYNEWT_VAL(BLE_HS_DEBUG)
78 
79 static uint8_t ble_sm_dbg_sc_pub_key[64];
80 static uint8_t ble_sm_dbg_sc_priv_key[32];
81 static uint8_t ble_sm_dbg_sc_keys_set;
82 
ble_sm_dbg_set_sc_keys(uint8_t * pubkey,uint8_t * privkey)83 void ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey)
84 {
85     memcpy_s(ble_sm_dbg_sc_pub_key, sizeof(ble_sm_dbg_sc_pub_key), pubkey,
86            sizeof ble_sm_dbg_sc_pub_key);
87     memcpy_s(ble_sm_dbg_sc_priv_key, sizeof(ble_sm_dbg_sc_priv_key), privkey,
88            sizeof ble_sm_dbg_sc_priv_key);
89     ble_sm_dbg_sc_keys_set = 1;
90 }
91 
92 #endif
93 
ble_sm_sc_io_action(struct ble_sm_proc * proc,uint8_t * action)94 int ble_sm_sc_io_action(struct ble_sm_proc *proc, uint8_t *action)
95 {
96     struct ble_sm_pair_cmd *pair_req, *pair_rsp;
97     pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
98     pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
99 
100     if (pair_req->oob_data_flag == BLE_SM_PAIR_OOB_YES ||
101             pair_rsp->oob_data_flag == BLE_SM_PAIR_OOB_YES) {
102         *action = BLE_SM_IOACT_OOB_SC;
103     } else if (!(pair_req->authreq & BLE_SM_PAIR_AUTHREQ_MITM) &&
104               !(pair_rsp->authreq & BLE_SM_PAIR_AUTHREQ_MITM)) {
105         *action = BLE_SM_IOACT_NONE;
106     } else if (pair_req->io_cap >= BLE_SM_IO_CAP_RESERVED ||
107               pair_rsp->io_cap >= BLE_SM_IO_CAP_RESERVED) {
108         *action = BLE_SM_IOACT_NONE;
109     } else if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
110         *action = ble_sm_sc_init_ioa[pair_rsp->io_cap][pair_req->io_cap];
111     } else {
112         *action = ble_sm_sc_resp_ioa[pair_rsp->io_cap][pair_req->io_cap];
113     }
114 
115     switch (*action) {
116         case BLE_SM_IOACT_NONE:
117             proc->pair_alg = BLE_SM_PAIR_ALG_JW;
118             break;
119 
120         case BLE_SM_IOACT_OOB_SC:
121             proc->pair_alg = BLE_SM_PAIR_ALG_OOB;
122             proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
123             break;
124 
125         case BLE_SM_IOACT_INPUT:
126         case BLE_SM_IOACT_DISP:
127             proc->pair_alg = BLE_SM_PAIR_ALG_PASSKEY;
128             proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
129             break;
130 
131         case BLE_SM_IOACT_NUMCMP:
132             proc->pair_alg = BLE_SM_PAIR_ALG_NUMCMP;
133             proc->flags |= BLE_SM_PROC_F_AUTHENTICATED;
134             break;
135 
136         default:
137             BLE_HS_DBG_ASSERT(0);
138             return BLE_HS_EINVAL;
139     }
140 
141     return 0;
142 }
143 
ble_sm_gen_pub_priv(uint8_t * pub,uint8_t * priv)144 static int ble_sm_gen_pub_priv(uint8_t *pub, uint8_t *priv)
145 {
146     int rc;
147 #if MYNEWT_VAL(BLE_HS_DEBUG)
148 
149     if (ble_sm_dbg_sc_keys_set) {
150         ble_sm_dbg_sc_keys_set = 0;
151         memcpy_s(pub, sizeof(*pub), ble_sm_dbg_sc_pub_key, sizeof ble_sm_dbg_sc_pub_key);
152         memcpy_s(priv, sizeof(*priv), ble_sm_dbg_sc_priv_key, sizeof ble_sm_dbg_sc_priv_key);
153         return 0;
154     }
155 
156 #endif
157     rc = ble_sm_alg_gen_key_pair(pub, priv);
158     if (rc != 0) {
159         return rc;
160     }
161 
162     return 0;
163 }
164 
ble_sm_sc_ensure_keys_generated(void)165 static int ble_sm_sc_ensure_keys_generated(void)
166 {
167     int rc;
168 
169     if (!ble_sm_sc_keys_generated) {
170         rc = ble_sm_gen_pub_priv(ble_sm_sc_pub_key, ble_sm_sc_priv_key);
171         if (rc != 0) {
172             return rc;
173         }
174 
175         ble_sm_sc_keys_generated = 1;
176     }
177 
178     BLE_HS_LOG(DEBUG, "our pubkey=");
179     ble_hs_log_flat_buf(&ble_sm_sc_pub_key, 64); // 64:len
180     BLE_HS_LOG(DEBUG, "\n");
181     BLE_HS_LOG(DEBUG, "our privkey=");
182     ble_hs_log_flat_buf(&ble_sm_sc_priv_key, 32); // 32:len
183     BLE_HS_LOG(DEBUG, "\n");
184     return 0;
185 }
186 
187 /* Initiator does not send a confirm when pairing algorithm is any of:
188  *     o just works
189  *     o numeric comparison
190  * (vol. 3, part H, 2.3.5.6.2)
191  */
ble_sm_sc_initiator_txes_confirm(struct ble_sm_proc * proc)192 static int ble_sm_sc_initiator_txes_confirm(struct ble_sm_proc *proc)
193 {
194     BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC);
195     return proc->pair_alg != BLE_SM_PAIR_ALG_JW &&
196            proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP;
197 }
198 
199 /* Responder does not verify the initiator's random number when pairing
200  * algorithm is any of:
201  *     o just works
202  *     o numeric comparison
203  * (vol. 3, part H, 2.3.5.6.2)
204  */
ble_sm_sc_responder_verifies_random(struct ble_sm_proc * proc)205 static int ble_sm_sc_responder_verifies_random(struct ble_sm_proc *proc)
206 {
207     BLE_HS_DBG_ASSERT(proc->flags & BLE_SM_PROC_F_SC);
208     return proc->pair_alg != BLE_SM_PAIR_ALG_JW &&
209            proc->pair_alg != BLE_SM_PAIR_ALG_NUMCMP;
210 }
211 
212 /**
213  * Generates the Ri byte used in the confirm message.  On success, the byte is
214  * written to the supplied procedure object.
215  */
ble_sm_sc_gen_ri(struct ble_sm_proc * proc)216 static int ble_sm_sc_gen_ri(struct ble_sm_proc *proc)
217 {
218     int byte;
219     int bit;
220 
221     switch (proc->pair_alg) {
222         case BLE_SM_PAIR_ALG_JW:
223         case BLE_SM_PAIR_ALG_NUMCMP:
224         case BLE_SM_PAIR_ALG_OOB:
225             proc->ri = 0;
226             return 0;
227 
228         case BLE_SM_PAIR_ALG_PASSKEY:
229             BLE_HS_DBG_ASSERT(proc->passkey_bits_exchanged <
230                               BLE_SM_SC_PASSKEY_BITS);
231             byte = proc->passkey_bits_exchanged / 8; // 8:byte alignment
232             bit = proc->passkey_bits_exchanged % 8; // 8:byte alignment
233             proc->ri = 0x80 | !!(proc->tk[byte] & (1 << bit));
234             proc->passkey_bits_exchanged++;
235             return 0;
236 
237         default:
238             BLE_HS_DBG_ASSERT(0);
239             return BLE_HS_EUNKNOWN;
240     }
241 }
242 
ble_sm_sc_oob_confirm(struct ble_sm_proc * proc,struct ble_sm_result * res)243 void ble_sm_sc_oob_confirm(struct ble_sm_proc *proc, struct ble_sm_result *res)
244 {
245     int err;
246     bool match;
247     uint8_t c[16];
248 
249     /* Authentication stage 1: Step 5 */
250     if (proc->oob_data_remote) {
251         err = ble_sm_alg_f4(proc->pub_key_peer.x, proc->pub_key_peer.x,
252                             proc->oob_data_remote->r, 0, c);
253         if (err) {
254             res->sm_err = BLE_SM_ERR_UNSPECIFIED;
255             res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_UNSPECIFIED);
256             res->enc_cb = 1;
257             return;
258         }
259 
260         match = (memcmp(c, proc->oob_data_remote->c, sizeof(c)) == 0);
261         if (!match) {
262             /* Random number mismatch. */
263             res->sm_err = BLE_SM_ERR_CONFIRM_MISMATCH;
264             res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH);
265             res->enc_cb = 1;
266             return;
267         }
268     }
269 
270     if ((proc->flags & BLE_SM_PROC_F_INITIATOR) ||
271             (proc->flags & BLE_SM_PROC_F_ADVANCE_ON_IO)) {
272         /* If is initiator or was waiting on
273          * IO then execute step 6: send Random
274          */
275         res->execute = 1;
276     }
277 }
278 
ble_sm_sc_confirm_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)279 void ble_sm_sc_confirm_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
280 {
281     struct ble_sm_pair_confirm *cmd;
282     struct os_mbuf *txom;
283     int rc;
284     rc = ble_sm_sc_gen_ri(proc);
285     if (rc != 0) {
286         res->app_status = rc;
287         res->enc_cb = 1;
288         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
289         return;
290     }
291 
292     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_CONFIRM, sizeof(*cmd), &txom);
293     if (cmd == NULL) {
294         rc = BLE_HS_ENOMEM;
295         res->app_status = rc;
296         res->enc_cb = 1;
297         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
298         return;
299     }
300 
301     rc = ble_sm_alg_f4(ble_sm_sc_pub_key, proc->pub_key_peer.x,
302                        ble_sm_our_pair_rand(proc), proc->ri, cmd->value);
303     if (rc != 0) {
304         os_mbuf_free_chain(txom);
305         res->app_status = rc;
306         res->enc_cb = 1;
307         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
308         return;
309     }
310 
311     rc = ble_sm_tx(proc->conn_handle, txom);
312     if (rc != 0) {
313         res->app_status = rc;
314         res->enc_cb = 1;
315         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
316         return;
317     }
318 
319     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
320         proc->state = BLE_SM_PROC_STATE_RANDOM;
321     }
322 }
323 
ble_sm_sc_gen_numcmp(struct ble_sm_proc * proc,struct ble_sm_result * res)324 static void ble_sm_sc_gen_numcmp(struct ble_sm_proc *proc, struct ble_sm_result *res)
325 {
326     uint8_t *pka;
327     uint8_t *pkb;
328 
329     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
330         pka = ble_sm_sc_pub_key;
331         pkb = proc->pub_key_peer.x;
332     } else {
333         pka = proc->pub_key_peer.x;
334         pkb = ble_sm_sc_pub_key;
335     }
336 
337     res->app_status = ble_sm_alg_g2(pka, pkb, proc->randm, proc->rands,
338                                     &res->passkey_params.numcmp);
339     if (res->app_status != 0) {
340         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
341         res->enc_cb = 1;
342     }
343 }
344 
345 /**
346  * Advances the supplied procedure object to the next state after it has
347  * completed the random state.
348  */
ble_sm_sc_random_advance(struct ble_sm_proc * proc)349 static int ble_sm_sc_random_advance(struct ble_sm_proc *proc)
350 {
351     int rc;
352 
353     if (proc->pair_alg != BLE_SM_PAIR_ALG_PASSKEY ||
354             proc->passkey_bits_exchanged >= BLE_SM_SC_PASSKEY_BITS) {
355         proc->state = BLE_SM_PROC_STATE_DHKEY_CHECK;
356     } else {
357         proc->state = BLE_SM_PROC_STATE_CONFIRM;
358         rc = ble_sm_gen_pair_rand(ble_sm_our_pair_rand(proc));
359         if (rc != 0) {
360             return rc;
361         }
362     }
363 
364     return 0;
365 }
366 
ble_sm_sc_random_exec(struct ble_sm_proc * proc,struct ble_sm_result * res)367 void ble_sm_sc_random_exec(struct ble_sm_proc *proc, struct ble_sm_result *res)
368 {
369     struct ble_sm_pair_random *cmd;
370     struct os_mbuf *txom;
371     uint8_t ioact;
372     int rc;
373     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_RANDOM, sizeof(*cmd), &txom);
374     if (cmd == NULL) {
375         rc = BLE_HS_ENOMEM;
376         res->enc_cb = 1;
377         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
378         return;
379     }
380 
381     memcpy_s(cmd->value, sizeof(cmd->value), ble_sm_our_pair_rand(proc), 16); // 16:size
382     rc = ble_sm_tx(proc->conn_handle, txom);
383     if (rc != 0) {
384         res->app_status = rc;
385         res->enc_cb = 1;
386         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
387         return;
388     }
389 
390     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
391         rc = ble_sm_sc_random_advance(proc);
392         if (rc != 0) {
393             res->app_status = rc;
394             res->enc_cb = 1;
395             res->sm_err = BLE_SM_ERR_UNSPECIFIED;
396             return;
397         }
398 
399         rc = ble_sm_sc_io_action(proc, &ioact);
400         BLE_HS_DBG_ASSERT(rc == 0);
401 
402         if (ble_sm_ioact_state(ioact) == proc->state &&
403                 !(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
404             res->passkey_params.action = ioact;
405             BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
406             ble_sm_sc_gen_numcmp(proc, res);
407         }
408     }
409 }
410 
ble_sm_sc_random_rx(struct ble_sm_proc * proc,struct ble_sm_result * res)411 void ble_sm_sc_random_rx(struct ble_sm_proc *proc, struct ble_sm_result *res)
412 {
413     uint8_t confirm_val[16];
414     uint8_t ia[6];
415     uint8_t ra[6];
416     uint8_t ioact;
417     uint8_t iat;
418     uint8_t rat;
419     int rc;
420 
421     if ((proc->pair_alg != BLE_SM_PAIR_ALG_OOB) && (
422         (proc->flags & BLE_SM_PROC_F_INITIATOR) ||
423         ble_sm_sc_responder_verifies_random(proc))) {
424         BLE_HS_LOG(DEBUG, "tk=");
425         ble_hs_log_flat_buf(proc->tk, 16); // 16:len
426         BLE_HS_LOG(DEBUG, "\n");
427         rc = ble_sm_alg_f4(proc->pub_key_peer.x, ble_sm_sc_pub_key,
428                            ble_sm_peer_pair_rand(proc), proc->ri,
429                            confirm_val);
430         if (rc != 0) {
431             res->app_status = rc;
432             res->sm_err = BLE_SM_ERR_UNSPECIFIED;
433             res->enc_cb = 1;
434             return;
435         }
436 
437         if (memcmp(proc->confirm_peer, confirm_val, 16) != 0) { // 16:size
438             /* Random number mismatch. */
439             res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_CONFIRM_MISMATCH);
440             res->sm_err = BLE_SM_ERR_CONFIRM_MISMATCH;
441             res->enc_cb = 1;
442             return;
443         }
444     }
445 
446     /* Calculate the mac key and ltk. */
447     ble_sm_ia_ra(proc, &iat, ia, &rat, ra);
448     rc = ble_sm_alg_f5(proc->dhkey, proc->randm, proc->rands,
449                        iat, ia, rat, ra, proc->mackey, proc->ltk);
450     if (rc != 0) {
451         res->app_status = rc;
452         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
453         res->enc_cb = 1;
454         return;
455     }
456 
457     /* Ensure proper key size */
458     memset_s(proc->ltk + proc->key_size, sizeof(proc->ltk + proc->key_size), 0, sizeof proc->ltk - proc->key_size);
459     /* Ensure the ltk gets persisted when the pairing procedure succeeds. */
460     memcpy_s(proc->our_keys.ltk, sizeof(proc->our_keys.ltk), proc->ltk, sizeof proc->our_keys.ltk);
461     proc->our_keys.ltk_valid = 1;
462     proc->our_keys.ediv = 0;
463     proc->our_keys.rand_val = 0;
464     proc->our_keys.ediv_rand_valid = 1;
465     proc->our_keys.key_size = proc->key_size;
466     memcpy_s(proc->peer_keys.ltk, sizeof(proc->peer_keys.ltk), proc->ltk, sizeof proc->peer_keys.ltk);
467     proc->peer_keys.ltk_valid = 1;
468     proc->peer_keys.ediv = 0;
469     proc->peer_keys.rand_val = 0;
470     proc->peer_keys.ediv_rand_valid = 1;
471     proc->peer_keys.key_size = proc->key_size;
472 
473     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
474         ble_sm_sc_random_advance(proc);
475         rc = ble_sm_sc_io_action(proc, &ioact);
476         if (rc != 0) {
477             BLE_HS_DBG_ASSERT(0);
478         }
479 
480         if (ble_sm_ioact_state(ioact) == proc->state &&
481                 !(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
482             res->passkey_params.action = ioact;
483             BLE_HS_DBG_ASSERT(ioact == BLE_SM_IOACT_NUMCMP);
484             ble_sm_sc_gen_numcmp(proc, res);
485         } else {
486             res->execute = 1;
487         }
488     } else {
489         if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB &&
490                 !(proc->flags & BLE_SM_PROC_F_IO_INJECTED)) {
491             proc->flags |= BLE_SM_PROC_F_ADVANCE_ON_IO;
492         } else {
493             res->execute = 1;
494         }
495     }
496 }
497 
ble_sm_sc_public_key_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)498 void ble_sm_sc_public_key_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, void *arg)
499 {
500     struct ble_sm_public_key *cmd;
501     struct os_mbuf *txom;
502     uint8_t ioact;
503     int rc;
504     res->app_status = ble_sm_sc_ensure_keys_generated();
505     if (res->app_status != 0) {
506         res->enc_cb = 1;
507         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
508         return;
509     }
510 
511     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_PUBLIC_KEY, sizeof(*cmd), &txom);
512     if (!cmd) {
513         res->app_status = BLE_HS_ENOMEM;
514         res->enc_cb = 1;
515         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
516         return;
517     }
518 
519     memcpy_s(cmd->x, sizeof(cmd->x), ble_sm_sc_pub_key + 0, 32); // 32:size
520     memcpy_s(cmd->y, sizeof(cmd->y), ble_sm_sc_pub_key + 32, 32); // 32:byte alignment & size
521     res->app_status = ble_sm_tx(proc->conn_handle, txom);
522     if (res->app_status != 0) {
523         res->enc_cb = 1;
524         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
525         return;
526     }
527 
528     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
529         if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB) {
530             proc->state = BLE_SM_PROC_STATE_RANDOM;
531         } else {
532             proc->state = BLE_SM_PROC_STATE_CONFIRM;
533         }
534 
535         rc = ble_sm_sc_io_action(proc, &ioact);
536         if (rc != 0) {
537             BLE_HS_DBG_ASSERT(0);
538         }
539 
540         if (ble_sm_ioact_state(ioact) == proc->state) {
541             res->passkey_params.action = ioact;
542         }
543 
544         if (ble_sm_proc_can_advance(proc) &&
545                 !ble_sm_sc_initiator_txes_confirm(proc)) {
546             res->execute = 1;
547         }
548     }
549 }
550 
ble_sm_sc_public_key_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)551 void ble_sm_sc_public_key_rx(uint16_t conn_handle, struct os_mbuf **om, struct ble_sm_result *res)
552 {
553     struct ble_sm_public_key *cmd;
554     struct ble_sm_proc *proc;
555     uint8_t ioact;
556     int rc;
557     res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
558     if (res->app_status != 0) {
559         res->enc_cb = 1;
560         return;
561     }
562 
563     res->app_status = ble_sm_sc_ensure_keys_generated();
564     if (res->app_status != 0) {
565         res->enc_cb = 1;
566         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
567         return;
568     }
569 
570     cmd = (struct ble_sm_public_key *)(*om)->om_data;
571     ble_hs_lock();
572     proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_PUBLIC_KEY, -1,
573                             NULL);
574     if (proc == NULL) {
575         res->app_status = BLE_HS_ENOENT;
576         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
577     } else {
578         memcpy_s(&proc->pub_key_peer, sizeof(proc->pub_key_peer), cmd, sizeof(*cmd));
579         rc = ble_sm_alg_gen_dhkey(proc->pub_key_peer.x,
580                                   proc->pub_key_peer.y,
581                                   ble_sm_sc_priv_key,
582                                   proc->dhkey);
583         if (rc != 0) {
584             res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_DHKEY);
585             res->sm_err = BLE_SM_ERR_DHKEY;
586             res->enc_cb = 1;
587         } else {
588             if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
589                 if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB) {
590                     proc->state = BLE_SM_PROC_STATE_RANDOM;
591                 } else {
592                     proc->state = BLE_SM_PROC_STATE_CONFIRM;
593                 }
594 
595                 rc = ble_sm_sc_io_action(proc, &ioact);
596                 if (rc != 0) {
597                     BLE_HS_DBG_ASSERT(0);
598                 }
599 
600                 if (ble_sm_ioact_state(ioact) == proc->state) {
601                     res->passkey_params.action = ioact;
602                 }
603 
604                 if (ble_sm_proc_can_advance(proc) &&
605                         ble_sm_sc_initiator_txes_confirm(proc)) {
606                     res->execute = 1;
607                 }
608             } else {
609                 res->execute = 1;
610             }
611         }
612     }
613 
614     ble_hs_unlock();
615 }
616 
ble_sm_sc_dhkey_addrs(struct ble_sm_proc * proc,ble_addr_t * our_addr,ble_addr_t * peer_addr)617 static void ble_sm_sc_dhkey_addrs(struct ble_sm_proc *proc, ble_addr_t *our_addr, ble_addr_t *peer_addr)
618 {
619     struct ble_hs_conn_addrs addrs;
620     struct ble_hs_conn *conn;
621     conn = ble_hs_conn_find_assert(proc->conn_handle);
622     ble_hs_conn_addrs(conn, &addrs);
623     *our_addr = addrs.our_ota_addr;
624     *peer_addr = addrs.peer_ota_addr;
625 }
626 
ble_sm_sc_dhkey_check_exec(struct ble_sm_proc * proc,struct ble_sm_result * res,void * arg)627 void ble_sm_sc_dhkey_check_exec(struct ble_sm_proc *proc, struct ble_sm_result *res, void *arg)
628 {
629     struct ble_sm_dhkey_check *cmd;
630     ble_addr_t our_addr;
631     ble_addr_t peer_addr;
632     struct os_mbuf *txom;
633     uint8_t *iocap;
634     int rc;
635 
636     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
637         struct ble_sm_pair_cmd *pair_req;
638         pair_req  = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
639         iocap = &pair_req->io_cap;
640     } else {
641         struct ble_sm_pair_cmd *pair_rsp;
642         pair_rsp  = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
643         iocap = &pair_rsp->io_cap;
644     }
645 
646     if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB) {
647         if (proc->oob_data_remote) {
648             memcpy_s(proc->tk, sizeof(proc->tk), proc->oob_data_remote->r, 16); // 16:size
649         } else {
650             memset_s(proc->tk, sizeof(proc->tk), 0, 16); // 16:size
651         }
652     }
653 
654     ble_sm_sc_dhkey_addrs(proc, &our_addr, &peer_addr);
655     cmd = ble_sm_cmd_get(BLE_SM_OP_PAIR_DHKEY_CHECK, sizeof(*cmd), &txom);
656     if (!cmd) {
657         rc = BLE_HS_ENOMEM;
658         goto err;
659     }
660 
661     rc = ble_sm_alg_f6(proc->mackey, ble_sm_our_pair_rand(proc),
662                        ble_sm_peer_pair_rand(proc), proc->tk, iocap,
663                        our_addr.type, our_addr.val, peer_addr.type,
664                        peer_addr.val, cmd->value);
665     if (rc != 0) {
666         os_mbuf_free_chain(txom);
667         goto err;
668     }
669 
670     rc = ble_sm_tx(proc->conn_handle, txom);
671     if (rc != 0) {
672         goto err;
673     }
674 
675     if (!(proc->flags & BLE_SM_PROC_F_INITIATOR)) {
676         proc->state = BLE_SM_PROC_STATE_LTK_START;
677     }
678 
679     return;
680 err:
681     res->app_status = rc;
682     res->enc_cb = 1;
683     res->sm_err = BLE_SM_ERR_UNSPECIFIED;
684 }
685 
ble_sm_dhkey_check_process(struct ble_sm_proc * proc,struct ble_sm_dhkey_check * cmd,struct ble_sm_result * res)686 static void ble_sm_dhkey_check_process(struct ble_sm_proc *proc,
687                                        struct ble_sm_dhkey_check *cmd,
688                                        struct ble_sm_result *res)
689 {
690     uint8_t exp_value[16];
691     ble_addr_t our_addr;
692     ble_addr_t peer_addr;
693     uint8_t *iocap;
694     uint8_t ioact;
695     int rc;
696 
697     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
698         struct ble_sm_pair_cmd *pair_rsp;
699         pair_rsp  = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
700         iocap = &pair_rsp->io_cap;
701 
702         if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB) {
703             if (pair_rsp->oob_data_flag) {
704                 memcpy_s(proc->tk, sizeof(proc->tk), proc->oob_data_local->r, 16); // 16:size
705             } else {
706                 memset_s(proc->tk, sizeof(proc->tk), 0, 16); // 16:size
707             }
708         }
709     } else {
710         struct ble_sm_pair_cmd *pair_req;
711         pair_req  = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
712         iocap = &pair_req->io_cap;
713 
714         if (proc->pair_alg == BLE_SM_PAIR_ALG_OOB) {
715             if (pair_req->oob_data_flag) {
716                 memcpy_s(proc->tk, sizeof(proc->tk), proc->oob_data_local->r, 16); // 16:size
717             } else {
718                 memset_s(proc->tk, sizeof(proc->tk), 0, 16); // 16:size
719             }
720         }
721     }
722 
723     ble_sm_sc_dhkey_addrs(proc, &our_addr, &peer_addr);
724     BLE_HS_LOG(DEBUG, "tk=");
725     ble_hs_log_flat_buf(proc->tk, 16); // 16:len
726     BLE_HS_LOG(DEBUG, "\n");
727     res->app_status = ble_sm_alg_f6(proc->mackey,
728                                     ble_sm_peer_pair_rand(proc),
729                                     ble_sm_our_pair_rand(proc),
730                                     proc->tk, iocap,
731                                     peer_addr.type, peer_addr.val,
732                                     our_addr.type, our_addr.val,
733                                     exp_value);
734 
735     if (res->app_status != 0) {
736         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
737         res->enc_cb = 1;
738         return;
739     }
740 
741     if (memcmp(cmd->value, exp_value, 16) != 0) { // 16:size
742         /* Random number mismatch. */
743         res->sm_err = BLE_SM_ERR_DHKEY;
744         res->app_status = BLE_HS_SM_US_ERR(BLE_SM_ERR_DHKEY);
745         res->enc_cb = 1;
746         return;
747     }
748 
749     rc = ble_sm_sc_io_action(proc, &ioact);
750     if (rc != 0) {
751         BLE_HS_DBG_ASSERT(0);
752     }
753 
754     if (ble_sm_ioact_state(ioact) == proc->state) {
755         proc->flags |= BLE_SM_PROC_F_ADVANCE_ON_IO;
756     }
757 
758     if (ble_sm_proc_can_advance(proc)) {
759         if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
760             proc->state = BLE_SM_PROC_STATE_ENC_START;
761         }
762 
763         res->execute = 1;
764     }
765 }
766 
ble_sm_sc_dhkey_check_rx(uint16_t conn_handle,struct os_mbuf ** om,struct ble_sm_result * res)767 void ble_sm_sc_dhkey_check_rx(uint16_t conn_handle, struct os_mbuf **om,
768                               struct ble_sm_result *res)
769 {
770     struct ble_sm_dhkey_check *cmd;
771     struct ble_sm_proc *proc;
772     res->app_status = ble_hs_mbuf_pullup_base(om, sizeof(*cmd));
773     if (res->app_status != 0) {
774         res->enc_cb = 1;
775         res->sm_err = BLE_SM_ERR_UNSPECIFIED;
776         return;
777     }
778 
779     cmd = (struct ble_sm_dhkey_check *)(*om)->om_data;
780     ble_hs_lock();
781     proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_DHKEY_CHECK, -1,
782                             NULL);
783     if (proc == NULL) {
784         res->app_status = BLE_HS_ENOENT;
785     } else {
786         ble_sm_dhkey_check_process(proc, cmd, res);
787     }
788 
789     ble_hs_unlock();
790 }
791 
ble_sm_sc_oob_data_check(struct ble_sm_proc * proc,bool oob_data_local_present,bool oob_data_remote_present)792 bool ble_sm_sc_oob_data_check(struct ble_sm_proc *proc,
793                               bool oob_data_local_present,
794                               bool oob_data_remote_present)
795 {
796     struct ble_sm_pair_cmd *pair_req;
797     struct ble_sm_pair_cmd *pair_rsp;
798     bool req_oob_present;
799     bool rsp_oob_present;
800     pair_req = (struct ble_sm_pair_cmd *) &proc->pair_req[1];
801     pair_rsp = (struct ble_sm_pair_cmd *) &proc->pair_rsp[1];
802     req_oob_present = pair_req->oob_data_flag == BLE_SM_PAIR_OOB_YES;
803     rsp_oob_present = pair_rsp->oob_data_flag == BLE_SM_PAIR_OOB_YES;
804 
805     if (proc->flags & BLE_SM_PROC_F_INITIATOR) {
806         return req_oob_present == oob_data_remote_present;
807     } else {
808         return rsp_oob_present == oob_data_remote_present;
809     }
810 }
811 
ble_sm_sc_oob_generate_data(struct ble_sm_sc_oob_data * oob_data)812 int ble_sm_sc_oob_generate_data(struct ble_sm_sc_oob_data *oob_data)
813 {
814     int rc;
815 #if !MYNEWT_VAL(BLE_SM_SC)
816     return BLE_HS_ENOTSUP;
817 #endif
818     rc = ble_sm_sc_ensure_keys_generated();
819     if (rc) {
820         return rc;
821     }
822 
823     rc = ble_hs_hci_util_rand(oob_data->r, 16); // 16:len
824     if (rc) {
825         return rc;
826     }
827 
828     rc = ble_sm_alg_f4(ble_sm_sc_pub_key, ble_sm_sc_pub_key, oob_data->r, 0,
829                        oob_data->c);
830     if (rc) {
831         return rc;
832     }
833 
834     return 0;
835 }
836 
ble_sm_sc_init(void)837 void ble_sm_sc_init(void)
838 {
839     ble_sm_alg_ecc_init();
840     ble_sm_sc_keys_generated = 0;
841 }
842 
843 #endif  /* MYNEWT_VAL(BLE_SM_SC) */