1 /* 2 * Copyright (C) 2018 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_network.c" 39 40 #include <stdint.h> 41 #include <stdio.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include "mesh/beacon.h" 45 #include "provisioning.h" 46 #include "provisioning_device.h" 47 #include "mesh_keys.h" 48 #include "mesh_foundation.h" 49 #include "btstack_util.h" 50 #include "btstack_debug.h" 51 #include "btstack_event.h" 52 #include "btstack_memory.h" 53 54 #ifdef ENABLE_MESH_ADV_BEARER 55 #include "mesh/adv_bearer.h" 56 #endif 57 58 #ifdef ENABLE_MESH_GATT_BEARER 59 #include "mesh/gatt_bearer.h" 60 #endif 61 62 // configuration 63 #define MESH_NETWORK_CACHE_SIZE 2 64 // #define ENABLE_MESH_RELAY 65 66 // debug config 67 // #define LOG_NETWORK 68 69 // structs 70 71 // globals 72 73 static uint32_t global_iv_index; 74 static int global_iv_update_active; 75 static uint16_t mesh_network_primary_address; 76 static uint16_t mesh_network_num_elements; 77 static void (*mesh_network_higher_layer_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu); 78 static void (*mesh_network_proxy_message_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu); 79 80 #ifdef ENABLE_MESH_GATT_BEARER 81 static hci_con_handle_t gatt_bearer_con_handle; 82 #endif 83 84 // shared send/receive crypto 85 static int mesh_crypto_active; 86 87 // crypto requests 88 static union { 89 btstack_crypto_ccm_t ccm; 90 btstack_crypto_aes128_t aes128; 91 } mesh_network_crypto_request; 92 93 static const mesh_network_key_t * current_network_key; 94 95 // PECB calculation 96 static uint8_t encryption_block[16]; 97 static uint8_t obfuscation_block[16]; 98 99 // Subnets 100 static btstack_linked_list_t subnets; 101 102 // Network Nonce 103 static uint8_t network_nonce[13]; 104 105 // INCOMING // 106 107 // unprocessed network pdu - added by mesh_network_pdus_received_message 108 static btstack_linked_list_t network_pdus_received; 109 110 // in validation 111 static mesh_network_pdu_t * network_pdu_in_validation; 112 static mesh_network_key_iterator_t validation_network_key_it; 113 114 // OUTGOING // 115 116 // Network PDUs queued by mesh_network_send 117 static btstack_linked_list_t network_pdus_queued; 118 119 // Network PDUs ready to send 120 static btstack_linked_list_t network_pdus_outgoing; 121 122 #ifdef ENABLE_MESH_ADV_BEARER 123 static mesh_network_pdu_t * adv_bearer_network_pdu; 124 #endif 125 126 #ifdef ENABLE_MESH_GATT_BEARER 127 static mesh_network_pdu_t * gatt_bearer_network_pdu; 128 #endif 129 130 // mesh network cache - we use 32-bit 'hashes' 131 static uint32_t mesh_network_cache[MESH_NETWORK_CACHE_SIZE]; 132 static int mesh_network_cache_index; 133 134 // prototypes 135 136 static void mesh_network_run(void); 137 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu); 138 139 // network caching 140 static uint32_t mesh_network_cache_hash(mesh_network_pdu_t * network_pdu){ 141 // - The SEQ field is a 24-bit integer that when combined with the IV Index, 142 // shall be a unique value for each new Network PDU originated by this node (=> SRC) 143 // - IV updates only rarely 144 // => 16 bit SRC, 1 bit IVI, 15 bit SEQ 145 uint8_t ivi = network_pdu->data[0] >> 7; 146 uint16_t seq = big_endian_read_16(network_pdu->data, 3); 147 uint16_t src = big_endian_read_16(network_pdu->data, 5); 148 return (src << 16) | (ivi << 15) | (seq & 0x7fff); 149 } 150 151 static int mesh_network_cache_find(uint32_t hash){ 152 int i; 153 for (i = 0; i < MESH_NETWORK_CACHE_SIZE; i++) { 154 if (mesh_network_cache[i] == hash) { 155 return 1; 156 } 157 } 158 return 0; 159 } 160 161 static void mesh_network_cache_add(uint32_t hash){ 162 mesh_network_cache[mesh_network_cache_index++] = hash; 163 if (mesh_network_cache_index >= MESH_NETWORK_CACHE_SIZE){ 164 mesh_network_cache_index = 0; 165 } 166 } 167 168 // common helper 169 int mesh_network_address_unicast(uint16_t addr){ 170 return addr != MESH_ADDRESS_UNSASSIGNED && (addr < 0x8000); 171 } 172 173 int mesh_network_address_virtual(uint16_t addr){ 174 return (addr & 0xC000) == 0x8000; // 0b10xx xxxx xxxx xxxx 175 } 176 177 int mesh_network_address_group(uint16_t addr){ 178 return (addr & 0xC000) == 0xC000; // 0b11xx xxxx xxxx xxxx 179 } 180 181 int mesh_network_address_all_proxies(uint16_t addr){ 182 return addr == MESH_ADDRESS_ALL_PROXIES; 183 } 184 185 int mesh_network_address_all_nodes(uint16_t addr){ 186 return addr == MESH_ADDRESS_ALL_NODES; 187 } 188 189 int mesh_network_address_all_friends(uint16_t addr){ 190 return addr == MESH_ADDRESS_ALL_FRIENDS; 191 } 192 193 int mesh_network_address_all_relays(uint16_t addr){ 194 return addr == MESH_ADDRESS_ALL_RELAYS; 195 } 196 197 int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst){ 198 // printf("CTL: %u\n", ctl); 199 // printf("SRC: %04x\n", src); 200 // printf("DST: %04x\n", dst); 201 if (src == 0){ 202 // printf("SRC Unassigned Addr -> ignore\n"); 203 return 0; 204 } 205 if ((src & 0xC000) == 0x8000){ 206 // printf("SRC Virtual Addr -> ignore\n"); 207 return 0; 208 } 209 if ((src & 0xC000) == 0xC000){ 210 // printf("SRC Group Addr -> ignore\n"); 211 return 0; 212 } 213 if (dst == 0){ 214 // printf("DST Unassigned Addr -> ignore\n"); 215 return 0; 216 } 217 if ( ((dst & 0xC000) == 0x8000) && (ctl == 1)){ 218 // printf("DST Virtual Addr in CONTROL -> ignore\n"); 219 return 0; 220 } 221 if ( (0xFF00 <= dst) && (dst <= 0xfffb) && (ctl == 0) ){ 222 // printf("DST RFU Group Addr in MESSAGE -> ignore\n"); 223 return 0; 224 } 225 // printf("SRC + DST Addr valid\n"); 226 return 1; 227 } 228 229 static void mesh_network_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){ 230 unsigned int pos = 0; 231 nonce[pos++] = 0x0; // Network Nonce 232 memcpy(&nonce[pos], &pdu->data[1], 6); 233 pos += 6; 234 big_endian_store_16(nonce, pos, 0); 235 pos += 2; 236 big_endian_store_32(nonce, pos, iv_index); 237 } 238 239 static void mesh_proxy_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){ 240 unsigned int pos = 0; 241 nonce[pos++] = 0x3; // Proxy Nonce 242 nonce[pos++] = 0; 243 memcpy(&nonce[pos], &pdu->data[2], 5); 244 pos += 5; 245 big_endian_store_16(nonce, pos, 0); 246 pos += 2; 247 big_endian_store_32(nonce, pos, iv_index); 248 } 249 250 // NID/IVI | obfuscated (CTL/TTL, SEQ (24), SRC (16) ), encrypted ( DST(16), TransportPDU), MIC(32 or 64) 251 252 static void mesh_network_send_d(mesh_network_pdu_t * network_pdu){ 253 254 #ifdef LOG_NETWORK 255 printf("TX-D-NetworkPDU (%p): ", network_pdu); 256 printf_hexdump(network_pdu->data, network_pdu->len); 257 #endif 258 259 // add to queue 260 btstack_linked_list_add_tail(&network_pdus_outgoing, (btstack_linked_item_t *) network_pdu); 261 262 // go 263 mesh_network_run(); 264 } 265 266 // new 267 static void mesh_network_send_c(void *arg){ 268 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 269 270 // obfuscate 271 unsigned int i; 272 for (i=0;i<6;i++){ 273 network_pdu->data[1+i] ^= obfuscation_block[i]; 274 } 275 276 #ifdef LOG_NETWORK 277 printf("TX-C-NetworkPDU (%p): ", network_pdu); 278 printf_hexdump(network_pdu->data, network_pdu->len); 279 #endif 280 281 // crypto done 282 mesh_crypto_active = 0; 283 284 // done 285 (network_pdu->callback)(network_pdu); 286 } 287 288 static void mesh_network_send_b(void *arg){ 289 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 290 291 uint32_t iv_index = mesh_get_iv_index_for_tx(); 292 293 // store NetMIC 294 uint8_t net_mic[8]; 295 btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic); 296 297 // store MIC 298 uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4; 299 memcpy(&network_pdu->data[network_pdu->len], net_mic, net_mic_len); 300 network_pdu->len += net_mic_len; 301 302 #ifdef LOG_NETWORK 303 printf("TX-B-NetworkPDU (%p): ", network_pdu); 304 printf_hexdump(network_pdu->data, network_pdu->len); 305 #endif 306 307 // calc PECB 308 memset(encryption_block, 0, 5); 309 big_endian_store_32(encryption_block, 5, iv_index); 310 memcpy(&encryption_block[9], &network_pdu->data[7], 7); 311 btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &mesh_network_send_c, network_pdu); 312 } 313 314 static void mesh_network_send_a(mesh_network_pdu_t * network_pdu){ 315 316 mesh_crypto_active = 1; 317 318 uint32_t iv_index = mesh_get_iv_index_for_tx(); 319 320 // lookup subnet by netkey_index 321 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(network_pdu->netkey_index); 322 if (!subnet) { 323 mesh_crypto_active = 0; 324 // notify upper layer 325 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 326 // run again 327 mesh_network_run(); 328 return; 329 } 330 331 // get network key to use for sending 332 current_network_key = mesh_subnet_get_outgoing_network_key(subnet); 333 334 // get network nonce 335 if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){ 336 mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index); 337 #ifdef LOG_NETWORK 338 printf("TX-ProxyNonce: "); 339 printf_hexdump(network_nonce, 13); 340 #endif 341 } else { 342 mesh_network_create_nonce(network_nonce, network_pdu, iv_index); 343 #ifdef LOG_NETWORK 344 printf("TX-NetworkNonce: "); 345 printf_hexdump(network_nonce, 13); 346 #endif 347 } 348 349 #ifdef LOG_NETWORK 350 printf("TX-EncryptionKey: "); 351 printf_hexdump(current_network_key->encryption_key, 16); 352 #endif 353 354 // start ccm 355 uint8_t cypher_len = network_pdu->len - 7; 356 uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4; 357 btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len); 358 btstack_crypto_ccm_encrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &network_pdu->data[7], &network_pdu->data[7], &mesh_network_send_b, network_pdu); 359 } 360 361 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER) 362 static void mesh_network_relay_message(mesh_network_pdu_t * network_pdu){ 363 uint8_t ctl_ttl = network_pdu->data[1]; 364 uint8_t ctl = ctl_ttl & 0x80; 365 uint8_t ttl = ctl_ttl & 0x7f; 366 uint8_t net_mic_len = ctl ? 8 : 4; 367 368 // prepare pdu for resending 369 network_pdu->len -= net_mic_len; 370 network_pdu->data[1] = (ctl << 7) | (ttl - 1); 371 network_pdu->flags |= MESH_NETWORK_PDU_FLAGS_RELAY; 372 373 // queue up 374 network_pdu->callback = &mesh_network_send_d; 375 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 376 } 377 #endif 378 379 void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu){ 380 381 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER) 382 383 // check if address does not matches elements on our node and TTL >= 2 384 uint16_t src = mesh_network_src(network_pdu); 385 uint8_t ttl = mesh_network_ttl(network_pdu); 386 if (((src < mesh_network_primary_address) || (src > (mesh_network_primary_address + mesh_network_num_elements))) && (ttl >= 2)){ 387 388 if ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0){ 389 390 // message received via ADV bearer are relayed: 391 392 #ifdef ENABLE_MESH_RELAY 393 if (mesh_foundation_relay_get() != 0){ 394 // - to ADV bearer, if Relay supported and enabled 395 mesh_network_relay_message(network_pdu); 396 mesh_network_run(); 397 return; 398 } 399 #endif 400 401 #ifdef ENABLE_MESH_PROXY_SERVER 402 if (mesh_foundation_gatt_proxy_get() != 0){ 403 // - to GATT bearer, if Proxy supported and enabled 404 mesh_network_relay_message(network_pdu); 405 mesh_network_run(); 406 return; 407 } 408 #endif 409 410 } else { 411 412 // messages received via GATT bearer are relayed: 413 414 #ifdef ENABLE_MESH_PROXY_SERVER 415 if (mesh_foundation_gatt_proxy_get() != 0){ 416 // - to ADV bearer, if Proxy supported and enabled 417 mesh_network_relay_message(network_pdu); 418 mesh_network_run(); 419 return; 420 } 421 #endif 422 423 } 424 } 425 #endif 426 427 // otherwise, we're done 428 btstack_memory_mesh_network_pdu_free(network_pdu); 429 } 430 431 static void process_network_pdu_done(void){ 432 btstack_memory_mesh_network_pdu_free(network_pdu_in_validation); 433 network_pdu_in_validation = NULL; 434 mesh_crypto_active = 0; 435 436 mesh_network_run(); 437 } 438 439 static void process_network_pdu_validate_d(void * arg){ 440 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 441 442 uint8_t ctl_ttl = network_pdu->data[1]; 443 uint8_t ctl = ctl_ttl >> 7; 444 uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4; 445 446 // store NetMIC 447 uint8_t net_mic[8]; 448 btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic); 449 #ifdef LOG_NETWORK 450 printf("RX-NetMIC: "); 451 printf_hexdump(net_mic, net_mic_len); 452 #endif 453 // store in pdu 454 memcpy(&network_pdu->data[network_pdu->len-net_mic_len], net_mic, net_mic_len); 455 456 #ifdef LOG_NETWORK 457 uint8_t cypher_len = network_pdu->len - 9 - net_mic_len; 458 printf("RX-Decrypted DST/TransportPDU: "); 459 printf_hexdump(&network_pdu->data[7], 2 + cypher_len); 460 461 printf("RX-Decrypted: "); 462 printf_hexdump(network_pdu->data, network_pdu->len); 463 #endif 464 465 // validate network mic 466 if (memcmp(net_mic, &network_pdu_in_validation->data[network_pdu->len-net_mic_len], net_mic_len) != 0){ 467 // fail 468 printf("RX-NetMIC mismatch, try next key\n"); 469 process_network_pdu_validate(network_pdu); 470 return; 471 } 472 473 // remove NetMIC from payload 474 network_pdu->len -= net_mic_len; 475 476 #ifdef LOG_NETWORK 477 // match 478 printf("RX-NetMIC matches\n"); 479 printf("RX-TTL: 0x%02x\n", network_pdu->data[1] & 0x7f); 480 #endif 481 482 // set netkey_index 483 network_pdu->netkey_index = current_network_key->netkey_index; 484 485 if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){ 486 487 // no additional checks for proxy messages 488 (*mesh_network_proxy_message_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu); 489 490 } else { 491 492 // validate src/dest addresses 493 uint16_t src = big_endian_read_16(network_pdu->data, 5); 494 uint16_t dst = big_endian_read_16(network_pdu->data, 7); 495 int valid = mesh_network_addresses_valid(ctl, src, dst); 496 if (!valid){ 497 printf("RX Address invalid\n"); 498 btstack_memory_mesh_network_pdu_free(network_pdu); 499 process_network_pdu_done(); 500 return; 501 } 502 503 // check cache 504 uint32_t hash = mesh_network_cache_hash(network_pdu); 505 #ifdef LOG_NETWORK 506 printf("RX-Hash: %08x\n", hash); 507 #endif 508 if (mesh_network_cache_find(hash)){ 509 // found in cache, drop 510 printf("Found in cache -> drop packet\n"); 511 btstack_memory_mesh_network_pdu_free(network_pdu); 512 process_network_pdu_done(); 513 return; 514 } 515 516 // store in network cache 517 mesh_network_cache_add(hash); 518 519 // forward to lower transport layer. message is freed by call to mesh_network_message_processed_by_upper_layer 520 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu); 521 } 522 523 // done 524 process_network_pdu_done(); 525 } 526 527 static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){ 528 // get IV Index and IVI 529 uint32_t iv_index = global_iv_index; 530 int ivi = network_pdu->data[0] >> 7; 531 532 // if least significant bit differs, use previous IV Index 533 if ((iv_index & 1 ) ^ ivi){ 534 iv_index--; 535 #ifdef LOG_NETWORK 536 printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index); 537 #endif 538 } 539 return iv_index; 540 } 541 542 static void process_network_pdu_validate_b(void * arg){ 543 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg; 544 545 #ifdef LOG_NETWORK 546 printf("RX-PECB: "); 547 printf_hexdump(obfuscation_block, 6); 548 #endif 549 550 // de-obfuscate 551 unsigned int i; 552 for (i=0;i<6;i++){ 553 network_pdu->data[1+i] = network_pdu_in_validation->data[1+i] ^ obfuscation_block[i]; 554 } 555 556 uint32_t iv_index = iv_index_for_pdu(network_pdu); 557 558 if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){ 559 // create network nonce 560 mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index); 561 #ifdef LOG_NETWORK 562 printf("RX-Proxy Nonce: "); 563 printf_hexdump(network_nonce, 13); 564 #endif 565 } else { 566 // create network nonce 567 mesh_network_create_nonce(network_nonce, network_pdu, iv_index); 568 #ifdef LOG_NETWORK 569 printf("RX-Network Nonce: "); 570 printf_hexdump(network_nonce, 13); 571 #endif 572 } 573 574 // 575 uint8_t ctl_ttl = network_pdu->data[1]; 576 uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4; 577 uint8_t cypher_len = network_pdu->len - 7 - net_mic_len; 578 579 #ifdef LOG_NETWORK 580 printf("RX-Cyper len %u, mic len %u\n", cypher_len, net_mic_len); 581 582 printf("RX-Encryption Key: "); 583 printf_hexdump(current_network_key->encryption_key, 16); 584 585 #endif 586 587 btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len); 588 btstack_crypto_ccm_decrypt_block(&mesh_network_crypto_request.ccm, cypher_len, &network_pdu_in_validation->data[7], &network_pdu->data[7], &process_network_pdu_validate_d, network_pdu); 589 } 590 591 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu){ 592 if (!mesh_network_key_nid_iterator_has_more(&validation_network_key_it)){ 593 printf("No valid network key found\n"); 594 btstack_memory_mesh_network_pdu_free(network_pdu); 595 process_network_pdu_done(); 596 return; 597 } 598 599 current_network_key = mesh_network_key_nid_iterator_get_next(&validation_network_key_it); 600 601 // calc PECB 602 uint32_t iv_index = iv_index_for_pdu(network_pdu); 603 memset(encryption_block, 0, 5); 604 big_endian_store_32(encryption_block, 5, iv_index); 605 memcpy(&encryption_block[9], &network_pdu_in_validation->data[7], 7); 606 btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &process_network_pdu_validate_b, network_pdu); 607 } 608 609 610 static void process_network_pdu(mesh_network_pdu_t * network_pdu){ 611 // 612 uint8_t nid_ivi = network_pdu_in_validation->data[0]; 613 614 // setup pdu object 615 network_pdu->data[0] = nid_ivi; 616 network_pdu->len = network_pdu_in_validation->len; 617 network_pdu->flags = network_pdu_in_validation->flags; 618 619 // init provisioning data iterator 620 uint8_t nid = nid_ivi & 0x7f; 621 // uint8_t iv_index = network_pdu_data[0] >> 7; 622 mesh_network_key_nid_iterator_init(&validation_network_key_it, nid); 623 624 process_network_pdu_validate(network_pdu); 625 } 626 627 // static void mesh_network_encrypt_and_obfuscate(mesh_network_pdu_t * network_pdu, void (*callback)(mesh_network_pdu_t * network_pdu)){ 628 // network_pdu->callback = callback; 629 // } 630 631 static void mesh_network_run(void){ 632 if (!btstack_linked_list_empty(&network_pdus_outgoing)){ 633 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing); 634 635 #ifdef ENABLE_MESH_GATT_BEARER 636 // request to send via gatt if: 637 // proxy active and connected 638 // packet wasn't received via gatt bearer 639 printf("mesh_network_run: pdu %p, proxy %u, con handle %4x\n", network_pdu, mesh_foundation_gatt_proxy_get(), gatt_bearer_con_handle); 640 if (network_pdu != NULL && 641 (mesh_foundation_gatt_proxy_get() != 0) && 642 (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID) && 643 ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0) 644 ){ 645 gatt_bearer_network_pdu = network_pdu; 646 network_pdu = NULL; 647 gatt_bearer_request_can_send_now_for_network_pdu(); 648 } 649 #endif 650 #ifdef ENABLE_MESH_ADV_BEARER 651 // request to send via adv 652 if (network_pdu != NULL){ 653 adv_bearer_network_pdu = network_pdu; 654 network_pdu = NULL; 655 adv_bearer_request_can_send_now_for_network_pdu(); 656 } 657 #endif 658 if (network_pdu != NULL){ 659 // notify upper layer 660 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 661 } 662 } 663 664 if (mesh_crypto_active) return; 665 666 if (!btstack_linked_list_empty(&network_pdus_received)){ 667 mesh_network_pdu_t * decode_pdu = mesh_network_pdu_get(); 668 if (!decode_pdu) return; 669 // get encoded network pdu and start processing 670 mesh_crypto_active = 1; 671 network_pdu_in_validation = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_received); 672 process_network_pdu(decode_pdu); 673 return; 674 } 675 676 if (!btstack_linked_list_empty(&network_pdus_queued)){ 677 // get queued network pdu and start processing 678 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_queued); 679 mesh_network_send_a(network_pdu); 680 return; 681 } 682 } 683 684 #ifdef ENABLE_MESH_ADV_BEARER 685 static void mesh_adv_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 686 mesh_network_pdu_t * network_pdu; 687 688 switch (packet_type){ 689 case MESH_NETWORK_PACKET: 690 // check len. minimal transport PDU len = 1, 32 bit NetMIC -> 13 bytes 691 if (size < 13) break; 692 693 #ifdef LOG_NETWORK 694 printf("received network pdu from adv (len %u): ", size); 695 printf_hexdump(packet, size); 696 #endif 697 mesh_network_received_message(packet, size, 0); 698 break; 699 700 case HCI_EVENT_PACKET: 701 switch(packet[0]){ 702 case HCI_EVENT_MESH_META: 703 switch(packet[2]){ 704 case MESH_SUBEVENT_CAN_SEND_NOW: 705 if (adv_bearer_network_pdu == NULL) break; 706 #ifdef LOG_NETWORK 707 printf("TX-E-NetworkPDU (%p): ", adv_bearer_network_pdu); 708 printf_hexdump(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len); 709 #endif 710 adv_bearer_send_network_pdu(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len); 711 network_pdu = adv_bearer_network_pdu; 712 adv_bearer_network_pdu = NULL; 713 714 // notify upper layer 715 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 716 717 // check if more to send 718 mesh_network_run(); 719 break; 720 default: 721 break; 722 } 723 break; 724 default: 725 break; 726 } 727 break; 728 } 729 } 730 #endif 731 732 #ifdef ENABLE_MESH_GATT_BEARER 733 static void mesh_network_gatt_bearer_outgoing_complete(void){ 734 735 if (gatt_bearer_network_pdu == NULL) return; 736 737 #ifdef ENABLE_MESH_ADV_BEARER 738 // forward to adv bearer 739 adv_bearer_network_pdu = gatt_bearer_network_pdu; 740 gatt_bearer_network_pdu = NULL; 741 adv_bearer_request_can_send_now_for_network_pdu(); 742 return; 743 #endif 744 745 // done, notify upper layer 746 mesh_network_pdu_t * network_pdu = gatt_bearer_network_pdu; 747 gatt_bearer_network_pdu = NULL; 748 (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu); 749 } 750 751 static void mesh_network_gatt_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 752 switch (packet_type){ 753 case MESH_PROXY_DATA_PACKET: 754 if (mesh_foundation_gatt_proxy_get() == 0) break; 755 #ifdef LOG_NETWORK 756 printf("received network pdu from gatt (len %u): ", size); 757 printf_hexdump(packet, size); 758 #endif 759 mesh_network_received_message(packet, size, MESH_NETWORK_PDU_FLAGS_GATT_BEARER); 760 break; 761 case HCI_EVENT_PACKET: 762 switch (hci_event_packet_get_type(packet)){ 763 case HCI_EVENT_MESH_META: 764 switch (hci_event_mesh_meta_get_subevent_code(packet)){ 765 case MESH_SUBEVENT_PROXY_CONNECTED: 766 gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet); 767 break; 768 case MESH_SUBEVENT_PROXY_DISCONNECTED: 769 gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID; 770 mesh_network_gatt_bearer_outgoing_complete(); 771 break; 772 case MESH_SUBEVENT_CAN_SEND_NOW: 773 if (gatt_bearer_network_pdu == NULL) break; 774 #ifdef LOG_NETWORK 775 printf("G-TX-E-NetworkPDU (%p): ", gatt_bearer_network_pdu); 776 printf_hexdump(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len); 777 #endif 778 gatt_bearer_send_network_pdu(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len); 779 break; 780 781 case MESH_SUBEVENT_MESSAGE_SENT: 782 mesh_network_gatt_bearer_outgoing_complete(); 783 break; 784 default: 785 break; 786 } 787 break; 788 default: 789 break; 790 } 791 break; 792 default: 793 break; 794 } 795 } 796 #endif 797 798 #ifdef ENABLE_MESH_GATT_BEARER 799 static void mesh_netework_gatt_bearer_handle_proxy_configuration(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 800 switch (packet_type){ 801 case MESH_PROXY_DATA_PACKET: 802 mesh_network_process_proxy_configuration_message(packet, size); 803 break; 804 case HCI_EVENT_PACKET: 805 switch (hci_event_packet_get_type(packet)){ 806 case HCI_EVENT_MESH_META: 807 switch (hci_event_mesh_meta_get_subevent_code(packet)){ 808 case MESH_SUBEVENT_CAN_SEND_NOW: 809 // forward to higher layer 810 (*mesh_network_proxy_message_handler)(MESH_NETWORK_CAN_SEND_NOW, NULL); 811 break; 812 default: 813 break; 814 } 815 break; 816 default: 817 break; 818 } 819 break; 820 default: 821 break; 822 } 823 } 824 #endif 825 826 void mesh_network_init(void){ 827 #ifdef ENABLE_MESH_ADV_BEARER 828 adv_bearer_register_for_network_pdu(&mesh_adv_bearer_handle_network_event); 829 #endif 830 #ifdef ENABLE_MESH_GATT_BEARER 831 gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID; 832 gatt_bearer_register_for_network_pdu(&mesh_network_gatt_bearer_handle_network_event); 833 gatt_bearer_register_for_mesh_proxy_configuration(&mesh_netework_gatt_bearer_handle_proxy_configuration); 834 #endif 835 } 836 837 void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){ 838 mesh_network_higher_layer_handler = packet_handler; 839 } 840 841 void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){ 842 mesh_network_proxy_message_handler = packet_handler; 843 } 844 845 void mesh_network_set_primary_element_address(uint16_t addr){ 846 mesh_network_primary_address = addr; 847 mesh_network_num_elements = 1; 848 } 849 850 void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len, uint8_t flags){ 851 // verify len 852 if (pdu_len > 29) return; 853 854 // allocate network_pdu 855 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 856 if (!network_pdu) return; 857 858 // store data 859 memcpy(network_pdu->data, pdu_data, pdu_len); 860 network_pdu->len = pdu_len; 861 network_pdu->flags = flags; 862 863 // add to list and go 864 btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu); 865 mesh_network_run(); 866 867 } 868 869 void mesh_network_process_proxy_configuration_message(const uint8_t * pdu_data, uint8_t pdu_len){ 870 // verify len 871 if (pdu_len > 29) return; 872 873 // allocate network_pdu 874 mesh_network_pdu_t * network_pdu = mesh_network_pdu_get(); 875 if (!network_pdu) return; 876 877 // store data 878 memcpy(network_pdu->data, pdu_data, pdu_len); 879 network_pdu->len = pdu_len; 880 network_pdu->flags = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION; // Network PDU 881 882 // add to list and go 883 btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu); 884 mesh_network_run(); 885 } 886 887 void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu){ 888 #ifdef LOG_NETWORK 889 printf("TX-A-NetworkPDU (%p): ", network_pdu); 890 printf_hexdump(network_pdu->data, network_pdu->len); 891 #endif 892 893 if (network_pdu->len > 29){ 894 printf("too long, %u\n", network_pdu->len); 895 return; 896 } 897 898 // setup callback 899 network_pdu->callback = &mesh_network_send_d; 900 network_pdu->flags = 0; 901 902 // queue up 903 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 904 905 // go 906 mesh_network_run(); 907 } 908 909 void mesh_network_encrypt_proxy_configuration_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback)){ 910 printf("ProxyPDU(unencrypted): "); 911 printf_hexdump(network_pdu->data, network_pdu->len); 912 913 // setup callback 914 network_pdu->callback = callback; 915 network_pdu->flags = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION; 916 917 // queue up 918 btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu); 919 920 // go 921 mesh_network_run(); 922 } 923 924 /* 925 * @brief Setup network pdu header 926 * @param netkey_index 927 * @param ctl 928 * @param ttl 929 * @param seq 930 * @param dest 931 */ 932 void mesh_network_setup_pdu(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest, const uint8_t * transport_pdu_data, uint8_t transport_pdu_len){ 933 memset(network_pdu, 0, sizeof(mesh_network_pdu_t)); 934 // set netkey_index 935 network_pdu->netkey_index = netkey_index; 936 // setup header 937 network_pdu->data[network_pdu->len++] = (mesh_get_iv_index_for_tx() << 7) | nid; 938 uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f); 939 network_pdu->data[network_pdu->len++] = ctl_ttl; 940 big_endian_store_24(network_pdu->data, 2, seq); 941 network_pdu->len += 3; 942 big_endian_store_16(network_pdu->data, network_pdu->len, src); 943 network_pdu->len += 2; 944 big_endian_store_16(network_pdu->data, network_pdu->len, dest); 945 network_pdu->len += 2; 946 memcpy(&network_pdu->data[network_pdu->len], transport_pdu_data, transport_pdu_len); 947 network_pdu->len += transport_pdu_len; 948 } 949 950 /* 951 * @brief Setup network pdu header 952 * @param netkey_index 953 * @param ctl 954 * @param ttl 955 * @param seq 956 * @param dest 957 */ 958 void mesh_network_setup_pdu_header(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t nid, uint8_t ctl, uint8_t ttl, uint32_t seq, uint16_t src, uint16_t dest){ 959 // set netkey_index 960 network_pdu->netkey_index = netkey_index; 961 // setup header 962 network_pdu->data[0] = (mesh_get_iv_index_for_tx() << 7) | nid; 963 uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f); 964 network_pdu->data[1] = ctl_ttl; 965 big_endian_store_24(network_pdu->data, 2, seq); 966 big_endian_store_16(network_pdu->data, 5, src); 967 big_endian_store_16(network_pdu->data, 7, dest); 968 } 969 970 void mesh_set_iv_index(uint32_t iv_index){ 971 global_iv_index = iv_index; 972 } 973 974 uint32_t mesh_get_iv_index(void){ 975 return global_iv_index; 976 } 977 978 uint32_t mesh_get_iv_index_for_tx(void){ 979 if (global_iv_update_active){ 980 return global_iv_index - 1; 981 } else { 982 return global_iv_index; 983 } 984 } 985 986 int mesh_iv_update_active(void){ 987 return global_iv_update_active; 988 } 989 990 void mesh_trigger_iv_update(void){ 991 if (global_iv_update_active) return; 992 993 // "A node shall not start an IV Update procedure more often than once every 192 hours." 994 // Unless triggered by user application, it will automatically triggered if sequene numbers are about to roll over 995 996 // "A node shall defer state change from IV Update in Progress to Normal Operation, as defined by this procedure, 997 // when the node has transmitted a Segmented Access message or a Segmented Control message without receiving the 998 // corresponding Segment Acknowledgment messages. The deferred change of the state shall be executed when the appropriate 999 // Segment Acknowledgment message is received or timeout for the delivery of this message is reached. 1000 // 1001 // Note: This requirement is necessary because upon completing the IV Update procedure the sequence number is reset 1002 // to 0x000000 and the SeqAuth value would not be valid." 1003 1004 // set IV Update in Progress 1005 global_iv_update_active = 1; 1006 // increase IV index 1007 global_iv_index++; 1008 } 1009 1010 void mesh_iv_update_completed(void){ 1011 if (!global_iv_update_active) return; 1012 // set Normal mode 1013 global_iv_update_active = 0; 1014 } 1015 1016 void mesh_iv_index_recovered(uint8_t iv_update_active, uint32_t iv_index){ 1017 log_info("mesh_iv_index_recovered: active %u, index %u", iv_update_active, (int) iv_index); 1018 global_iv_index = iv_index; 1019 global_iv_update_active = iv_update_active; 1020 } 1021 1022 // Network PDU Getter 1023 uint8_t mesh_network_nid(mesh_network_pdu_t * network_pdu){ 1024 return network_pdu->data[0] & 0x7f; 1025 } 1026 uint16_t mesh_network_control(mesh_network_pdu_t * network_pdu){ 1027 return network_pdu->data[1] & 0x80; 1028 } 1029 uint8_t mesh_network_ttl(mesh_network_pdu_t * network_pdu){ 1030 return network_pdu->data[1] & 0x7f; 1031 } 1032 uint32_t mesh_network_seq(mesh_network_pdu_t * network_pdu){ 1033 return big_endian_read_24(network_pdu->data, 2); 1034 } 1035 uint16_t mesh_network_src(mesh_network_pdu_t * network_pdu){ 1036 return big_endian_read_16(network_pdu->data, 5); 1037 } 1038 uint16_t mesh_network_dst(mesh_network_pdu_t * network_pdu){ 1039 return big_endian_read_16(network_pdu->data, 7); 1040 } 1041 int mesh_network_segmented(mesh_network_pdu_t * network_pdu){ 1042 return network_pdu->data[9] & 0x80; 1043 } 1044 uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu){ 1045 return &network_pdu->data[9]; 1046 } 1047 uint8_t mesh_network_pdu_len(mesh_network_pdu_t * network_pdu){ 1048 return network_pdu->len - 9; 1049 } 1050 1051 static void mesh_network_dump_network_pdu(mesh_network_pdu_t * network_pdu){ 1052 if (network_pdu){ 1053 printf("- %p: ", network_pdu); printf_hexdump(network_pdu->data, network_pdu->len); 1054 } 1055 } 1056 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list){ 1057 printf("List: %s:\n", name); 1058 btstack_linked_list_iterator_t it; 1059 btstack_linked_list_iterator_init(&it, list); 1060 while (btstack_linked_list_iterator_has_next(&it)){ 1061 mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t*) btstack_linked_list_iterator_next(&it); 1062 mesh_network_dump_network_pdu(network_pdu); 1063 } 1064 } 1065 static void mesh_network_reset_network_pdus(btstack_linked_list_t * list){ 1066 while (!btstack_linked_list_empty(list)){ 1067 mesh_network_pdu_t * pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(list); 1068 btstack_memory_mesh_network_pdu_free(pdu); 1069 } 1070 } 1071 void mesh_network_dump(void){ 1072 mesh_network_dump_network_pdus("network_pdus_received", &network_pdus_received); 1073 mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued); 1074 mesh_network_dump_network_pdus("network_pdus_outgoing", &network_pdus_outgoing); 1075 printf("network_pdu_in_validation: \n"); 1076 mesh_network_dump_network_pdu(network_pdu_in_validation); 1077 } 1078 void mesh_network_reset(void){ 1079 mesh_network_reset_network_pdus(&network_pdus_received); 1080 mesh_network_reset_network_pdus(&network_pdus_queued); 1081 mesh_network_reset_network_pdus(&network_pdus_outgoing); 1082 } 1083 1084 // buffer pool 1085 mesh_network_pdu_t * mesh_network_pdu_get(void){ 1086 mesh_network_pdu_t * network_pdu = btstack_memory_mesh_network_pdu_get(); 1087 if (network_pdu) { 1088 memset(network_pdu, 0, sizeof(mesh_network_pdu_t)); 1089 network_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_NETWORK; 1090 } 1091 return network_pdu; 1092 } 1093 1094 void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu){ 1095 btstack_memory_mesh_network_pdu_free(network_pdu); 1096 } 1097 1098 // Mesh Subnet Management 1099 1100 void mesh_subnet_add(mesh_subnet_t * subnet){ 1101 btstack_linked_list_add_tail(&subnets, (btstack_linked_item_t *) subnet); 1102 } 1103 1104 void mesh_subnet_remove(mesh_subnet_t * subnet){ 1105 btstack_linked_list_remove(&subnets, (btstack_linked_item_t *) subnet); 1106 } 1107 1108 mesh_subnet_t * mesh_subnet_get_by_netkey_index(uint16_t netkey_index){ 1109 btstack_linked_list_iterator_t it; 1110 btstack_linked_list_iterator_init(&it, &subnets); 1111 while (btstack_linked_list_iterator_has_next(&it)){ 1112 mesh_subnet_t * item = (mesh_subnet_t *) btstack_linked_list_iterator_next(&it); 1113 if (item->netkey_index == netkey_index) return item; 1114 } 1115 return NULL; 1116 } 1117 1118 int mesh_subnet_list_count(void){ 1119 return btstack_linked_list_count(&subnets); 1120 } 1121 1122 // mesh network key iterator over all keys 1123 void mesh_subnet_iterator_init(mesh_subnet_iterator_t *it){ 1124 btstack_linked_list_iterator_init(&it->it, &subnets); 1125 } 1126 1127 int mesh_subnet_iterator_has_more(mesh_subnet_iterator_t *it){ 1128 return btstack_linked_list_iterator_has_next(&it->it); 1129 } 1130 1131 mesh_subnet_t * mesh_subnet_iterator_get_next(mesh_subnet_iterator_t *it){ 1132 return (mesh_subnet_t *) btstack_linked_list_iterator_next(&it->it); 1133 } 1134 1135 mesh_network_key_t * mesh_subnet_get_outgoing_network_key(mesh_subnet_t * subnet){ 1136 switch (subnet->key_refresh){ 1137 case MESH_KEY_REFRESH_SECOND_PHASE: 1138 return subnet->new_key; 1139 case MESH_KEY_REFRESH_NOT_ACTIVE: 1140 case MESH_KEY_REFRESH_FIRST_PHASE: 1141 default: 1142 return subnet->old_key; 1143 } 1144 } 1145 1146 /** 1147 * @brief Setup subnet for given netkey index 1148 */ 1149 void mesh_subnet_setup_for_netkey_index(uint16_t netkey_index){ 1150 mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index); 1151 if (subnet != NULL) return; 1152 1153 // find old / new keys 1154 mesh_network_key_t * old_key = NULL; 1155 mesh_network_key_t * new_key = NULL; 1156 mesh_network_key_iterator_t it; 1157 mesh_network_key_iterator_init(&it); 1158 while (mesh_network_key_iterator_has_more(&it)){ 1159 mesh_network_key_t * network_key = mesh_network_key_iterator_get_next(&it); 1160 if (network_key->netkey_index != netkey_index) continue; 1161 if (old_key == NULL){ 1162 old_key = network_key; 1163 continue; 1164 } 1165 // assign current key depending on key version 1166 if (((int8_t) (network_key->version - new_key->version)) > 0) { 1167 new_key = network_key; 1168 } else { 1169 new_key = old_key; 1170 old_key = network_key; 1171 } 1172 } 1173 1174 // create subnet for netkey index 1175 subnet = btstack_memory_mesh_subnet_get(); 1176 if (subnet == NULL) return; 1177 subnet->netkey_index = netkey_index; 1178 mesh_subnet_add(subnet); 1179 1180 // set keys 1181 subnet->old_key = old_key; 1182 subnet->new_key = new_key; 1183 1184 // key refresh 1185 if (new_key == NULL){ 1186 // single key -> key refresh not active 1187 subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; 1188 } 1189 else { 1190 // two keys -> at least phase 1 1191 subnet->key_refresh = MESH_KEY_REFRESH_FIRST_PHASE; 1192 } 1193 } 1194