mesh: sort upper transport

This commit is contained in:
Matthias Ringwald 2020-03-14 17:33:24 +01:00
parent e3bfb018e7
commit cae44b3ba8

View File

@ -57,17 +57,6 @@
// TODO: extract mesh_pdu functions into lower transport or network // TODO: extract mesh_pdu functions into lower transport or network
#include "mesh/mesh_access.h" #include "mesh/mesh_access.h"
static void (*higher_layer_handler)( mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu);
static void mesh_print_hex(const char * name, const uint8_t * data, uint16_t len){
printf("%-20s ", name);
printf_hexdump(data, len);
}
// static void mesh_print_x(const char * name, uint32_t value){
// printf("%20s: 0x%x", name, (int) value);
// }
// combined key x address iterator for upper transport decryption // combined key x address iterator for upper transport decryption
typedef struct { typedef struct {
@ -82,6 +71,61 @@ typedef struct {
// key info // key info
} mesh_transport_key_and_virtual_address_iterator_t; } mesh_transport_key_and_virtual_address_iterator_t;
static void (*higher_layer_handler)( mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu);
static void mesh_upper_transport_validate_unsegmented_message(void);
static void mesh_upper_transport_validate_segmented_message(void);
static void mesh_upper_transport_run(void);
static int crypto_active;
static mesh_unsegmented_incoming_pdu_t * incoming_unsegmented_pdu_raw;
static mesh_network_pdu_t * incoming_network_pdu_decoded;
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 uint8_t application_nonce[13];
static btstack_crypto_ccm_t ccm;
static mesh_transport_key_and_virtual_address_iterator_t mesh_transport_key_it;
// upper transport callbacks - in access layer
static void (*mesh_access_message_handler)(mesh_pdu_t * pdu);
static void (*mesh_control_message_handler)(mesh_pdu_t * pdu);
// incoming unsegmented (network) and segmented (transport) control and access messages
static btstack_linked_list_t upper_transport_incoming;
// outgoing unsegmented (network) and segmented (uppert_transport_outgoing) control and access messages
static btstack_linked_list_t upper_transport_outgoing;
// TODO: higher layer define used for assert
#define MESH_ACCESS_OPCODE_NOT_SET 0xFFFFFFFEu
void mesh_upper_transport_send_access_pdu(mesh_pdu_t *pdu){
btstack_assert(pdu->pdu_type != MESH_PDU_TYPE_NETWORK);
btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
mesh_upper_transport_run();
}
void mesh_upper_transport_send_control_pdu(mesh_pdu_t * pdu){
if (pdu->pdu_type == MESH_PDU_TYPE_NETWORK){
btstack_assert( ((mesh_network_pdu_t *) pdu)->len >= 9);
}
btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
mesh_upper_transport_run();
}
static void mesh_print_hex(const char * name, const uint8_t * data, uint16_t len){
printf("%-20s ", name);
printf_hexdump(data, len);
}
// static void mesh_print_x(const char * name, uint32_t value){
// printf("%20s: 0x%x", name, (int) value);
// }
static void mesh_transport_key_and_virtual_address_iterator_init(mesh_transport_key_and_virtual_address_iterator_t *it, static void mesh_transport_key_and_virtual_address_iterator_init(mesh_transport_key_and_virtual_address_iterator_t *it,
uint16_t dst, uint16_t netkey_index, uint8_t akf, uint16_t dst, uint16_t netkey_index, uint8_t akf,
uint8_t aid) { uint8_t aid) {
@ -131,32 +175,6 @@ static void mesh_transport_key_and_virtual_address_iterator_next(mesh_transport_
// stub lower transport // stub lower transport
static void mesh_upper_transport_validate_unsegmented_message(void);
static void mesh_upper_transport_validate_segmented_message(void);
static void mesh_upper_transport_run(void);
static int crypto_active;
static mesh_unsegmented_incoming_pdu_t * incoming_unsegmented_pdu_raw;
static mesh_network_pdu_t * incoming_network_pdu_decoded;
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 uint8_t application_nonce[13];
static btstack_crypto_ccm_t ccm;
static mesh_transport_key_and_virtual_address_iterator_t mesh_transport_key_it;
// upper transport callbacks - in access layer
static void (*mesh_access_message_handler)(mesh_pdu_t * pdu);
static void (*mesh_control_message_handler)(mesh_pdu_t * pdu);
// incoming unsegmented (network) and segmented (transport) control and access messages
static btstack_linked_list_t upper_transport_incoming;
// outgoing unsegmented (network) and segmented (uppert_transport_outgoing) control and access messages
static btstack_linked_list_t upper_transport_outgoing;
static void mesh_upper_transport_dump_pdus(const char *name, btstack_linked_list_t *list){ static void mesh_upper_transport_dump_pdus(const char *name, btstack_linked_list_t *list){
printf("List: %s:\n", name); printf("List: %s:\n", name);
btstack_linked_list_iterator_t it; btstack_linked_list_iterator_t it;
@ -191,6 +209,54 @@ void mesh_upper_transport_reset(void){
mesh_upper_transport_reset_pdus(&upper_transport_incoming); mesh_upper_transport_reset_pdus(&upper_transport_incoming);
} }
static uint32_t iv_index_for_ivi_nid(uint8_t ivi_nid){
// get IV Index and IVI
uint32_t iv_index = mesh_get_iv_index();
int ivi = ivi_nid >> 7;
// if least significant bit differs, use previous IV Index
if ((iv_index & 1 ) ^ ivi){
iv_index--;
}
return iv_index;
}
static void transport_unsegmented_setup_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[1] = 0x00; // SZMIC if a Segmented Access message or 0 for all other message formats
(void)memcpy(&nonce[2], &network_pdu->data[2], 7);
big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(network_pdu->data[0]));
}
static void transport_segmented_setup_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[1] = transport_pdu->transmic_len == 8 ? 0x80 : 0x00;
(void)memcpy(&nonce[2], &transport_pdu->network_header[2], 7);
big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(transport_pdu->network_header[0]));
}
static void transport_unsegmented_setup_application_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[0] = 0x01;
transport_unsegmented_setup_nonce(nonce, network_pdu);
mesh_print_hex("AppNonce", nonce, 13);
}
static void transport_unsegmented_setup_device_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[0] = 0x02;
transport_unsegmented_setup_nonce(nonce, network_pdu);
mesh_print_hex("DeviceNonce", nonce, 13);
}
static void transport_segmented_setup_application_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[0] = 0x01;
transport_segmented_setup_nonce(nonce, transport_pdu);
mesh_print_hex("AppNonce", nonce, 13);
}
static void transport_segmented_setup_device_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[0] = 0x02;
transport_segmented_setup_nonce(nonce, transport_pdu);
mesh_print_hex("DeviceNonce", nonce, 13);
}
static void mesh_upper_unsegmented_control_message_received(mesh_network_pdu_t * network_pdu){ static void mesh_upper_unsegmented_control_message_received(mesh_network_pdu_t * network_pdu){
uint8_t * lower_transport_pdu = mesh_network_pdu_data(network_pdu); uint8_t * lower_transport_pdu = mesh_network_pdu_data(network_pdu);
uint8_t opcode = lower_transport_pdu[0]; uint8_t opcode = lower_transport_pdu[0];
@ -245,54 +311,6 @@ static void mesh_upper_transport_process_segmented_message_done(mesh_transport_p
mesh_upper_transport_run(); mesh_upper_transport_run();
} }
static uint32_t iv_index_for_ivi_nid(uint8_t ivi_nid){
// get IV Index and IVI
uint32_t iv_index = mesh_get_iv_index();
int ivi = ivi_nid >> 7;
// if least significant bit differs, use previous IV Index
if ((iv_index & 1 ) ^ ivi){
iv_index--;
}
return iv_index;
}
static void transport_unsegmented_setup_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[1] = 0x00; // SZMIC if a Segmented Access message or 0 for all other message formats
(void)memcpy(&nonce[2], &network_pdu->data[2], 7);
big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(network_pdu->data[0]));
}
static void transport_segmented_setup_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[1] = transport_pdu->transmic_len == 8 ? 0x80 : 0x00;
(void)memcpy(&nonce[2], &transport_pdu->network_header[2], 7);
big_endian_store_32(nonce, 9, iv_index_for_ivi_nid(transport_pdu->network_header[0]));
}
static void transport_unsegmented_setup_application_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[0] = 0x01;
transport_unsegmented_setup_nonce(nonce, network_pdu);
mesh_print_hex("AppNonce", nonce, 13);
}
static void transport_unsegmented_setup_device_nonce(uint8_t * nonce, const mesh_network_pdu_t * network_pdu){
nonce[0] = 0x02;
transport_unsegmented_setup_nonce(nonce, network_pdu);
mesh_print_hex("DeviceNonce", nonce, 13);
}
static void transport_segmented_setup_application_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[0] = 0x01;
transport_segmented_setup_nonce(nonce, transport_pdu);
mesh_print_hex("AppNonce", nonce, 13);
}
static void transport_segmented_setup_device_nonce(uint8_t * nonce, const mesh_transport_pdu_t * transport_pdu){
nonce[0] = 0x02;
transport_segmented_setup_nonce(nonce, transport_pdu);
mesh_print_hex("DeviceNonce", nonce, 13);
}
static void mesh_upper_transport_validate_unsegmented_message_ccm(void * arg){ static void mesh_upper_transport_validate_unsegmented_message_ccm(void * arg){
UNUSED(arg); UNUSED(arg);
@ -395,23 +413,6 @@ static void mesh_upper_transport_validate_segmented_message_ccm(void * arg){
} }
} }
void mesh_upper_transport_message_processed_by_higher_layer(mesh_pdu_t * pdu){
crypto_active = 0;
switch (pdu->pdu_type){
case MESH_PDU_TYPE_NETWORK:
mesh_upper_transport_process_unsegmented_message_done((mesh_network_pdu_t *) pdu);
break;
case MESH_PDU_TYPE_TRANSPORT:
mesh_upper_transport_process_segmented_message_done((mesh_transport_pdu_t *) pdu);
break;
case MESH_PDU_TYPE_MESSAGE:
mesh_upper_transport_process_message_done((mesh_message_pdu_t *) pdu);
break;
default:
break;
}
}
static void mesh_upper_transport_validate_segmented_message_digest(void * arg){ static void mesh_upper_transport_validate_segmented_message_digest(void * arg){
UNUSED(arg); UNUSED(arg);
uint8_t upper_transport_pdu_len = incoming_transport_pdu_raw->len - incoming_transport_pdu_raw->transmic_len; uint8_t upper_transport_pdu_len = incoming_transport_pdu_raw->len - incoming_transport_pdu_raw->transmic_len;
@ -565,26 +566,7 @@ static void mesh_upper_transport_message_received(mesh_pdu_t * pdu){
mesh_upper_transport_run(); mesh_upper_transport_run();
} }
void mesh_upper_transport_pdu_free(mesh_pdu_t * pdu){
mesh_network_pdu_t * network_pdu;
mesh_transport_pdu_t * transport_pdu;
mesh_message_pdu_t * message_pdu;
switch (pdu->pdu_type) {
case MESH_PDU_TYPE_NETWORK:
network_pdu = (mesh_network_pdu_t *) pdu;
mesh_network_pdu_free(network_pdu);
break;
case MESH_PDU_TYPE_TRANSPORT:
transport_pdu = (mesh_transport_pdu_t *) pdu;
mesh_transport_pdu_free(transport_pdu);
break;
case MESH_PDU_TYPE_MESSAGE:
message_pdu = (mesh_message_pdu_t *) pdu;
mesh_message_pdu_free(message_pdu);
default:
break;
}
}
static void mesh_upper_transport_pdu_handler(mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu){ static void mesh_upper_transport_pdu_handler(mesh_transport_callback_type_t callback_type, mesh_transport_status_t status, mesh_pdu_t * pdu){
switch (callback_type){ switch (callback_type){
@ -1144,6 +1126,44 @@ static void mesh_upper_transport_run(void){
} }
} }
void mesh_upper_transport_pdu_free(mesh_pdu_t * pdu){
mesh_network_pdu_t * network_pdu;
mesh_transport_pdu_t * transport_pdu;
mesh_message_pdu_t * message_pdu;
switch (pdu->pdu_type) {
case MESH_PDU_TYPE_NETWORK:
network_pdu = (mesh_network_pdu_t *) pdu;
mesh_network_pdu_free(network_pdu);
break;
case MESH_PDU_TYPE_TRANSPORT:
transport_pdu = (mesh_transport_pdu_t *) pdu;
mesh_transport_pdu_free(transport_pdu);
break;
case MESH_PDU_TYPE_MESSAGE:
message_pdu = (mesh_message_pdu_t *) pdu;
mesh_message_pdu_free(message_pdu);
default:
break;
}
}
void mesh_upper_transport_message_processed_by_higher_layer(mesh_pdu_t * pdu){
crypto_active = 0;
switch (pdu->pdu_type){
case MESH_PDU_TYPE_NETWORK:
mesh_upper_transport_process_unsegmented_message_done((mesh_network_pdu_t *) pdu);
break;
case MESH_PDU_TYPE_TRANSPORT:
mesh_upper_transport_process_segmented_message_done((mesh_transport_pdu_t *) pdu);
break;
case MESH_PDU_TYPE_MESSAGE:
mesh_upper_transport_process_message_done((mesh_message_pdu_t *) pdu);
break;
default:
break;
}
}
void mesh_upper_transport_register_access_message_handler(void (*callback)(mesh_pdu_t *pdu)){ void mesh_upper_transport_register_access_message_handler(void (*callback)(mesh_pdu_t *pdu)){
mesh_access_message_handler = callback; mesh_access_message_handler = callback;
} }
@ -1159,22 +1179,3 @@ void mesh_upper_transport_set_higher_layer_handler(void (*pdu_handler)( mesh_tra
void mesh_upper_transport_init(){ void mesh_upper_transport_init(){
mesh_lower_transport_set_higher_layer_handler(&mesh_upper_transport_pdu_handler); mesh_lower_transport_set_higher_layer_handler(&mesh_upper_transport_pdu_handler);
} }
// TODO: higher layer define used for assert
#define MESH_ACCESS_OPCODE_NOT_SET 0xFFFFFFFEu
void mesh_upper_transport_send_access_pdu(mesh_pdu_t *pdu){
btstack_assert(pdu->pdu_type != MESH_PDU_TYPE_NETWORK);
btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
mesh_upper_transport_run();
}
void mesh_upper_transport_send_control_pdu(mesh_pdu_t * pdu){
if (pdu->pdu_type == MESH_PDU_TYPE_NETWORK){
btstack_assert( ((mesh_network_pdu_t *) pdu)->len >= 9);
}
btstack_linked_list_add_tail(&upper_transport_outgoing, (btstack_linked_item_t*) pdu);
mesh_upper_transport_run();
}