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