mesh: move key refresh and secure beacon data from mesh_network_key_t to mesh_subnet_t

This commit is contained in:
Matthias Ringwald 2019-07-02 17:39:24 +02:00
parent b1dda14141
commit 2fa98d7e52
8 changed files with 62 additions and 70 deletions

View File

@ -113,7 +113,7 @@ static void beacon_timer_handler(btstack_timer_source_t * ts){
#endif
static void mesh_secure_network_beacon_auth_value_calculated(void * arg){
mesh_network_key_t * mesh_network_key = (mesh_network_key_t *) arg;
mesh_subnet_t * mesh_subnet = (mesh_subnet_t *) arg;
memcpy(&mesh_beacon_data[14], mesh_secure_network_beacon_auth_value, 8);
mesh_beacon_len = SECURE_NETWORK_BEACON_LEN;
@ -122,14 +122,14 @@ static void mesh_secure_network_beacon_auth_value_calculated(void * arg){
printf("- ");
printf_hexdump(mesh_beacon_data, mesh_beacon_len);
mesh_network_key->beacon_state = MESH_SECURE_NETWORK_BEACON_AUTH_VALUE;
mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_AUTH_VALUE;
mesh_secure_network_beacon_run(NULL);
}
static uint8_t mesh_secure_network_beacon_get_flags(mesh_network_key_t * mesh_network_key){
static uint8_t mesh_secure_network_beacon_get_flags(mesh_subnet_t * mesh_subnet){
uint8_t mesh_flags = 0;
if (mesh_network_key->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){
if (mesh_subnet->key_refresh != MESH_KEY_REFRESH_NOT_ACTIVE){
mesh_flags |= 1;
}
@ -137,16 +137,18 @@ static uint8_t mesh_secure_network_beacon_get_flags(mesh_network_key_t * mesh_ne
return mesh_flags;
}
static void mesh_secure_network_beacon_setup(mesh_network_key_t * mesh_network_key){
static void mesh_secure_network_beacon_setup(mesh_subnet_t * mesh_subnet){
mesh_beacon_data[0] = BEACON_TYPE_SECURE_NETWORK;
mesh_beacon_data[1] = mesh_secure_network_beacon_get_flags(mesh_network_key);
memcpy(&mesh_beacon_data[2], mesh_network_key->network_id, 8);
mesh_beacon_data[1] = mesh_secure_network_beacon_get_flags(mesh_subnet);
// TODO: pick correct key based on key refresh phase
memcpy(&mesh_beacon_data[2], mesh_subnet->old_key->network_id, 8);
big_endian_store_32(mesh_beacon_data, 10, mesh_get_iv_index());
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, mesh_network_key->beacon_key, 13,
&mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_network_key);
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, mesh_subnet->old_key->beacon_key, 13,
&mesh_beacon_data[1], mesh_secure_network_beacon_auth_value, &mesh_secure_network_beacon_auth_value_calculated, mesh_subnet);
}
static void mesh_secure_network_beacon_update_interval(mesh_network_key_t * subnet){
static void mesh_secure_network_beacon_update_interval(mesh_subnet_t * subnet){
uint32_t min_observation_period_ms = 2 * subnet->beacon_interval_ms;
uint32_t actual_observation_period = btstack_time_delta(btstack_run_loop_get_time_ms(), subnet->beacon_observation_start_ms);
@ -175,10 +177,10 @@ static void mesh_secure_network_beacon_run(btstack_timer_source_t * ts){
uint32_t next_timeout_ms = 0;
// iterate over all networks
mesh_network_key_iterator_t it;
mesh_network_key_iterator_init(&it);
while (mesh_network_key_iterator_has_more(&it)){
mesh_network_key_t * subnet = mesh_network_key_iterator_get_next(&it);
mesh_subnet_iterator_t it;
mesh_subnet_iterator_init(&it);
while (mesh_subnet_iterator_has_more(&it)){
mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
switch (subnet->beacon_state){
case MESH_SECURE_NETWORK_BEACON_W4_INTERVAL:
// update beacon interval
@ -266,12 +268,13 @@ static void beacon_handle_secure_beacon(uint8_t * packet, uint16_t size){
// lookup subnet by network id
uint8_t * beacon_network_id = &packet[2];
mesh_network_key_iterator_t it;
mesh_network_key_iterator_init(&it);
mesh_network_key_t * subnet = NULL;
while (mesh_network_key_iterator_has_more(&it)){
mesh_network_key_t * item = mesh_network_key_iterator_get_next(&it);
if (memcmp(item->network_id, beacon_network_id, 8) != 0 ) continue;
mesh_subnet_iterator_t it;
mesh_subnet_iterator_init(&it);
mesh_subnet_t * subnet = NULL;
while (mesh_subnet_iterator_has_more(&it)){
mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it);
// TODO: handle old/new keys
if (memcmp(item->old_key->network_id, beacon_network_id, 8) != 0 ) continue;
subnet = item;
break;
}
@ -292,7 +295,8 @@ static void beacon_handle_secure_beacon(uint8_t * packet, uint16_t size){
mesh_secure_network_beacon_active = 1;
memcpy(mesh_secure_network_beacon_validate_buffer, &packet[0], SECURE_NETWORK_BEACON_LEN);
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, subnet->beacon_key, 13,
// TODO: handle odl/new keys
btstack_crypto_aes128_cmac_message(&mesh_secure_network_beacon_cmac_request, subnet->old_key->beacon_key, 13,
&mesh_secure_network_beacon_validate_buffer[1], mesh_secure_network_beacon_auth_value, &beacon_handle_secure_beacon_auth_value_calculated, subnet);
}
@ -314,7 +318,7 @@ static void beacon_handle_beacon_packet(uint8_t packet_type, uint16_t channel, u
#ifdef ENABLE_MESH_ADV_BEARER
static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
mesh_network_key_iterator_t it;
mesh_subnet_iterator_t it;
switch (packet_type){
case HCI_EVENT_PACKET:
switch(packet[0]){
@ -327,9 +331,9 @@ static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, ui
break;
}
// secure beacon state machine
mesh_network_key_iterator_init(&it);
while (mesh_network_key_iterator_has_more(&it)){
mesh_network_key_t * subnet = mesh_network_key_iterator_get_next(&it);
mesh_subnet_iterator_init(&it);
while (mesh_subnet_iterator_has_more(&it)){
mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
switch (subnet->beacon_state){
case MESH_SECURE_NETWORK_BEACON_W2_SEND_ADV:
adv_bearer_send_beacon(mesh_beacon_data, mesh_beacon_len);
@ -361,10 +365,10 @@ static void beacon_adv_packet_handler (uint8_t packet_type, uint16_t channel, ui
#ifdef ENABLE_MESH_GATT_BEARER
// handle MESH_SUBEVENT_PROXY_DISCONNECTED and MESH_SUBEVENT_CAN_SEND_NOW
static void beacon_gatt_handle_mesh_event(uint8_t mesh_subevent){
mesh_network_key_iterator_t it;
mesh_network_key_iterator_init(&it);
while (mesh_network_key_iterator_has_more(&it)){
mesh_network_key_t * subnet = mesh_network_key_iterator_get_next(&it);
mesh_subnet_iterator_t it;
mesh_subnet_iterator_init(&it);
while (mesh_subnet_iterator_has_more(&it)){
mesh_subnet_t * subnet = mesh_subnet_iterator_get_next(&it);
switch (subnet->beacon_state){
case MESH_SECURE_NETWORK_BEACON_W2_SEND_GATT:
// skip send on MESH_SUBEVENT_PROXY_DISCONNECTED
@ -451,12 +455,12 @@ void beacon_unprovisioned_device_stop(void){
// secure network beacons
void beacon_secure_network_start(mesh_network_key_t * mesh_network_key){
void beacon_secure_network_start(mesh_subnet_t * mesh_subnet){
// default interval
mesh_network_key->beacon_interval_ms = SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
mesh_network_key->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
mesh_network_key->beacon_observation_start_ms = btstack_run_loop_get_time_ms();
mesh_network_key->beacon_observation_counter = 0;
mesh_subnet->beacon_interval_ms = SECURE_NETWORK_BEACON_INTERVAL_MIN_MS;
mesh_subnet->beacon_state = MESH_SECURE_NETWORK_BEACON_W2_AUTH_VALUE;
mesh_subnet->beacon_observation_start_ms = btstack_run_loop_get_time_ms();
mesh_subnet->beacon_observation_counter = 0;
// start sending
mesh_secure_network_beacon_run(NULL);

View File

@ -42,6 +42,7 @@
#include <stdint.h>
#include "btstack_defines.h"
#include "mesh_keys.h"
#include "mesh/mesh_network.h"
#if defined __cplusplus
extern "C" {
@ -65,9 +66,9 @@ void beacon_unprovisioned_device_stop(void);
/**
* Start sending Secure Network Beacons on given subnet
* @param mesh_network_key subnet
* @param mesh_subnet
*/
void beacon_secure_network_start(mesh_network_key_t * mesh_network_key);
void beacon_secure_network_start(mesh_subnet_t * mesh_subnet);
/**
* Register Beacon handler for unprovisioned device beacons

View File

@ -56,13 +56,13 @@ LDFLAGS += -lCppUTest -lCppUTestExt
mesh: mesh.h ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${GATT_SERVER_OBJ} ${SM_OBJ} pb_adv.o pb_gatt.o mesh_foundation.o mesh_provisioning_service_server.o mesh_crypto.o provisioning_device.o mesh_network.o mesh_peer.o mesh_lower_transport.o mesh_upper_transport.o mesh_virtual_addresses.o mesh_keys.o mesh_proxy.o mesh_access.o mesh_configuration_server.o mesh_generic_server.o mesh_generic_level_server.o mesh_generic_client.o mesh_generic_level_client.o mesh.o
${CC} $(filter-out mesh.h,$^) ${CFLAGS} ${LDFLAGS} -o $@
provisioner: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${SM_OBJ} pb_adv.o mesh_crypto.o provisioning_provisioner.o mesh_keys.o mesh_foundation.o provisioner.o
provisioner: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${SM_OBJ} pb_adv.o mesh_crypto.o provisioning_provisioner.o mesh_keys.o mesh_foundation.o mesh_network.o provisioner.o
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
mesh_message_test: mesh_foundation.o mesh_message_test.c mesh_network.o mesh_peer.o mesh_lower_transport.o mesh_upper_transport.o mesh_virtual_addresses.o mesh_keys.o mesh_crypto.o btstack_memory.o btstack_memory_pool.o btstack_util.o btstack_crypto.o btstack_linked_list.o hci_dump.o uECC.o mock.o rijndael.o hci_cmd.o
g++ $^ ${CFLAGS} ${LDFLAGS} -o $@
sniffer: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${SM_OBJ} mesh_keys.o mesh_foundation.o sniffer.c
sniffer: ${CORE_OBJ} ${COMMON_OBJ} ${ATT_OBJ} ${SM_OBJ} mesh_keys.o mesh_network.o mesh_foundation.o sniffer.c
${CC} $^ ${CFLAGS} ${LDFLAGS} -o $@
provisioning_device_test: provisioning_device_test.cpp uECC.o mesh_crypto.o provisioning_device.o btstack_crypto.o btstack_util.o btstack_linked_list.o mock.o rijndael.o hci_cmd.o hci_dump.o

View File

@ -324,9 +324,9 @@ static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *pack
#if defined(ENABLE_MESH_ADV_BEARER) || defined(ENABLE_MESH_PB_ADV)
// start sending Secure Network Beacon
mesh_network_key_t * network_key = mesh_network_key_list_get(0);
if (network_key){
beacon_secure_network_start(network_key);
mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(0);
if (subnet){
beacon_secure_network_start(subnet);
}
// setup scanning
@ -366,6 +366,8 @@ static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t cha
if (packet_type != HCI_EVENT_PACKET) return;
mesh_provisioning_data_t provisioning_data;
mesh_network_key_t * primary_network_key;
mesh_subnet_t * primary_subnet;
switch(packet[0]){
case HCI_EVENT_MESH_META:
switch(packet[2]){
@ -420,7 +422,8 @@ static void mesh_provisioning_message_handler (uint8_t packet_type, uint16_t cha
mesh_proxy_set_advertising_with_node_id(primary_network_key->netkey_index, MESH_NODE_IDENTITY_STATE_ADVERTISING_RUNNING);
// start sending Secure Network Beacons
beacon_secure_network_start(primary_network_key);
primary_subnet = mesh_subnet_get_by_netkey_index(0);
beacon_secure_network_start(primary_subnet);
break;
default:

View File

@ -843,11 +843,13 @@ static void config_netkey_add_handler(mesh_model_t * mesh_model, mesh_pdu_t * pd
if (internal_index == 0 || (config_netkey_list_max && mesh_network_key_list_count() >= config_netkey_list_max)){
status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES;
} else {
// setup new key
mesh_network_key_t * new_network_key = btstack_memory_mesh_network_key_get();
if (new_network_key == NULL){
status = MESH_FOUNDATION_STATUS_INSUFFICIENT_RESOURCES;
} else {
// TODO: check if subnet could get created
access_pdu_in_process = pdu;
new_network_key->internal_index = internal_index;
new_network_key->netkey_index = new_netkey_index;
@ -900,7 +902,6 @@ static void config_netkey_update_handler(mesh_model_t * mesh_model, mesh_pdu_t *
access_pdu_in_process = pdu;
new_network_key->internal_index = internal_index;
new_network_key->netkey_index = netkey_index;
new_network_key->key_refresh = 1;
memcpy(new_network_key->net_key, new_netkey, 16);
mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_add_or_update_derived, new_network_key);
}
@ -2041,14 +2042,14 @@ static void config_key_refresh_phase_get_handler(mesh_model_t *mesh_model, mesh_
mesh_access_parser_state_t parser;
mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
uint16_t netkey_index = mesh_access_parser_get_u16(&parser);
mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index);
mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index);
uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX;
mesh_key_refresh_state_t key_refresh_state = MESH_KEY_REFRESH_NOT_ACTIVE;
if (network_key != NULL){
if (subnet != NULL){
status = MESH_FOUNDATION_STATUS_SUCCESS;
key_refresh_state = network_key->key_refresh;
key_refresh_state = subnet->key_refresh;
}
config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, key_refresh_state);
@ -2060,30 +2061,30 @@ static void config_key_refresh_phase_set_handler(mesh_model_t *mesh_model, mesh_
mesh_access_parser_init(&parser, (mesh_pdu_t*) pdu);
uint16_t netkey_index = mesh_access_parser_get_u16(&parser);
uint8_t key_refresh_phase_transition = mesh_access_parser_get_u8(&parser);
mesh_network_key_t * network_key = mesh_network_key_list_get(netkey_index);
mesh_subnet_t * subnet = mesh_subnet_get_by_netkey_index(netkey_index);
uint8_t status = MESH_FOUNDATION_STATUS_INVALID_NETKEY_INDEX;
if (network_key != NULL){
if (subnet != NULL){
status = MESH_FOUNDATION_STATUS_SUCCESS;
switch (key_refresh_phase_transition){
case 0x02:
switch (network_key->key_refresh){
switch (subnet->key_refresh){
case MESH_KEY_REFRESH_FIRST_PHASE:
case MESH_KEY_REFRESH_SECOND_PHASE:
network_key->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE;
subnet->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE;
break;
default:
break;
}
break;
case 0x03:
switch (network_key->key_refresh){
switch (subnet->key_refresh){
case MESH_KEY_REFRESH_FIRST_PHASE:
case MESH_KEY_REFRESH_SECOND_PHASE:
// TODO: invoke Key Refresh Phase 3, then
// set network_key->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE;
// set subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE;
printf("TODO: invoke Key Refresh Phase 3, then set key refresh phase to MESH_KEY_REFRESH_NOT_ACTIVE\n");
break;
default:
@ -2096,7 +2097,7 @@ static void config_key_refresh_phase_set_handler(mesh_model_t *mesh_model, mesh_
}
}
config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, network_key->key_refresh);
config_key_refresh_phase_status(mesh_model, mesh_pdu_netkey_index(pdu), mesh_pdu_src(pdu), status, netkey_index, subnet->key_refresh);
mesh_access_message_processed(pdu);
}

View File

@ -97,21 +97,12 @@ typedef struct {
uint8_t encryption_key[16];
uint8_t privacy_key[16];
// key refresh
mesh_key_refresh_state_t key_refresh;
// subnet state
uint8_t node_id_advertisement_running;
// advertisement data for proxy
adv_bearer_connectable_advertisement_data_item_t advertisement_with_network_id;
// secure network beacons
mesh_secure_network_beacon_state_t beacon_state;
uint32_t beacon_interval_ms;
uint32_t beacon_observation_start_ms;
uint16_t beacon_observation_counter;
} mesh_network_key_t;
typedef struct {

View File

@ -274,10 +274,6 @@ static void stdin_process(char cmd){
}
}
uint32_t mesh_get_iv_index(void){
return 0;
}
int btstack_main(void);
int btstack_main(void)
{

View File

@ -282,10 +282,6 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
}
/* LISTING_END */
uint32_t mesh_get_iv_index(void){
return 0;
}
int btstack_main(void);
int btstack_main(void)
{