From 2951b4690d8527575c44f2eeedfcd7993b1c99ca Mon Sep 17 00:00:00 2001 From: Matthias Ringwald Date: Thu, 4 Jul 2019 14:09:49 +0200 Subject: [PATCH] mesh: trigger key refresh transitions via secure network beacons --- test/mesh/mesh_access.c | 72 +++++++++++++++++++++++++++ test/mesh/mesh_access.h | 2 + test/mesh/mesh_configuration_server.c | 12 ++--- 3 files changed, 77 insertions(+), 9 deletions(-) diff --git a/test/mesh/mesh_access.c b/test/mesh/mesh_access.c index 4481da0bd..a1da0006a 100644 --- a/test/mesh/mesh_access.c +++ b/test/mesh/mesh_access.c @@ -41,6 +41,7 @@ #include #include #include "mesh/mesh_upper_transport.h" +#include "mesh/beacon.h" #include "mesh_access.h" #include "btstack_memory.h" #include "btstack_debug.h" @@ -50,6 +51,7 @@ #define MEST_TRANSACTION_TIMEOUT_MS 6000 static void mesh_access_message_process_handler(mesh_pdu_t * pdu); +static void mesh_access_secure_network_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size); static uint16_t primary_element_address; @@ -80,6 +82,9 @@ void mesh_access_init(void){ // register with upper transport mesh_upper_transport_register_access_message_handler(&mesh_access_message_process_handler); + + // register for secure network beacons + beacon_register_for_secure_network_beacons(&mesh_access_secure_network_beacon_handler); } void mesh_access_emit_state_update_bool(btstack_packet_handler_t * event_handler, uint8_t element_index, uint32_t model_identifier, @@ -1341,3 +1346,70 @@ void mesh_access_state_changed(mesh_model_t * mesh_model){ publication_model->publish_now = 1; mesh_model_publication_run(NULL); } + +void mesh_access_netkey_finalize(mesh_network_key_t * network_key){ + mesh_network_key_remove(network_key); + mesh_delete_network_key(network_key->internal_index); + btstack_memory_mesh_network_key_free(network_key); +} + +static void mesh_access_secure_network_beacon_handler(uint8_t packet_type, uint16_t channel, uint8_t * packet, uint16_t size){ + UNUSED(channel); + if (packet_type != MESH_BEACON_PACKET) return; + + // lookup subnet and netkey by network id + uint8_t * beacon_network_id = &packet[2]; + mesh_subnet_iterator_t it; + mesh_subnet_iterator_init(&it); + mesh_subnet_t * subnet = NULL; + mesh_network_key_t * network_key = NULL; + uint8_t new_key = 0; + while (mesh_subnet_iterator_has_more(&it)){ + mesh_subnet_t * item = mesh_subnet_iterator_get_next(&it); + if (memcmp(item->old_key->network_id, beacon_network_id, 8) == 0 ) { + subnet = item; + network_key = item->old_key; + } + if (item->new_key != NULL && memcmp(item->new_key->network_id, beacon_network_id, 8) == 0 ) { + subnet = item; + network_key = item->new_key; + new_key = 1; + } + break; + } + if (subnet == NULL) return; + + // Key refresh via secure network beacons that are authenticated with new netkey + if (new_key){ + // either first or second phase (in phase 0, new key is not set) + int key_refresh_flag = packet[1] & 1; + if (key_refresh_flag){ + // transition to phase 3 from either phase 1 or 2 + switch (subnet->key_refresh){ + case MESH_KEY_REFRESH_FIRST_PHASE: + case MESH_KEY_REFRESH_SECOND_PHASE: + // -- revoke old key + mesh_access_netkey_finalize(subnet->old_key); + subnet->old_key = subnet->new_key; + subnet->new_key = NULL; + // -- update state + subnet->key_refresh = MESH_KEY_REFRESH_NOT_ACTIVE; + break; + default: + break; + } + } else { + // transition to phase 2 from either phase 1 + switch (subnet->key_refresh){ + case MESH_KEY_REFRESH_FIRST_PHASE: + // -- update state + subnet->key_refresh = MESH_KEY_REFRESH_SECOND_PHASE; + break; + default: + break; + } + } + } + + // TODO: IV Update +} diff --git a/test/mesh/mesh_access.h b/test/mesh/mesh_access.h index 45a01dda5..847969f2f 100644 --- a/test/mesh/mesh_access.h +++ b/test/mesh/mesh_access.h @@ -336,6 +336,8 @@ void mesh_delete_network_key(uint16_t internal_index); void mesh_delete_network_keys(void); void mesh_load_network_keys(void); +void mesh_access_netkey_finalize(mesh_network_key_t * network_key); + // Mesh Appkeys void mesh_store_app_key(uint16_t internal_index, uint16_t netkey_index, uint16_t appkey_index, uint8_t aid, const uint8_t * application_key); void mesh_delete_app_key(uint16_t internal_index); diff --git a/test/mesh/mesh_configuration_server.c b/test/mesh/mesh_configuration_server.c index d44a95ce4..3a638579f 100644 --- a/test/mesh/mesh_configuration_server.c +++ b/test/mesh/mesh_configuration_server.c @@ -930,12 +930,6 @@ static void config_netkey_update_handler(mesh_model_t * mesh_model, mesh_pdu_t * mesh_network_key_derive(&configuration_server_cmac_request, new_network_key, config_netkey_update_derived, subnet); } -static void config_netkey_finalize(mesh_network_key_t * network_key){ - mesh_network_key_remove(network_key); - mesh_delete_network_key(network_key->internal_index); - btstack_memory_mesh_network_key_free(network_key); -} - static void config_netkey_delete_handler(mesh_model_t * mesh_model, mesh_pdu_t * pdu) { mesh_access_parser_state_t parser; mesh_access_parser_init(&parser, (mesh_pdu_t *) pdu); @@ -960,12 +954,12 @@ static void config_netkey_delete_handler(mesh_model_t * mesh_model, mesh_pdu_t * } // delete old/current key - config_netkey_finalize(subnet->old_key); + mesh_access_netkey_finalize(subnet->old_key); subnet->old_key = NULL; // delete new key if (subnet->new_key != NULL){ - config_netkey_finalize(subnet->new_key); + mesh_access_netkey_finalize(subnet->new_key); subnet->new_key = NULL; } @@ -2128,7 +2122,7 @@ static void config_key_refresh_phase_set_handler(mesh_model_t *mesh_model, mesh_ case MESH_KEY_REFRESH_SECOND_PHASE: // key refresh phase 3 entered // -- revoke old key - config_netkey_finalize(subnet->old_key); + mesh_access_netkey_finalize(subnet->old_key); subnet->old_key = subnet->new_key; subnet->new_key = NULL; // -- update state