xref: /btstack/src/mesh/mesh_network.c (revision 0882d02cd26985658f09856bdb4aedd48004d287)
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