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