Skip to content

Commit 7350634

Browse files
author
Mika Leppänen
committed
Corrected initial EAPOL-key trickle retries
Minimum interval for first retry is now always at least 5 minutes and maximum can be 60 minutes on very slow network. Decreased number of retries from three to two to keep the time taken by the sequence roughly the same as before (previously sequence took about 15 to 20 minutes). After the last retry, the supplicant now waits for 2 to 4 minutes for authenticator to answer and not the expiry of last interval as before. For default network sizes, the I interval is from 6 to 12 minutes. There is also initial delay of 2 minutes before the first retry to ensure that the first retry happens at minimum at 5 minutes. This results that the first retry happens at 5 (2 + 3) to 14 (2 + 12) minutes after the initial attempt, and the second retry at 6 to 12 minutes from the first expiry of interval. The whole sequence (with 2 to 4 minutes wait after the last retry) takes on minimum 16 minutes and on maximum 30 minutes. On very slow networks, the I interval is from 10 to 60 minutes. This results that the first retry happens at 5 to 60 minutes after the initial attempt (there is no initial delay), and the second retry at 10 to 60 minutes from the first expiry of interval. The whole sequence (with 2 to 4 minutes wait after the last retry) takes on minimum 22 minutes and on maximum 124 minutes.
1 parent ac33518 commit 7350634

File tree

1 file changed

+111
-20
lines changed

1 file changed

+111
-20
lines changed

source/6LoWPAN/ws/ws_pae_supp.c

Lines changed: 111 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -91,13 +91,15 @@ typedef struct {
9191
supp_entry_t entry; /**< Supplicant data */
9292
kmp_addr_t target_addr; /**< EAPOL target (parent) address */
9393
uint16_t initial_key_timer; /**< Timer to trigger initial EAPOL-Key */
94+
uint16_t initial_key_retry_timer; /**< Timer to trigger initial EAPOL-Key 1st retry */
9495
trickle_t auth_trickle_timer; /**< Trickle timer for re-sending initial EAPOL-key or for GTK mismatch */
9596
trickle_params_t auth_trickle_params; /**< Trickle parameters for initial EAPOL-key or for GTK mismatch */
9697
sec_prot_gtk_keys_t gtks; /**< GTKs */
9798
uint8_t new_br_eui_64[8]; /**< Border router EUI-64 indicated by bootstrap */
9899
sec_prot_keys_nw_info_t sec_keys_nw_info; /**< Security keys network information */
99100
timer_settings_t *timer_settings; /**< Timer settings */
100101
uint8_t nw_keys_used_cnt; /**< How many times bootstrap has been tried with current keys */
102+
uint8_t initial_key_retry_cnt; /**< initial EAPOL-Key retry counter */
101103
bool auth_trickle_running : 1; /**< Initial EAPOL-Key Trickle timer running */
102104
bool auth_requested : 1; /**< Authentication has been requested by the bootstrap */
103105
bool timer_running : 1; /**< Timer is running */
@@ -106,14 +108,30 @@ typedef struct {
106108
bool entry_address_active: 1;
107109
} pae_supp_t;
108110

111+
// How many times sending of initial EAPOL-key is retried
112+
#define INITIAL_KEY_RETRY_COUNT 2
109113

110-
#define TRICKLE_IMIN_180_SECS 180
114+
// How long the wait is before the first initial EAPOL-key retry
115+
#define DEFAULT_INITIAL_KEY_RETRY_TIMER 120
116+
#define NONE_INITIAL_KEY_RETRY_TIMER 0
117+
118+
// Default trickle values for sending of initial EAPOL-key
119+
#define DEFAULT_TRICKLE_IMIN_SECS 360 /* 6 to 12 minutes */
120+
#define DEFAULT_TRICKLE_IMAX_SECS 720
121+
122+
// Very slow network values for sending of initial EAPOL-key
123+
#define VERY_SLOW_NW_TRICKLE_IMIN_SECS 600 /* 10 to 60 minutes */
124+
#define VERY_SLOW_NW_TRICKLE_IMAX_SECS 3600
125+
126+
// Trickle timer on how long to wait response after last retry before failing authentication
127+
#define LAST_INTERVAL_TRICKLE_IMIN_SECS 240 /* 4 minutes */
128+
#define LAST_INTERVAL_TRICKLE_IMAX_SECS 240
111129

112130
static trickle_params_t initial_eapol_key_trickle_params = {
113-
.Imin = TRICKLE_IMIN_180_SECS, /* 180 second; ticks are 1 second */
114-
.Imax = TRICKLE_IMIN_180_SECS << 1, /* 360 second */
115-
.k = 0, /* infinity - no consistency checking */
116-
.TimerExpirations = 3
131+
.Imin = DEFAULT_TRICKLE_IMIN_SECS, /* 360 second; ticks are 1 second */
132+
.Imax = DEFAULT_TRICKLE_IMAX_SECS, /* 720 second */
133+
.k = 0, /* infinity - no consistency checking */
134+
.TimerExpirations = 2
117135
};
118136

119137
static void ws_pae_supp_free(pae_supp_t *pae_supp);
@@ -126,6 +144,8 @@ static int8_t ws_pae_supp_nvm_keys_write(pae_supp_t *pae_supp);
126144
static pae_supp_t *ws_pae_supp_get(protocol_interface_info_entry_t *interface_ptr);
127145
static int8_t ws_pae_supp_event_send(kmp_service_t *service, void *data);
128146
static void ws_pae_supp_tasklet_handler(arm_event_s *event);
147+
static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp);
148+
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp);
129149
static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp);
130150
static int8_t ws_pae_supp_timer_if_stop(kmp_service_t *service, kmp_api_t *kmp);
131151
static int8_t ws_pae_supp_timer_start(pae_supp_t *pae_supp);
@@ -156,6 +176,7 @@ static const char *KEYS_FILE = KEYS_FILE_NAME;
156176

