mesh: split mesh_upper_transport_process_segmented_message_done into control and access variant

This commit is contained in:
Matthias Ringwald 2020-03-16 11:17:07 +01:00
parent 84011563af
commit 7667b5d16d

View File

@ -84,6 +84,10 @@ static mesh_transport_pdu_t incoming_transport_pdu_singleton;
static mesh_transport_pdu_t * incoming_transport_pdu_raw;
static mesh_transport_pdu_t * incoming_transport_pdu_decoded;
static mesh_message_pdu_t incoming_message_pdu_singleton;
static mesh_access_pdu_t incoming_access_pdu_encrypted;
static mesh_access_pdu_t incoming_access_pdu_decrypted;
static uint8_t application_nonce[13];
static btstack_crypto_ccm_t ccm;
static mesh_transport_key_and_virtual_address_iterator_t mesh_transport_key_it;
@ -173,6 +177,11 @@ static void mesh_transport_key_and_virtual_address_iterator_next(mesh_transport_
// UPPER TRANSPORT
static uint16_t mesh_access_dst(mesh_access_pdu_t * access_pdu){
return big_endian_read_16(access_pdu->network_header, 7);
}
// stub lower transport
static void mesh_upper_transport_dump_pdus(const char *name, btstack_linked_list_t *list){
@ -305,17 +314,20 @@ static void mesh_upper_transport_process_unsegmented_message_done(mesh_pdu_t * p
mesh_upper_transport_run();
}
static void mesh_upper_transport_process_segmented_message_done(mesh_transport_pdu_t *transport_pdu){
static void mesh_upper_transport_process_segmented_access_message_done(mesh_transport_pdu_t *transport_pdu){
crypto_active = 0;
if (mesh_transport_ctl(transport_pdu)) {
btstack_assert(0);
} else {
mesh_transport_pdu_free(transport_pdu);
incoming_transport_pdu_raw = NULL;
}
btstack_assert(mesh_transport_ctl(transport_pdu) == 0);
mesh_transport_pdu_free(transport_pdu);
incoming_transport_pdu_raw = NULL;
mesh_upper_transport_run();
}
static void mesh_upper_transport_process_segmented_control_message_done(mesh_transport_pdu_t *transport_pdu){
crypto_active = 0;
btstack_assert(mesh_transport_ctl(transport_pdu) != 0);
btstack_assert(0);
}
static void mesh_upper_transport_validate_unsegmented_message_ccm(void * arg){
UNUSED(arg);
@ -393,16 +405,11 @@ static void mesh_upper_transport_validate_segmented_message_ccm(void * arg){
}
// pass to upper layer
if (mesh_access_message_handler){
mesh_pdu_t * pdu = (mesh_pdu_t*) incoming_transport_pdu_decoded;
incoming_network_pdu_decoded = NULL;
mesh_access_message_handler(pdu);
} else {
printf("[!] Unhandled Segmented Access/Control message\n");
// done
mesh_upper_transport_process_segmented_message_done(incoming_transport_pdu_decoded);
}
btstack_assert(mesh_access_message_handler != NULL);
mesh_pdu_t * pdu = (mesh_pdu_t*) incoming_transport_pdu_decoded;
incoming_network_pdu_decoded = NULL;
mesh_access_message_handler(pdu);
printf("\n");
} else {
@ -413,7 +420,7 @@ static void mesh_upper_transport_validate_segmented_message_ccm(void * arg){
} else {
printf("TransMIC does not match device key, done\n");
// done
mesh_upper_transport_process_segmented_message_done(incoming_transport_pdu_decoded);
mesh_upper_transport_process_segmented_access_message_done(incoming_transport_pdu_decoded);
}
}
}
@ -483,12 +490,13 @@ static void mesh_upper_transport_validate_unsegmented_message(void){
}
static void mesh_upper_transport_validate_segmented_message(void){
#if 1
uint8_t * upper_transport_pdu_data = incoming_transport_pdu_decoded->data;
uint8_t upper_transport_pdu_len = incoming_transport_pdu_decoded->len - incoming_transport_pdu_decoded->transmic_len;
if (!mesh_transport_key_and_virtual_address_iterator_has_more(&mesh_transport_key_it)){
printf("No valid transport key found\n");
mesh_upper_transport_process_segmented_message_done(incoming_transport_pdu_decoded);
mesh_upper_transport_process_segmented_access_message_done(incoming_transport_pdu_decoded);
return;
}
mesh_transport_key_and_virtual_address_iterator_next(&mesh_transport_key_it);
@ -519,6 +527,44 @@ static void mesh_upper_transport_validate_segmented_message(void){
} else {
mesh_upper_transport_validate_segmented_message_digest(NULL);
}
#else
uint8_t * upper_transport_pdu_data = incoming_access_pdu_encrypted.data;
uint8_t upper_transport_pdu_len = incoming_access_pdu_encrypted.len - incoming_access_pdu_encrypted.transmic_len;
if (!mesh_transport_key_and_virtual_address_iterator_has_more(&mesh_transport_key_it)){
printf("No valid transport key found\n");
mesh_upper_transport_process_segmented_message_done(&incoming_access_pdu_encrypted);
return;
}
mesh_transport_key_and_virtual_address_iterator_next(&mesh_transport_key_it);
const mesh_transport_key_t * message_key = mesh_transport_key_it.key;
if (message_key->akf){
transport_segmented_setup_application_nonce(application_nonce, incoming_transport_pdu_raw);
} else {
transport_segmented_setup_device_nonce(application_nonce, incoming_transport_pdu_raw);
}
// store application / device key index
mesh_print_hex("AppOrDevKey", message_key->key, 16);
incoming_transport_pdu_decoded->appkey_index = message_key->appkey_index;
mesh_print_hex("EncAccessPayload", upper_transport_pdu_data, upper_transport_pdu_len);
// decrypt ccm
crypto_active = 1;
uint16_t aad_len = 0;
if (mesh_network_address_virtual(mesh_transport_dst(incoming_transport_pdu_decoded))){
aad_len = 16;
}
btstack_crypto_ccm_init(&ccm, message_key->key, application_nonce, upper_transport_pdu_len, aad_len, incoming_transport_pdu_decoded->transmic_len);
if (aad_len){
btstack_crypto_ccm_digest(&ccm, (uint8_t *) mesh_transport_key_it.address->label_uuid, aad_len, &mesh_upper_transport_validate_segmented_message_digest, NULL);
} else {
mesh_upper_transport_validate_segmented_message_digest(NULL);
}
#endif
}
static void mesh_upper_transport_process_unsegmented_access_message(void){
@ -546,6 +592,7 @@ static void mesh_upper_transport_process_unsegmented_access_message(void){
}
static void mesh_upper_transport_process_message(void){
#if 1
// copy original pdu
(void)memcpy(incoming_transport_pdu_decoded, incoming_transport_pdu_raw,
sizeof(mesh_transport_pdu_t));
@ -564,6 +611,22 @@ static void mesh_upper_transport_process_message(void){
mesh_transport_key_and_virtual_address_iterator_init(&mesh_transport_key_it, mesh_transport_dst(incoming_transport_pdu_decoded),
incoming_transport_pdu_decoded->netkey_index, akf, aid);
mesh_upper_transport_validate_segmented_message();
#else
uint8_t * upper_transport_pdu = incoming_access_pdu_encrypted.data;
uint8_t upper_transport_pdu_len = incoming_access_pdu_encrypted.len - incoming_access_pdu_encrypted.transmic_len;
mesh_print_hex("Upper Transport pdu", upper_transport_pdu, upper_transport_pdu_len);
uint8_t aid = incoming_access_pdu_encrypted.akf_aid_control & 0x3f;
uint8_t akf = (incoming_access_pdu_encrypted.akf_aid_control & 0x40) >> 6;
printf("AKF: %u\n", akf);
printf("AID: %02x\n", aid);
mesh_transport_key_and_virtual_address_iterator_init(&mesh_transport_key_it, mesh_access_dst(&incoming_access_pdu_encrypted),
incoming_access_pdu_encrypted.netkey_index, akf, aid);
mesh_upper_transport_validate_segmented_message();
#endif
}
static void mesh_upper_transport_message_received(mesh_pdu_t * pdu){
@ -1034,6 +1097,7 @@ static void mesh_upper_transport_run(void){
(void) btstack_linked_list_pop(&upper_transport_incoming);
mesh_lower_transport_message_processed_by_higher_layer(pdu);
} else {
#if 1
incoming_transport_pdu_decoded = mesh_transport_pdu_get();
if (!incoming_transport_pdu_decoded) return;
@ -1064,7 +1128,37 @@ static void mesh_upper_transport_run(void){
(void)memcpy(transport_pdu->network_header, message_pdu->network_header, 9);
mesh_print_hex("Assembled payload", transport_pdu->data, transport_pdu->len);
#else
incoming_access_pdu_encrypted.pdu_header.pdu_type = MESH_PDU_TYPE_ACCESS;
// flatten segmented message into mesh_transport_pdu_t
// assemble payload
while (message_pdu->segments){
mesh_network_pdu_t * segment = (mesh_network_pdu_t *) btstack_linked_list_pop(&message_pdu->segments);
// get segment n
uint8_t * lower_transport_pdu = mesh_network_pdu_data(segment);
uint8_t seg_o = ( big_endian_read_16(lower_transport_pdu, 2) >> 5) & 0x001f;
uint8_t * segment_data = &lower_transport_pdu[4];
(void)memcpy(&incoming_access_pdu_encrypted.data[seg_o * 12], segment_data, 12);
}
// copy meta data into encrypted pdu buffer
incoming_access_pdu_encrypted.len = message_pdu->len;
incoming_access_pdu_encrypted.netkey_index = message_pdu->netkey_index;
incoming_access_pdu_encrypted.transmic_len = message_pdu->transmic_len;
incoming_access_pdu_encrypted.akf_aid_control = message_pdu->akf_aid_control;
(void)memcpy(incoming_access_pdu_encrypted.network_header, message_pdu->network_header, 9);
mesh_print_hex("Assembled payload", incoming_access_pdu_encrypted.data, incoming_access_pdu_encrypted.len);
// copy meta data into decrypted pdu buffer
incoming_access_pdu_decrypted.len = message_pdu->len;
incoming_access_pdu_decrypted.netkey_index = message_pdu->netkey_index;
incoming_access_pdu_decrypted.transmic_len = message_pdu->transmic_len;
incoming_access_pdu_decrypted.akf_aid_control = message_pdu->akf_aid_control;
(void)memcpy(incoming_access_pdu_decrypted.network_header, message_pdu->network_header, 9);
#endif
// free mesh message
mesh_lower_transport_message_processed_by_higher_layer((mesh_pdu_t *)message_pdu);
@ -1146,7 +1240,7 @@ void mesh_upper_transport_message_processed_by_higher_layer(mesh_pdu_t * pdu){
crypto_active = 0;
switch (pdu->pdu_type){
case MESH_PDU_TYPE_TRANSPORT:
mesh_upper_transport_process_segmented_message_done((mesh_transport_pdu_t *) pdu);
mesh_upper_transport_process_segmented_access_message_done((mesh_transport_pdu_t *) pdu);
break;
case MESH_PDU_TYPE_MESSAGE:
mesh_upper_transport_process_message_done((mesh_message_pdu_t *) pdu);