From ed9eb0503f43b8cd7d09700e66ad4839aedec462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Thu, 17 Jun 2021 15:08:12 +0300 Subject: [PATCH] GTKs are removed only when fresh GTK hash is received On some timing cases after bootstrap, nodes could remove GTK keys based on previous GTK hash received (hash had been updated by BR but indication had not reached all nodes yet). This is now corrected so that GTKs are removed only when fresh GTK hash is received. --- source/6LoWPAN/ws/ws_pae_controller.c | 6 +++--- source/6LoWPAN/ws/ws_pae_supp.c | 6 +++--- source/6LoWPAN/ws/ws_pae_supp.h | 3 ++- source/Security/protocols/sec_prot_keys.c | 15 +++++++++++---- source/Security/protocols/sec_prot_keys.h | 3 ++- 5 files changed, 21 insertions(+), 12 deletions(-) diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index 805cb07d8bc2..504aadcedf3c 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -51,7 +51,7 @@ typedef void ws_pae_timer(uint16_t ticks); typedef int8_t ws_pae_br_addr_write(protocol_interface_info_entry_t *interface_ptr, const uint8_t *eui_64); typedef int8_t ws_pae_br_addr_read(protocol_interface_info_entry_t *interface_ptr, uint8_t *eui_64); typedef void ws_pae_gtks_updated(protocol_interface_info_entry_t *interface_ptr); -typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); +typedef int8_t ws_pae_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch); typedef int8_t ws_pae_nw_key_index_update(protocol_interface_info_entry_t *interface_ptr, uint8_t index); typedef int8_t ws_pae_nw_info_set(protocol_interface_info_entry_t *interface_ptr, uint16_t pan_id, char *network_name, bool updated); @@ -196,7 +196,7 @@ int8_t ws_pae_controller_bootstrap_done(protocol_interface_info_entry_t *interfa /* Trigger GTK hash update to supplicant, so it can check whether keys have been updated during bootstrap. Does nothing if GTKs are up to date. */ - ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash); + ws_pae_supp_gtk_hash_update(interface_ptr, controller->gtkhash, false); #endif return 0; @@ -1662,7 +1662,7 @@ int8_t ws_pae_controller_gtk_hash_update(protocol_interface_info_entry_t *interf memcpy(controller->gtkhash, gtkhash, 32); if (controller->pae_gtk_hash_update) { - return controller->pae_gtk_hash_update(interface_ptr, controller->gtkhash); + return controller->pae_gtk_hash_update(interface_ptr, controller->gtkhash, true); } return 0; diff --git a/source/6LoWPAN/ws/ws_pae_supp.c b/source/6LoWPAN/ws/ws_pae_supp.c index 6aab0d9cae4b..7e518c465beb 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.c +++ b/source/6LoWPAN/ws/ws_pae_supp.c @@ -294,7 +294,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp) } // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */ - gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash); + gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash, false); if (mismatch != GTK_NO_MISMATCH) { return -1; } @@ -303,7 +303,7 @@ static int8_t ws_pae_supp_gtk_hash_mismatch_check(pae_supp_t *pae_supp) return 0; } -int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash) +int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch) { pae_supp_t *pae_supp = ws_pae_supp_get(interface_ptr); if (!pae_supp) { @@ -311,7 +311,7 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt } // Check GTK hashes and initiate EAPOL procedure if mismatch is detected */ - gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash); + gtk_mismatch_e mismatch = sec_prot_keys_gtks_hash_update(pae_supp->sec_keys_nw_info->gtks, gtkhash, del_gtk_on_mismatch); if (mismatch > GTK_NO_MISMATCH) { tr_info("GTK hash update %s %s %s %s", trace_array(>khash[0], 8), diff --git a/source/6LoWPAN/ws/ws_pae_supp.h b/source/6LoWPAN/ws/ws_pae_supp.h index 1ccd78c21ea0..c991d65062c7 100644 --- a/source/6LoWPAN/ws/ws_pae_supp.h +++ b/source/6LoWPAN/ws/ws_pae_supp.h @@ -130,12 +130,13 @@ int8_t ws_pae_supp_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, * * \param interface_ptr interface * \param gtkhash GTK hash, 32 bytes + * \param del_gtk_on_mismatch Delete GTK in case of mismatch * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash); +int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_ptr, uint8_t *gtkhash, bool del_gtk_on_mismatch); /** * ws_pae_supp_nw_key_index_update key index been updated (on PAN configuration) diff --git a/source/Security/protocols/sec_prot_keys.c b/source/Security/protocols/sec_prot_keys.c index 02748f08fcd6..22268ac1f150 100644 --- a/source/Security/protocols/sec_prot_keys.c +++ b/source/Security/protocols/sec_prot_keys.c @@ -716,7 +716,7 @@ int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk) return 0; } -gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash) +gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash, bool del_gtk_on_mismatch) { uint8_t *gtk_hash_ptr = gtkhash; @@ -729,11 +729,15 @@ gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t uint32_t lifetime = sec_prot_keys_gtk_lifetime_get(gtks, i); if (lifetime > GTK_EXPIRE_MISMATCH_TIME) { tr_info("GTK mismatch %i expired time, lifetime: %"PRIu32"", i, lifetime); - if (mismatch < GTK_LIFETIME_MISMATCH) { + // Only indicate mismatch in case fresh hash is received + if (mismatch < GTK_LIFETIME_MISMATCH && del_gtk_on_mismatch) { mismatch = GTK_LIFETIME_MISMATCH; } } - sec_prot_keys_gtk_clear(gtks, i); + // Only delete in case fresh hash is received + if (del_gtk_on_mismatch) { + sec_prot_keys_gtk_clear(gtks, i); + } } } else { // Check is hash matches to existing key @@ -759,7 +763,10 @@ gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t if (mismatch < GTK_HASH_MISMATCH) { mismatch = GTK_HASH_MISMATCH; } - sec_prot_keys_gtk_clear(gtks, i); + // Only delete in case fresh hash is received + if (del_gtk_on_mismatch) { + sec_prot_keys_gtk_clear(gtks, i); + } } } } diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index 6215bdc759f5..c397a93618f8 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -806,11 +806,12 @@ int8_t sec_prot_keys_gtk_valid_check(uint8_t *gtk); * * \param gtks GTK keys * \param gtk_hash GTK hash + * \param del_gtk_on_mismatch Delete GTK in case of mismatch * * \return GTK mismatch type or no mismatch * */ -gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash); +gtk_mismatch_e sec_prot_keys_gtks_hash_update(sec_prot_gtk_keys_t *gtks, uint8_t *gtkhash, bool del_gtk_on_mismatch); /** * sec_prot_keys_gtk_hash_empty checks if GTK hash field is empty