xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/src/ble_sm_alg.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
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