157177
static int8_t tasklet_id = -1;
158178
static NS_LIST_DEFINE(pae_supp_list, pae_supp_t, link);
179+
static uint8_t timing_value = 0; // Timing value set based e.g. on network size
159180

160181
static void ws_pae_supp_address_set(pae_supp_t *pae_supp, kmp_addr_t *address)
161182
{
@@ -323,14 +344,12 @@ int8_t ws_pae_supp_gtk_hash_update(protocol_interface_info_entry_t *interface_pt
323344
// Starts trickle
324345
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
325346
pae_supp->auth_trickle_running = true;
347+
pae_supp->initial_key_retry_timer = 0;
326348

327349
// Starts supplicant timer
328350
ws_pae_supp_timer_start(pae_supp);
329351

330352
tr_info("GTK update start imin: %i, imax: %i, max mismatch: %i, tr time: %i", pae_supp->timer_settings->gtk_request_imin, pae_supp->timer_settings->gtk_request_imax, pae_supp->timer_settings->gtk_max_mismatch, pae_supp->auth_trickle_timer.t);
331-
} else {
332-
// If trickle is already running, set inconsistent heard to speed up the trickle
333-
trickle_inconsistent_heard(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
334353
}
335354
}
336355

@@ -597,8 +616,10 @@ int8_t ws_pae_supp_init(protocol_interface_info_entry_t *interface_ptr, const se
597616
pae_supp->nw_key_insert = NULL;
598617
pae_supp->nw_key_index_set = NULL;
599618
pae_supp->initial_key_timer = 0;
619+
pae_supp->initial_key_retry_timer = 0;
600620
pae_supp->nw_keys_used_cnt = 0;
601621
pae_supp->timer_settings = timer_settings;
622+
pae_supp->initial_key_retry_cnt = 0;
602623
pae_supp->auth_trickle_running = false;
603624
pae_supp->auth_requested = false;
604625
pae_supp->timer_running = false;
@@ -702,6 +723,7 @@ int8_t ws_pae_supp_delete(protocol_interface_info_entry_t *interface_ptr)
702723

703724
int8_t ws_pae_supp_timing_adjust(uint8_t timing)
704725
{
726+
timing_value = timing;
705727
supp_fwh_sec_prot_timing_adjust(timing);
706728
supp_eap_sec_prot_timing_adjust(timing);
707729
return 0;
@@ -817,14 +839,38 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
817839

818840
// Checks whether initial EAPOL-Key message needs to be re-send or new GTK request to be sent
819841
if (pae_supp->auth_trickle_running) {
820-
if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
821-
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
822-
tr_info("EAPOL-Key send failed");
842+
if (pae_supp->initial_key_retry_timer > 0) {
843+
if (pae_supp->initial_key_retry_timer > seconds) {
844+
pae_supp->initial_key_retry_timer -= seconds;
845+
} else {
846+
pae_supp->initial_key_retry_timer = 0;
847+
tr_info("initial key retry timer expired");
848+
}
849+
} else {
850+
// Checks if trickle timer expires
851+
if (trickle_timer(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params, seconds)) {
852+
if (pae_supp->initial_key_retry_cnt < INITIAL_KEY_RETRY_COUNT) {
853+
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
854+
tr_info("EAPOL-Key send failed");
855+
}
856+
}
857+
pae_supp->initial_key_retry_cnt++;
858+
859+
/* Wait time for the authenticator to answer the last re-transmit expires;
860+
fails authentication */
861+
if (pae_supp->initial_key_retry_cnt > INITIAL_KEY_RETRY_COUNT) {
862+
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
863+
} else if (pae_supp->initial_key_retry_cnt == INITIAL_KEY_RETRY_COUNT) {
864+
// Starts wait time for the authenticator to answer
865+
tr_info("Initial EAPOL-Key wait for last re-transmit answer");
866+
ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp);
867+
}
868+
}
869+
870+
// Sanity check, should be running until authentication failure
871+
if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) {
872+
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
823873
}
824-
}
825-
// Maximum number of trickle expires, authentication fails
826-
if (!trickle_running(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params)) {
827-
ws_pae_supp_authenticate_response(pae_supp, AUTH_RESULT_ERR_UNSPEC);
828874
}
829875
}
830876

