xref: /btstack/src/mesh/mesh_network.c (revision 9a470f7ba0784e2196ce0e9ef3c35c3c5213f880)
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 
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 < 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 = global_iv_index;
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     // lookup subnet by netkey_index
317     mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(network_pdu->netkey_index);
318     if (!subnet) {
319         mesh_crypto_active = 0;
320         // notify upper layer
321         (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
322         // run again
323         mesh_network_run();
324         return;
325     }
326 
327     // get network key to use for sending
328     current_network_key = mesh_subnet_get_outgoing_network_key(subnet);
329 
330     // get network nonce
331     if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
332         mesh_proxy_create_nonce(network_nonce, network_pdu, global_iv_index);
333 #ifdef LOG_NETWORK
334         printf("TX-ProxyNonce:  ");
335         printf_hexdump(network_nonce, 13);
336 #endif
337     } else {
338         mesh_network_create_nonce(network_nonce, network_pdu, global_iv_index);
339 #ifdef LOG_NETWORK
340         printf("TX-NetworkNonce:  ");
341         printf_hexdump(network_nonce, 13);
342 #endif
343     }
344 
345 #ifdef LOG_NETWORK
346    printf("TX-EncryptionKey: ");
347     printf_hexdump(current_network_key->encryption_key, 16);
348 #endif
349 
350     // start ccm
351     uint8_t cypher_len  = network_pdu->len - 7;
352     uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4;
353     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
354     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);
355 }
356 
357 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER)
358 static void mesh_network_relay_message(mesh_network_pdu_t * network_pdu){
359     uint8_t ctl_ttl     = network_pdu->data[1];
360     uint8_t ctl         = ctl_ttl & 0x80;
361     uint8_t ttl         = ctl_ttl & 0x7f;
362     uint8_t net_mic_len = ctl ? 8 : 4;
363 
364     // prepare pdu for resending
365     network_pdu->len    -= net_mic_len;
366     network_pdu->data[1] = (ctl << 7) | (ttl - 1);
367     network_pdu->flags |= MESH_NETWORK_PDU_FLAGS_RELAY;
368 
369     // queue up
370     network_pdu->callback = &mesh_network_send_d;
371     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
372 }
373 #endif
374 
375 void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu){
376 
377 #if defined(ENABLE_MESH_RELAY) || defined (ENABLE_MESH_PROXY_SERVER)
378 
379     // check if address does not matches elements on our node and TTL >= 2
380     uint16_t src     = mesh_network_src(network_pdu);
381     uint8_t  ttl     = mesh_network_ttl(network_pdu);
382     if (((src < mesh_network_primary_address) || (src > (mesh_network_primary_address + mesh_network_num_elements))) && (ttl >= 2)){
383 
384         if ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0){
385 
386             // message received via ADV bearer are relayed:
387 
388 #ifdef ENABLE_MESH_RELAY
389             if (mesh_foundation_relay_get() != 0){
390                 // - to ADV bearer, if Relay supported and enabled
391                 mesh_network_relay_message(network_pdu);
392                 mesh_network_run();
393                 return;
394             }
395 #endif
396 
397 #ifdef ENABLE_MESH_PROXY_SERVER
398             if (mesh_foundation_gatt_proxy_get() != 0){
399                 // - to GATT bearer, if Proxy supported and enabled
400                 mesh_network_relay_message(network_pdu);
401                 mesh_network_run();
402                 return;
403             }
404 #endif
405 
406         } else {
407 
408             // messages received via GATT bearer are relayed:
409 
410 #ifdef ENABLE_MESH_PROXY_SERVER
411             if (mesh_foundation_gatt_proxy_get() != 0){
412                 // - to ADV bearer, if Proxy supported and enabled
413                 mesh_network_relay_message(network_pdu);
414                 mesh_network_run();
415                 return;
416             }
417 #endif
418 
419         }
420     }
421 #endif
422 
423     // otherwise, we're done
424     btstack_memory_mesh_network_pdu_free(network_pdu);
425 }
426 
427 static void process_network_pdu_done(void){
428     btstack_memory_mesh_network_pdu_free(network_pdu_in_validation);
429     network_pdu_in_validation = NULL;
430     mesh_crypto_active = 0;
431 
432     mesh_network_run();
433 }
434 
435 static void process_network_pdu_validate_d(void * arg){
436     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
437 
438     uint8_t ctl_ttl     = network_pdu->data[1];
439     uint8_t ctl         = ctl_ttl >> 7;
440     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
441 
442     // store NetMIC
443     uint8_t net_mic[8];
444     btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic);
445 #ifdef LOG_NETWORK
446     printf("RX-NetMIC: ");
447     printf_hexdump(net_mic, net_mic_len);
448 #endif
449     // store in pdu
450     memcpy(&network_pdu->data[network_pdu->len-net_mic_len], net_mic, net_mic_len);
451 
452 #ifdef LOG_NETWORK
453     uint8_t cypher_len  = network_pdu->len - 9 - net_mic_len;
454     printf("RX-Decrypted DST/TransportPDU: ");
455     printf_hexdump(&network_pdu->data[7], 2 + cypher_len);
456 
457     printf("RX-Decrypted: ");
458     printf_hexdump(network_pdu->data, network_pdu->len);
459 #endif
460 
461     // validate network mic
462     if (memcmp(net_mic, &network_pdu_in_validation->data[network_pdu->len-net_mic_len], net_mic_len) != 0){
463         // fail
464         printf("RX-NetMIC mismatch, try next key\n");
465         process_network_pdu_validate(network_pdu);
466         return;
467     }
468 
469     // remove NetMIC from payload
470     network_pdu->len -= net_mic_len;
471 
472 #ifdef LOG_NETWORK
473     // match
474     printf("RX-NetMIC matches\n");
475     printf("RX-TTL: 0x%02x\n", network_pdu->data[1] & 0x7f);
476 #endif
477 
478     // set netkey_index
479     network_pdu->netkey_index = current_network_key->netkey_index;
480 
481     if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
482 
483         // no additional checks for proxy messages
484         (*mesh_network_proxy_message_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu);
485 
486     } else {
487 
488         // validate src/dest addresses
489         uint16_t src = big_endian_read_16(network_pdu->data, 5);
490         uint16_t dst = big_endian_read_16(network_pdu->data, 7);
491         int valid = mesh_network_addresses_valid(ctl, src, dst);
492         if (!valid){
493             printf("RX Address invalid\n");
494             btstack_memory_mesh_network_pdu_free(network_pdu);
495             process_network_pdu_done();
496             return;
497         }
498 
499         // check cache
500         uint32_t hash = mesh_network_cache_hash(network_pdu);
501 #ifdef LOG_NETWORK
502         printf("RX-Hash: %08x\n", hash);
503 #endif
504         if (mesh_network_cache_find(hash)){
505             // found in cache, drop
506             printf("Found in cache -> drop packet\n");
507             btstack_memory_mesh_network_pdu_free(network_pdu);
508             process_network_pdu_done();
509             return;
510         }
511 
512         // store in network cache
513         mesh_network_cache_add(hash);
514 
515         // forward to lower transport layer. message is freed by call to mesh_network_message_processed_by_upper_layer
516         (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu);
517     }
518 
519     // done
520     process_network_pdu_done();
521 }
522 
523 static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){
524     // get IV Index and IVI
525     uint32_t iv_index = global_iv_index;
526     int ivi = network_pdu->data[0] >> 7;
527 
528     // if least significant bit differs, use previous IV Index
529     if ((iv_index & 1 ) ^ ivi){
530         iv_index--;
531 #ifdef LOG_NETWORK
532         printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index);
533 #endif
534     }
535     return iv_index;
536 }
537 
538 static void process_network_pdu_validate_b(void * arg){
539     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
540 
541 #ifdef LOG_NETWORK
542     printf("RX-PECB: ");
543     printf_hexdump(obfuscation_block, 6);
544 #endif
545 
546     // de-obfuscate
547     unsigned int i;
548     for (i=0;i<6;i++){
549         network_pdu->data[1+i] = network_pdu_in_validation->data[1+i] ^ obfuscation_block[i];
550     }
551 
552     uint32_t iv_index = iv_index_for_pdu(network_pdu);
553 
554     if (network_pdu->flags & MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION){
555         // create network nonce
556         mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index);
557 #ifdef LOG_NETWORK
558         printf("RX-Proxy Nonce: ");
559         printf_hexdump(network_nonce, 13);
560 #endif
561     } else {
562         // create network nonce
563         mesh_network_create_nonce(network_nonce, network_pdu, iv_index);
564 #ifdef LOG_NETWORK
565         printf("RX-Network Nonce: ");
566         printf_hexdump(network_nonce, 13);
567 #endif
568     }
569 
570     //
571     uint8_t ctl_ttl     = network_pdu->data[1];
572     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
573     uint8_t cypher_len  = network_pdu->len - 7 - net_mic_len;
574 
575 #ifdef LOG_NETWORK
576     printf("RX-Cyper len %u, mic len %u\n", cypher_len, net_mic_len);
577 
578     printf("RX-Encryption Key: ");
579     printf_hexdump(current_network_key->encryption_key, 16);
580 
581 #endif
582 
583     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
584     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);
585 }
586 
587 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu){
588     if (!mesh_network_key_nid_iterator_has_more(&validation_network_key_it)){
589         printf("No valid network key found\n");
590         btstack_memory_mesh_network_pdu_free(network_pdu);
591         process_network_pdu_done();
592         return;
593     }
594 
595     current_network_key = mesh_network_key_nid_iterator_get_next(&validation_network_key_it);
596 
597     // calc PECB
598     uint32_t iv_index = iv_index_for_pdu(network_pdu);
599     memset(encryption_block, 0, 5);
600     big_endian_store_32(encryption_block, 5, iv_index);
601     memcpy(&encryption_block[9], &network_pdu_in_validation->data[7], 7);
602     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);
603 }
604 
605 
606 static void process_network_pdu(mesh_network_pdu_t * network_pdu){
607     //
608     uint8_t nid_ivi = network_pdu_in_validation->data[0];
609 
610     // setup pdu object
611     network_pdu->data[0] = nid_ivi;
612     network_pdu->len     = network_pdu_in_validation->len;
613     network_pdu->flags   = network_pdu_in_validation->flags;
614 
615     // init provisioning data iterator
616     uint8_t nid = nid_ivi & 0x7f;
617     // uint8_t iv_index = network_pdu_data[0] >> 7;
618     mesh_network_key_nid_iterator_init(&validation_network_key_it, nid);
619 
620     process_network_pdu_validate(network_pdu);
621 }
622 
623 // static void mesh_network_encrypt_and_obfuscate(mesh_network_pdu_t * network_pdu, void (*callback)(mesh_network_pdu_t * network_pdu)){
624 //     network_pdu->callback = callback;
625 // }
626 
627 static void mesh_network_run(void){
628     if (!btstack_linked_list_empty(&network_pdus_outgoing)){
629         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing);
630 
631 #ifdef ENABLE_MESH_GATT_BEARER
632         // request to send via gatt if:
633         // proxy active and connected
634         // packet wasn't received via gatt bearer
635         printf("mesh_network_run: pdu %p, proxy %u, con handle %4x\n", network_pdu, mesh_foundation_gatt_proxy_get(), gatt_bearer_con_handle);
636         if (network_pdu != NULL &&
637             (mesh_foundation_gatt_proxy_get() != 0) &&
638             (gatt_bearer_con_handle != HCI_CON_HANDLE_INVALID) &&
639             ((network_pdu->flags & MESH_NETWORK_PDU_FLAGS_GATT_BEARER) == 0)
640         ){
641             gatt_bearer_network_pdu = network_pdu;
642             network_pdu = NULL;
643             gatt_bearer_request_can_send_now_for_network_pdu();
644         }
645 #endif
646 #ifdef ENABLE_MESH_ADV_BEARER
647          // request to send via adv
648         if (network_pdu != NULL){
649             adv_bearer_network_pdu = network_pdu;
650             network_pdu = NULL;
651             adv_bearer_request_can_send_now_for_network_pdu();
652         }
653 #endif
654         if (network_pdu !=  NULL){
655             // notify upper layer
656             (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
657         }
658     }
659 
660     if (mesh_crypto_active) return;
661 
662     if (!btstack_linked_list_empty(&network_pdus_received)){
663         mesh_network_pdu_t * decode_pdu = mesh_network_pdu_get();
664         if (!decode_pdu) return;
665         // get encoded network pdu and start processing
666         mesh_crypto_active = 1;
667         network_pdu_in_validation = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_received);
668         process_network_pdu(decode_pdu);
669         return;
670     }
671 
672     if (!btstack_linked_list_empty(&network_pdus_queued)){
673         // get queued network pdu and start processing
674         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_queued);
675         mesh_network_send_a(network_pdu);
676         return;
677     }
678 }
679 
680 #ifdef ENABLE_MESH_ADV_BEARER
681 static void mesh_adv_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
682     mesh_network_pdu_t * network_pdu;
683 
684     switch (packet_type){
685         case MESH_NETWORK_PACKET:
686             // check len. minimal transport PDU len = 1, 32 bit NetMIC -> 13 bytes
687             if (size < 13) break;
688 
689 #ifdef LOG_NETWORK
690             printf("received network pdu from adv (len %u): ", size);
691             printf_hexdump(packet, size);
692 #endif
693             mesh_network_received_message(packet, size, 0);
694             break;
695 
696         case HCI_EVENT_PACKET:
697             switch(packet[0]){
698                 case HCI_EVENT_MESH_META:
699                     switch(packet[2]){
700                         case MESH_SUBEVENT_CAN_SEND_NOW:
701                             if (adv_bearer_network_pdu == NULL) break;
702 #ifdef LOG_NETWORK
703                             printf("TX-E-NetworkPDU (%p): ", adv_bearer_network_pdu);
704                             printf_hexdump(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len);
705 #endif
706                             adv_bearer_send_network_pdu(adv_bearer_network_pdu->data, adv_bearer_network_pdu->len);
707                             network_pdu = adv_bearer_network_pdu;
708                             adv_bearer_network_pdu = NULL;
709 
710                             // notify upper layer
711                             (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
712 
713                             // check if more to send
714                             mesh_network_run();
715                             break;
716                         default:
717                             break;
718                     }
719                     break;
720                 default:
721                     break;
722             }
723             break;
724     }
725 }
726 #endif
727 
728 #ifdef ENABLE_MESH_GATT_BEARER
729 static void mesh_network_gatt_bearer_outgoing_complete(void){
730 
731     if (gatt_bearer_network_pdu == NULL) return;
732 
733 #ifdef ENABLE_MESH_ADV_BEARER
734     // forward to adv bearer
735     adv_bearer_network_pdu = gatt_bearer_network_pdu;
736     gatt_bearer_network_pdu = NULL;
737     adv_bearer_request_can_send_now_for_network_pdu();
738     return;
739 #endif
740 
741     // done, notify upper layer
742      mesh_network_pdu_t * network_pdu = gatt_bearer_network_pdu;
743     gatt_bearer_network_pdu = NULL;
744     (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
745 }
746 
747 static void mesh_network_gatt_bearer_handle_network_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
748     switch (packet_type){
749         case MESH_PROXY_DATA_PACKET:
750             if (mesh_foundation_gatt_proxy_get() == 0) break;
751 #ifdef LOG_NETWORK
752             printf("received network pdu from gatt (len %u): ", size);
753             printf_hexdump(packet, size);
754 #endif
755             mesh_network_received_message(packet, size, MESH_NETWORK_PDU_FLAGS_GATT_BEARER);
756             break;
757         case HCI_EVENT_PACKET:
758             switch (hci_event_packet_get_type(packet)){
759                 case HCI_EVENT_MESH_META:
760                     switch (hci_event_mesh_meta_get_subevent_code(packet)){
761                         case MESH_SUBEVENT_PROXY_CONNECTED:
762                             gatt_bearer_con_handle = mesh_subevent_proxy_connected_get_con_handle(packet);
763                             break;
764                         case MESH_SUBEVENT_PROXY_DISCONNECTED:
765                             gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
766                             mesh_network_gatt_bearer_outgoing_complete();
767                             break;
768                         case MESH_SUBEVENT_CAN_SEND_NOW:
769                             if (gatt_bearer_network_pdu == NULL) break;
770 #ifdef LOG_NETWORK
771                             printf("G-TX-E-NetworkPDU (%p): ", gatt_bearer_network_pdu);
772                             printf_hexdump(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len);
773 #endif
774                             gatt_bearer_send_network_pdu(gatt_bearer_network_pdu->data, gatt_bearer_network_pdu->len);
775                             break;
776 
777                         case MESH_SUBEVENT_MESSAGE_SENT:
778                             mesh_network_gatt_bearer_outgoing_complete();
779                             break;
780                         default:
781                             break;
782                     }
783                     break;
784                 default:
785                     break;
786             }
787             break;
788         default:
789             break;
790     }
791 }
792 #endif
793 
794 #ifdef ENABLE_MESH_GATT_BEARER
795 static void mesh_netework_gatt_bearer_handle_proxy_configuration(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
796     switch (packet_type){
797         case MESH_PROXY_DATA_PACKET:
798             mesh_network_process_proxy_configuration_message(packet, size);
799             break;
800         case HCI_EVENT_PACKET:
801             switch (hci_event_packet_get_type(packet)){
802                 case HCI_EVENT_MESH_META:
803                     switch (hci_event_mesh_meta_get_subevent_code(packet)){
804                         case MESH_SUBEVENT_CAN_SEND_NOW:
805                             // forward to higher layer
806                             (*mesh_network_proxy_message_handler)(MESH_NETWORK_CAN_SEND_NOW, NULL);
807                             break;
808                         default:
809                             break;
810                     }
811                     break;
812                 default:
813                     break;
814             }
815             break;
816         default:
817             break;
818     }
819 }
820 #endif
821 
822 void mesh_network_init(void){
823 #ifdef ENABLE_MESH_ADV_BEARER
824     adv_bearer_register_for_network_pdu(&mesh_adv_bearer_handle_network_event);
825 #endif
826 #ifdef ENABLE_MESH_GATT_BEARER
827     gatt_bearer_con_handle = HCI_CON_HANDLE_INVALID;
828     gatt_bearer_register_for_network_pdu(&mesh_network_gatt_bearer_handle_network_event);
829     gatt_bearer_register_for_mesh_proxy_configuration(&mesh_netework_gatt_bearer_handle_proxy_configuration);
830 #endif
831 }
832 
833 void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
834     mesh_network_higher_layer_handler = packet_handler;
835 }
836 
837 void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
838     mesh_network_proxy_message_handler = packet_handler;
839 }
840 
841 void mesh_network_set_primary_element_address(uint16_t addr){
842     mesh_network_primary_address = addr;
843     mesh_network_num_elements = 1;
844 }
845 
846 void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len, uint8_t flags){
847     // verify len
848     if (pdu_len > 29) return;
849 
850     // allocate network_pdu
851     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
852     if (!network_pdu) return;
853 
854     // store data
855     memcpy(network_pdu->data, pdu_data, pdu_len);
856     network_pdu->len = pdu_len;
857     network_pdu->flags = flags;
858 
859     // add to list and go
860     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
861     mesh_network_run();
862 
863 }
864 
865 void mesh_network_process_proxy_configuration_message(const uint8_t * pdu_data, uint8_t pdu_len){
866     // verify len
867     if (pdu_len > 29) return;
868 
869     // allocate network_pdu
870     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
871     if (!network_pdu) return;
872 
873     // store data
874     memcpy(network_pdu->data, pdu_data, pdu_len);
875     network_pdu->len = pdu_len;
876     network_pdu->flags = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION; // Network PDU
877 
878     // add to list and go
879     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
880     mesh_network_run();
881 }
882 
883 void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu){
884 #ifdef LOG_NETWORK
885     printf("TX-A-NetworkPDU (%p): ", network_pdu);
886     printf_hexdump(network_pdu->data, network_pdu->len);
887 #endif
888 
889     if (network_pdu->len > 29){
890         printf("too long, %u\n", network_pdu->len);
891         return;
892     }
893 
894     // setup callback
895     network_pdu->callback = &mesh_network_send_d;
896     network_pdu->flags    = 0;
897 
898     // queue up
899     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
900 
901     // go
902     mesh_network_run();
903 }
904 
905 void mesh_network_encrypt_proxy_configuration_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback)){
906     printf("ProxyPDU(unencrypted): ");
907     printf_hexdump(network_pdu->data, network_pdu->len);
908 
909     // setup callback
910     network_pdu->callback = callback;
911     network_pdu->flags    = MESH_NETWORK_PDU_FLAGS_PROXY_CONFIGURATION;
912 
913     // queue up
914     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
915 
916     // go
917     mesh_network_run();
918 }
919 
920 /*
921  * @brief Setup network pdu header
922  * @param netkey_index
923  * @param ctl
924  * @param ttl
925  * @param seq
926  * @param dest
927  */
928 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){
929     memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
930     // set netkey_index
931     network_pdu->netkey_index = netkey_index;
932     // setup header
933     network_pdu->data[network_pdu->len++] = (global_iv_index << 7) |  nid;
934     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
935     network_pdu->data[network_pdu->len++] = ctl_ttl;
936     big_endian_store_24(network_pdu->data, 2, seq);
937     network_pdu->len += 3;
938     big_endian_store_16(network_pdu->data, network_pdu->len, src);
939     network_pdu->len += 2;
940     big_endian_store_16(network_pdu->data, network_pdu->len, dest);
941     network_pdu->len += 2;
942     memcpy(&network_pdu->data[network_pdu->len], transport_pdu_data, transport_pdu_len);
943     network_pdu->len += transport_pdu_len;
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_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){
955     // set netkey_index
956     network_pdu->netkey_index = netkey_index;
957     // setup header
958     network_pdu->data[0] = (global_iv_index << 7) |  nid;
959     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
960     network_pdu->data[1] = ctl_ttl;
961     big_endian_store_24(network_pdu->data, 2, seq);
962     big_endian_store_16(network_pdu->data, 5, src);
963     big_endian_store_16(network_pdu->data, 7, dest);
964 }
965 
966 void mesh_set_iv_index(uint32_t iv_index){
967     global_iv_index = iv_index;
968 }
969 
970 uint32_t mesh_get_iv_index(void){
971     return  global_iv_index;
972 }
973 
974 // Network PDU Getter
975 uint8_t  mesh_network_nid(mesh_network_pdu_t * network_pdu){
976     return network_pdu->data[0] & 0x7f;
977 }
978 uint16_t mesh_network_control(mesh_network_pdu_t * network_pdu){
979     return network_pdu->data[1] & 0x80;
980 }
981 uint8_t mesh_network_ttl(mesh_network_pdu_t * network_pdu){
982     return network_pdu->data[1] & 0x7f;
983 }
984 uint32_t mesh_network_seq(mesh_network_pdu_t * network_pdu){
985     return big_endian_read_24(network_pdu->data, 2);
986 }
987 uint16_t mesh_network_src(mesh_network_pdu_t * network_pdu){
988     return big_endian_read_16(network_pdu->data, 5);
989 }
990 uint16_t mesh_network_dst(mesh_network_pdu_t * network_pdu){
991     return big_endian_read_16(network_pdu->data, 7);
992 }
993 int mesh_network_segmented(mesh_network_pdu_t * network_pdu){
994     return network_pdu->data[9] & 0x80;
995 }
996 uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu){
997     return &network_pdu->data[9];
998 }
999 uint8_t   mesh_network_pdu_len(mesh_network_pdu_t * network_pdu){
1000     return network_pdu->len - 9;
1001 }
1002 
1003 static void mesh_network_dump_network_pdu(mesh_network_pdu_t * network_pdu){
1004     if (network_pdu){
1005         printf("- %p: ", network_pdu); printf_hexdump(network_pdu->data, network_pdu->len);
1006     }
1007 }
1008 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list){
1009     printf("List: %s:\n", name);
1010     btstack_linked_list_iterator_t it;
1011     btstack_linked_list_iterator_init(&it, list);
1012     while (btstack_linked_list_iterator_has_next(&it)){
1013         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t*) btstack_linked_list_iterator_next(&it);
1014         mesh_network_dump_network_pdu(network_pdu);
1015     }
1016 }
1017 static void mesh_network_reset_network_pdus(btstack_linked_list_t * list){
1018     while (!btstack_linked_list_empty(list)){
1019         mesh_network_pdu_t * pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(list);
1020         btstack_memory_mesh_network_pdu_free(pdu);
1021     }
1022 }
1023 void mesh_network_dump(void){
1024     mesh_network_dump_network_pdus("network_pdus_received", &network_pdus_received);
1025     mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
1026     mesh_network_dump_network_pdus("network_pdus_outgoing", &network_pdus_outgoing);
1027     printf("network_pdu_in_validation: \n");
1028     mesh_network_dump_network_pdu(network_pdu_in_validation);
1029 }
1030 void mesh_network_reset(void){
1031     mesh_network_reset_network_pdus(&network_pdus_received);
1032     mesh_network_reset_network_pdus(&network_pdus_queued);
1033     mesh_network_reset_network_pdus(&network_pdus_outgoing);
1034 }
1035 
1036 // buffer pool
1037 mesh_network_pdu_t * mesh_network_pdu_get(void){
1038     mesh_network_pdu_t * network_pdu = btstack_memory_mesh_network_pdu_get();
1039     if (network_pdu) {
1040         memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
1041         network_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_NETWORK;
1042     }
1043     return network_pdu;
1044 }
1045 
1046 void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu){
1047     btstack_memory_mesh_network_pdu_free(network_pdu);
1048 }
1049 
1050 // Mesh Subnet Management
1051 
1052 void mesh_subnet_add(mesh_subnet_t * subnet){
1053     btstack_linked_list_add_tail(&subnets, (btstack_linked_item_t *) subnet);
1054 }
1055 
1056 void mesh_subnet_remove(mesh_subnet_t * subnet){
1057     btstack_linked_list_remove(&subnets, (btstack_linked_item_t *) subnet);
1058 }
1059 
1060 mesh_subnet_t * mesh_subnet_get_by_netkey_index(uint16_t netkey_index){
1061     btstack_linked_list_iterator_t it;
1062     btstack_linked_list_iterator_init(&it, &subnets);
1063     while (btstack_linked_list_iterator_has_next(&it)){
1064         mesh_subnet_t * item = (mesh_subnet_t *) btstack_linked_list_iterator_next(&it);
1065         if (item->netkey_index == netkey_index) return item;
1066     }
1067     return NULL;
1068 }
1069 
1070 int mesh_subnet_list_count(void){
1071     return btstack_linked_list_count(&subnets);
1072 }
1073 
1074 // mesh network key iterator over all keys
1075 void mesh_subnet_iterator_init(mesh_subnet_iterator_t *it){
1076     btstack_linked_list_iterator_init(&it->it, &subnets);
1077 }
1078 
1079 int mesh_subnet_iterator_has_more(mesh_subnet_iterator_t *it){
1080     return btstack_linked_list_iterator_has_next(&it->it);
1081 }
1082 
1083 mesh_subnet_t * mesh_subnet_iterator_get_next(mesh_subnet_iterator_t *it){
1084     return (mesh_subnet_t *) btstack_linked_list_iterator_next(&it->it);
1085 }
1086 
1087 mesh_network_key_t * mesh_subnet_get_outgoing_network_key(mesh_subnet_t * subnet){
1088     switch (subnet->key_refresh){
1089         case MESH_KEY_REFRESH_SECOND_PHASE:
1090             return subnet->new_key;
1091         case MESH_KEY_REFRESH_NOT_ACTIVE:
1092         case MESH_KEY_REFRESH_FIRST_PHASE:
1093         default:
1094             return subnet->old_key;
1095     }
1096 }
1097 
1098 /**
1099  * @brief Update subnet for given netkey index
1100  */
1101 void mesh_subnet_update_for_netkey_index(uint16_t netkey_index){
1102     // find old / new keys
1103     mesh_network_key_t * old_key = NULL;
1104     mesh_network_key_t * new_key = NULL;
1105     mesh_network_key_iterator_t it;
1106     mesh_network_key_iterator_init(&it);
1107     while (mesh_network_key_iterator_has_more(&it)){
1108         mesh_network_key_t * network_key = mesh_network_key_iterator_get_next(&it);
1109         if (network_key->netkey_index != netkey_index) continue;
1110         if (old_key == NULL){
1111             old_key = network_key;
1112             continue;
1113         }
1114         // assign current key depending on key version
1115         if (((int8_t) (network_key->version - new_key->version)) > 0) {
1116             new_key = network_key;
1117         } else {
1118             new_key = old_key;
1119             old_key = network_key;
1120         }
1121     }
1122 
1123     // get subnet
1124     mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index);
1125 
1126     // no keys -> no subnet
1127     if (old_key == NULL) {
1128         if (subnet == NULL) return;
1129         mesh_subnet_remove(subnet);
1130         return;
1131     }
1132 
1133     // create subnet for netkey index if needed
1134     if (subnet == NULL){
1135         subnet = btstack_memory_mesh_subnet_get();
1136         if (subnet == NULL) return;
1137         subnet->netkey_index = netkey_index;
1138     }
1139 
1140     // set keys
1141     subnet->old_key = old_key;
1142     subnet->new_key = new_key;
1143 
1144     // key refresh
1145     if (new_key == NULL){
1146         // single key -> key refresh not active
1147         subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE;
1148     }
1149     else {
1150         // two keys -> at least phase 1
1151         if (subnet->key_refresh == MESH_KEY_REFRESH_NOT_ACTIVE){
1152             subnet->key_refresh = MESH_KEY_REFRESH_FIRST_PHASE;
1153         }
1154     }
1155 
1156     // TODO: advertisement using node id active
1157     // TODO: secure network beacons
1158 }
1159