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 MATTHIAS 24 * RINGWALD 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 <stdint.h> 41 #include <string.h> 42 #include "btstack_debug.h" 43 #include "btstack_util.h" 44 #include "mesh_crypto.h" 45 46 // mesh k1 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k1_t struct 47 static uint8_t mesh_k1_temp[16]; 48 static void (* mesh_k1_callback)(void * arg); 49 static void * mesh_k1_arg; 50 static const uint8_t * mesh_k1_p; 51 static uint16_t mesh_k1_p_len; 52 static uint8_t * mesh_k1_result; 53 54 static void mesh_k1_temp_calculated(void * arg){ 55 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 56 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); 57 } 58 59 void mesh_k1(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint16_t n_len, const uint8_t * salt, 60 const uint8_t * p, const uint16_t p_len, uint8_t * result, void (* callback)(void * arg), void * callback_arg){ 61 mesh_k1_callback = callback; 62 mesh_k1_arg = callback_arg; 63 mesh_k1_p = p; 64 mesh_k1_p_len = p_len; 65 mesh_k1_result = result; 66 btstack_crypto_aes128_cmac_message(request, salt, n_len, n, mesh_k1_temp, mesh_k1_temp_calculated, request); 67 } 68 69 // mesh k2 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k2_t struct 70 static void (* mesh_k2_callback)(void * arg); 71 static void * mesh_k2_arg; 72 static uint8_t * mesh_k2_result; 73 static uint8_t mesh_k2_t[16]; 74 static uint8_t mesh_k2_t1[18]; 75 static uint8_t mesh_k2_t2[16]; 76 77 static const uint8_t mesh_salt_smk2[] = { 0x4f, 0x90, 0x48, 0x0c, 0x18, 0x71, 0xbf, 0xbf, 0xfd, 0x16, 0x97, 0x1f, 0x4d, 0x8d, 0x10, 0xb1 }; 78 79 static void mesh_k2_callback_d(void * arg){ 80 // btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 81 UNUSED(arg); 82 log_info("PrivacyKey: "); 83 log_info_hexdump(mesh_k2_t, 16); 84 // collect result 85 memcpy(&mesh_k2_result[17], mesh_k2_t2, 16); 86 // 87 (*mesh_k2_callback)(mesh_k2_arg); 88 } 89 static void mesh_k2_callback_c(void * arg){ 90 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 91 log_info("EncryptionKey: "); 92 log_info_hexdump(mesh_k2_t, 16); 93 // collect result 94 memcpy(&mesh_k2_result[1], mesh_k2_t2, 16); 95 // 96 memcpy(mesh_k2_t1, mesh_k2_t2, 16); 97 mesh_k2_t1[16] = 0; // p 98 mesh_k2_t1[17] = 0x03; 99 btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 18, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_d, request); 100 } 101 static void mesh_k2_callback_b(void * arg){ 102 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 103 log_info("NID: 0x%02x\n", mesh_k2_t2[15] & 0x7f); 104 // collect result 105 mesh_k2_result[0] = mesh_k2_t2[15] & 0x7f; 106 // 107 memcpy(mesh_k2_t1, mesh_k2_t2, 16); 108 mesh_k2_t1[16] = 0; // p 109 mesh_k2_t1[17] = 0x02; 110 btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 18, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_c, request); 111 } 112 static void mesh_k2_callback_a(void * arg){ 113 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 114 log_info("T:"); 115 log_info_hexdump(mesh_k2_t, 16); 116 mesh_k2_t1[0] = 0; // p 117 mesh_k2_t1[1] = 0x01; 118 btstack_crypto_aes128_cmac_message(request, mesh_k2_t, 2, mesh_k2_t1, mesh_k2_t2, mesh_k2_callback_b, request); 119 } 120 void mesh_k2(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){ 121 mesh_k2_callback = callback; 122 mesh_k2_arg = callback_arg; 123 mesh_k2_result = result; 124 btstack_crypto_aes128_cmac_message(request, mesh_salt_smk2, 16, n, mesh_k2_t, mesh_k2_callback_a, request); 125 } 126 127 128 // mesh k3 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k3_t struct 129 static const uint8_t mesh_k3_tag[5] = { 'i', 'd', '6', '4', 0x01}; 130 static uint8_t mesh_k3_temp[16]; 131 static uint8_t mesh_k3_result128[16]; 132 static void (* mesh_k3_callback)(void * arg); 133 static void * mesh_k3_arg; 134 static const uint8_t * mesh_k3_n; 135 static uint8_t * mesh_k3_result; 136 137 // AES-CMAC_ZERO('smk3') 138 static const uint8_t mesh_salt_smk3[] = { 0x00, 0x36, 0x44, 0x35, 0x03, 0xf1, 0x95, 0xcc, 0x8a, 0x71, 0x6e, 0x13, 0x62, 0x91, 0xc3, 0x02, }; 139 140 static void mesh_k3_result128_calculated(void * arg){ 141 UNUSED(arg); 142 memcpy(mesh_k3_result, &mesh_k3_result128[8], 8); 143 (*mesh_k3_callback)(mesh_k3_arg); 144 } 145 static void mesh_k3_temp_callback(void * arg){ 146 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 147 btstack_crypto_aes128_cmac_message(request, mesh_k3_temp, sizeof(mesh_k3_tag), mesh_k3_tag, mesh_k3_result128, mesh_k3_result128_calculated, request); 148 } 149 void mesh_k3(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){ 150 mesh_k3_callback = callback; 151 mesh_k3_arg = callback_arg; 152 mesh_k3_n = n; 153 mesh_k3_result = result; 154 btstack_crypto_aes128_cmac_message(request, mesh_salt_smk3, 16, mesh_k3_n, mesh_k3_temp, mesh_k3_temp_callback, request); 155 } 156 157 // mesh k4 - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_k4_t struct 158 // k4N 63964771734fbd76e3b40519d1d94a48 159 // k4 SALT 0e9ac1b7cefa66874c97ee54ac5f49be 160 // k4T 921cb4f908cc5932e1d7b059fc163ce6 161 // k4 CMAC(id6|0x01) 5f79cf09bbdab560e7f1ee404fd341a6 162 // AID 26 163 static const uint8_t mesh_k4_tag[4] = { 'i', 'd', '6', 0x01}; 164 static uint8_t mesh_k4_temp[16]; 165 static uint8_t mesh_k4_result128[16]; 166 static void (* mesh_k4_callback)(void * arg); 167 static void * mesh_k4_arg; 168 static const uint8_t * mesh_k4_n; 169 static uint8_t * mesh_k4_result; 170 171 // AES-CMAC_ZERO('smk4') 172 static const uint8_t mesh_salt_smk4[] = { 0x0E, 0x9A, 0xC1, 0xB7, 0xCE, 0xFA, 0x66, 0x87, 0x4C, 0x97, 0xEE, 0x54, 0xAC, 0x5F, 0x49, 0xBE }; 173 static void mesh_k4_result128_calculated(void * arg){ 174 UNUSED(arg); 175 mesh_k4_result[0] = mesh_k4_result128[15] & 0x3f; 176 (*mesh_k4_callback)(mesh_k4_arg); 177 } 178 static void mesh_k4_temp_callback(void * arg){ 179 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 180 btstack_crypto_aes128_cmac_message(request, mesh_k4_temp, sizeof(mesh_k4_tag), mesh_k4_tag, mesh_k4_result128, mesh_k4_result128_calculated, request); 181 } 182 void mesh_k4(btstack_crypto_aes128_cmac_t * request, const uint8_t * n, uint8_t * result, void (* callback)(void * arg), void * callback_arg){ 183 mesh_k4_callback = callback; 184 mesh_k4_arg = callback_arg; 185 mesh_k4_n = n; 186 mesh_k4_result = result; 187 btstack_crypto_aes128_cmac_message(request, mesh_salt_smk4, 16, mesh_k4_n, mesh_k4_temp, mesh_k4_temp_callback, request); 188 } 189 190 // mesh virtual address hash - might get moved to btstack_crypto and all vars go into btstack_crypto_mesh_virtual_address_t struct 191 192 static uint8_t mesh_salt_vtad[] = { 0xce, 0xf7, 0xfa, 0x9d, 0xc4, 0x7b, 0xaf, 0x5d, 0xaa, 0xee, 0xd1, 0x94, 0x06, 0x09, 0x4f, 0x37, }; 193 static void * mesh_virtual_address_arg; 194 static void (* mesh_virtual_address_callback)(void * arg); 195 static uint16_t * mesh_virtual_address_hash; 196 static uint8_t mesh_virtual_address_temp[16]; 197 198 static void mesh_virtual_address_temp_callback(void * arg){ 199 uint16_t addr = (big_endian_read_16(mesh_virtual_address_temp, 14) & 0x3fff) | 0x8000; 200 *mesh_virtual_address_hash = addr; 201 (*mesh_virtual_address_callback)(mesh_virtual_address_arg); 202 } 203 204 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){ 205 mesh_virtual_address_callback = callback; 206 mesh_virtual_address_arg = callback_arg; 207 mesh_virtual_address_hash = addr; 208 btstack_crypto_aes128_cmac_message(request, mesh_salt_vtad, 16, label_uuid, mesh_virtual_address_temp, mesh_virtual_address_temp_callback, request); 209 } 210 211 // 212 static void * mesh_network_key_derive_arg; 213 static void (* mesh_network_key_derive_callback)(void * arg); 214 static mesh_network_key_t * mesh_network_key_derive_key; 215 216 // AES-CMAC_ZERO('nhbk') 217 static const uint8_t mesh_salt_nhbk[] = { 218 0x2c, 0x24, 0x61, 0x9a, 0xb7, 0x93, 0xc1, 0x23, 0x3f, 0x6e, 0x22, 0x67, 0x38, 0x39, 0x3d, 0xec, }; 219 220 // AES-CMAC_ZERO('nkik') 221 static const uint8_t mesh_salt_nkik[] = { 222 0xF8, 0x79, 0x5A, 0x1A, 0xAB, 0xF1, 0x82, 0xE4, 0xF1, 0x63, 0xD8, 0x6E, 0x24, 0x5E, 0x19, 0xF4}; 223 224 static const uint8_t id128_tag[] = { 'i', 'd', '1', '2', '8', 0x01}; 225 226 // k2: NID (7), EncryptionKey (128), PrivacyKey (128) 227 static uint8_t k2_result[33]; 228 229 static void mesh_network_key_derive_network_id_calculated(void * arg) { 230 // done 231 (*mesh_network_key_derive_callback)(mesh_network_key_derive_arg); 232 } 233 234 static void mesh_network_key_derive_k2_calculated(void * arg){ 235 // store 236 mesh_network_key_derive_key->nid = k2_result[0]; 237 memcpy(mesh_network_key_derive_key->encryption_key, &k2_result[1], 16); 238 memcpy(mesh_network_key_derive_key->privacy_key, &k2_result[17], 16); 239 240 // calculate Network ID / k3 241 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 242 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); 243 } 244 245 static void mesh_network_key_derive_identity_key_calculated(void *arg) { 246 // calc k2 247 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 248 mesh_k2(request, mesh_network_key_derive_key->net_key, k2_result, &mesh_network_key_derive_k2_calculated, request); 249 } 250 251 static void mesh_network_key_derive_beacon_key_calculated(void *arg){ 252 // calc identity key 253 btstack_crypto_aes128_cmac_t * request = (btstack_crypto_aes128_cmac_t*) arg; 254 mesh_k1(request, mesh_network_key_derive_key->net_key, 16, mesh_salt_nkik, id128_tag, sizeof(id128_tag), 255 mesh_network_key_derive_key->identity_key, &mesh_network_key_derive_identity_key_calculated, request); 256 } 257 258 void mesh_network_key_derive(btstack_crypto_aes128_cmac_t * request, mesh_network_key_t * network_key, void (* callback)(void * arg), void * callback_arg){ 259 mesh_network_key_derive_callback = callback; 260 mesh_network_key_derive_arg = callback_arg; 261 mesh_network_key_derive_key = network_key; 262 263 // calc k1 using 264 mesh_k1(request, mesh_network_key_derive_key->net_key, 16, mesh_salt_nhbk, id128_tag, sizeof(id128_tag), 265 mesh_network_key_derive_key->beacon_key, &mesh_network_key_derive_beacon_key_calculated, request); 266 } 267 268 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){ 269 mesh_k4(request, app_key->key, &app_key->aid, callback, callback_arg); 270 } 271 272