@@ -846,16 +892,61 @@ void ws_pae_supp_slow_timer(uint16_t seconds)
846892
if (ws_pae_supp_initial_key_send(pae_supp) < 0) {
847893
tr_info("EAPOL-Key send failed");
848894
}
849-
850-
// Starts trickle
851-
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
852-
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
853-
pae_supp->auth_trickle_running = true;
895+
// Start trickle timer
896+
ws_pae_supp_initial_trickle_timer_start(pae_supp);
854897
}
855898
}
856899
}
857900
}
858901

902+
static void ws_pae_supp_initial_trickle_timer_start(pae_supp_t *pae_supp)
903+
{
904+
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
905+
906+
// Very fast, medium and slow network
907+
if (timing_value < 25) {
908+
/* Starts trickle for initial EAPOL-key. Sequence has fixed delay of 2 minutes,
909+
* one re-transmit interval, last re-transmit interval transmit time and a wait time
910+
* for the authenticator to answer the last re-transmit.
911+
*
912+
* Interval I [6,12] minutes. Sequence:
913+
*
914+
* fixed 2 minutes delay + I + last I transmit time t + wait for answer [2,4] minutes
915+
*
916+
* There are two retries. Minimum time that sequence takes before authentication failure
917+
* is 16 minutes and maximum is 30 minutes.
918+
*/
919+
pae_supp->initial_key_retry_timer = DEFAULT_INITIAL_KEY_RETRY_TIMER; // 2 minutes
920+
} else {
921+
/* Extremely slow network
922+
*
923+
* Starts trickle for initial EAPOL-key, Interval I [10,60] minutes. Sequence:
924+
* I + last I transmit time t + wait for answer [2,4] minutes
925+
* There are two retries. Minimum time that sequence takes before authentication failure
926+
* is 22 minutes and maximum is 124 minutes.
927+
*/
928+
pae_supp->auth_trickle_params.Imin = VERY_SLOW_NW_TRICKLE_IMIN_SECS;
929+
pae_supp->auth_trickle_params.Imax = VERY_SLOW_NW_TRICKLE_IMAX_SECS;
930+
pae_supp->initial_key_retry_timer = NONE_INITIAL_KEY_RETRY_TIMER; // 0 seconds
931+
}
932+
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
933+
tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t);
934+
pae_supp->auth_trickle_running = true;
935+
pae_supp->initial_key_retry_cnt = 0;
936+
}
937+
938+
static void ws_pae_supp_initial_last_interval_trickle_timer_start(pae_supp_t *pae_supp)
939+
{
940+
// Starts trickle last to wait response after last retry before failing authentication
941+
pae_supp->auth_trickle_params = initial_eapol_key_trickle_params;
942+
pae_supp->auth_trickle_params.Imin = LAST_INTERVAL_TRICKLE_IMIN_SECS;
943+
pae_supp->auth_trickle_params.Imax = LAST_INTERVAL_TRICKLE_IMAX_SECS;
944+
pae_supp->auth_trickle_params.TimerExpirations = 1;
945+
// Set I to [iMin,iMax] (4 to 4 minutes) -> t is [I/2 - I] (2 minutes to 4 minutes)
946+
trickle_start(&pae_supp->auth_trickle_timer, &pae_supp->auth_trickle_params);
947+
tr_info("Initial EAPOL-Key trickle I: [%i,%i] %i, t: %i", pae_supp->auth_trickle_params.Imin, pae_supp->auth_trickle_params.Imax, pae_supp->auth_trickle_timer.I, pae_supp->auth_trickle_timer.t);
948+
}
949+
859950
static int8_t ws_pae_supp_timer_if_start(kmp_service_t *service, kmp_api_t *kmp)
860951
{
861952
pae_supp_t *pae_supp = ws_pae_supp_by_kmp_service_get(service);

0 commit comments

Comments
 (0)