xref: /btstack/src/mesh/mesh_network.c (revision eead582d3ed193b740965124ded54d360b0fd74b)
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 "btstack_util.h"
49 #include "btstack_memory.h"
50 
51 #ifdef ENABLE_MESH_ADV_BEARER
52 #include "mesh/adv_bearer.h"
53 #endif
54 
55 #ifdef ENABLE_MESH_GATT_BEARER
56 #include "mesh/gatt_bearer.h"
57 #endif
58 
59 // configuration
60 #define MESH_NETWORK_CACHE_SIZE 2
61 // #define ENABLE_MESH_RELAY
62 
63 // debug config
64 // #define LOG_NETWORK
65 
66 // structs
67 
68 // globals
69 
70 static uint32_t global_iv_index;
71 static uint16_t mesh_network_primary_address;
72 static uint16_t mesh_network_num_elements;
73 static void (*mesh_network_higher_layer_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu);
74 static void (*mesh_network_proxy_message_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu);
75 
76 // shared send/receive crypto
77 static int mesh_crypto_active;
78 
79 // crypto requests
80 static union {
81     btstack_crypto_ccm_t         ccm;
82     btstack_crypto_aes128_t      aes128;
83 } mesh_network_crypto_request;
84 
85 static const mesh_network_key_t *  current_network_key;
86 
87 // PECB calculation
88 static uint8_t encryption_block[16];
89 static uint8_t obfuscation_block[16];
90 
91 // Network Nonce
92 static uint8_t network_nonce[13];
93 
94 // INCOMING //
95 
96 // unprocessed network pdu - added by mesh_network_pdus_received_message
97 static btstack_linked_list_t        network_pdus_received;
98 
99 // in validation
100 static mesh_network_pdu_t *         network_pdu_in_validation;
101 static mesh_network_key_iterator_t  validation_network_key_it;
102 
103 // OUTGOING //
104 
105 // Network PDUs queued by mesh_network_send
106 static btstack_linked_list_t network_pdus_queued;
107 
108 // Network PDUs ready to send
109 static btstack_linked_list_t network_pdus_outgoing;
110 
111 // Network PDU ready to send via gatt/adv bearer
112 static mesh_network_pdu_t * actual_bearer_network_pdu;
113 
114 // mesh network cache - we use 32-bit 'hashes'
115 static uint32_t mesh_network_cache[MESH_NETWORK_CACHE_SIZE];
116 static int      mesh_network_cache_index;
117 
118 // prototypes
119 
120 static void mesh_network_run(void);
121 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu);
122 
123 // network caching
124 static uint32_t mesh_network_cache_hash(mesh_network_pdu_t * network_pdu){
125     // - The SEQ field is a 24-bit integer that when combined with the IV Index,
126     // shall be a unique value for each new Network PDU originated by this node (=> SRC)
127     // - IV updates only rarely
128     // => 16 bit SRC, 1 bit IVI, 15 bit SEQ
129     uint8_t  ivi = network_pdu->data[0] >> 7;
130     uint16_t seq = big_endian_read_16(network_pdu->data, 3);
131     uint16_t src = big_endian_read_16(network_pdu->data, 5);
132     return (src << 16) | (ivi << 15) | (seq & 0x7fff);
133 }
134 
135 static int mesh_network_cache_find(uint32_t hash){
136     int i;
137     for (i = 0; i < MESH_NETWORK_CACHE_SIZE; i++) {
138         if (mesh_network_cache[i] == hash) {
139             return 1;
140         }
141     }
142     return 0;
143 }
144 
145 static void mesh_network_cache_add(uint32_t hash){
146     mesh_network_cache[mesh_network_cache_index++] = hash;
147     if (mesh_network_cache_index >= MESH_NETWORK_CACHE_SIZE){
148         mesh_network_cache_index = 0;
149     }
150 }
151 
152 // common helper
153 int mesh_network_address_unicast(uint16_t addr){
154     return addr < 0x8000;
155 }
156 
157 int mesh_network_address_virtual(uint16_t addr){
158     return (addr & 0xC000) == 0x8000;   // 0b10xx xxxx xxxx xxxx
159 }
160 
161 int mesh_network_address_group(uint16_t addr){
162     return (addr & 0xC000) == 0xC000;   // 0b11xx xxxx xxxx xxxx
163 }
164 
165 int mesh_network_address_all_proxies(uint16_t addr){
166     return addr == MESH_ADDRESS_ALL_PROXIES;
167 }
168 
169 int mesh_network_address_all_nodes(uint16_t addr){
170     return addr == MESH_ADDRESS_ALL_NODES;
171 }
172 
173 int mesh_network_address_all_friends(uint16_t addr){
174     return addr == MESH_ADDRESS_ALL_FRIENDS;
175 }
176 
177 int mesh_network_address_all_relays(uint16_t addr){
178     return addr == MESH_ADDRESS_ALL_RELAYS;
179 }
180 
181 int mesh_network_addresses_valid(uint8_t ctl, uint16_t src, uint16_t dst){
182     // printf("CTL: %u\n", ctl);
183     // printf("SRC: %04x\n", src);
184     // printf("DST: %04x\n", dst);
185     if (src == 0){
186         // printf("SRC Unassigned Addr -> ignore\n");
187         return 0;
188     }
189     if ((src & 0xC000) == 0x8000){
190         // printf("SRC Virtual Addr -> ignore\n");
191         return 0;
192     }
193     if ((src & 0xC000) == 0xC000){
194         // printf("SRC Group Addr -> ignore\n");
195         return 0;
196     }
197     if (dst == 0){
198         // printf("DST Unassigned Addr -> ignore\n");
199         return 0;
200     }
201     if ( ((dst & 0xC000) == 0x8000) && (ctl == 1)){
202         // printf("DST Virtual Addr in CONTROL -> ignore\n");
203         return 0;
204     }
205     if ( (0xFF00 <= dst) && (dst <= 0xfffb) && (ctl == 0) ){
206         // printf("DST RFU Group Addr in MESSAGE -> ignore\n");
207         return 0;
208     }
209     // printf("SRC + DST Addr valid\n");
210     return 1;
211 }
212 
213 static void mesh_network_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){
214     unsigned int pos = 0;
215     nonce[pos++] = 0x0;      // Network Nonce
216     memcpy(&nonce[pos], &pdu->data[1], 6);
217     pos += 6;
218     big_endian_store_16(nonce, pos, 0);
219     pos += 2;
220     big_endian_store_32(nonce, pos, iv_index);
221 }
222 
223 static void mesh_proxy_create_nonce(uint8_t * nonce, const mesh_network_pdu_t * pdu, uint32_t iv_index){
224     unsigned int pos = 0;
225     nonce[pos++] = 0x3;      // Proxy Nonce
226     nonce[pos++] = 0;
227     memcpy(&nonce[pos], &pdu->data[2], 5);
228     pos += 5;
229     big_endian_store_16(nonce, pos, 0);
230     pos += 2;
231     big_endian_store_32(nonce, pos, iv_index);
232 }
233 
234 // NID/IVI | obfuscated (CTL/TTL, SEQ (24), SRC (16) ), encrypted ( DST(16), TransportPDU), MIC(32 or 64)
235 
236 static void mesh_network_send_d(mesh_network_pdu_t * network_pdu){
237 
238 #ifdef LOG_NETWORK
239     printf("TX-D-NetworkPDU (%p): ", network_pdu);
240     printf_hexdump(network_pdu->data, network_pdu->len);
241 #endif
242 
243     // add to queue
244     btstack_linked_list_add_tail(&network_pdus_outgoing, (btstack_linked_item_t *) network_pdu);
245 
246     // go
247     mesh_network_run();
248 }
249 
250 // new
251 static void mesh_network_send_c(void *arg){
252     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
253 
254     // obfuscate
255     unsigned int i;
256     for (i=0;i<6;i++){
257         network_pdu->data[1+i] ^= obfuscation_block[i];
258     }
259 
260 #ifdef LOG_NETWORK
261     printf("TX-C-NetworkPDU (%p): ", network_pdu);
262     printf_hexdump(network_pdu->data, network_pdu->len);
263 #endif
264 
265     // crypto done
266     mesh_crypto_active = 0;
267 
268     // done
269     (network_pdu->callback)(network_pdu);
270 }
271 
272 static void mesh_network_send_b(void *arg){
273     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
274 
275     uint32_t iv_index = global_iv_index;
276 
277     // store NetMIC
278     uint8_t net_mic[8];
279     btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic);
280 
281     // store MIC
282     uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4;
283     memcpy(&network_pdu->data[network_pdu->len], net_mic, net_mic_len);
284     network_pdu->len += net_mic_len;
285 
286 #ifdef LOG_NETWORK
287     printf("TX-B-NetworkPDU (%p): ", network_pdu);
288     printf_hexdump(network_pdu->data, network_pdu->len);
289 #endif
290 
291     // calc PECB
292     memset(encryption_block, 0, 5);
293     big_endian_store_32(encryption_block, 5, iv_index);
294     memcpy(&encryption_block[9], &network_pdu->data[7], 7);
295     btstack_crypto_aes128_encrypt(&mesh_network_crypto_request.aes128, current_network_key->privacy_key, encryption_block, obfuscation_block, &mesh_network_send_c, network_pdu);
296 }
297 
298 static void mesh_network_send_a(mesh_network_pdu_t * network_pdu){
299 
300     mesh_crypto_active = 1;
301 
302     // lookup network by netkey_index
303     current_network_key = mesh_network_key_list_get(network_pdu->netkey_index);
304     if (!current_network_key) {
305         mesh_crypto_active = 0;
306         // notify upper layer
307         (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
308         // run again
309         mesh_network_run();
310         return;
311     }
312 
313     // get network nonce
314     if (network_pdu->flags & 1){
315         mesh_proxy_create_nonce(network_nonce, network_pdu, global_iv_index);
316 #ifdef LOG_NETWORK
317         printf("TX-ProxyNonce:  ");
318         printf_hexdump(network_nonce, 13);
319 #endif
320     } else {
321         mesh_network_create_nonce(network_nonce, network_pdu, global_iv_index);
322 #ifdef LOG_NETWORK
323         printf("TX-NetworkNonce:  ");
324         printf_hexdump(network_nonce, 13);
325 #endif
326     }
327 
328 #ifdef LOG_NETWORK
329    printf("TX-EncryptionKey: ");
330     printf_hexdump(current_network_key->encryption_key, 16);
331 #endif
332 
333     // start ccm
334     uint8_t cypher_len  = network_pdu->len - 7;
335     uint8_t net_mic_len = network_pdu->data[1] & 0x80 ? 8 : 4;
336     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
337     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);
338 }
339 
340 void mesh_network_message_processed_by_higher_layer(mesh_network_pdu_t * network_pdu){
341 #ifdef ENABLE_MESH_RELAY
342     uint8_t ctl_ttl = network_pdu->data[1];
343     uint8_t ctl     = ctl_ttl >> 7;
344     uint8_t ttl     = ctl_ttl & 0x7f;
345     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
346     uint16_t src    = big_endian_read_16(network_pdu->data, 5);
347 
348     // check if address matches elements on our node and TTL >= 2
349     if (((src < mesh_network_primary_address) || (src > (mesh_network_primary_address + mesh_network_num_elements))) && (ttl >= 2)){
350         // prepare pdu for resending
351         network_pdu->len    -= net_mic_len;
352         network_pdu->data[1] = (ctl << 7) | (ttl - 1);
353 
354         // queue up
355         network_pdu->callback = &mesh_network_send_d;
356         btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
357 
358         // go
359         mesh_network_run();
360 
361         return;
362     }
363 #endif
364     btstack_memory_mesh_network_pdu_free(network_pdu);
365 }
366 
367 static void process_network_pdu_done(void){
368     btstack_memory_mesh_network_pdu_free(network_pdu_in_validation);
369     network_pdu_in_validation = NULL;
370     mesh_crypto_active = 0;
371 
372     mesh_network_run();
373 }
374 
375 static void process_network_pdu_validate_d(void * arg){
376     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
377 
378     uint8_t ctl_ttl     = network_pdu->data[1];
379     uint8_t ctl         = ctl_ttl >> 7;
380     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
381 
382     // store NetMIC
383     uint8_t net_mic[8];
384     btstack_crypto_ccm_get_authentication_value(&mesh_network_crypto_request.ccm, net_mic);
385 #ifdef LOG_NETWORK
386     printf("RX-NetMIC: ");
387     printf_hexdump(net_mic, net_mic_len);
388 #endif
389     // store in pdu
390     memcpy(&network_pdu->data[network_pdu->len-net_mic_len], net_mic, net_mic_len);
391 
392 #ifdef LOG_NETWORK
393     uint8_t cypher_len  = network_pdu->len - 9 - net_mic_len;
394     printf("RX-Decrypted DST/TransportPDU: ");
395     printf_hexdump(&network_pdu->data[7], 2 + cypher_len);
396 
397     printf("RX-Decrypted: ");
398     printf_hexdump(network_pdu->data, network_pdu->len);
399 #endif
400 
401     // validate network mic
402     if (memcmp(net_mic, &network_pdu_in_validation->data[network_pdu->len-net_mic_len], net_mic_len) != 0){
403         // fail
404         printf("RX-NetMIC mismatch, try next key\n");
405         process_network_pdu_validate(network_pdu);
406         return;
407     }
408 
409     // remove NetMIC from payload
410     network_pdu->len -= net_mic_len;
411 
412 #ifdef LOG_NETWORK
413     // match
414     printf("RX-NetMIC matches\n");
415     printf("RX-TTL: 0x%02x\n", network_pdu->data[1] & 0x7f);
416 #endif
417 
418     // set netkey_index
419     network_pdu->netkey_index = current_network_key->netkey_index;
420 
421     if (network_pdu->flags & 1){
422 
423         // no additional checks for proxy messages
424         (*mesh_network_proxy_message_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu);
425 
426     } else {
427 
428         // validate src/dest addresses
429         uint16_t src = big_endian_read_16(network_pdu->data, 5);
430         uint16_t dst = big_endian_read_16(network_pdu->data, 7);
431         int valid = mesh_network_addresses_valid(ctl, src, dst);
432         if (!valid){
433             printf("RX Address invalid\n");
434             btstack_memory_mesh_network_pdu_free(network_pdu);
435             process_network_pdu_done();
436             return;
437         }
438 
439         // check cache
440         uint32_t hash = mesh_network_cache_hash(network_pdu);
441 #ifdef LOG_NETWORK
442         printf("RX-Hash: %08x\n", hash);
443 #endif
444         if (mesh_network_cache_find(hash)){
445             // found in cache, drop
446             printf("Found in cache -> drop packet\n");
447             btstack_memory_mesh_network_pdu_free(network_pdu);
448             process_network_pdu_done();
449             return;
450         }
451 
452         // store in network cache
453         mesh_network_cache_add(hash);
454 
455         // forward to lower transport layer. message is freed by call to mesh_network_message_processed_by_upper_layer
456         (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_RECEIVED, network_pdu);
457     }
458 
459     // done
460     process_network_pdu_done();
461 }
462 
463 static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){
464     // get IV Index and IVI
465     uint32_t iv_index = global_iv_index;
466     int ivi = network_pdu->data[0] >> 7;
467 
468     // if least significant bit differs, use previous IV Index
469     if ((iv_index & 1 ) ^ ivi){
470         iv_index--;
471 #ifdef LOG_NETWORK
472         printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index);
473 #endif
474     }
475     return iv_index;
476 }
477 
478 static void process_network_pdu_validate_b(void * arg){
479     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
480 
481 #ifdef LOG_NETWORK
482     printf("RX-PECB: ");
483     printf_hexdump(obfuscation_block, 6);
484 #endif
485 
486     // de-obfuscate
487     unsigned int i;
488     for (i=0;i<6;i++){
489         network_pdu->data[1+i] = network_pdu_in_validation->data[1+i] ^ obfuscation_block[i];
490     }
491 
492     uint32_t iv_index = iv_index_for_pdu(network_pdu);
493 
494     if (network_pdu->flags & 1){
495         // create network nonce
496         mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index);
497 #ifdef LOG_NETWORK
498         printf("RX-Proxy Nonce: ");
499         printf_hexdump(network_nonce, 13);
500 #endif
501     } else {
502         // create network nonce
503         mesh_network_create_nonce(network_nonce, network_pdu, iv_index);
504 #ifdef LOG_NETWORK
505         printf("RX-Network Nonce: ");
506         printf_hexdump(network_nonce, 13);
507 #endif
508     }
509 
510     //
511     uint8_t ctl_ttl     = network_pdu->data[1];
512     uint8_t net_mic_len = (ctl_ttl & 0x80) ? 8 : 4;
513     uint8_t cypher_len  = network_pdu->len - 7 - net_mic_len;
514 
515 #ifdef LOG_NETWORK
516     printf("RX-Cyper len %u, mic len %u\n", cypher_len, net_mic_len);
517 
518     printf("RX-Encryption Key: ");
519     printf_hexdump(current_network_key->encryption_key, 16);
520 
521 #endif
522 
523     btstack_crypto_ccm_init(&mesh_network_crypto_request.ccm, current_network_key->encryption_key, network_nonce, cypher_len, 0, net_mic_len);
524     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);
525 }
526 
527 static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu){
528     if (!mesh_network_key_nid_iterator_has_more(&validation_network_key_it)){
529         printf("No valid network key found\n");
530         btstack_memory_mesh_network_pdu_free(network_pdu);
531         process_network_pdu_done();
532         return;
533     }
534 
535     current_network_key = mesh_network_key_nid_iterator_get_next(&validation_network_key_it);
536 
537     // calc PECB
538     uint32_t iv_index = iv_index_for_pdu(network_pdu);
539     memset(encryption_block, 0, 5);
540     big_endian_store_32(encryption_block, 5, iv_index);
541     memcpy(&encryption_block[9], &network_pdu_in_validation->data[7], 7);
542     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);
543 }
544 
545 
546 static void process_network_pdu(mesh_network_pdu_t * network_pdu){
547     //
548     uint8_t nid_ivi = network_pdu_in_validation->data[0];
549 
550     // setup pdu object
551     network_pdu->data[0] = nid_ivi;
552     network_pdu->len     = network_pdu_in_validation->len;
553     network_pdu->flags   = network_pdu_in_validation->flags;
554 
555     // init provisioning data iterator
556     uint8_t nid = nid_ivi & 0x7f;
557     // uint8_t iv_index = network_pdu_data[0] >> 7;
558     mesh_network_key_nid_iterator_init(&validation_network_key_it, nid);
559 
560     process_network_pdu_validate(network_pdu);
561 }
562 
563 // static void mesh_network_encrypt_and_obfuscate(mesh_network_pdu_t * network_pdu, void (*callback)(mesh_network_pdu_t * network_pdu)){
564 //     network_pdu->callback = callback;
565 // }
566 
567 static void mesh_network_run(void){
568     if (!btstack_linked_list_empty(&network_pdus_outgoing)){
569         actual_bearer_network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_outgoing);
570 
571         int send_to_next_bearer = 1;
572 #ifdef ENABLE_MESH_GATT_BEARER
573         // request to send via gatt
574         if (send_to_next_bearer){
575             send_to_next_bearer = 0;
576             gatt_bearer_request_can_send_now_for_mesh_network_pdu();
577         }
578 #endif
579 #ifdef ENABLE_MESH_ADV_BEARER
580          // request to send via adv
581         if (send_to_next_bearer){
582             send_to_next_bearer = 0;
583             adv_bearer_request_can_send_now_for_mesh_message();
584         }
585 #endif
586         if (send_to_next_bearer == 1){
587             // TODO: notify done
588         }
589     }
590 
591     if (mesh_crypto_active) return;
592 
593     if (!btstack_linked_list_empty(&network_pdus_received)){
594         mesh_network_pdu_t * decode_pdu = mesh_network_pdu_get();
595         if (!decode_pdu) return;
596         // get encoded network pdu and start processing
597         mesh_crypto_active = 1;
598         network_pdu_in_validation = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_received);
599         process_network_pdu(decode_pdu);
600         return;
601     }
602 
603     if (!btstack_linked_list_empty(&network_pdus_queued)){
604         // get queued network pdu and start processing
605         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&network_pdus_queued);
606         mesh_network_send_a(network_pdu);
607         return;
608     }
609 }
610 
611 #ifdef ENABLE_MESH_ADV_BEARER
612 static void mesh_adv_message_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
613     mesh_network_pdu_t * network_pdu;
614 
615     switch (packet_type){
616         case MESH_NETWORK_PACKET:
617             // check len. minimal transport PDU len = 1, 32 bit NetMIC -> 13 bytes
618             if (size < 13) break;
619 
620 #ifdef LOG_NETWORK
621             printf("received mesh message (len %u): ", size);
622             printf_hexdump(packet, size);
623 #endif
624             mesh_network_received_message(packet, size);
625             break;
626 
627         case HCI_EVENT_PACKET:
628             switch(packet[0]){
629                 case HCI_EVENT_MESH_META:
630                     switch(packet[2]){
631                         case MESH_SUBEVENT_CAN_SEND_NOW:
632                             if (actual_bearer_network_pdu == NULL) break;
633 #ifdef LOG_NETWORK
634                             printf("TX-E-NetworkPDU (%p): ", actual_bearer_network_pdu);
635                             printf_hexdump(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len);
636 #endif
637                             adv_bearer_send_mesh_message(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len);
638                             network_pdu = actual_bearer_network_pdu;
639                             actual_bearer_network_pdu = NULL;
640 
641                             // notify upper layer
642                             (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
643 
644                             // check if more to send
645                             mesh_network_run();
646                             break;
647                         default:
648                             break;
649                     }
650                     break;
651                 default:
652                     break;
653             }
654             break;
655     }
656 }
657 #endif
658 
659 void mesh_gatt_handle_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
660 #ifdef ENABLE_MESH_GATT_BEARER
661     mesh_network_pdu_t * network_pdu;
662     switch (packet_type){
663         case HCI_EVENT_PACKET:
664             switch(packet[0]){
665                 case HCI_EVENT_MESH_META:
666                     switch(packet[2]){
667                         case MESH_SUBEVENT_CAN_SEND_NOW:
668                             if (actual_bearer_network_pdu == NULL) break;
669 #ifdef LOG_NETWORK
670                             printf("G-TX-E-NetworkPDU (%p): ", actual_bearer_network_pdu);
671                             printf_hexdump(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len);
672 #endif
673                             gatt_bearer_send_mesh_network_pdu(actual_bearer_network_pdu->data, actual_bearer_network_pdu->len);
674                             break;
675 
676                         case MESH_SUBEVENT_MESSAGE_SENT:
677                             if (actual_bearer_network_pdu == NULL) break;
678 #ifdef ENABLE_MESH_ADV_BEARER
679                             // request to send via adv bearer
680                             adv_bearer_request_can_send_now_for_mesh_message();
681                             break;
682 #else
683                             // notify upper layer
684                             network_pdu = actual_bearer_network_pdu;
685                             actual_bearer_network_pdu = NULL;
686                             (*mesh_network_higher_layer_handler)(MESH_NETWORK_PDU_SENT, network_pdu);
687 #endif
688                             break;
689                         default:
690                             break;
691                     }
692                     break;
693                 default:
694                     break;
695             }
696             break;
697     }
698 #endif
699 }
700 
701 void mesh_network_init(void){
702 #ifdef ENABLE_MESH_ADV_BEARER
703     adv_bearer_register_for_mesh_message(&mesh_adv_message_handler);
704 #endif
705 }
706 
707 void mesh_network_set_higher_layer_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
708     mesh_network_higher_layer_handler = packet_handler;
709 }
710 
711 void mesh_network_set_proxy_message_handler(void (*packet_handler)(mesh_network_callback_type_t callback_type, mesh_network_pdu_t * network_pdu)){
712     mesh_network_proxy_message_handler = packet_handler;
713 }
714 
715 void mesh_network_set_primary_element_address(uint16_t addr){
716     mesh_network_primary_address = addr;
717     mesh_network_num_elements = 1;
718 }
719 
720 void mesh_network_received_message(const uint8_t * pdu_data, uint8_t pdu_len){
721     // verify len
722     if (pdu_len > 29) return;
723 
724     // allocate network_pdu
725     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
726     if (!network_pdu) return;
727 
728     // store data
729     memcpy(network_pdu->data, pdu_data, pdu_len);
730     network_pdu->len = pdu_len;
731     network_pdu->flags = 0; // Network PDU
732 
733     // add to list and go
734     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
735     mesh_network_run();
736 
737 }
738 
739 void mesh_network_process_proxy_message(const uint8_t * pdu_data, uint8_t pdu_len){
740     // verify len
741     if (pdu_len > 29) return;
742 
743     // allocate network_pdu
744     mesh_network_pdu_t * network_pdu = mesh_network_pdu_get();
745     if (!network_pdu) return;
746 
747     // store data
748     memcpy(network_pdu->data, pdu_data, pdu_len);
749     network_pdu->len = pdu_len;
750     network_pdu->flags = 1; // Network PDU
751 
752     // add to list and go
753     btstack_linked_list_add_tail(&network_pdus_received, (btstack_linked_item_t *) network_pdu);
754     mesh_network_run();
755 }
756 
757 void mesh_network_send_pdu(mesh_network_pdu_t * network_pdu){
758 #ifdef LOG_NETWORK
759     printf("TX-A-NetworkPDU (%p): ", network_pdu);
760     printf_hexdump(network_pdu->data, network_pdu->len);
761 #endif
762 
763     if (network_pdu->len > 29){
764         printf("too long, %u\n", network_pdu->len);
765         return;
766     }
767 
768     // setup callback
769     network_pdu->callback = &mesh_network_send_d;
770     network_pdu->flags    = 0;
771 
772     // queue up
773     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
774 
775     // go
776     mesh_network_run();
777 }
778 
779 void mesh_network_encrypt_proxy_message(mesh_network_pdu_t * network_pdu, void (* callback)(mesh_network_pdu_t * callback)){
780     printf("ProxyPDU(unencrypted): ");
781     printf_hexdump(network_pdu->data, network_pdu->len);
782 
783     // setup callback
784     network_pdu->callback = callback;
785     network_pdu->flags    = 1;
786 
787     // queue up
788     btstack_linked_list_add_tail(&network_pdus_queued, (btstack_linked_item_t *) network_pdu);
789 
790     // go
791     mesh_network_run();
792 }
793 
794 /*
795  * @brief Setup network pdu header
796  * @param netkey_index
797  * @param ctl
798  * @param ttl
799  * @param seq
800  * @param dest
801  */
802 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){
803     memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
804     // set netkey_index
805     network_pdu->netkey_index = netkey_index;
806     // setup header
807     network_pdu->data[network_pdu->len++] = (global_iv_index << 7) |  nid;
808     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
809     network_pdu->data[network_pdu->len++] = ctl_ttl;
810     big_endian_store_24(network_pdu->data, 2, seq);
811     network_pdu->len += 3;
812     big_endian_store_16(network_pdu->data, network_pdu->len, src);
813     network_pdu->len += 2;
814     big_endian_store_16(network_pdu->data, network_pdu->len, dest);
815     network_pdu->len += 2;
816     memcpy(&network_pdu->data[network_pdu->len], transport_pdu_data, transport_pdu_len);
817     network_pdu->len += transport_pdu_len;
818 }
819 
820 /*
821  * @brief Setup network pdu header
822  * @param netkey_index
823  * @param ctl
824  * @param ttl
825  * @param seq
826  * @param dest
827  */
828 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){
829     // set netkey_index
830     network_pdu->netkey_index = netkey_index;
831     // setup header
832     network_pdu->data[0] = (global_iv_index << 7) |  nid;
833     uint8_t ctl_ttl = (ctl << 7) | (ttl & 0x7f);
834     network_pdu->data[1] = ctl_ttl;
835     big_endian_store_24(network_pdu->data, 2, seq);
836     big_endian_store_16(network_pdu->data, 5, src);
837     big_endian_store_16(network_pdu->data, 7, dest);
838 }
839 
840 void mesh_set_iv_index(uint32_t iv_index){
841     global_iv_index = iv_index;
842 }
843 
844 uint32_t mesh_get_iv_index(void){
845     return  global_iv_index;
846 }
847 
848 // Network PDU Getter
849 uint8_t  mesh_network_nid(mesh_network_pdu_t * network_pdu){
850     return network_pdu->data[0] & 0x7f;
851 }
852 uint16_t mesh_network_control(mesh_network_pdu_t * network_pdu){
853     return network_pdu->data[1] & 0x80;
854 }
855 uint8_t mesh_network_ttl(mesh_network_pdu_t * network_pdu){
856     return network_pdu->data[1] & 0x7f;
857 }
858 uint32_t mesh_network_seq(mesh_network_pdu_t * network_pdu){
859     return big_endian_read_24(network_pdu->data, 2);
860 }
861 uint16_t mesh_network_src(mesh_network_pdu_t * network_pdu){
862     return big_endian_read_16(network_pdu->data, 5);
863 }
864 uint16_t mesh_network_dst(mesh_network_pdu_t * network_pdu){
865     return big_endian_read_16(network_pdu->data, 7);
866 }
867 int mesh_network_segmented(mesh_network_pdu_t * network_pdu){
868     return network_pdu->data[9] & 0x80;
869 }
870 uint8_t * mesh_network_pdu_data(mesh_network_pdu_t * network_pdu){
871     return &network_pdu->data[9];
872 }
873 uint8_t   mesh_network_pdu_len(mesh_network_pdu_t * network_pdu){
874     return network_pdu->len - 9;
875 }
876 
877 static void mesh_network_dump_network_pdu(mesh_network_pdu_t * network_pdu){
878     if (network_pdu){
879         printf("- %p: ", network_pdu); printf_hexdump(network_pdu->data, network_pdu->len);
880     }
881 }
882 static void mesh_network_dump_network_pdus(const char * name, btstack_linked_list_t * list){
883     printf("List: %s:\n", name);
884     btstack_linked_list_iterator_t it;
885     btstack_linked_list_iterator_init(&it, list);
886     while (btstack_linked_list_iterator_has_next(&it)){
887         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t*) btstack_linked_list_iterator_next(&it);
888         mesh_network_dump_network_pdu(network_pdu);
889     }
890 }
891 static void mesh_network_reset_network_pdus(btstack_linked_list_t * list){
892     while (!btstack_linked_list_empty(list)){
893         mesh_network_pdu_t * pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(list);
894         btstack_memory_mesh_network_pdu_free(pdu);
895     }
896 }
897 void mesh_network_dump(void){
898     mesh_network_dump_network_pdus("network_pdus_received", &network_pdus_received);
899     mesh_network_dump_network_pdus("network_pdus_queued", &network_pdus_queued);
900     mesh_network_dump_network_pdus("network_pdus_outgoing", &network_pdus_outgoing);
901     printf("network_pdu_in_validation: \n");
902     mesh_network_dump_network_pdu(network_pdu_in_validation);
903 }
904 void mesh_network_reset(void){
905     mesh_network_reset_network_pdus(&network_pdus_received);
906     mesh_network_reset_network_pdus(&network_pdus_queued);
907     mesh_network_reset_network_pdus(&network_pdus_outgoing);
908 }
909 
910 // buffer pool
911 mesh_network_pdu_t * mesh_network_pdu_get(void){
912     mesh_network_pdu_t * network_pdu = btstack_memory_mesh_network_pdu_get();
913     if (network_pdu) {
914         memset(network_pdu, 0, sizeof(mesh_network_pdu_t));
915         network_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_NETWORK;
916     }
917     return network_pdu;
918 }
919 
920 void mesh_network_pdu_free(mesh_network_pdu_t * network_pdu){
921     btstack_memory_mesh_network_pdu_free(network_pdu);
922 }
923