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