1 /*
2 * Copyright (c) 2015 Intel Corporation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /* These functions are adapted from the Intel Zephyr BLE security manager
18 * code.
19 */
20
21 #include <inttypes.h>
22 #include <string.h>
23 #include "syscfg/syscfg.h"
24 #include "nimble/nimble_opt.h"
25
26 #if NIMBLE_BLE_SM
27
28 #include "nimble/ble.h"
29 #include "nimble/nimble_opt.h"
30 #include "ble_hs_priv.h"
31 #include "tinycrypt/aes.h"
32 #include "tinycrypt/constants.h"
33 #include "tinycrypt/utils.h"
34
35 #if MYNEWT_VAL(BLE_SM_SC)
36 #include "tinycrypt/cmac_mode.h"
37 #include "tinycrypt/ecc_dh.h"
38 #if MYNEWT_VAL(TRNG)
39 #include "trng/trng.h"
40 #endif
41 #endif
42
43 #if MYNEWT_VAL(BLE_SM_SC) && MYNEWT_VAL(TRNG)
44 static struct trng_dev *g_trng;
45 #endif
46
47 static void
ble_sm_alg_xor_128(uint8_t * p,uint8_t * q,uint8_t * r)48 ble_sm_alg_xor_128(uint8_t *p, uint8_t *q, uint8_t *r)
49 {
50 int i;
51
52 for (i = 0; i < 16; i++) {
53 r[i] = p[i] ^ q[i];
54 }
55 }
56
57 static int
ble_sm_alg_encrypt(uint8_t * key,uint8_t * plaintext,uint8_t * enc_data)58 ble_sm_alg_encrypt(uint8_t *key, uint8_t *plaintext, uint8_t *enc_data)
59 {
60 struct tc_aes_key_sched_struct s;
61 uint8_t tmp[16];
62
63 swap_buf(tmp, key, 16);
64
65 if (tc_aes128_set_encrypt_key(&s, tmp) == TC_CRYPTO_FAIL) {
66 return BLE_HS_EUNKNOWN;
67 }
68
69 swap_buf(tmp, plaintext, 16);
70
71
72
73 if (tc_aes_encrypt(enc_data, tmp, &s) == TC_CRYPTO_FAIL) {
74 return BLE_HS_EUNKNOWN;
75 }
76
77 swap_in_place(enc_data, 16);
78
79 return 0;
80 }
81
82 int
ble_sm_alg_s1(uint8_t * k,uint8_t * r1,uint8_t * r2,uint8_t * out)83 ble_sm_alg_s1(uint8_t *k, uint8_t *r1, uint8_t *r2, uint8_t *out)
84 {
85 int rc;
86
87 /* The most significant 64-bits of r1 are discarded to generate
88 * r1' and the most significant 64-bits of r2 are discarded to
89 * generate r2'.
90 * r1' is concatenated with r2' to generate r' which is used as
91 * the 128-bit input parameter plaintextData to security function e:
92 *
93 * r' = r1' || r2'
94 */
95 memcpy(out, r2, 8);
96 memcpy(out + 8, r1, 8);
97
98 /* s1(k, r1 , r2) = e(k, r') */
99 rc = ble_sm_alg_encrypt(k, out, out);
100 if (rc != 0) {
101 return rc;
102 }
103
104 BLE_HS_LOG(DEBUG, "ble_sm_alg_s1()\n k=");
105 ble_hs_log_flat_buf(k, 16);
106 BLE_HS_LOG(DEBUG, "\n r1=");
107 ble_hs_log_flat_buf(r1, 16);
108 BLE_HS_LOG(DEBUG, "\n r2=");
109 ble_hs_log_flat_buf(r2, 16);
110 BLE_HS_LOG(DEBUG, "\n out=");
111 ble_hs_log_flat_buf(out, 16);
112 BLE_HS_LOG(DEBUG, "\n");
113
114 return 0;
115 }
116
117 int
ble_sm_alg_c1(uint8_t * k,uint8_t * r,uint8_t * preq,uint8_t * pres,uint8_t iat,uint8_t rat,uint8_t * ia,uint8_t * ra,uint8_t * out_enc_data)118 ble_sm_alg_c1(uint8_t *k, uint8_t *r,
119 uint8_t *preq, uint8_t *pres,
120 uint8_t iat, uint8_t rat,
121 uint8_t *ia, uint8_t *ra,
122 uint8_t *out_enc_data)
123 {
124 uint8_t p1[16], p2[16];
125 int rc;
126
127 BLE_HS_LOG(DEBUG, "ble_sm_alg_c1()\n k=");
128 ble_hs_log_flat_buf(k, 16);
129 BLE_HS_LOG(DEBUG, "\n r=");
130 ble_hs_log_flat_buf(r, 16);
131 BLE_HS_LOG(DEBUG, "\n iat=%d rat=%d", iat, rat);
132 BLE_HS_LOG(DEBUG, "\n ia=");
133 ble_hs_log_flat_buf(ia, 6);
134 BLE_HS_LOG(DEBUG, "\n ra=");
135 ble_hs_log_flat_buf(ra, 6);
136 BLE_HS_LOG(DEBUG, "\n preq=");
137 ble_hs_log_flat_buf(preq, 7);
138 BLE_HS_LOG(DEBUG, "\n pres=");
139 ble_hs_log_flat_buf(pres, 7);
140
141 /* pres, preq, rat and iat are concatenated to generate p1 */
142 p1[0] = iat;
143 p1[1] = rat;
144 memcpy(p1 + 2, preq, 7);
145 memcpy(p1 + 9, pres, 7);
146
147 BLE_HS_LOG(DEBUG, "\n p1=");
148 ble_hs_log_flat_buf(p1, sizeof p1);
149
150 /* c1 = e(k, e(k, r XOR p1) XOR p2) */
151
152 /* Using out_enc_data as temporary output buffer */
153 ble_sm_alg_xor_128(r, p1, out_enc_data);
154
155 rc = ble_sm_alg_encrypt(k, out_enc_data, out_enc_data);
156 if (rc != 0) {
157 rc = BLE_HS_EUNKNOWN;
158 goto done;
159 }
160
161 /* ra is concatenated with ia and padding to generate p2 */
162 memcpy(p2, ra, 6);
163 memcpy(p2 + 6, ia, 6);
164 memset(p2 + 12, 0, 4);
165
166 BLE_HS_LOG(DEBUG, "\n p2=");
167 ble_hs_log_flat_buf(p2, sizeof p2);
168
169 ble_sm_alg_xor_128(out_enc_data, p2, out_enc_data);
170
171 rc = ble_sm_alg_encrypt(k, out_enc_data, out_enc_data);
172 if (rc != 0) {
173 rc = BLE_HS_EUNKNOWN;
174 goto done;
175 }
176
177 BLE_HS_LOG(DEBUG, "\n out_enc_data=");
178 ble_hs_log_flat_buf(out_enc_data, 16);
179
180 rc = 0;
181
182 done:
183 BLE_HS_LOG(DEBUG, "\n rc=%d\n", rc);
184 return rc;
185 }
186
187 #if MYNEWT_VAL(BLE_SM_SC)
188
189 static void
ble_sm_alg_log_buf(const char * name,const uint8_t * buf,int len)190 ble_sm_alg_log_buf(const char *name, const uint8_t *buf, int len)
191 {
192 BLE_HS_LOG(DEBUG, " %s=", name);
193 ble_hs_log_flat_buf(buf, len);
194 BLE_HS_LOG(DEBUG, "\n");
195 }
196
197 /**
198 * Cypher based Message Authentication Code (CMAC) with AES 128 bit
199 *
200 * @param key 128-bit key.
201 * @param in Message to be authenticated.
202 * @param len Length of the message in octets.
203 * @param out Output; message authentication code.
204 */
205 static int
ble_sm_alg_aes_cmac(const uint8_t * key,const uint8_t * in,size_t len,uint8_t * out)206 ble_sm_alg_aes_cmac(const uint8_t *key, const uint8_t *in, size_t len,
207 uint8_t *out)
208 {
209 struct tc_aes_key_sched_struct sched;
210 struct tc_cmac_struct state;
211
212 if (tc_cmac_setup(&state, key, &sched) == TC_CRYPTO_FAIL) {
213 return BLE_HS_EUNKNOWN;
214 }
215
216 if (tc_cmac_update(&state, in, len) == TC_CRYPTO_FAIL) {
217 return BLE_HS_EUNKNOWN;
218 }
219
220 if (tc_cmac_final(out, &state) == TC_CRYPTO_FAIL) {
221 return BLE_HS_EUNKNOWN;
222 }
223
224 return 0;
225 }
226
227 int
ble_sm_alg_f4(uint8_t * u,uint8_t * v,uint8_t * x,uint8_t z,uint8_t * out_enc_data)228 ble_sm_alg_f4(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t z,
229 uint8_t *out_enc_data)
230 {
231 uint8_t xs[16];
232 uint8_t m[65];
233 int rc;
234
235 BLE_HS_LOG(DEBUG, "ble_sm_alg_f4()\n u=");
236 ble_hs_log_flat_buf(u, 32);
237 BLE_HS_LOG(DEBUG, "\n v=");
238 ble_hs_log_flat_buf(v, 32);
239 BLE_HS_LOG(DEBUG, "\n x=");
240 ble_hs_log_flat_buf(x, 16);
241 BLE_HS_LOG(DEBUG, "\n z=0x%02x\n", z);
242
243 /*
244 * U, V and Z are concatenated and used as input m to the function
245 * AES-CMAC and X is used as the key k.
246 *
247 * Core Spec 4.2 Vol 3 Part H 2.2.5
248 *
249 * note:
250 * ble_sm_alg_aes_cmac uses BE data; ble_sm_alg_f4 accepts LE so we swap.
251 */
252 swap_buf(m, u, 32);
253 swap_buf(m + 32, v, 32);
254 m[64] = z;
255
256 swap_buf(xs, x, 16);
257
258 rc = ble_sm_alg_aes_cmac(xs, m, sizeof(m), out_enc_data);
259 if (rc != 0) {
260 return BLE_HS_EUNKNOWN;
261 }
262
263 swap_in_place(out_enc_data, 16);
264
265 BLE_HS_LOG(DEBUG, " out_enc_data=");
266 ble_hs_log_flat_buf(out_enc_data, 16);
267 BLE_HS_LOG(DEBUG, "\n");
268
269 return 0;
270 }
271
272 int
ble_sm_alg_f5(uint8_t * w,uint8_t * n1,uint8_t * n2,uint8_t a1t,uint8_t * a1,uint8_t a2t,uint8_t * a2,uint8_t * mackey,uint8_t * ltk)273 ble_sm_alg_f5(uint8_t *w, uint8_t *n1, uint8_t *n2, uint8_t a1t,
274 uint8_t *a1, uint8_t a2t, uint8_t *a2, uint8_t *mackey,
275 uint8_t *ltk)
276 {
277 static const uint8_t salt[16] = { 0x6c, 0x88, 0x83, 0x91, 0xaa, 0xf5,
278 0xa5, 0x38, 0x60, 0x37, 0x0b, 0xdb,
279 0x5a, 0x60, 0x83, 0xbe };
280 uint8_t m[53] = {
281 0x00, /* counter */
282 0x62, 0x74, 0x6c, 0x65, /* keyID */
283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*n1*/
284 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
285 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*2*/
286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a1 */
288 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a2 */
289 0x01, 0x00 /* length */
290 };
291 uint8_t ws[32];
292 uint8_t t[16];
293 int rc;
294
295 BLE_HS_LOG(DEBUG, "ble_sm_alg_f5()\n");
296 ble_sm_alg_log_buf("w", w, 32);
297 ble_sm_alg_log_buf("n1", n1, 16);
298 ble_sm_alg_log_buf("n2", n2, 16);
299
300 swap_buf(ws, w, 32);
301
302 rc = ble_sm_alg_aes_cmac(salt, ws, 32, t);
303 if (rc != 0) {
304 return BLE_HS_EUNKNOWN;
305 }
306
307 ble_sm_alg_log_buf("t", t, 16);
308
309 swap_buf(m + 5, n1, 16);
310 swap_buf(m + 21, n2, 16);
311 m[37] = a1t;
312 swap_buf(m + 38, a1, 6);
313 m[44] = a2t;
314 swap_buf(m + 45, a2, 6);
315
316 rc = ble_sm_alg_aes_cmac(t, m, sizeof(m), mackey);
317 if (rc != 0) {
318 return BLE_HS_EUNKNOWN;
319 }
320
321 ble_sm_alg_log_buf("mackey", mackey, 16);
322
323 swap_in_place(mackey, 16);
324
325 /* Counter for ltk is 1. */
326 m[0] = 0x01;
327
328 rc = ble_sm_alg_aes_cmac(t, m, sizeof(m), ltk);
329 if (rc != 0) {
330 return BLE_HS_EUNKNOWN;
331 }
332
333 ble_sm_alg_log_buf("ltk", ltk, 16);
334
335 swap_in_place(ltk, 16);
336
337 return 0;
338 }
339
340 int
ble_sm_alg_f6(const uint8_t * w,const uint8_t * n1,const uint8_t * n2,const uint8_t * r,const uint8_t * iocap,uint8_t a1t,const uint8_t * a1,uint8_t a2t,const uint8_t * a2,uint8_t * check)341 ble_sm_alg_f6(const uint8_t *w, const uint8_t *n1, const uint8_t *n2,
342 const uint8_t *r, const uint8_t *iocap, uint8_t a1t,
343 const uint8_t *a1, uint8_t a2t, const uint8_t *a2,
344 uint8_t *check)
345 {
346 uint8_t ws[16];
347 uint8_t m[65];
348 int rc;
349
350 BLE_HS_LOG(DEBUG, "ble_sm_alg_f6()\n");
351 ble_sm_alg_log_buf("w", w, 16);
352 ble_sm_alg_log_buf("n1", n1, 16);
353 ble_sm_alg_log_buf("n2", n2, 16);
354 ble_sm_alg_log_buf("r", r, 16);
355 ble_sm_alg_log_buf("iocap", iocap, 3);
356 ble_sm_alg_log_buf("a1t", &a1t, 1);
357 ble_sm_alg_log_buf("a1", a1, 6);
358 ble_sm_alg_log_buf("a2t", &a2t, 1);
359 ble_sm_alg_log_buf("a2", a2, 6);
360
361 swap_buf(m, n1, 16);
362 swap_buf(m + 16, n2, 16);
363 swap_buf(m + 32, r, 16);
364 swap_buf(m + 48, iocap, 3);
365
366 m[51] = a1t;
367 memcpy(m + 52, a1, 6);
368 swap_buf(m + 52, a1, 6);
369
370 m[58] = a2t;
371 memcpy(m + 59, a2, 6);
372 swap_buf(m + 59, a2, 6);
373
374 swap_buf(ws, w, 16);
375
376 rc = ble_sm_alg_aes_cmac(ws, m, sizeof(m), check);
377 if (rc != 0) {
378 return BLE_HS_EUNKNOWN;
379 }
380
381 ble_sm_alg_log_buf("res", check, 16);
382
383 swap_in_place(check, 16);
384
385 return 0;
386 }
387
388 int
ble_sm_alg_g2(uint8_t * u,uint8_t * v,uint8_t * x,uint8_t * y,uint32_t * passkey)389 ble_sm_alg_g2(uint8_t *u, uint8_t *v, uint8_t *x, uint8_t *y,
390 uint32_t *passkey)
391 {
392 uint8_t m[80], xs[16];
393 int rc;
394
395 BLE_HS_LOG(DEBUG, "ble_sm_alg_g2()\n");
396 ble_sm_alg_log_buf("u", u, 32);
397 ble_sm_alg_log_buf("v", v, 32);
398 ble_sm_alg_log_buf("x", x, 16);
399 ble_sm_alg_log_buf("y", y, 16);
400
401 swap_buf(m, u, 32);
402 swap_buf(m + 32, v, 32);
403 swap_buf(m + 64, y, 16);
404
405 swap_buf(xs, x, 16);
406
407 /* reuse xs (key) as buffer for result */
408 rc = ble_sm_alg_aes_cmac(xs, m, sizeof(m), xs);
409 if (rc != 0) {
410 return BLE_HS_EUNKNOWN;
411 }
412
413 ble_sm_alg_log_buf("res", xs, 16);
414
415 *passkey = get_be32(xs + 12) % 1000000;
416 BLE_HS_LOG(DEBUG, " passkey=%u\n", *passkey);
417
418 return 0;
419 }
420
421 int
ble_sm_alg_gen_dhkey(uint8_t * peer_pub_key_x,uint8_t * peer_pub_key_y,uint8_t * our_priv_key,uint8_t * out_dhkey)422 ble_sm_alg_gen_dhkey(uint8_t *peer_pub_key_x, uint8_t *peer_pub_key_y,
423 uint8_t *our_priv_key, uint8_t *out_dhkey)
424 {
425 uint8_t dh[32];
426 uint8_t pk[64];
427 uint8_t priv[32];
428 int rc;
429
430 swap_buf(pk, peer_pub_key_x, 32);
431 swap_buf(&pk[32], peer_pub_key_y, 32);
432 swap_buf(priv, our_priv_key, 32);
433
434 if (uECC_valid_public_key(pk, &curve_secp256r1) < 0) {
435 return BLE_HS_EUNKNOWN;
436 }
437
438 rc = uECC_shared_secret(pk, priv, dh, &curve_secp256r1);
439 if (rc == TC_CRYPTO_FAIL) {
440 return BLE_HS_EUNKNOWN;
441 }
442
443 swap_buf(out_dhkey, dh, 32);
444
445 return 0;
446 }
447
448 /* based on Core Specification 4.2 Vol 3. Part H 2.3.5.6.1 */
449 static const uint8_t ble_sm_alg_dbg_priv_key[32] = {
450 0x3f, 0x49, 0xf6, 0xd4, 0xa3, 0xc5, 0x5f, 0x38, 0x74, 0xc9, 0xb3, 0xe3,
451 0xd2, 0x10, 0x3f, 0x50, 0x4a, 0xff, 0x60, 0x7b, 0xeb, 0x40, 0xb7, 0x99,
452 0x58, 0x99, 0xb8, 0xa6, 0xcd, 0x3c, 0x1a, 0xbd
453 };
454
455 #if MYNEWT_VAL(BLE_SM_SC_DEBUG_KEYS)
456 static const uint8_t ble_sm_alg_dbg_pub_key[64] = {
457 /* X */
458 0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c, 0x5e, 0x2c, 0x83, 0xa7,
459 0xe9, 0xf9, 0xa5, 0xb9, 0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb,
460 0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6,
461 /* Y */
462 0xdc, 0x80, 0x9c, 0x49, 0x65, 0x2a, 0xeb, 0x6d, 0x63, 0x32, 0x9a, 0xbf,
463 0x5a, 0x52, 0x15, 0x5c, 0x76, 0x63, 0x45, 0xc2, 0x8f, 0xed, 0x30, 0x24,
464 0x74, 0x1c, 0x8e, 0xd0, 0x15, 0x89, 0xd2, 0x8b,
465 };
466 #endif
467
468 /**
469 * pub: 64 bytes
470 * priv: 32 bytes
471 */
472 int
ble_sm_alg_gen_key_pair(uint8_t * pub,uint8_t * priv)473 ble_sm_alg_gen_key_pair(uint8_t *pub, uint8_t *priv)
474 {
475 #if MYNEWT_VAL(BLE_SM_SC_DEBUG_KEYS)
476 swap_buf(pub, ble_sm_alg_dbg_pub_key, 32);
477 swap_buf(&pub[32], &ble_sm_alg_dbg_pub_key[32], 32);
478 swap_buf(priv, ble_sm_alg_dbg_priv_key, 32);
479 #else
480 uint8_t pk[64];
481
482 do {
483 if (uECC_make_key(pk, priv, &curve_secp256r1) != TC_CRYPTO_SUCCESS) {
484 return BLE_HS_EUNKNOWN;
485 }
486
487 /* Make sure generated key isn't debug key. */
488 } while (memcmp(priv, ble_sm_alg_dbg_priv_key, 32) == 0);
489
490 swap_buf(pub, pk, 32);
491 swap_buf(&pub[32], &pk[32], 32);
492 swap_in_place(priv, 32);
493 #endif
494
495 return 0;
496 }
497
498 /* used by uECC to get random data */
499 static int
ble_sm_alg_rand(uint8_t * dst,unsigned int size)500 ble_sm_alg_rand(uint8_t *dst, unsigned int size)
501 {
502 #if MYNEWT_VAL(TRNG)
503 size_t num;
504
505 if (!g_trng) {
506 g_trng = (struct trng_dev *)os_dev_open("trng", OS_WAIT_FOREVER, NULL);
507 assert(g_trng);
508 }
509
510 while (size) {
511 num = trng_read(g_trng, dst, size);
512 dst += num;
513 size -= num;
514 }
515 #else
516 if (ble_hs_hci_util_rand(dst, size)) {
517 return 0;
518 }
519 #endif
520
521 return 1;
522 }
523
524 void
ble_sm_alg_ecc_init(void)525 ble_sm_alg_ecc_init(void)
526 {
527 uECC_set_rng(ble_sm_alg_rand);
528 }
529
530 #endif
531 #endif
532