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