mesh: handle network messages where IVI field indicates previous IV Index

This commit is contained in:
Matthias Ringwald 2019-03-28 18:00:24 +01:00
parent 5e31cfbcf4
commit 16753ea2f9
2 changed files with 34 additions and 5 deletions

View File

@ -490,6 +490,21 @@ static void process_network_pdu_validate_d(void * arg){
process_network_pdu_done();
}
static uint32_t iv_index_for_pdu(const mesh_network_pdu_t * network_pdu){
// get IV Index and IVI
uint32_t iv_index = global_iv_index;
int ivi = network_pdu->data[0] >> 7;
// if least significant bit differs, use previous IV Index
if ((iv_index & 1 ) ^ ivi){
iv_index--;
#ifdef LOG_NETWORK
printf("RX-IV: IVI indicates previous IV index, using 0x%08x\n", iv_index);
#endif
}
return iv_index;
}
static void process_network_pdu_validate_b(void * arg){
mesh_network_pdu_t * network_pdu = (mesh_network_pdu_t *) arg;
@ -504,16 +519,18 @@ static void process_network_pdu_validate_b(void * arg){
network_pdu->data[1+i] = network_pdu_in_validation->data[1+i] ^ obfuscation_block[i];
}
uint32_t iv_index = iv_index_for_pdu(network_pdu);
if (network_pdu->flags & 1){
// create network nonce
mesh_proxy_create_nonce(network_nonce, network_pdu, global_iv_index);
mesh_proxy_create_nonce(network_nonce, network_pdu, iv_index);
#ifdef LOG_NETWORK
printf("RX-Proxy Nonce: ");
printf_hexdump(network_nonce, 13);
#endif
} else {
// create network nonce
mesh_network_create_nonce(network_nonce, network_pdu, global_iv_index);
mesh_network_create_nonce(network_nonce, network_pdu, iv_index);
#ifdef LOG_NETWORK
printf("RX-Network Nonce: ");
printf_hexdump(network_nonce, 13);
@ -548,8 +565,9 @@ static void process_network_pdu_validate(mesh_network_pdu_t * network_pdu){
current_network_key = mesh_network_key_iterator_get_next(&validation_network_key_it);
// calc PECB
uint32_t iv_index = iv_index_for_pdu(network_pdu);
memset(encryption_block, 0, 5);
big_endian_store_32(encryption_block, 5, global_iv_index);
big_endian_store_32(encryption_block, 5, iv_index);
memcpy(&encryption_block[9], &network_pdu_in_validation->data[7], 7);
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);
}

View File

@ -277,17 +277,28 @@ static uint16_t upper_transport_outgoing_seg_o;
static uint32_t upper_transport_seq;
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
memcpy(&nonce[2], &network_pdu->data[2], 7);
big_endian_store_32(nonce, 9, mesh_get_iv_index());
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;
memcpy(&nonce[2], &transport_pdu->network_header[2], 7);
big_endian_store_32(nonce, 9, mesh_get_iv_index());
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){