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