@@ -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
112130static 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
119137static 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);
126144static pae_supp_t * ws_pae_supp_get (protocol_interface_info_entry_t * interface_ptr );
127145static int8_t ws_pae_supp_event_send (kmp_service_t * service , void * data );
128146static 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 );
129149static int8_t ws_pae_supp_timer_if_start (kmp_service_t * service , kmp_api_t * kmp );
130150static int8_t ws_pae_supp_timer_if_stop (kmp_service_t * service , kmp_api_t * kmp );
131151static 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
157177static int8_t tasklet_id = -1 ;
158178static 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
160181static 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
703724int8_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+
859950static 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