xref: /btstack/src/mesh/mesh_crypto.c (revision 077fecbb6ed539507f37505ebd8a5b00e01c55e9)
1 /*
2  * Copyright (C) 2017 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #define BTSTACK_FILE__ "mesh_crypto.c"
39 
40 #include <string.h>
41 
42 #include "btstack_debug.h"
43 #include "btstack_util.h"
44 
45 #include "mesh/mesh_crypto.h"
46 
47 // mesh k1 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k1_t struct
48 static uint8_t         mesh_k1_temp[16];
49 static void (*         mesh_k1_callback)(void * arg);
50 static void *          mesh_k1_arg;
51 static const uint8_t * mesh_k1_p;
52 static uint16_t        mesh_k1_p_len;
53 static uint8_t *       mesh_k1_result;
54 
55 static void mesh_k1_temp_calculated(void * arg){
56     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
57     btstack_crypto_aes128_cmac_message(request, mesh_k1_temp, mesh_k1_p_len, mesh_k1_p, mesh_k1_result, mesh_k1_callback, mesh_k1_arg);
58 }
59 
60 void mesh_k1(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint16_t n_len, const uint8_t * salt,
61     const uint8_t * p, const uint16_t p_len, uint8_t * result, void (* callback)(void * arg), void * callback_arg){
62     mesh_k1_callback = callback;
63     mesh_k1_arg      = callback_arg;
64     mesh_k1_p        = p;
65     mesh_k1_p_len    = p_len;
66     mesh_k1_result   = result;
67     btstack_crypto_aes128_cmac_message(request, salt, n_len, n, mesh_k1_temp, mesh_k1_temp_calculated, request);
68 }
69 
70 // mesh k2 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k2_t struct
71 static void (*         mesh_k2_callback)(void * arg);
72 static void *          mesh_k2_arg;
73 static uint8_t       * mesh_k2_result;
74 static uint8_t         mesh_k2_t[16];
75 static uint8_t         mesh_k2_t1[18];
76 static uint8_t         mesh_k2_t2[16];
77 
78 static const uint8_t mesh_salt_smk2[] = { 0x4f, 0x90, 0x48, 0x0c, 0x18, 0x71, 0xbf, 0xbf, 0xfd, 0x16, 0x97, 0x1f, 0x4d, 0x8d, 0x10, 0xb1 };
79 
80 static void mesh_k2_callback_d(void * arg){
81     // btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
82     UNUSED(arg);
83     log_info("PrivacyKey: ");
84     log_info_hexdump(mesh_k2_t, 16);
85     // collect result
86     (void)memcpy(&mesh_k2_result[17], mesh_k2_t2, 16);
87     //
88     (*mesh_k2_callback)(mesh_k2_arg);
89 }
90 static void mesh_k2_callback_c(void * arg){
91     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
92     log_info("EncryptionKey: ");
93     log_info_hexdump(mesh_k2_t, 16);
94     // collect result
95     (void)memcpy(&mesh_k2_result[1], mesh_k2_t2, 16);
96     //
97     (void)memcpy(mesh_k2_t1, mesh_k2_t2, 16);
98     mesh_k2_t1[16] = 0; // p
99     mesh_k2_t1[17] = 0x03;
100     btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 18, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_d, request);
101 }
102 static void mesh_k2_callback_b(void * arg){
103     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
104     log_info("NID: 0x%02x\n", mesh_k2_t2[15] & 0x7f);
105     // collect result
106     mesh_k2_result[0] = mesh_k2_t2[15] & 0x7f;
107     //
108     (void)memcpy(mesh_k2_t1, mesh_k2_t2, 16);
109     mesh_k2_t1[16] = 0; // p
110     mesh_k2_t1[17] = 0x02;
111     btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 18, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_c, request);
112 }
113 static void mesh_k2_callback_a(void * arg){
114     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
115     log_info("T:");
116     log_info_hexdump(mesh_k2_t, 16);
117     mesh_k2_t1[0] = 0; // p
118     mesh_k2_t1[1] = 0x01;
119     btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 2, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_b, request);
120 }
121 void mesh_k2(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){
122     mesh_k2_callback = callback;
123     mesh_k2_arg      = callback_arg;
124     mesh_k2_result   = result;
125     btstack_crypto_aes128_cmac_message(request, mesh_salt_smk2, 16, n, mesh_k2_t, mesh_k2_callback_a, request);
126 }
127 
128 
129 // mesh k3 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k3_t struct
130 static const uint8_t   mesh_k3_tag[5] = { 'i', 'd', '6', '4', 0x01};
131 static uint8_t         mesh_k3_temp[16];
132 static uint8_t         mesh_k3_result128[16];
133 static void (*         mesh_k3_callback)(void * arg);
134 static void *          mesh_k3_arg;
135 static const uint8_t * mesh_k3_n;
136 static uint8_t       * mesh_k3_result;
137 
138 // AES-CMAC_ZERO('smk3')
139 static const uint8_t mesh_salt_smk3[] = { 0x00, 0x36, 0x44, 0x35, 0x03, 0xf1, 0x95, 0xcc, 0x8a, 0x71, 0x6e, 0x13, 0x62, 0x91, 0xc3, 0x02, };
140 
141 static void mesh_k3_result128_calculated(void * arg){
142     UNUSED(arg);
143     (void)memcpy(mesh_k3_result, &mesh_k3_result128[8], 8);
144     (*mesh_k3_callback)(mesh_k3_arg);
145 }
146 static void mesh_k3_temp_callback(void * arg){
147     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
148     btstack_crypto_aes128_cmac_message(request, mesh_k3_temp, sizeof(mesh_k3_tag), mesh_k3_tag, mesh_k3_result128, mesh_k3_result128_calculated, request);
149 }
150 void mesh_k3(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){
151     mesh_k3_callback = callback;
152     mesh_k3_arg      = callback_arg;
153     mesh_k3_n        = n;
154     mesh_k3_result   = result;
155     btstack_crypto_aes128_cmac_message(request, mesh_salt_smk3, 16, mesh_k3_n, mesh_k3_temp, mesh_k3_temp_callback, request);
156 }
157 
158 // mesh k4 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k4_t struct
159 // k4N     63964771734fbd76e3b40519d1d94a48
160 // k4 SALT 0e9ac1b7cefa66874c97ee54ac5f49be
161 // k4T     921cb4f908cc5932e1d7b059fc163ce6
162 // k4 CMAC(id6|0x01) 5f79cf09bbdab560e7f1ee404fd341a6
163 // AID 26
164 static const uint8_t   mesh_k4_tag[4] = { 'i', 'd', '6', 0x01};
165 static uint8_t         mesh_k4_temp[16];
166 static uint8_t         mesh_k4_result128[16];
167 static void (*         mesh_k4_callback)(void * arg);
168 static void *          mesh_k4_arg;
169 static const uint8_t * mesh_k4_n;
170 static uint8_t       * mesh_k4_result;
171 
172 // AES-CMAC_ZERO('smk4')
173 static const uint8_t mesh_salt_smk4[] = { 0x0E, 0x9A, 0xC1, 0xB7, 0xCE, 0xFA, 0x66, 0x87, 0x4C, 0x97, 0xEE, 0x54, 0xAC, 0x5F, 0x49, 0xBE };
174 static void mesh_k4_result128_calculated(void * arg){
175     UNUSED(arg);
176     mesh_k4_result[0] = mesh_k4_result128[15] & 0x3f;
177     (*mesh_k4_callback)(mesh_k4_arg);
178 }
179 static void mesh_k4_temp_callback(void * arg){
180     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
181     btstack_crypto_aes128_cmac_message(request, mesh_k4_temp, sizeof(mesh_k4_tag), mesh_k4_tag, mesh_k4_result128, mesh_k4_result128_calculated, request);
182 }
183 void mesh_k4(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){
184     mesh_k4_callback = callback;
185     mesh_k4_arg      = callback_arg;
186     mesh_k4_n        = n;
187     mesh_k4_result   = result;
188     btstack_crypto_aes128_cmac_message(request, mesh_salt_smk4, 16, mesh_k4_n, mesh_k4_temp, mesh_k4_temp_callback, request);
189 }
190 
191 // mesh virtual address hash - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_virtual_address_t struct
192 
193 static uint8_t mesh_salt_vtad[] = { 0xce, 0xf7, 0xfa, 0x9d, 0xc4, 0x7b, 0xaf, 0x5d, 0xaa, 0xee, 0xd1, 0x94, 0x06, 0x09, 0x4f, 0x37, };
194 static void *  mesh_virtual_address_arg;
195 static void (* mesh_virtual_address_callback)(void * arg);
196 static uint16_t * mesh_virtual_address_hash;
197 static uint8_t mesh_virtual_address_temp[16];
198 
199 static void mesh_virtual_address_temp_callback(void * arg){
200     UNUSED(arg);
201     uint16_t addr = (big_endian_read_16(mesh_virtual_address_temp, 14) & 0x3fff) | 0x8000;
202     *mesh_virtual_address_hash = addr;
203     (*mesh_virtual_address_callback)(mesh_virtual_address_arg);
204 }
205 
206 void mesh_virtual_address(btstack_crypto_aes128_cmac_t * request, const uint8_t * label_uuid, uint16_t * addr, void (* callback)(void * arg), void * callback_arg){
207     mesh_virtual_address_callback  = callback;
208     mesh_virtual_address_arg       = callback_arg;
209     mesh_virtual_address_hash      = addr;
210     btstack_crypto_aes128_cmac_message(request, mesh_salt_vtad, 16, label_uuid, mesh_virtual_address_temp, mesh_virtual_address_temp_callback, request);
211 }
212 
213 //
214 static void *  mesh_network_key_derive_arg;
215 static void (* mesh_network_key_derive_callback)(void * arg);
216 static mesh_network_key_t * mesh_network_key_derive_key;
217 
218 // AES-CMAC_ZERO('nhbk')
219 static const uint8_t mesh_salt_nhbk[] = {
220         0x2c, 0x24, 0x61, 0x9a, 0xb7, 0x93, 0xc1, 0x23, 0x3f, 0x6e, 0x22, 0x67, 0x38, 0x39, 0x3d, 0xec, };
221 
222 // AES-CMAC_ZERO('nkik')
223 static const uint8_t mesh_salt_nkik[] = {
224         0xF8, 0x79, 0x5A, 0x1A, 0xAB, 0xF1, 0x82, 0xE4, 0xF1, 0x63, 0xD8, 0x6E, 0x24, 0x5E, 0x19, 0xF4};
225 
226 static const uint8_t id128_tag[] = { 'i', 'd', '1', '2', '8', 0x01};
227 
228 // k2: NID (7), EncryptionKey (128), PrivacyKey (128)
229 static uint8_t k2_result[33];
230 
231 static void mesh_network_key_derive_network_id_calculated(void * arg) {
232     UNUSED(arg);
233     // done
234     (*mesh_network_key_derive_callback)(mesh_network_key_derive_arg);
235 }
236 
237 static void mesh_network_key_derive_k2_calculated(void * arg){
238     // store
239     mesh_network_key_derive_key->nid = k2_result[0];
240     (void)memcpy(mesh_network_key_derive_key->encryption_key, &k2_result[1],
241                  16);
242     (void)memcpy(mesh_network_key_derive_key->privacy_key, &k2_result[17], 16);
243 
244     // calculate Network ID / k3
245     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
246     mesh_k3(request, mesh_network_key_derive_key->net_key, mesh_network_key_derive_key->network_id, &mesh_network_key_derive_network_id_calculated, request);
247 }
248 
249 static void mesh_network_key_derive_identity_key_calculated(void *arg) {
250     // calc k2
251     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
252     mesh_k2(request, mesh_network_key_derive_key->net_key, k2_result, &mesh_network_key_derive_k2_calculated, request);
253 }
254 
255 static void mesh_network_key_derive_beacon_key_calculated(void *arg){
256     // calc identity key
257     btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg;
258     mesh_k1(request, mesh_network_key_derive_key->net_key, 16, mesh_salt_nkik, id128_tag, sizeof(id128_tag),
259             mesh_network_key_derive_key->identity_key, &mesh_network_key_derive_identity_key_calculated, request);
260 }
261 
262 void mesh_network_key_derive(btstack_crypto_aes128_cmac_t * request, mesh_network_key_t * network_key, void (* callback)(void * arg), void * callback_arg){
263     mesh_network_key_derive_callback = callback;
264     mesh_network_key_derive_arg = callback_arg;
265     mesh_network_key_derive_key = network_key;
266 
267     // calc k1 using
268     mesh_k1(request, mesh_network_key_derive_key->net_key, 16, mesh_salt_nhbk, id128_tag, sizeof(id128_tag),
269             mesh_network_key_derive_key->beacon_key, &mesh_network_key_derive_beacon_key_calculated, request);
270 }
271 
272 void mesh_transport_key_calc_aid(btstack_crypto_aes128_cmac_t * request, mesh_transport_key_t * app_key, void (* callback)(void * arg), void * callback_arg){
273     mesh_k4(request, app_key->key, &app_key->aid, callback, callback_arg);
274 }
275 
276