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) */