xref: /btstack/src/mesh/mesh_upper_transport.c (revision 1fda7ff0dd9ac6995145987c7ebb673effbfdfd3)
1 /*
2  * Copyright (C) 2014 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_upper_transport.c"
39 
40 #include "mesh/mesh_upper_transport.h"
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 
46 #include "btstack_util.h"
47 #include "btstack_memory.h"
48 #include "btstack_debug.h"
49 
50 #include "mesh/beacon.h"
51 #include "mesh/mesh_iv_index_seq_number.h"
52 #include "mesh/mesh_keys.h"
53 #include "mesh/mesh_lower_transport.h"
54 #include "mesh/mesh_peer.h"
55 #include "mesh/mesh_virtual_addresses.h"
56 
57 // TODO: extract mesh_pdu functions into lower transport or network
58 #include "mesh/mesh_access.h"
59 
60 // combined key x address iterator for upper transport decryption
61 
62 typedef struct {
63     // state
64     mesh_transport_key_iterator_t  key_it;
65     mesh_virtual_address_iterator_t address_it;
66     // elements
67     const mesh_transport_key_t *   key;
68     const mesh_virtual_address_t * address;
69     // address - might be virtual
70     uint16_t dst;
71     // key info
72 } mesh_transport_key_and_virtual_address_iterator_t;
73 
74 static void (*higher_layer_handler)( mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu);
75 
76 static void mesh_upper_transport_validate_unsegmented_message(void);
77 static void mesh_upper_transport_validate_segmented_message(void);
78 static void mesh_upper_transport_run(void);
79 
80 static int crypto_active;
81 
82 static mesh_unsegmented_pdu_t * incoming_unsegmented_pdu_raw;
83 static mesh_network_pdu_t   * incoming_network_pdu_decoded;
84 
85 static mesh_segmented_pdu_t     incoming_message_pdu_singleton;
86 
87 static mesh_access_pdu_t    * incoming_access_pdu_encrypted;
88 static mesh_access_pdu_t    * incoming_access_pdu_decrypted;
89 
90 static mesh_access_pdu_t      incoming_access_pdu_encrypted_singleton;
91 static mesh_access_pdu_t      incoming_access_pdu_decrypted_singleton;
92 
93 static mesh_segmented_pdu_t     outgoing_segmented_message_singleton;
94 static mesh_transport_pdu_t * outgoing_segmented_pdu;
95 static mesh_unsegmented_pdu_t outgoing_unsegmented_pdu;
96 
97 static uint8_t application_nonce[13];
98 static btstack_crypto_ccm_t ccm;
99 static mesh_transport_key_and_virtual_address_iterator_t mesh_transport_key_it;
100 
101 // upper transport callbacks - in access layer
102 static void (*mesh_access_message_handler)(mesh_pdu_t * pdu);
103 static void (*mesh_control_message_handler)(mesh_pdu_t * pdu);
104 
105 // incoming unsegmented (network) and segmented (transport) control and access messages
106 static btstack_linked_list_t upper_transport_incoming;
107 
108 // outgoing unsegmented (network) and segmented (uppert_transport_outgoing) control and access messages
109 static btstack_linked_list_t upper_transport_outgoing;
110 
111 
112 // TODO: higher layer define used for assert
113 #define MESH_ACCESS_OPCODE_NOT_SET 0xFFFFFFFEu
114 
115 void mesh_upper_transport_send_access_pdu(mesh_pdu_t *pdu){
116     switch (pdu->pdu_type){
117         case MESH_PDU_TYPE_UNSEGMENTED:
118         case MESH_PDU_TYPE_TRANSPORT:
119             break;
120         default:
121             btstack_assert(false);
122             break;
123     }
124 
125     btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
126     mesh_upper_transport_run();
127 }
128 
129 void mesh_upper_transport_send_control_pdu(mesh_pdu_t * pdu){
130     if (pdu->pdu_type == MESH_PDU_TYPE_NETWORK){
131         btstack_assert( ((mesh_network_pdu_t *) pdu)->len >= 9);
132     }
133 
134     btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
135     mesh_upper_transport_run();
136 }
137 
138 static void mesh_print_hex(const char * name, const uint8_t * data, uint16_t len){
139     printf("%-20s ", name);
140     printf_hexdump(data, len);
141 }
142 // static void mesh_print_x(const char * name, uint32_t value){
143 //     printf("%20s: 0x%x", name, (int) value);
144 // }
145 
146 static void mesh_transport_key_and_virtual_address_iterator_init(mesh_transport_key_and_virtual_address_iterator_t *it,
147                                                                  uint16_t dst, uint16_t netkey_index, uint8_t akf,
148                                                                  uint8_t aid) {
149     printf("KEY_INIT: dst %04x, akf %x, aid %x\n", dst, akf, aid);
150     // config
151     it->dst   = dst;
152     // init elements
153     it->key     = NULL;
154     it->address = NULL;
155     // init element iterators
156     mesh_transport_key_aid_iterator_init(&it->key_it, netkey_index, akf, aid);
157     // init address iterator
158     if (mesh_network_address_virtual(it->dst)){
159         mesh_virtual_address_iterator_init(&it->address_it, dst);
160         // get first key
161         if (mesh_transport_key_aid_iterator_has_more(&it->key_it)) {
162             it->key = mesh_transport_key_aid_iterator_get_next(&it->key_it);
163         }
164     }
165 }
166 
167 // cartesian product: keys x addressses
168 static int mesh_transport_key_and_virtual_address_iterator_has_more(mesh_transport_key_and_virtual_address_iterator_t * it){
169     if (mesh_network_address_virtual(it->dst)) {
170         // find next valid entry
171         while (true){
172             if (mesh_virtual_address_iterator_has_more(&it->address_it)) return 1;
173             if (!mesh_transport_key_aid_iterator_has_more(&it->key_it)) return 0;
174             // get next key
175             it->key = mesh_transport_key_aid_iterator_get_next(&it->key_it);
176             mesh_virtual_address_iterator_init(&it->address_it, it->dst);
177         }
178     } else {
179         return mesh_transport_key_aid_iterator_has_more(&it->key_it);
180     }
181 }
182 
183 static void mesh_transport_key_and_virtual_address_iterator_next(mesh_transport_key_and_virtual_address_iterator_t * it){
184     if (mesh_network_address_virtual(it->dst)) {
185         it->address = mesh_virtual_address_iterator_get_next(&it->address_it);
186     } else {
187         it->key = mesh_transport_key_aid_iterator_get_next(&it->key_it);
188     }
189 }
190 
191 // UPPER TRANSPORT
192 
193 static uint16_t mesh_access_dst(mesh_access_pdu_t * access_pdu){
194     return big_endian_read_16(access_pdu->network_header, 7);
195 }
196 
197 uint16_t mesh_access_ctl(mesh_access_pdu_t * access_pdu){
198     return access_pdu->network_header[1] >> 7;
199 }
200 
201 
202 // stub lower transport
203 
204 static void mesh_upper_transport_dump_pdus(const char *name, btstack_linked_list_t *list){
205     printf("List: %s:\n", name);
206     btstack_linked_list_iterator_t it;
207     btstack_linked_list_iterator_init(&it, list);
208     while (btstack_linked_list_iterator_has_next(&it)){
209         mesh_pdu_t * pdu = (mesh_pdu_t*) btstack_linked_list_iterator_next(&it);
210         printf("- %p\n", pdu);
211         // printf_hexdump( mesh_pdu_data(pdu), mesh_pdu_len(pdu));
212     }
213 }
214 
215 static void mesh_upper_transport_reset_pdus(btstack_linked_list_t *list){
216     while (!btstack_linked_list_empty(list)){
217         mesh_upper_transport_pdu_free((mesh_pdu_t *) btstack_linked_list_pop(list));
218     }
219 }
220 
221 void mesh_upper_transport_dump(void){
222     printf("incoming_unsegmented_pdu_raw: %p\n", incoming_unsegmented_pdu_raw);
223     printf("incoming_network_pdu_decoded: %p\n", incoming_network_pdu_decoded);
224     mesh_upper_transport_dump_pdus("upper_transport_incoming", &upper_transport_incoming);
225 }
226 
227 void mesh_upper_transport_reset(void){
228     crypto_active = 0;
229     if (incoming_unsegmented_pdu_raw){
230         mesh_network_pdu_t * network_pdu = incoming_unsegmented_pdu_raw->segment;
231         btstack_assert(network_pdu != NULL);
232         incoming_unsegmented_pdu_raw->segment = NULL;
233         mesh_network_pdu_free(network_pdu);
234         incoming_unsegmented_pdu_raw = NULL;
235     }
236     if (outgoing_segmented_pdu != NULL){
237         mesh_transport_pdu_free(outgoing_segmented_pdu);
238         outgoing_segmented_pdu = NULL;
239     }
240     mesh_upper_transport_reset_pdus(&upper_transport_incoming);
241 }
242 
243 static uint32_t iv_index_for_ivi_nid(uint8_t ivi_nid){
244     // get IV Index and IVI
245     uint32_t iv_index = mesh_get_iv_index();
246     int ivi = ivi_nid >> 7;
247 
248     // if least significant bit differs, use previous IV Index
249     if ((iv_index & 1 ) ^ ivi){
250         iv_index--;
251     }
252     return iv_index;
253 }
254 
255 static void transport_unsegmented_setup_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
256     nonce[1] = 0x00;    // SZMIC if a Segmented Access message or 0 for all other message formats
257     (void)memcpy(&nonce[2], &network_pdu->data[2], 7);
258     big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(network_pdu->data[0]));
259 }
260 
261 static void transport_segmented_setup_nonce(uint8_t * nonce, const mesh_pdu_t * pdu){
262     mesh_transport_pdu_t * transport_pdu;
263     mesh_access_pdu_t * access_pdu;
264     switch (pdu->pdu_type){
265         case MESH_PDU_TYPE_TRANSPORT:
266             transport_pdu = (mesh_transport_pdu_t *) pdu;
267             nonce[1] = transport_pdu->transmic_len == 8 ? 0x80 : 0x00;
268             (void)memcpy(&nonce[2], &transport_pdu->network_header[2], 7);
269             big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(transport_pdu->network_header[0]));
270             break;
271         case MESH_PDU_TYPE_ACCESS:
272             access_pdu = (mesh_access_pdu_t *) pdu;
273             nonce[1] = access_pdu->transmic_len == 8 ? 0x80 : 0x00;
274             (void)memcpy(&nonce[2], &access_pdu->network_header[2], 7);
275             big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(access_pdu->network_header[0]));
276             break;
277         default:
278             btstack_assert(0);
279             break;
280     }
281 }
282 
283 static void transport_unsegmented_setup_application_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
284     nonce[0] = 0x01;
285     transport_unsegmented_setup_nonce(nonce, network_pdu);
286     mesh_print_hex("AppNonce", nonce, 13);
287 }
288 
289 static void transport_unsegmented_setup_device_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
290     nonce[0] = 0x02;
291     transport_unsegmented_setup_nonce(nonce, network_pdu);
292     mesh_print_hex("DeviceNonce", nonce, 13);
293 }
294 
295 static void transport_segmented_setup_application_nonce(uint8_t * nonce, const mesh_pdu_t * pdu){
296     nonce[0] = 0x01;
297     transport_segmented_setup_nonce(nonce, pdu);
298     mesh_print_hex("AppNonce", nonce, 13);
299 }
300 
301 static void transport_segmented_setup_device_nonce(uint8_t * nonce, const mesh_pdu_t * pdu){
302     nonce[0] = 0x02;
303     transport_segmented_setup_nonce(nonce, pdu);
304     mesh_print_hex("DeviceNonce", nonce, 13);
305 }
306 
307 static void mesh_upper_unsegmented_control_message_received(mesh_unsegmented_pdu_t * unsegmented_incoming_pdu){
308     if (mesh_control_message_handler){
309         mesh_control_message_handler((mesh_pdu_t*) unsegmented_incoming_pdu);
310     } else {
311         mesh_network_pdu_t * network_pdu =unsegmented_incoming_pdu->segment;
312         uint8_t * lower_transport_pdu     = mesh_network_pdu_data(network_pdu);
313         uint8_t  opcode = lower_transport_pdu[0];
314         printf("[!] Unhandled Control message with opcode %02x\n", opcode);
315         // done
316         mesh_lower_transport_message_processed_by_higher_layer((mesh_pdu_t*) unsegmented_incoming_pdu);
317     }
318 }
319 
320 static void mesh_upper_transport_process_message_done(mesh_segmented_pdu_t *message_pdu){
321     crypto_active = 0;
322     btstack_assert(message_pdu == &incoming_message_pdu_singleton);
323     mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&incoming_message_pdu_singleton.segments);
324     if (mesh_network_control(network_pdu)) {
325         btstack_assert(0);
326     } else {
327         btstack_assert(network_pdu != NULL);
328         mesh_network_pdu_free(network_pdu);
329         mesh_pdu_t * pdu = (mesh_pdu_t *) incoming_unsegmented_pdu_raw;
330         incoming_unsegmented_pdu_raw = NULL;
331         mesh_lower_transport_message_processed_by_higher_layer(pdu);
332     }
333     mesh_upper_transport_run();
334 }
335 
336 static void mesh_upper_transport_process_unsegmented_message_done(mesh_pdu_t * pdu){
337     btstack_assert(pdu != NULL);
338     btstack_assert(pdu->pdu_type == MESH_PDU_TYPE_UNSEGMENTED);
339 
340     mesh_unsegmented_pdu_t * unsegmented_incoming_pdu = (mesh_unsegmented_pdu_t *) pdu;
341     btstack_assert(unsegmented_incoming_pdu == incoming_unsegmented_pdu_raw);
342 
343     crypto_active = 0;
344     incoming_unsegmented_pdu_raw = NULL;
345     mesh_network_pdu_t * network_pdu = unsegmented_incoming_pdu->segment;
346     if (!mesh_network_control(network_pdu)) {
347         mesh_network_pdu_free(network_pdu);
348     }
349 
350     mesh_lower_transport_message_processed_by_higher_layer(pdu);
351     mesh_upper_transport_run();
352 }
353 
354 static void mesh_upper_transport_process_segmented_access_message_done(mesh_access_pdu_t *access_pdu){
355     crypto_active = 0;
356     btstack_assert(mesh_access_ctl(access_pdu) == 0);
357     incoming_access_pdu_encrypted = NULL;
358     mesh_upper_transport_run();
359 }
360 
361 static void mesh_upper_transport_validate_unsegmented_message_ccm(void * arg){
362     UNUSED(arg);
363 
364     uint8_t * lower_transport_pdu = mesh_network_pdu_data(incoming_network_pdu_decoded);
365     uint8_t trans_mic_len = 4;
366 
367     // store TransMIC
368     uint8_t trans_mic[8];
369     btstack_crypto_ccm_get_authentication_value(&ccm, trans_mic);
370     mesh_print_hex("TransMIC", trans_mic, trans_mic_len);
371 
372     uint8_t * upper_transport_pdu     = mesh_network_pdu_data(incoming_network_pdu_decoded) + 1;
373     uint8_t   upper_transport_pdu_len = mesh_network_pdu_len(incoming_network_pdu_decoded)  - 1;
374 
375     mesh_print_hex("Decryted PDU", upper_transport_pdu, upper_transport_pdu_len - trans_mic_len);
376 
377     if (memcmp(trans_mic, &upper_transport_pdu[upper_transport_pdu_len - trans_mic_len], trans_mic_len) == 0){
378         printf("TransMIC matches\n");
379 
380         // remove TransMIC from payload
381         incoming_network_pdu_decoded->len -= trans_mic_len;
382 
383         // if virtual address, update dst to pseudo_dst
384         if (mesh_network_address_virtual(mesh_network_dst(incoming_network_pdu_decoded))){
385             big_endian_store_16(incoming_network_pdu_decoded->data, 7, mesh_transport_key_it.address->pseudo_dst);
386         }
387 
388         // pass to upper layer
389         if (mesh_access_message_handler){
390             mesh_pdu_t * pdu = (mesh_pdu_t*) incoming_network_pdu_decoded;
391             incoming_network_pdu_decoded = NULL;
392             mesh_access_message_handler((mesh_pdu_t*) &incoming_message_pdu_singleton);
393         } else {
394             printf("[!] Unhandled Unsegmented Access message\n");
395             // done
396             mesh_upper_transport_process_unsegmented_message_done((mesh_pdu_t*) incoming_unsegmented_pdu_raw);
397         }
398 
399         printf("\n");
400     } else {
401         uint8_t afk = lower_transport_pdu[0] & 0x40;
402         if (afk){
403             printf("TransMIC does not match, try next key\n");
404             mesh_upper_transport_validate_unsegmented_message();
405         } else {
406             printf("TransMIC does not match device key, done\n");
407             // done
408             mesh_upper_transport_process_unsegmented_message_done((mesh_pdu_t*) incoming_unsegmented_pdu_raw);
409         }
410     }
411 }
412 
413 static void mesh_upper_transport_validate_segmented_message_ccm(void * arg){
414     UNUSED(arg);
415 
416     uint8_t * upper_transport_pdu     = incoming_access_pdu_decrypted->data;
417     uint8_t   upper_transport_pdu_len = incoming_access_pdu_decrypted->len - incoming_access_pdu_decrypted->transmic_len;
418 
419     mesh_print_hex("Decrypted PDU", upper_transport_pdu, upper_transport_pdu_len);
420 
421     // store TransMIC
422     uint8_t trans_mic[8];
423     btstack_crypto_ccm_get_authentication_value(&ccm, trans_mic);
424     mesh_print_hex("TransMIC", trans_mic, incoming_access_pdu_decrypted->transmic_len);
425 
426     if (memcmp(trans_mic, &upper_transport_pdu[upper_transport_pdu_len], incoming_access_pdu_decrypted->transmic_len) == 0){
427         printf("TransMIC matches\n");
428 
429         // remove TransMIC from payload
430         incoming_access_pdu_decrypted->len -= incoming_access_pdu_decrypted->transmic_len;
431 
432         // if virtual address, update dst to pseudo_dst
433         if (mesh_network_address_virtual(mesh_access_dst(incoming_access_pdu_decrypted))){
434             big_endian_store_16(incoming_access_pdu_decrypted->network_header, 7, mesh_transport_key_it.address->pseudo_dst);
435         }
436 
437         // pass to upper layer
438         btstack_assert(mesh_access_message_handler != NULL);
439         mesh_pdu_t * pdu = (mesh_pdu_t*) incoming_access_pdu_decrypted;
440         incoming_network_pdu_decoded = NULL;
441         mesh_access_message_handler(pdu);
442 
443         printf("\n");
444 
445     } else {
446         uint8_t akf = incoming_access_pdu_decrypted->akf_aid_control & 0x40;
447         if (akf){
448             printf("TransMIC does not match, try next key\n");
449             mesh_upper_transport_validate_segmented_message();
450         } else {
451             printf("TransMIC does not match device key, done\n");
452             // done
453             mesh_upper_transport_process_segmented_access_message_done(incoming_access_pdu_decrypted);
454         }
455     }
456 }
457 
458 static void mesh_upper_transport_validate_segmented_message_digest(void * arg){
459     UNUSED(arg);
460     uint8_t   upper_transport_pdu_len      = incoming_access_pdu_encrypted->len - incoming_access_pdu_encrypted->transmic_len;
461     uint8_t * upper_transport_pdu_data_in  = incoming_access_pdu_encrypted->data;
462     uint8_t * upper_transport_pdu_data_out = incoming_access_pdu_decrypted->data;
463     btstack_crypto_ccm_decrypt_block(&ccm, upper_transport_pdu_len, upper_transport_pdu_data_in, upper_transport_pdu_data_out, &mesh_upper_transport_validate_segmented_message_ccm, NULL);
464 }
465 
466 static void mesh_upper_transport_validate_unsegmented_message_digest(void * arg){
467     UNUSED(arg);
468     mesh_network_pdu_t * network_pdu = incoming_unsegmented_pdu_raw->segment;
469     uint8_t   trans_mic_len = 4;
470     uint8_t   lower_transport_pdu_len      = network_pdu->len - 9;
471     uint8_t * upper_transport_pdu_data_in  = &network_pdu->data[10];
472     uint8_t * upper_transport_pdu_data_out = &incoming_network_pdu_decoded->data[10];
473     uint8_t   upper_transport_pdu_len      = lower_transport_pdu_len - 1 - trans_mic_len;
474     btstack_crypto_ccm_decrypt_block(&ccm, upper_transport_pdu_len, upper_transport_pdu_data_in, upper_transport_pdu_data_out, &mesh_upper_transport_validate_unsegmented_message_ccm, NULL);
475 }
476 
477 static void mesh_upper_transport_validate_unsegmented_message(void){
478 
479     if (!mesh_transport_key_and_virtual_address_iterator_has_more(&mesh_transport_key_it)){
480         printf("No valid transport key found\n");
481         mesh_upper_transport_process_unsegmented_message_done((mesh_pdu_t*) incoming_unsegmented_pdu_raw);
482         return;
483     }
484     mesh_transport_key_and_virtual_address_iterator_next(&mesh_transport_key_it);
485     const mesh_transport_key_t * message_key = mesh_transport_key_it.key;
486 
487     mesh_network_pdu_t * network_pdu = incoming_unsegmented_pdu_raw->segment;
488     if (message_key->akf){
489         transport_unsegmented_setup_application_nonce(application_nonce, network_pdu);
490     } else {
491         transport_unsegmented_setup_device_nonce(application_nonce, network_pdu);
492     }
493 
494     // store application / device key index
495     mesh_print_hex("AppOrDevKey", message_key->key, 16);
496     incoming_message_pdu_singleton.appkey_index = message_key->appkey_index;
497 
498     // unsegmented message have TransMIC of 32 bit
499     uint8_t trans_mic_len = 4;
500     printf("Unsegmented Access message with TransMIC len 4\n");
501 
502     uint8_t   lower_transport_pdu_len = network_pdu->len - 9;
503     uint8_t * upper_transport_pdu_data = &network_pdu->data[10];
504     uint8_t   upper_transport_pdu_len  = lower_transport_pdu_len - 1 - trans_mic_len;
505 
506     mesh_print_hex("EncAccessPayload", upper_transport_pdu_data, upper_transport_pdu_len);
507 
508     // decrypt ccm
509     crypto_active = 1;
510     uint16_t aad_len  = 0;
511     if (mesh_network_address_virtual(mesh_network_dst(incoming_network_pdu_decoded))){
512         aad_len  = 16;
513     }
514     btstack_crypto_ccm_init(&ccm, message_key->key, application_nonce, upper_transport_pdu_len, aad_len, trans_mic_len);
515     if (aad_len){
516         btstack_crypto_ccm_digest(&ccm, (uint8_t*) mesh_transport_key_it.address->label_uuid, aad_len, &mesh_upper_transport_validate_unsegmented_message_digest, NULL);
517     } else {
518         mesh_upper_transport_validate_unsegmented_message_digest(incoming_network_pdu_decoded);
519     }
520 }
521 
522 static void mesh_upper_transport_validate_segmented_message(void){
523     uint8_t * upper_transport_pdu_data =  incoming_access_pdu_decrypted->data;
524     uint8_t   upper_transport_pdu_len  = incoming_access_pdu_decrypted->len - incoming_access_pdu_decrypted->transmic_len;
525 
526     if (!mesh_transport_key_and_virtual_address_iterator_has_more(&mesh_transport_key_it)){
527         printf("No valid transport key found\n");
528         mesh_upper_transport_process_segmented_access_message_done(incoming_access_pdu_decrypted);
529         return;
530     }
531     mesh_transport_key_and_virtual_address_iterator_next(&mesh_transport_key_it);
532     const mesh_transport_key_t * message_key = mesh_transport_key_it.key;
533 
534     if (message_key->akf){
535         transport_segmented_setup_application_nonce(application_nonce, (mesh_pdu_t *) incoming_access_pdu_encrypted);
536     } else {
537         transport_segmented_setup_device_nonce(application_nonce, (mesh_pdu_t *) incoming_access_pdu_encrypted);
538     }
539 
540     // store application / device key index
541     mesh_print_hex("AppOrDevKey", message_key->key, 16);
542     incoming_access_pdu_decrypted->appkey_index = message_key->appkey_index;
543 
544     mesh_print_hex("EncAccessPayload", upper_transport_pdu_data, upper_transport_pdu_len);
545 
546     // decrypt ccm
547     crypto_active = 1;
548     uint16_t aad_len  = 0;
549     if (mesh_network_address_virtual(mesh_access_dst(incoming_access_pdu_decrypted))){
550         aad_len  = 16;
551     }
552     btstack_crypto_ccm_init(&ccm, message_key->key, application_nonce, upper_transport_pdu_len, aad_len, incoming_access_pdu_decrypted->transmic_len);
553 
554     if (aad_len){
555         btstack_crypto_ccm_digest(&ccm, (uint8_t *) mesh_transport_key_it.address->label_uuid, aad_len, &mesh_upper_transport_validate_segmented_message_digest, NULL);
556     } else {
557         mesh_upper_transport_validate_segmented_message_digest(NULL);
558     }
559 }
560 
561 static void mesh_upper_transport_process_unsegmented_access_message(void){
562     // copy original pdu
563     mesh_network_pdu_t * raw_network_pdu = incoming_unsegmented_pdu_raw->segment;
564     incoming_network_pdu_decoded->len = raw_network_pdu->len;
565     (void)memcpy(incoming_network_pdu_decoded->data,
566                  raw_network_pdu->data,
567                  incoming_network_pdu_decoded->len);
568 
569     //
570     uint8_t * lower_transport_pdu     = &raw_network_pdu->data[9];
571     uint8_t   lower_transport_pdu_len = raw_network_pdu->len - 9;
572 
573     mesh_print_hex("Lower Transport network pdu", &raw_network_pdu->data[9], lower_transport_pdu_len);
574 
575     uint8_t aid =  lower_transport_pdu[0] & 0x3f;
576     uint8_t akf = (lower_transport_pdu[0] & 0x40) >> 6;
577     printf("AKF: %u\n",   akf);
578     printf("AID: %02x\n", aid);
579 
580     mesh_transport_key_and_virtual_address_iterator_init(&mesh_transport_key_it, mesh_network_dst(incoming_network_pdu_decoded),
581             incoming_network_pdu_decoded->netkey_index, akf, aid);
582     mesh_upper_transport_validate_unsegmented_message();
583 }
584 
585 static void mesh_upper_transport_process_message(void){
586     // copy original pdu
587     (void)memcpy(incoming_access_pdu_decrypted, incoming_access_pdu_encrypted,
588                  sizeof(mesh_transport_pdu_t));
589 
590     //
591     uint8_t * upper_transport_pdu     =  incoming_access_pdu_decrypted->data;
592     uint8_t   upper_transport_pdu_len = incoming_access_pdu_decrypted->len - incoming_access_pdu_decrypted->transmic_len;
593     mesh_print_hex("Upper Transport pdu", upper_transport_pdu, upper_transport_pdu_len);
594 
595     uint8_t aid = incoming_access_pdu_decrypted->akf_aid_control & 0x3f;
596     uint8_t akf = (incoming_access_pdu_decrypted->akf_aid_control & 0x40) >> 6;
597 
598     printf("AKF: %u\n",   akf);
599     printf("AID: %02x\n", aid);
600 
601     mesh_transport_key_and_virtual_address_iterator_init(&mesh_transport_key_it, mesh_access_dst(incoming_access_pdu_decrypted),
602                                                          incoming_access_pdu_decrypted->netkey_index, akf, aid);
603     mesh_upper_transport_validate_segmented_message();
604 }
605 
606 static void mesh_upper_transport_message_received(mesh_pdu_t * pdu){
607     btstack_linked_list_add_tail(&upper_transport_incoming, (btstack_linked_item_t*) pdu);
608     mesh_upper_transport_run();
609 }
610 
611 
612 
613 static void mesh_upper_transport_pdu_handler(mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu){
614     mesh_transport_pdu_t * transport_pdu;
615     mesh_network_pdu_t * network_pdu;
616     switch (callback_type){
617         case MESH_TRANSPORT_PDU_RECEIVED:
618             mesh_upper_transport_message_received(pdu);
619             break;
620         case MESH_TRANSPORT_PDU_SENT:
621             switch (pdu->pdu_type){
622                 case MESH_PDU_TYPE_SEGMENTED:
623                     // free chunks
624                     while (!btstack_linked_list_empty(&outgoing_segmented_message_singleton.segments)){
625                         mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) btstack_linked_list_pop(&outgoing_segmented_message_singleton.segments);
626                         mesh_network_pdu_free(network_pdu);
627                     }
628                     // notify upper layer but use transport pdu
629                     transport_pdu = (mesh_transport_pdu_t *) outgoing_segmented_pdu;
630                     outgoing_segmented_pdu = NULL;
631                     if (higher_layer_handler){
632                         higher_layer_handler(callback_type, status, (mesh_pdu_t*) transport_pdu);
633                     } else {
634                         mesh_transport_pdu_free(transport_pdu);
635                     }
636                     break;
637                 case MESH_PDU_TYPE_UNSEGMENTED:
638                     // notify upper layer but use network pdu
639                     network_pdu = outgoing_unsegmented_pdu.segment;
640                     outgoing_unsegmented_pdu.segment = NULL;
641                     if (higher_layer_handler){
642                         higher_layer_handler(callback_type, status, (mesh_pdu_t*) network_pdu);
643                     } else {
644                         mesh_network_pdu_free(network_pdu);
645                     }
646                     break;
647                 default:
648                     btstack_assert(false);
649                     break;
650             }
651             mesh_upper_transport_run();
652             break;
653         default:
654             break;
655     }
656 }
657 static void mesh_upper_transport_send_unsegmented_access_pdu_ccm(void * arg){
658     crypto_active = 0;
659 
660     mesh_unsegmented_pdu_t * unsegmented_pdu = (mesh_unsegmented_pdu_t *) arg;
661     mesh_network_pdu_t * network_pdu = unsegmented_pdu->segment;
662 
663     uint8_t * upper_transport_pdu     = mesh_network_pdu_data(network_pdu) + 1;
664     uint8_t   upper_transport_pdu_len = mesh_network_pdu_len(network_pdu)  - 1;
665     mesh_print_hex("EncAccessPayload", upper_transport_pdu, upper_transport_pdu_len);
666     // store TransMIC
667     btstack_crypto_ccm_get_authentication_value(&ccm, &upper_transport_pdu[upper_transport_pdu_len]);
668     mesh_print_hex("TransMIC", &upper_transport_pdu[upper_transport_pdu_len], 4);
669     network_pdu->len        += 4;
670     upper_transport_pdu_len += 4;
671     mesh_print_hex("UpperTransportPDU", upper_transport_pdu, upper_transport_pdu_len);
672     // send network pdu
673     mesh_lower_transport_send_pdu((mesh_pdu_t*) unsegmented_pdu);
674 }
675 
676 static void mesh_upper_transport_send_segmented_pdu(mesh_transport_pdu_t * transport_pdu){
677     outgoing_segmented_pdu = transport_pdu;
678     mesh_segmented_pdu_t * message_pdu   = &outgoing_segmented_message_singleton;
679     message_pdu->pdu_header.pdu_type = MESH_PDU_TYPE_SEGMENTED;
680 
681     // convert mesh_transport_pdu_t into mesh_segmented_pdu_t
682     uint16_t message_offset = 0;
683     uint16_t bytes_current_segment = 0;
684     mesh_network_pdu_t * network_pdu = NULL;
685     while (message_offset < transport_pdu->len){
686         if (bytes_current_segment == 0){
687             network_pdu = mesh_network_pdu_get();
688             btstack_assert(network_pdu != NULL);
689             btstack_linked_list_add_tail(&message_pdu->segments, (btstack_linked_item_t *) network_pdu);
690             bytes_current_segment = MESH_NETWORK_PAYLOAD_MAX;
691         }
692         uint16_t bytes_to_copy = btstack_max(bytes_current_segment, transport_pdu->len - message_offset);
693         (void) memcpy(&network_pdu->data[network_pdu->len], &transport_pdu->data[message_offset], bytes_to_copy);
694         bytes_current_segment -= bytes_to_copy;
695         network_pdu->len += bytes_to_copy;
696         message_offset += bytes_to_copy;
697     }
698     // copy meta
699     message_pdu->len = transport_pdu->len;
700     message_pdu->netkey_index = transport_pdu->netkey_index;
701     message_pdu->transmic_len = transport_pdu->transmic_len;
702     message_pdu->akf_aid_control = transport_pdu->akf_aid_control;
703     message_pdu->flags = transport_pdu->flags;
704     (void)memcpy(message_pdu->network_header, transport_pdu->network_header, 9);
705 
706     mesh_lower_transport_send_pdu((mesh_pdu_t*) message_pdu);
707 }
708 
709 static void mesh_upper_transport_send_segmented_access_pdu_ccm(void * arg){
710     crypto_active = 0;
711 
712     mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) arg;
713     mesh_print_hex("EncAccessPayload", transport_pdu->data, transport_pdu->len);
714     // store TransMIC
715     btstack_crypto_ccm_get_authentication_value(&ccm, &transport_pdu->data[transport_pdu->len]);
716     mesh_print_hex("TransMIC", &transport_pdu->data[transport_pdu->len], transport_pdu->transmic_len);
717     transport_pdu->len += transport_pdu->transmic_len;
718     mesh_print_hex("UpperTransportPDU", transport_pdu->data, transport_pdu->len);
719     mesh_upper_transport_send_segmented_pdu(transport_pdu);
720 }
721 
722 static uint8_t mesh_upper_transport_setup_unsegmented_control_pdu(mesh_network_pdu_t * network_pdu, uint16_t netkey_index, uint8_t ttl, uint16_t src, uint16_t dest, uint8_t opcode,
723                           const uint8_t * control_pdu_data, uint16_t control_pdu_len){
724 
725     if (control_pdu_len > 11) return 1;
726 
727     const mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index);
728     if (!network_key) return 1;
729 
730     uint8_t transport_pdu_data[12];
731     transport_pdu_data[0] = opcode;
732     (void)memcpy(&transport_pdu_data[1], control_pdu_data, control_pdu_len);
733     uint16_t transport_pdu_len = control_pdu_len + 1;
734 
735     // setup network_pdu
736     mesh_network_setup_pdu(network_pdu, netkey_index, network_key->nid, 1, ttl, 0, src, dest, transport_pdu_data, transport_pdu_len);
737 
738     return 0;
739 }
740 
741 static uint8_t mesh_upper_transport_setup_segmented_control_pdu(mesh_transport_pdu_t * transport_pdu, uint16_t netkey_index, uint8_t ttl, uint16_t src, uint16_t dest, uint8_t opcode,
742                           const uint8_t * control_pdu_data, uint16_t control_pdu_len){
743 
744     if (control_pdu_len > 256) return 1;
745 
746     const mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index);
747     if (!network_key) return 1;
748 
749     (void)memcpy(transport_pdu->data, control_pdu_data, control_pdu_len);
750     transport_pdu->len = control_pdu_len;
751     transport_pdu->netkey_index = netkey_index;
752     transport_pdu->akf_aid_control = opcode;
753     transport_pdu->transmic_len = 0;    // no TransMIC for control
754     mesh_transport_set_nid_ivi(transport_pdu, network_key->nid);
755     mesh_transport_set_src(transport_pdu, src);
756     mesh_transport_set_dest(transport_pdu, dest);
757     mesh_transport_set_ctl_ttl(transport_pdu, 0x80 | ttl);
758 
759     return 0;
760 }
761 
762 uint8_t mesh_upper_transport_setup_control_pdu(mesh_pdu_t * pdu, uint16_t netkey_index,
763                                                uint8_t ttl, uint16_t src, uint16_t dest, uint8_t opcode, const uint8_t * control_pdu_data, uint16_t control_pdu_len){
764     switch (pdu->pdu_type){
765         case MESH_PDU_TYPE_NETWORK:
766             return mesh_upper_transport_setup_unsegmented_control_pdu((mesh_network_pdu_t *) pdu, netkey_index, ttl, src, dest, opcode, control_pdu_data, control_pdu_len);
767         case MESH_PDU_TYPE_TRANSPORT:
768             return mesh_upper_transport_setup_segmented_control_pdu((mesh_transport_pdu_t *) pdu, netkey_index, ttl, src, dest, opcode, control_pdu_data, control_pdu_len);
769         case MESH_PDU_TYPE_SEGMENTED:
770             btstack_assert(0);
771             break;
772         default:
773             return 1;
774     }
775 }
776 
777 static uint8_t mesh_upper_transport_setup_unsegmented_access_pdu_header(mesh_unsegmented_pdu_t * unsegmented_pdu, uint16_t netkey_index,
778                                                                         uint16_t appkey_index, uint8_t ttl, uint16_t src, uint16_t dest){
779 
780     mesh_network_pdu_t * network_pdu = unsegmented_pdu->segment;
781 
782     // get app or device key
783     const mesh_transport_key_t * appkey;
784     appkey = mesh_transport_key_get(appkey_index);
785     if (appkey == NULL){
786         printf("appkey_index %x unknown\n", appkey_index);
787         return 1;
788     }
789     uint8_t akf_aid = (appkey->akf << 6) | appkey->aid;
790 
791     // lookup network by netkey_index
792     const mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index);
793     if (!network_key) return 1;
794 
795     unsegmented_pdu->appkey_index = appkey_index;
796 
797     network_pdu->data[9] = akf_aid;
798     // setup network_pdu
799     mesh_network_setup_pdu_header(network_pdu, netkey_index, network_key->nid, 0, ttl, 0, src, dest);
800     return 0;
801 }
802 
803 static uint8_t mesh_upper_transport_setup_unsegmented_access_pdu(mesh_unsegmented_pdu_t * unsegmented_pdu, uint16_t netkey_index, uint16_t appkey_index, uint8_t ttl, uint16_t src, uint16_t dest,
804                                                                  const uint8_t * access_pdu_data, uint8_t access_pdu_len){
805 
806     int status = mesh_upper_transport_setup_unsegmented_access_pdu_header(unsegmented_pdu, netkey_index, appkey_index, ttl, src, dest);
807     if (status) return status;
808 
809     // store in unsegmented pdu
810     mesh_network_pdu_t * network_pdu = unsegmented_pdu->segment;
811     (void)memcpy(&network_pdu->data[10], access_pdu_data, access_pdu_len);
812     network_pdu->len = 10 + access_pdu_len;
813     return 0;
814 }
815 
816 static uint8_t mesh_upper_transport_setup_segmented_access_pdu_header(mesh_transport_pdu_t * transport_pdu, uint16_t netkey_index,
817     uint16_t appkey_index, uint8_t ttl, uint16_t src, uint16_t dest, uint8_t szmic){
818 
819     // get app or device key
820     const mesh_transport_key_t *appkey;
821     appkey = mesh_transport_key_get(appkey_index);
822     if (appkey == NULL) {
823         printf("[!] Upper transport, setup segmented Access PDU - appkey_index %x unknown\n", appkey_index);
824         return 1;
825     }
826     uint8_t akf_aid = (appkey->akf << 6) | appkey->aid;
827 
828     // lookup network by netkey_index
829     const mesh_network_key_t *network_key = mesh_network_key_list_get(netkey_index);
830     if (!network_key) return 1;
831     if (network_key == NULL) {
832         printf("[!] Upper transport, setup segmented Access PDU - netkey_index %x unknown\n", appkey_index);
833         return 1;
834     }
835 
836     const uint8_t trans_mic_len = szmic ? 8 : 4;
837 
838     // store in transport pdu
839     transport_pdu->transmic_len = trans_mic_len;
840     transport_pdu->netkey_index = netkey_index;
841     transport_pdu->appkey_index = appkey_index;
842     transport_pdu->akf_aid_control = akf_aid;
843     mesh_transport_set_nid_ivi(transport_pdu, network_key->nid | ((mesh_get_iv_index_for_tx() & 1) << 7));
844     mesh_transport_set_src(transport_pdu, src);
845     mesh_transport_set_dest(transport_pdu, dest);
846     mesh_transport_set_ctl_ttl(transport_pdu, ttl);
847     return 0;
848 }
849 
850 
851 static uint8_t mesh_upper_transport_setup_segmented_access_pdu(mesh_transport_pdu_t * transport_pdu, uint16_t netkey_index, uint16_t appkey_index, uint8_t ttl, uint16_t src, uint16_t dest,
852                           uint8_t szmic, const uint8_t * access_pdu_data, uint8_t access_pdu_len){
853     int status = mesh_upper_transport_setup_segmented_access_pdu_header(transport_pdu, netkey_index, appkey_index, ttl, src, dest, szmic);
854     if (status) return status;
855 
856     // store in transport pdu
857     (void)memcpy(transport_pdu->data, access_pdu_data, access_pdu_len);
858     transport_pdu->len = access_pdu_len;
859     return 0;
860 }
861 uint8_t mesh_upper_transport_setup_access_pdu_header(mesh_pdu_t * pdu, uint16_t netkey_index, uint16_t appkey_index,
862                                               uint8_t ttl, uint16_t src, uint16_t dest, uint8_t szmic){
863     switch (pdu->pdu_type){
864         case MESH_PDU_TYPE_TRANSPORT:
865             return mesh_upper_transport_setup_segmented_access_pdu_header((mesh_transport_pdu_t *) pdu, netkey_index, appkey_index, ttl, src, dest, szmic);
866         case MESH_PDU_TYPE_UNSEGMENTED:
867             return mesh_upper_transport_setup_unsegmented_access_pdu_header((mesh_unsegmented_pdu_t *) pdu, netkey_index, appkey_index, ttl, src, dest);
868         default:
869             btstack_assert(false);
870             return 1;
871     }
872 }
873 
874 uint8_t mesh_upper_transport_setup_access_pdu(mesh_pdu_t * pdu, uint16_t netkey_index, uint16_t appkey_index,
875                                               uint8_t ttl, uint16_t src, uint16_t dest, uint8_t szmic,
876                                               const uint8_t * access_pdu_data, uint8_t access_pdu_len){
877     switch (pdu->pdu_type){
878         case MESH_PDU_TYPE_UNSEGMENTED:
879             return mesh_upper_transport_setup_unsegmented_access_pdu((mesh_unsegmented_pdu_t *) pdu, netkey_index, appkey_index, ttl, src, dest, access_pdu_data, access_pdu_len);
880         case MESH_PDU_TYPE_TRANSPORT:
881             return mesh_upper_transport_setup_segmented_access_pdu((mesh_transport_pdu_t *) pdu, netkey_index, appkey_index, ttl, src, dest, szmic, access_pdu_data, access_pdu_len);
882         default:
883             btstack_assert(false);
884             return 1;
885     }
886 }
887 
888 static void mesh_upper_transport_send_unsegmented_access_pdu_digest(void * arg){
889     mesh_unsegmented_pdu_t * unsegmented_pdu = (mesh_unsegmented_pdu_t *) arg;
890     mesh_network_pdu_t * network_pdu = unsegmented_pdu->segment;
891     uint8_t * access_pdu_data = mesh_network_pdu_data(network_pdu) + 1;
892     uint16_t  access_pdu_len  = mesh_network_pdu_len(network_pdu)  - 1;
893     btstack_crypto_ccm_encrypt_block(&ccm, access_pdu_len, access_pdu_data, access_pdu_data, &mesh_upper_transport_send_unsegmented_access_pdu_ccm, unsegmented_pdu);
894 }
895 
896 static mesh_transport_key_t * mesh_upper_transport_get_outgoing_appkey(uint16_t netkey_index, uint16_t appkey_index){
897     // Device Key is fixed
898     if (appkey_index == MESH_DEVICE_KEY_INDEX) {
899         return mesh_transport_key_get(appkey_index);
900     }
901 
902     // Get key refresh state from subnet
903     mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index);
904     if (subnet == NULL) return NULL;
905 
906     // identify old and new app keys for given appkey_index
907     mesh_transport_key_t * old_key = NULL;
908     mesh_transport_key_t * new_key = NULL;
909     mesh_transport_key_iterator_t it;
910     mesh_transport_key_iterator_init(&it, netkey_index);
911     while (mesh_transport_key_iterator_has_more(&it)){
912         mesh_transport_key_t * transport_key = mesh_transport_key_iterator_get_next(&it);
913         if (transport_key->appkey_index != appkey_index) continue;
914         if (transport_key->old_key == 0) {
915             new_key = transport_key;
916         } else {
917             old_key = transport_key;
918         }
919     }
920 
921     // if no key is marked as old, just use the current one
922     if (old_key == NULL) return new_key;
923 
924     // use new key if it exists in phase two
925     if ((subnet->key_refresh == MESH_KEY_REFRESH_SECOND_PHASE) && (new_key != NULL)){
926         return new_key;
927     } else {
928         return old_key;
929     }
930 }
931 
932 static void mesh_upper_transport_send_unsegmented_access_pdu(mesh_unsegmented_pdu_t * unsegmented_pdu){
933 
934     mesh_network_pdu_t * network_pdu = unsegmented_pdu->segment;
935 
936     // if dst is virtual address, lookup label uuid and hash
937     uint16_t aad_len = 0;
938     mesh_virtual_address_t * virtual_address = NULL;
939     uint16_t dst = mesh_network_dst(network_pdu);
940     if (mesh_network_address_virtual(dst)){
941         virtual_address = mesh_virtual_address_for_pseudo_dst(dst);
942         if (!virtual_address){
943             printf("No virtual address register for pseudo dst %4x\n", dst);
944             btstack_memory_mesh_network_pdu_free(network_pdu);
945             return;
946         }
947         aad_len = 16;
948         big_endian_store_16(network_pdu->data, 7, virtual_address->hash);
949     }
950 
951     // reserve slot
952     mesh_lower_transport_reserve_slot();
953 
954     // Nonce for Access Payload based on Network Sequence number: needs to be fixed now and lower layers need to send packet in right order
955     uint32_t seq = mesh_sequence_number_next();
956     mesh_network_pdu_set_seq(network_pdu, seq);
957 
958     // Dump PDU
959     printf("[+] Upper transport, send unsegmented Access PDU - dest %04x, seq %06x\n", dst, mesh_network_seq(network_pdu));
960     mesh_print_hex("Access Payload", &network_pdu->data[10], network_pdu->len - 10);
961 
962     // setup nonce
963     uint16_t appkey_index = unsegmented_pdu->appkey_index;
964     if (appkey_index == MESH_DEVICE_KEY_INDEX){
965         transport_unsegmented_setup_device_nonce(application_nonce, network_pdu);
966     } else {
967         transport_unsegmented_setup_application_nonce(application_nonce, network_pdu);
968     }
969 
970     // get app or device key
971     const mesh_transport_key_t * appkey = mesh_upper_transport_get_outgoing_appkey(network_pdu->netkey_index, appkey_index);
972     mesh_print_hex("AppOrDevKey", appkey->key, 16);
973 
974     // encrypt ccm
975     uint8_t   trans_mic_len = 4;
976     uint16_t  access_pdu_len  = mesh_network_pdu_len(network_pdu)  - 1;
977     crypto_active = 1;
978 
979     btstack_crypto_ccm_init(&ccm, appkey->key, application_nonce, access_pdu_len, aad_len, trans_mic_len);
980     if (virtual_address){
981         mesh_print_hex("LabelUUID", virtual_address->label_uuid, 16);
982         btstack_crypto_ccm_digest(&ccm, virtual_address->label_uuid, 16, &mesh_upper_transport_send_unsegmented_access_pdu_digest, unsegmented_pdu);
983     } else {
984         mesh_upper_transport_send_unsegmented_access_pdu_digest(unsegmented_pdu);
985     }
986 }
987 
988 static void mesh_upper_transport_send_segmented_access_pdu_digest(void *arg){
989     mesh_transport_pdu_t * transport_pdu = (mesh_transport_pdu_t *) arg;
990     uint16_t  access_pdu_len  = transport_pdu->len;
991     uint8_t * access_pdu_data = transport_pdu->data;
992     btstack_crypto_ccm_encrypt_block(&ccm, access_pdu_len,access_pdu_data, access_pdu_data, &mesh_upper_transport_send_segmented_access_pdu_ccm, transport_pdu);
993 }
994 
995 static void mesh_upper_transport_send_segmented_access_pdu(mesh_transport_pdu_t * transport_pdu){
996 
997     // if dst is virtual address, lookup label uuid and hash
998     uint16_t aad_len = 0;
999     mesh_virtual_address_t * virtual_address = NULL;
1000     uint16_t dst = mesh_transport_dst(transport_pdu);
1001     if (mesh_network_address_virtual(dst)){
1002         virtual_address = mesh_virtual_address_for_pseudo_dst(dst);
1003         if (!virtual_address){
1004             printf("No virtual address register for pseudo dst %4x\n", dst);
1005             btstack_memory_mesh_transport_pdu_free(transport_pdu);
1006             return;
1007         }
1008         // printf("Using hash %4x with LabelUUID: ", virtual_address->hash);
1009         // printf_hexdump(virtual_address->label_uuid, 16);
1010         aad_len = 16;
1011         big_endian_store_16(transport_pdu->network_header, 7, virtual_address->hash);
1012     }
1013 
1014     // get app or device key
1015     uint16_t appkey_index = transport_pdu->appkey_index;
1016     const mesh_transport_key_t * appkey = mesh_upper_transport_get_outgoing_appkey(transport_pdu->netkey_index, appkey_index);
1017     if (appkey == NULL){
1018         printf("AppKey %04x not found, drop message\n", appkey_index);
1019         btstack_memory_mesh_transport_pdu_free(transport_pdu);
1020         return;
1021     }
1022 
1023     // reserve slot
1024     mesh_lower_transport_reserve_slot();
1025 
1026     // reserve one sequence number, which is also used to encrypt access payload
1027     uint32_t seq = mesh_sequence_number_next();
1028     transport_pdu->flags |= MESH_TRANSPORT_FLAG_SEQ_RESERVED;
1029     mesh_transport_set_seq(transport_pdu, seq);
1030 
1031     // Dump PDU
1032     printf("[+] Upper transport, send segmented Access PDU - dest %04x, seq %06x\n", dst, mesh_transport_seq(transport_pdu));
1033     mesh_print_hex("Access Payload", transport_pdu->data, transport_pdu->len);
1034 
1035     // setup nonce - uses dst, so after pseudo address translation
1036     if (appkey_index == MESH_DEVICE_KEY_INDEX){
1037         transport_segmented_setup_device_nonce(application_nonce, (mesh_pdu_t *) transport_pdu);
1038     } else {
1039         transport_segmented_setup_application_nonce(application_nonce, (mesh_pdu_t *) transport_pdu);
1040     }
1041 
1042     // Dump key
1043     mesh_print_hex("AppOrDevKey", appkey->key, 16);
1044 
1045     // encrypt ccm
1046     uint8_t   transmic_len    = transport_pdu->transmic_len;
1047     uint16_t  access_pdu_len  = transport_pdu->len;
1048     crypto_active = 1;
1049     btstack_crypto_ccm_init(&ccm, appkey->key, application_nonce, access_pdu_len, aad_len, transmic_len);
1050     if (virtual_address){
1051         mesh_print_hex("LabelUUID", virtual_address->label_uuid, 16);
1052         btstack_crypto_ccm_digest(&ccm, virtual_address->label_uuid, 16, &mesh_upper_transport_send_segmented_access_pdu_digest, transport_pdu);
1053     } else {
1054         mesh_upper_transport_send_segmented_access_pdu_digest(transport_pdu);
1055     }
1056 }
1057 
1058 static void mesh_upper_transport_send_unsegmented_control_pdu(mesh_network_pdu_t * network_pdu){
1059     // reserve slot
1060     mesh_lower_transport_reserve_slot();
1061     // reserve sequence number
1062     uint32_t seq = mesh_sequence_number_next();
1063     mesh_network_pdu_set_seq(network_pdu, seq);
1064     // Dump PDU
1065     uint8_t opcode = network_pdu->data[9];
1066     printf("[+] Upper transport, send unsegmented Control PDU %p - seq %06x opcode %02x\n", network_pdu, seq, opcode);
1067     mesh_print_hex("Access Payload", &network_pdu->data[10], network_pdu->len - 10);
1068     // wrap into mesh-unsegmented-pdu
1069     outgoing_unsegmented_pdu.pdu_header.pdu_type = MESH_PDU_TYPE_UNSEGMENTED;
1070     outgoing_unsegmented_pdu.segment = network_pdu;
1071 
1072     // send
1073     mesh_lower_transport_send_pdu((mesh_pdu_t *) &outgoing_unsegmented_pdu);
1074 }
1075 
1076 static void mesh_upper_transport_send_segmented_control_pdu(mesh_transport_pdu_t * transport_pdu){
1077     // reserve slot
1078     mesh_lower_transport_reserve_slot();
1079     // reserve sequence number
1080     uint32_t seq = mesh_sequence_number_next();
1081     transport_pdu->flags |= MESH_TRANSPORT_FLAG_SEQ_RESERVED;
1082     mesh_transport_set_seq(transport_pdu, seq);
1083     // Dump PDU
1084     uint8_t opcode = transport_pdu->data[0];
1085     printf("[+] Upper transport, send segmented Control PDU %p - seq %06x opcode %02x\n", transport_pdu, seq, opcode);
1086     mesh_print_hex("Access Payload", &transport_pdu->data[1], transport_pdu->len - 1);
1087     // send
1088     mesh_upper_transport_send_segmented_pdu(transport_pdu);
1089 }
1090 
1091 static void mesh_upper_transport_run(void){
1092 
1093     while(!btstack_linked_list_empty(&upper_transport_incoming)){
1094 
1095         if (crypto_active) return;
1096 
1097         // peek at next message
1098         mesh_pdu_t * pdu =  (mesh_pdu_t *) btstack_linked_list_get_first_item(&upper_transport_incoming);
1099         mesh_network_pdu_t   * network_pdu;
1100         mesh_transport_pdu_t * transport_pdu;
1101         mesh_segmented_pdu_t   * message_pdu;
1102         mesh_unsegmented_pdu_t * unsegmented_pdu;
1103         switch (pdu->pdu_type){
1104             case MESH_PDU_TYPE_UNSEGMENTED:
1105                 unsegmented_pdu = (mesh_unsegmented_pdu_t *) pdu;
1106                 network_pdu = unsegmented_pdu->segment;
1107                 btstack_assert(network_pdu != NULL);
1108                 incoming_unsegmented_pdu_raw = unsegmented_pdu;
1109                 // control?
1110                 if (mesh_network_control(network_pdu)) {
1111                     (void) btstack_linked_list_pop(&upper_transport_incoming);
1112                     mesh_upper_unsegmented_control_message_received(unsegmented_pdu);
1113                     break;
1114                 } else {
1115                     incoming_network_pdu_decoded = mesh_network_pdu_get();
1116                     if (!incoming_network_pdu_decoded) return;
1117 
1118                     (void) btstack_linked_list_pop(&upper_transport_incoming);
1119 
1120                     // use pre-allocated message pdu
1121                     incoming_message_pdu_singleton.pdu_header.pdu_type = MESH_PDU_TYPE_SEGMENTED;
1122                     btstack_linked_list_add(&incoming_message_pdu_singleton.segments, (btstack_linked_item_t *) incoming_network_pdu_decoded);
1123                     mesh_upper_transport_process_unsegmented_access_message();
1124                 }
1125                 break;
1126             case MESH_PDU_TYPE_SEGMENTED:
1127                 message_pdu = (mesh_segmented_pdu_t *) pdu;
1128                 uint8_t ctl = mesh_message_ctl(message_pdu);
1129                 if (ctl){
1130                     printf("Ignoring Segmented Control Message\n");
1131                     (void) btstack_linked_list_pop(&upper_transport_incoming);
1132                     mesh_lower_transport_message_processed_by_higher_layer(pdu);
1133                 } else {
1134 
1135                     incoming_access_pdu_encrypted = &incoming_access_pdu_encrypted_singleton;
1136                     incoming_access_pdu_encrypted->pdu_header.pdu_type = MESH_PDU_TYPE_ACCESS;
1137 
1138                     // flatten segmented message into mesh_transport_pdu_t
1139 
1140                     // assemble payload
1141                     while (message_pdu->segments){
1142                         mesh_network_pdu_t * segment  = (mesh_network_pdu_t *) btstack_linked_list_pop(&message_pdu->segments);
1143                         // get segment n
1144                         uint8_t * lower_transport_pdu = mesh_network_pdu_data(segment);
1145                         uint8_t   seg_o               =  ( big_endian_read_16(lower_transport_pdu, 2) >> 5) & 0x001f;
1146                         uint8_t * segment_data = &lower_transport_pdu[4];
1147                         (void)memcpy(&incoming_access_pdu_encrypted->data[seg_o * 12], segment_data, 12);
1148                     }
1149 
1150                     // copy meta data into encrypted pdu buffer
1151                     incoming_access_pdu_encrypted->len =  message_pdu->len;
1152                     incoming_access_pdu_encrypted->netkey_index =  message_pdu->netkey_index;
1153                     incoming_access_pdu_encrypted->transmic_len =  message_pdu->transmic_len;
1154                     incoming_access_pdu_encrypted->akf_aid_control =  message_pdu->akf_aid_control;
1155                     (void)memcpy(incoming_access_pdu_encrypted->network_header, message_pdu->network_header, 9);
1156 
1157                     mesh_print_hex("Assembled payload", incoming_access_pdu_encrypted->data, incoming_access_pdu_encrypted->len);
1158 
1159                     // copy meta data into decrypted pdu buffer
1160                     incoming_access_pdu_decrypted = &incoming_access_pdu_decrypted_singleton;
1161                     incoming_access_pdu_decrypted->pdu_header.pdu_type = MESH_PDU_TYPE_ACCESS;
1162                     incoming_access_pdu_decrypted->len =  message_pdu->len;
1163                     incoming_access_pdu_decrypted->netkey_index =  message_pdu->netkey_index;
1164                     incoming_access_pdu_decrypted->transmic_len =  message_pdu->transmic_len;
1165                     incoming_access_pdu_decrypted->akf_aid_control =  message_pdu->akf_aid_control;
1166                     (void)memcpy(incoming_access_pdu_decrypted->network_header, message_pdu->network_header, 9);
1167 
1168                     // free mesh message
1169                     mesh_lower_transport_message_processed_by_higher_layer((mesh_pdu_t *)message_pdu);
1170 
1171                     // get encoded transport pdu and start processing
1172                     (void) btstack_linked_list_pop(&upper_transport_incoming);
1173                     mesh_upper_transport_process_message();
1174                 }
1175                 break;
1176             default:
1177                 btstack_assert(0);
1178                 break;
1179         }
1180     }
1181 
1182     while (!btstack_linked_list_empty(&upper_transport_outgoing)){
1183 
1184         if (crypto_active) break;
1185 
1186         if (outgoing_segmented_pdu != NULL) break;
1187 
1188         mesh_pdu_t * pdu =  (mesh_pdu_t *) btstack_linked_list_get_first_item(&upper_transport_outgoing);
1189         if (mesh_lower_transport_can_send_to_dest(mesh_pdu_dst(pdu)) == 0) break;
1190 
1191         (void) btstack_linked_list_pop(&upper_transport_outgoing);
1192 
1193         if (mesh_pdu_ctl(pdu)){
1194             switch (pdu->pdu_type){
1195                 case MESH_PDU_TYPE_NETWORK:
1196                     mesh_upper_transport_send_unsegmented_control_pdu((mesh_network_pdu_t *) pdu);
1197                     break;
1198                 case MESH_PDU_TYPE_SEGMENTED:
1199                     btstack_assert(0);
1200                     break;
1201                 case MESH_PDU_TYPE_TRANSPORT:
1202                     mesh_upper_transport_send_segmented_control_pdu((mesh_transport_pdu_t *) pdu);
1203                     break;
1204                 default:
1205                     break;
1206             }
1207         } else {
1208             switch (pdu->pdu_type){
1209                 case MESH_PDU_TYPE_NETWORK:
1210                     btstack_assert(0);
1211                     break;
1212                 case MESH_PDU_TYPE_UNSEGMENTED:
1213                     mesh_upper_transport_send_unsegmented_access_pdu((mesh_unsegmented_pdu_t *) pdu);
1214                     break;
1215                 case MESH_PDU_TYPE_TRANSPORT:
1216                     mesh_upper_transport_send_segmented_access_pdu((mesh_transport_pdu_t *) pdu);
1217                     break;
1218                 default:
1219                     break;
1220             }
1221         }
1222     }
1223 }
1224 
1225 void mesh_upper_transport_pdu_free(mesh_pdu_t * pdu){
1226     mesh_network_pdu_t   * network_pdu;
1227     mesh_transport_pdu_t * transport_pdu;
1228     mesh_segmented_pdu_t   * message_pdu;
1229     switch (pdu->pdu_type) {
1230         case MESH_PDU_TYPE_NETWORK:
1231             network_pdu = (mesh_network_pdu_t *) pdu;
1232             mesh_network_pdu_free(network_pdu);
1233             break;
1234         case MESH_PDU_TYPE_TRANSPORT:
1235             transport_pdu = (mesh_transport_pdu_t *) pdu;
1236             mesh_transport_pdu_free(transport_pdu);
1237             break;
1238         case MESH_PDU_TYPE_SEGMENTED:
1239             message_pdu = (mesh_segmented_pdu_t *) pdu;
1240             mesh_message_pdu_free(message_pdu);
1241         default:
1242             break;
1243     }
1244 }
1245 
1246 void mesh_upper_transport_message_processed_by_higher_layer(mesh_pdu_t * pdu){
1247     crypto_active = 0;
1248     switch (pdu->pdu_type){
1249         case MESH_PDU_TYPE_ACCESS:
1250             mesh_upper_transport_process_segmented_access_message_done((mesh_access_pdu_t *) pdu);
1251             break;
1252         case MESH_PDU_TYPE_SEGMENTED:
1253             mesh_upper_transport_process_message_done((mesh_segmented_pdu_t *) pdu);
1254             break;
1255         case MESH_PDU_TYPE_UNSEGMENTED:
1256             mesh_upper_transport_process_unsegmented_message_done(pdu);
1257             break;
1258         default:
1259             btstack_assert(0);
1260             break;
1261     }
1262 }
1263 
1264 void mesh_upper_transport_register_access_message_handler(void (*callback)(mesh_pdu_t *pdu)){
1265     mesh_access_message_handler = callback;
1266 }
1267 
1268 void mesh_upper_transport_register_control_message_handler(void (*callback)(mesh_pdu_t *pdu)){
1269     mesh_control_message_handler = callback;
1270 }
1271 
1272 void mesh_upper_transport_set_higher_layer_handler(void (*pdu_handler)( mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu)){
1273     higher_layer_handler = pdu_handler;
1274 }
1275 
1276 void mesh_upper_transport_init(){
1277     mesh_lower_transport_set_higher_layer_handler(&mesh_upper_transport_pdu_handler);
1278 }
1279