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