From 7415bc724b2d0c1bc47f877dc64f69754e502871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=20Lepp=C3=A4nen?= Date: Tue, 17 Aug 2021 09:43:56 +0300 Subject: [PATCH] Added checks for Border Router frame counter space exhaustion (#2660) * Added checks for Border Router frame counter space exhaustion Added three checks for Border Router frame counter space exhaustion: 1) Compares GTK lifetime left to frame counter space left (as percent) and decrements GTK lifetime if frame counter space is exhausting faster than GTK lifetime. 2) Calculates an estimate for how much free frame counter space is needed for the GTK update and initiates it faster if needed. 3) Calculates an estimate for how much free frame counter space is needed for the GTK activation and initiates it faster if needed. --- CHANGELOG.md | 1 + source/6LoWPAN/ws/ws_pae_auth.c | 123 +++++++++++++++++++++- source/6LoWPAN/ws/ws_pae_auth.h | 23 +++- source/6LoWPAN/ws/ws_pae_controller.c | 21 +++- source/6LoWPAN/ws/ws_pae_nvm_data.c | 9 +- source/6LoWPAN/ws/ws_pae_nvm_data.h | 4 +- source/Security/protocols/sec_prot_keys.c | 2 +- source/Security/protocols/sec_prot_keys.h | 5 +- 8 files changed, 170 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59d9ba1f3a40..ecbbf65a23cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Features * Added support for triggering test procedures (e.g. for manually sending DIS, DIO, DAO, PAS, PS, PCS and PC). * Added automatic test procedure triggering during bootstrap (PAS, EAPOL target selection, PCS, DIS, RPL parent selection). +* Added checks for Border Router frame counter space exhaustion. ### Changes * PAN_TIMEOUT for medium sized network changed to 30 minutes. diff --git a/source/6LoWPAN/ws/ws_pae_auth.c b/source/6LoWPAN/ws/ws_pae_auth.c index da2c3cf104d9..86a2cda51b93 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.c +++ b/source/6LoWPAN/ws/ws_pae_auth.c @@ -80,6 +80,11 @@ // Short GTK lifetime value, for GTK install check #define SHORT_GTK_LIFETIME 10 * 3600 // 10 hours +// Frame counter exhaust check timer +#define FRAME_CNT_TIMER 3600 + +#define SECONDS_IN_DAY (3600 * 24) + typedef struct { ns_list_link_t link; /**< Link */ uint16_t pan_id; /**< PAN ID */ @@ -93,6 +98,7 @@ typedef struct { ws_pae_auth_nw_info_updated *nw_info_updated; /**< Security keys network info updated callback */ ws_pae_auth_ip_addr_get *ip_addr_get; /**< IP address get callback */ ws_pae_auth_congestion_get *congestion_get; /**< Congestion get callback */ + ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read; /**< Network frame counter read callback */ supp_list_t active_supp_list; /**< List of active supplicants */ supp_list_t waiting_supp_list; /**< List of waiting supplicants */ shared_comp_list_t shared_comp_list; /**< Shared component list */ @@ -101,6 +107,9 @@ typedef struct { const sec_prot_certs_t *certs; /**< Certificates */ sec_prot_keys_nw_info_t *sec_keys_nw_info; /**< Security keys network information */ sec_cfg_t *sec_cfg; /**< Security configuration */ + frame_counters_t *frame_counters; /**< Frame counters */ + uint32_t prev_frame_cnt; /**< Previous frame counter */ + uint16_t prev_frame_cnt_timer; /**< Previous frame counter timer */ uint16_t supp_max_number; /**< Max number of stored supplicants */ uint16_t waiting_supp_list_size; /**< Waiting supplicants list size */ uint8_t relay_socked_msg_if_instance_id; /**< Relay socket message interface instance identifier */ @@ -108,6 +117,7 @@ typedef struct { bool timer_running : 1; /**< Timer is running */ bool gtk_new_inst_req_exp : 1; /**< GTK new install required timer expired */ bool gtk_new_act_time_exp: 1; /**< GTK new activation time expired */ + bool prev_frame_cnt_set : 1; /**< Previous frame counter set */ } pae_auth_t; static int8_t ws_pae_auth_network_keys_from_gtks_set(pae_auth_t *pae_auth, bool force_install); @@ -118,6 +128,7 @@ static pae_auth_t *ws_pae_auth_get(protocol_interface_info_entry_t *interface_pt static pae_auth_t *ws_pae_auth_by_kmp_service_get(kmp_service_t *service); static int8_t ws_pae_auth_event_send(kmp_service_t *service, void *data); static void ws_pae_auth_tasklet_handler(arm_event_s *event); +static uint32_t ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth_t *pae_auth, uint8_t gtk_index, uint16_t seconds); static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth); static int8_t ws_pae_auth_new_gtk_activate(pae_auth_t *pae_auth); static int8_t ws_pae_auth_timer_if_start(kmp_service_t *service, kmp_api_t *kmp); @@ -145,9 +156,9 @@ static void ws_pae_auth_waiting_supp_deleted(void *pae_auth); static int8_t tasklet_id = -1; static NS_LIST_DEFINE(pae_auth_list, pae_auth_t, link); -int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info) +int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info, frame_counters_t *frame_counters) { - if (!interface_ptr || !next_gtks || !certs || !sec_cfg || !sec_keys_nw_info) { + if (!interface_ptr || !next_gtks || !certs || !sec_cfg || !sec_keys_nw_info || !frame_counters) { return -1; } @@ -175,16 +186,21 @@ int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot pae_auth->nw_info_updated = NULL; pae_auth->ip_addr_get = NULL; pae_auth->congestion_get = NULL; + pae_auth->nw_frame_cnt_read = NULL; pae_auth->next_gtks = next_gtks; pae_auth->certs = certs; pae_auth->sec_keys_nw_info = sec_keys_nw_info; pae_auth->sec_cfg = sec_cfg; + pae_auth->frame_counters = frame_counters; + pae_auth->prev_frame_cnt = 0; + pae_auth->prev_frame_cnt_timer = FRAME_CNT_TIMER; pae_auth->supp_max_number = SUPPLICANT_MAX_NUMBER; pae_auth->waiting_supp_list_size = 0; pae_auth->gtk_new_inst_req_exp = false; pae_auth->gtk_new_act_time_exp = false; + pae_auth->prev_frame_cnt_set = false; pae_auth->relay_socked_msg_if_instance_id = 0; pae_auth->radius_socked_msg_if_instance_id = 0; @@ -316,7 +332,7 @@ int8_t ws_pae_auth_delete(protocol_interface_info_entry_t *interface_ptr) return 0; } -void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get) +void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get, ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read) { if (!interface_ptr) { return; @@ -333,6 +349,7 @@ void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_ pae_auth->nw_info_updated = nw_info_updated; pae_auth->ip_addr_get = ip_addr_get; pae_auth->congestion_get = congestion_get; + pae_auth->nw_frame_cnt_read = nw_frame_cnt_read; } void ws_pae_auth_start(protocol_interface_info_entry_t *interface_ptr) @@ -734,7 +751,11 @@ void ws_pae_auth_slow_timer(uint16_t seconds) if (!sec_prot_keys_gtk_is_set(pae_auth->sec_keys_nw_info->gtks, i)) { continue; } - uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds, true); + uint32_t gtk_lifetime_dec_extra_seconds = 0; + if (active_index == i) { + gtk_lifetime_dec_extra_seconds = ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth, i, seconds); + } + uint32_t timer_seconds = sec_prot_keys_gtk_lifetime_decrement(pae_auth->sec_keys_nw_info->gtks, i, current_time, seconds + gtk_lifetime_dec_extra_seconds, true); if (active_index == i) { if (!pae_auth->gtk_new_inst_req_exp) { pae_auth->gtk_new_inst_req_exp = ws_pae_timers_gtk_new_install_required(pae_auth->sec_cfg, timer_seconds); @@ -786,6 +807,100 @@ void ws_pae_auth_slow_timer(uint16_t seconds) ws_pae_key_storage_timer(seconds); } +static uint32_t ws_pae_auth_lifetime_key_frame_cnt_check(pae_auth_t *pae_auth, uint8_t gtk_index, uint16_t seconds) +{ + uint32_t decrement_seconds = 0; + + if (pae_auth->prev_frame_cnt_timer > seconds) { + pae_auth->prev_frame_cnt_timer -= seconds; + return 0; + } + pae_auth->prev_frame_cnt_timer = FRAME_CNT_TIMER; + + uint32_t frame_cnt = 0; + if (pae_auth->nw_frame_cnt_read(pae_auth->interface_ptr, &frame_cnt, gtk_index) < 0) { + return 0; + } + + sec_timer_cfg_t *timer_cfg = &pae_auth->sec_cfg->timer_cfg; + + // For GTK lifetime and frame counter space calculate the percent that has been used + uint32_t gtk_lifetime_left = sec_prot_keys_gtk_lifetime_get(pae_auth->sec_keys_nw_info->gtks, gtk_index); + uint32_t gtk_lifetime = timer_cfg->gtk_expire_offset; + uint32_t gtk_lifetime_left_percent = gtk_lifetime_left * 100 / gtk_lifetime; + + uint32_t frame_cnt_left_percent = ((uint64_t)((UINT32_MAX - frame_cnt))) * 100 / UINT32_MAX; + + tr_info("Active GTK lifetime %"PRIu32", frame counter %"PRIu32" percent, counter %"PRIu32, gtk_lifetime_left_percent, frame_cnt_left_percent, frame_cnt); + + /* If frame counter space has been exhausted faster than should be based on GTK lifetime + * decrements GTK lifetime. Do not check until 20% of the frame counter space has been used + * so that we have data from longer time period. As sanity check, validate that GTK lifetime + * is not more than 105% of the GTK lifetime. + */ + uint32_t gtk_new_install_req_seconds = timer_cfg->gtk_expire_offset - timer_cfg->gtk_new_install_req * timer_cfg->gtk_expire_offset / 100; + if ((frame_cnt_left_percent < gtk_lifetime_left_percent && frame_cnt_left_percent < 80) || + gtk_lifetime_left_percent > 105) { + // If not yet on GTK update period + if (gtk_lifetime_left > (gtk_new_install_req_seconds + SECONDS_IN_DAY)) { + uint32_t diff = gtk_lifetime_left_percent - frame_cnt_left_percent; + decrement_seconds = gtk_lifetime * diff / 100 + SECONDS_IN_DAY; + if (decrement_seconds > gtk_lifetime_left - gtk_new_install_req_seconds) { + decrement_seconds = gtk_lifetime_left - gtk_new_install_req_seconds; + } + tr_info("Decrement GTK lifetime percent, seconds %"PRIu32, decrement_seconds); + } + } + + // Calculate how much frame counters have changed and store maximum if larger than previous maximum + uint32_t frame_cnt_diff = 0; + if (pae_auth->prev_frame_cnt_set && frame_cnt > pae_auth->prev_frame_cnt) { + frame_cnt_diff = frame_cnt - pae_auth->prev_frame_cnt; + if (frame_cnt_diff > pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg) { + pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg = frame_cnt_diff; + } + } + + tr_info("Frame counter change %"PRIu32", max %"PRIu32, frame_cnt_diff, pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg); + + /* Calculates an estimate for how much free frame counter space is needed for the GTK update and + * initiates it faster if needed (default length of GTK update is 6 days). + */ + uint32_t max_needed_frame_counters = + pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg * gtk_new_install_req_seconds / 3600; + // Adds 20% to calculated value + max_needed_frame_counters = max_needed_frame_counters * 120 / 100; + // If estimated value is more than is left starts GTK update right away (if not already started) + if (max_needed_frame_counters >= (UINT32_MAX - frame_cnt)) { + if (gtk_lifetime_left > gtk_new_install_req_seconds) { + decrement_seconds = gtk_lifetime_left - gtk_new_install_req_seconds; + tr_info("Decrement GTK lifetime update, seconds %"PRIu32, decrement_seconds); + } + } + + /* Calculates an estimate for how much free frame counter space is needed for the GTK activation and + * initiates it faster if needed (default length of GTK activation is 60 minutes). + */ + uint32_t gtk_new_activation_time_seconds = timer_cfg->gtk_expire_offset / timer_cfg->gtk_new_act_time; + // Calculates the estimated maximum value for frame counter during GTK update + max_needed_frame_counters = + pae_auth->frame_counters->counter[gtk_index].max_frame_counter_chg * gtk_new_activation_time_seconds / 3600; + // Adds 200% to calculated value + max_needed_frame_counters = max_needed_frame_counters * 300 / 100; + // If estimated value is more than is left starts GTK update right away (if not already started) + if (max_needed_frame_counters >= (UINT32_MAX - frame_cnt)) { + if (gtk_lifetime_left > gtk_new_activation_time_seconds) { + decrement_seconds = gtk_lifetime_left - gtk_new_activation_time_seconds; + tr_info("Decrement GTK lifetime activation, seconds %"PRIu32, decrement_seconds); + } + } + + pae_auth->prev_frame_cnt = frame_cnt; + pae_auth->prev_frame_cnt_set = true; + + return decrement_seconds; +} + static void ws_pae_auth_gtk_key_insert(pae_auth_t *pae_auth) { // Gets index to install the key diff --git a/source/6LoWPAN/ws/ws_pae_auth.h b/source/6LoWPAN/ws/ws_pae_auth.h index 4b6dd0743231..8abfe1e97047 100644 --- a/source/6LoWPAN/ws/ws_pae_auth.h +++ b/source/6LoWPAN/ws/ws_pae_auth.h @@ -48,12 +48,13 @@ * \param timer_settings timer settings * \param sec_cfg security configuration * \param sec_keys_nw_info security keys network information + * \param frame_counters frame counters * * \return < 0 failure * \return >= 0 success * */ -int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info); +int8_t ws_pae_auth_init(protocol_interface_info_entry_t *interface_ptr, sec_prot_gtk_keys_t *next_gtks, const sec_prot_certs_t *certs, sec_cfg_t *sec_cfg, sec_prot_keys_nw_info_t *sec_keys_nw_info, frame_counters_t *frame_counters); /** * ws_pae_auth_addresses_set set relay addresses @@ -260,6 +261,19 @@ typedef void ws_pae_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ */ typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); +/** + * ws_pae_auth_nw_frame_counter_read network frame counter read callback + * + * \param interface_ptr interface + * \param counter frame counter + * \param gtk_index GTK index + * + * \return < 0 failure + * \return >= 0 success + * + */ +typedef int8_t ws_pae_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index); + /** * ws_pae_auth_cb_register register PAE authenticator callbacks * @@ -270,17 +284,18 @@ typedef bool ws_pae_auth_congestion_get(protocol_interface_info_entry_t *interfa * \param nw_info_updated network keys updated callback * \param ip_addr_get IP addressing information callback * \param congestion_get congestion get callback + * \param nw_frame_cnt_read network frame counter read callback * */ -void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get); +void ws_pae_auth_cb_register(protocol_interface_info_entry_t *interface_ptr, ws_pae_auth_gtk_hash_set *hash_set, ws_pae_auth_nw_key_insert *nw_key_insert, ws_pae_auth_nw_key_index_set *nw_key_index_set, ws_pae_auth_nw_info_updated *nw_info_updated, ws_pae_auth_ip_addr_get *ip_addr_get, ws_pae_auth_congestion_get *congestion_get, ws_pae_auth_nw_frame_counter_read *nw_frame_cnt_read); #else -#define ws_pae_auth_init(interface_ptr, next_gtks, certs, sec_cfg, sec_keys_nw_info) 1 +#define ws_pae_auth_init(interface_ptr, next_gtks, certs, sec_cfg, sec_keys_nw_info, frame_counters) 1 #define ws_pae_auth_timing_adjust(timing) #define ws_pae_auth_addresses_set(interface_ptr, local_port, remote_addr, remote_port) 1 #define ws_pae_auth_delete NULL -#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get) {(void) hash_set;} +#define ws_pae_auth_cb_register(interface_ptr, hash_set, nw_key_insert, nw_key_index_set, nw_info_updated, ip_addr_get, congestion_get, nw_frame_cnt_read) {(void) hash_set;} #define ws_pae_auth_start(interface_ptr) #define ws_pae_auth_gtks_updated NULL #define ws_pae_auth_nw_key_index_update NULL diff --git a/source/6LoWPAN/ws/ws_pae_controller.c b/source/6LoWPAN/ws/ws_pae_controller.c index a7778db54a41..0ea3fd325e62 100644 --- a/source/6LoWPAN/ws/ws_pae_controller.c +++ b/source/6LoWPAN/ws/ws_pae_controller.c @@ -119,6 +119,7 @@ static void ws_pae_controller_nw_info_updated_check(protocol_interface_info_entr #ifdef HAVE_PAE_AUTH static void ws_pae_controller_auth_ip_addr_get(protocol_interface_info_entry_t *interface_ptr, uint8_t *address); static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_t *interface_ptr, uint16_t active_supp); +static int8_t ws_pae_controller_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index); #endif static pae_controller_t *ws_pae_controller_get(protocol_interface_info_entry_t *interface_ptr); static void ws_pae_controller_frame_counter_timer(uint16_t seconds, pae_controller_t *entry); @@ -239,7 +240,7 @@ int8_t ws_pae_controller_authenticator_start(protocol_interface_info_entry_t *in ws_pae_auth_node_limit_set(controller->interface_ptr, pae_controller_config.node_limit); } - ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get, ws_pae_controller_auth_congestion_get); + ws_pae_auth_cb_register(interface_ptr, ws_pae_controller_gtk_hash_set, ws_pae_controller_nw_key_check_and_insert, ws_pae_controller_nw_key_index_check_and_set, ws_pae_controller_nw_info_updated_check, ws_pae_controller_auth_ip_addr_get, ws_pae_controller_auth_congestion_get, ws_pae_controller_auth_nw_frame_counter_read); controller->auth_started = true; @@ -410,6 +411,21 @@ static bool ws_pae_controller_auth_congestion_get(protocol_interface_info_entry_ return controller->congestion_get(interface_ptr, active_supp); } + +static int8_t ws_pae_controller_auth_nw_frame_counter_read(protocol_interface_info_entry_t *interface_ptr, uint32_t *counter, uint8_t gtk_index) +{ + if (!interface_ptr) { + return -1; + } + + pae_controller_t *controller = ws_pae_controller_get(interface_ptr); + if (!controller) { + return -1; + } + + controller->nw_frame_counter_read(interface_ptr, counter, gtk_index); + return 0; +} #endif int8_t ws_pae_controller_nw_key_valid(protocol_interface_info_entry_t *interface_ptr, uint8_t *br_iid) @@ -849,6 +865,7 @@ static void ws_pae_controller_frame_counter_index_reset(frame_counters_t *frame_ memset(frame_counters->counter[index].gtk, 0, GTK_LEN); frame_counters->counter[index].frame_counter = 0; frame_counters->counter[index].stored_frame_counter = 0; + frame_counters->counter[index].max_frame_counter_chg = 0; frame_counters->counter[index].set = false; } @@ -951,7 +968,7 @@ int8_t ws_pae_controller_auth_init(protocol_interface_info_entry_t *interface_pt return -1; } - if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info) < 0) { + if (ws_pae_auth_init(controller->interface_ptr, &controller->next_gtks, &controller->certs, &controller->sec_cfg, &controller->sec_keys_nw_info, &controller->frame_counters) < 0) { return -1; } diff --git a/source/6LoWPAN/ws/ws_pae_nvm_data.c b/source/6LoWPAN/ws/ws_pae_nvm_data.c index 27eacbc45f0e..72c59e2ce5b0 100644 --- a/source/6LoWPAN/ws/ws_pae_nvm_data.c +++ b/source/6LoWPAN/ws/ws_pae_nvm_data.c @@ -304,14 +304,15 @@ void ws_pae_nvm_store_frame_counter_tlv_create(frame_cnt_nvm_tlv_t *tlv_entry, u for (uint8_t index = 0; index < GTK_NUM; index++) { if (!counters->counter[index].set) { *tlv++ = PAE_NVM_FIELD_NOT_SET; - memset(tlv, 0, GTK_LEN + 4); - tlv += GTK_LEN + 4; + memset(tlv, 0, GTK_LEN + 4 + 4); + tlv += GTK_LEN + 4 + 4; continue; } *tlv++ = PAE_NVM_FIELD_SET; memcpy(tlv, counters->counter[index].gtk, GTK_LEN); tlv += GTK_LEN; tlv = common_write_32_bit(counters->counter[index].frame_counter, tlv); + tlv = common_write_32_bit(counters->counter[index].max_frame_counter_chg, tlv); } tr_debug("NVM FRAME COUNTER write"); @@ -342,7 +343,7 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, u // Frame counter not set if (*tlv++ == PAE_NVM_FIELD_NOT_SET) { counters->counter[index].set = false; - tlv += GTK_LEN + 4; + tlv += GTK_LEN + 4 + 4; continue; } // Frame counter is set, read GTK key and counter values @@ -351,6 +352,8 @@ int8_t ws_pae_nvm_store_frame_counter_tlv_read(frame_cnt_nvm_tlv_t *tlv_entry, u tlv += GTK_LEN; counters->counter[index].frame_counter = common_read_32_bit(tlv); tlv += 4; + counters->counter[index].max_frame_counter_chg = common_read_32_bit(tlv); + tlv += 4; } tr_debug("NVM FRAME COUNTER read"); diff --git a/source/6LoWPAN/ws/ws_pae_nvm_data.h b/source/6LoWPAN/ws/ws_pae_nvm_data.h index 9194e2b5b98d..c2a6af731d4a 100644 --- a/source/6LoWPAN/ws/ws_pae_nvm_data.h +++ b/source/6LoWPAN/ws/ws_pae_nvm_data.h @@ -41,8 +41,8 @@ // 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 -// restart counter + stored time + pan version + (frame counter set (1) + GTK (16) + frame counter (4)) * 4 -#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + 2 + (1 + GTK_LEN + 4) * GTK_NUM +// restart counter + stored time + pan version + (frame counter set (1) + GTK (16) + frame counter (4) + max frame counter change (4)) * 4 +#define PAE_NVM_FRAME_COUNTER_LEN 4 + 8 + 2 + (1 + GTK_LEN + 4 + 4) * GTK_NUM #define PAE_NVM_DEFAULT_BUFFER_SIZE sizeof(nvm_tlv_t) + PAE_NVM_NW_INFO_LEN diff --git a/source/Security/protocols/sec_prot_keys.c b/source/Security/protocols/sec_prot_keys.c index 22268ac1f150..161cbc9a5b87 100644 --- a/source/Security/protocols/sec_prot_keys.c +++ b/source/Security/protocols/sec_prot_keys.c @@ -507,7 +507,7 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index return gtks->gtk[index].lifetime; } -uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable) +uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint32_t seconds, bool gtk_update_enable) { if (gtks->gtk[index].lifetime > seconds) { gtks->gtk[index].lifetime -= seconds; diff --git a/source/Security/protocols/sec_prot_keys.h b/source/Security/protocols/sec_prot_keys.h index c397a93618f8..3d435e6e42f9 100644 --- a/source/Security/protocols/sec_prot_keys.h +++ b/source/Security/protocols/sec_prot_keys.h @@ -108,7 +108,8 @@ typedef struct { typedef struct { uint8_t gtk[GTK_LEN]; /**< GTK of the frame counter */ uint32_t frame_counter; /**< Current frame counter */ - uint32_t stored_frame_counter; /**< Stored Frame counter */ + uint32_t stored_frame_counter; /**< Stored frame counter */ + uint32_t max_frame_counter_chg; /**< Maximum frame counter change */ bool set : 1; /**< Value has been set */ } frame_counter_t; @@ -630,7 +631,7 @@ uint32_t sec_prot_keys_gtk_lifetime_get(sec_prot_gtk_keys_t *gtks, uint8_t index * \return new GTK lifetime * */ -uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint16_t seconds, bool gtk_update_enable); +uint32_t sec_prot_keys_gtk_lifetime_decrement(sec_prot_gtk_keys_t *gtks, uint8_t index, uint64_t current_time, uint32_t seconds, bool gtk_update_enable); /** * sec_prot_keys_gtk_exptime_from_lifetime_get converts GTK lifetime to expiry time.