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