From a87646d77a9cecd72fc3337c254e9ccf4134be88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Thu, 4 Mar 2021 11:12:37 +0200 Subject: [PATCH] On startup deletes NVM GTKs if EUI-64 has been changed (#2576) BR and node now stores the EUI-64 with GTK to NVM so that when storage is read, the current EUI-64 can be compared to the stored one. --- CHANGELOG.md | 3 ++- source/6LoWPAN/ws/ws_pae_controller.c | 39 ++++++++++++++++++++------- source/6LoWPAN/ws/ws_pae_nvm_data.c | 10 +++++-- source/6LoWPAN/ws/ws_pae_nvm_data.h | 8 +++--- 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbc4f52a996e..7644f3f3ff5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,8 @@ ### Changes * Added throttling of number of simultaneous EAPOL authentications based on Border Router TX queue size * Domain configuration functions implemented. Replacing existing PHY mode ID and channel plan ID set functions. -* Added EAPOL authentication waiting queue to Border Router. Queue makes it possible to start new authentication faster after previous authentication has completed. +* Added EAPOL authentication waiting queue to Border Router. Queue makes it possible to start new authentication faster after previous authentication has completed. +* On startup deletes NVM GTKs if EUI-64 has been changed. ### Bugfix * All MAC TX failure causes now trigger target change on supplicant EAPOL inititial-key sending diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index da74695ee367..0f299ce55d63 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -141,8 +141,8 @@ static int8_t ws_pae_controller_frame_counter_read(pae_controller_t *controller) static void ws_pae_controller_frame_counter_reset(frame_counters_t *frame_counters); static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_counters, uint8_t index); static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks); -static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, sec_prot_gtk_keys_t *gtks); -static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, sec_prot_gtk_keys_t *gtks); +static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks); +static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks); static const char *FRAME_COUNTER_FILE = FRAME_COUNTER_FILE_NAME; @@ -371,7 +371,13 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr } if (controller->sec_keys_nw_info.updated || sec_prot_keys_gtks_are_updated(controller->sec_keys_nw_info.gtks)) { - ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, controller->sec_keys_nw_info.gtks); + // Get own EUI-64 + uint8_t gtk_eui64[8] = {0}; + link_layer_address_s mac_params; + if (arm_nwk_mac_address_read(interface_ptr->id, &mac_params) >= 0) { + memcpy(gtk_eui64, mac_params.mac_long, 8); + } + ws_pae_controller_nvm_nw_info_write(interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, controller->sec_keys_nw_info.gtks); controller->sec_keys_nw_info.updated = false; sec_prot_keys_gtks_updated_reset(controller->sec_keys_nw_info.gtks); } @@ -844,32 +850,46 @@ static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_ static int8_t ws_pae_controller_nw_info_read(pae_controller_t *controller, sec_prot_gtk_keys_t *gtks) { - if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtks) < 0) { + uint8_t nvm_gtk_eui64[8]; + if (ws_pae_controller_nvm_nw_info_read(controller->interface_ptr, &controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, nvm_gtk_eui64, gtks) < 0) { // If no stored GTKs and network info (pan_id and network name) exits return -1; } + /* Get own EUI-64 and compare to the one read from the NVM. In case of mismatch delete GTKs and make + full authentication to update keys with new EUI-64 and in case of authenticator to update new + authenticator EUI-64 to the network. */ + uint8_t gtk_eui64[8] = {0}; + link_layer_address_s mac_params; + if (arm_nwk_mac_address_read(controller->interface_ptr->id, &mac_params) >= 0) { + memcpy(gtk_eui64, mac_params.mac_long, 8); + } + if (memcmp(nvm_gtk_eui64, gtk_eui64, 8) != 0) { + tr_warn("NVM EUI-64 mismatch, current: %s stored: %s", tr_array(gtk_eui64, 8), tr_array(nvm_gtk_eui64, 8)); + sec_prot_keys_gtks_clear(gtks); + } + // Sets also new pan_id used for pan_id set by bootstrap controller->sec_keys_nw_info.new_pan_id = controller->sec_keys_nw_info.key_pan_id; return 0; } -static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, sec_prot_gtk_keys_t *gtks) +static int8_t ws_pae_controller_nvm_nw_info_write(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks) { nw_info_nvm_tlv_t *tlv = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr); if (!tlv) { return -1; } - ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtks); + ws_pae_nvm_store_nw_info_tlv_create(tlv, pan_id, network_name, gtk_eui64, gtks); ws_pae_nvm_store_tlv_file_write(NW_INFO_FILE, (nvm_tlv_t *) tlv); return 0; } -static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, sec_prot_gtk_keys_t *gtks) +static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t *interface_ptr, uint16_t *pan_id, char *network_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks) { nw_info_nvm_tlv_t *tlv_entry = (nw_info_nvm_tlv_t *) ws_pae_controller_nvm_tlv_get(interface_ptr); if (!tlv_entry) { @@ -882,7 +902,7 @@ static int8_t ws_pae_controller_nvm_nw_info_read(protocol_interface_info_entry_t return -1; } - if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtks) < 0) { + if (ws_pae_nvm_store_nw_info_tlv_read(tlv_entry, pan_id, network_name, gtk_eui64, gtks) < 0) { return -1; } @@ -964,7 +984,8 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt } if (!read_gtks_to || sec_prot_keys_gtk_count(read_gtks_to) == 0) { // Key material invalid or GTKs are expired, delete GTKs from NVM - ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, NULL); + uint8_t gtk_eui64[8] = {0}; // Set GTK EUI-64 to zero + ws_pae_controller_nvm_nw_info_write(controller->interface_ptr, controller->sec_keys_nw_info.key_pan_id, controller->sec_keys_nw_info.network_name, gtk_eui64, NULL); } } diff --git a/source/6LoWPAN/ws/ws_pae_nvm_data.c b/source/6LoWPAN/ws/ws_pae_nvm_data.c index fa26ab3f5c5f..ba575c2acb0d 100644 --- a/source/6LoWPAN/ws/ws_pae_nvm_data.c +++ b/source/6LoWPAN/ws/ws_pae_nvm_data.c @@ -67,7 +67,7 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry) ns_dyn_mem_free(tlv_entry); } -void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) +void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks) { int len; tlv_entry->tag = PAE_NVM_NW_INFO_TAG; @@ -87,6 +87,9 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t memcpy((char *)tlv, nw_name, len); tlv += 33; + memcpy((char *)tlv, gtk_eui64, 8); + tlv += 8; + uint64_t current_time = ws_pae_current_time_get(); for (uint8_t i = 0; i < GTK_NUM; i++) { @@ -119,7 +122,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t } -int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks) +int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks) { if (!tlv_entry || !pan_id || !nw_name) { return -1; @@ -144,6 +147,9 @@ int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t } tlv += 33; + memcpy(gtk_eui64, (char *)tlv, 8); + tlv += 8; + uint64_t current_time = ws_pae_current_time_get(); tr_debug("NVM NW_INFO current time: %"PRIi64, current_time); diff --git a/source/6LoWPAN/ws/ws_pae_nvm_data.h b/source/6LoWPAN/ws/ws_pae_nvm_data.h index 23f164d4d8eb..3d6e6432312f 100644 --- a/source/6LoWPAN/ws/ws_pae_nvm_data.h +++ b/source/6LoWPAN/ws/ws_pae_nvm_data.h @@ -35,8 +35,8 @@ #define PAE_NVM_KEY_STORAGE_INDEX_TAG 4 #define PAE_NVM_KEY_STORAGE_TAG 5 -// pan_id (2) + network name (33) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4 -#define PAE_NVM_NW_INFO_LEN 2 + 33 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM +// pan_id (2) + network name (33) + GTK EUI-64 (own EUI-64) (8) + (GTK set (1) + GTK expiry timestamp (8) + status (1) + install order (1) + GTK (16)) * 4 +#define PAE_NVM_NW_INFO_LEN 2 + 33 + 8 + (1 + 8 + 1 + 1 + GTK_LEN) * GTK_NUM // PTK EUI-64 set (1) + PTK EUI-64 (8) + PMK set (1) + PMK lifetime (4) + PMK (32) + PMK replay counter (8) + PTK set (1) + PTK lifetime (4) + PTK (48) #define PAE_NVM_KEYS_LEN 1 + 8 + 1 + 4 + PMK_LEN + 8 + 1 + 4 + PTK_LEN @@ -95,7 +95,7 @@ void ws_pae_nvm_store_generic_tlv_free(nvm_tlv_t *tlv_entry); * \return TLV entry or NULL * */ -void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); +void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks); /** * ws_pae_nvm_store_nw_info_tlv_read read from NVM network info TLV @@ -109,7 +109,7 @@ void ws_pae_nvm_store_nw_info_tlv_create(nw_info_nvm_tlv_t *tlv_entry, uint16_t * \return >= 0 success * */ -int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, sec_prot_gtk_keys_t *gtks); +int8_t ws_pae_nvm_store_nw_info_tlv_read(nw_info_nvm_tlv_t *tlv_entry, uint16_t *pan_id, char *nw_name, uint8_t *gtk_eui64, sec_prot_gtk_keys_t *gtks); /** * ws_pae_nvm_store_keys_tlv_create create NVM keys TLV