]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
FILS: Fix PTK rekeying
authorJouni Malinen <jouni@codeaurora.org>
Wed, 17 Apr 2019 19:52:23 +0000 (22:52 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 18 Apr 2019 18:55:39 +0000 (21:55 +0300)
The PMK and PMKID information from FILS ERP and FILS PMKSA caching needs
to be stored within struct wpa_state_machine for PTK to work. Without
this, PTK derivation would fail and attempt to go through rekeying would
result in disconnection. Furthermore, wpa_rekey_ptk() timer needs to be
started at the completion of FILS association since the place where it
was done for non-FILS cases at the end of 4-way handshake is not reached
when FILS authentication is used.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
src/ap/ieee802_11.c
src/ap/ieee802_1x.c
src/ap/wpa_auth.c
src/ap/wpa_auth.h

index 6fe5192552ace2670413b7cbff71a14a496eb574..fde19b526f05136dcd665a453392ba561bc46495 100644 (file)
@@ -1821,6 +1821,8 @@ prepare_auth_resp_fils(struct hostapd_data *hapd,
                        }
 
                        sta->fils_erp_pmkid_set = 0;
+                       wpa_auth_add_fils_pmk_pmkid(sta->wpa_sm, pmk, pmk_len,
+                                                   sta->fils_erp_pmkid);
                        if (!hapd->conf->disable_pmksa_caching &&
                            wpa_auth_pmksa_add2(
                                    hapd->wpa_auth, sta->addr,
index 870329a859415957dc55e3add189046b80a36f63..97f503f75cc3dd10e23c9df7273b00bf7fadfd6f 100644 (file)
@@ -1236,6 +1236,7 @@ void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta)
                sta->eapol_sm->portValid = TRUE;
                if (sta->eapol_sm->eap)
                        eap_sm_notify_cached(sta->eapol_sm->eap);
+               wpa_auth_set_ptk_rekey_timer(sta->wpa_sm);
                return;
        }
 #endif /* CONFIG_FILS */
index 616b20592caf68368aba4bbcffdb8a7cd1b473a7..4c7fe05b0ce96eb147b8034abbf161071dd68d3b 100644 (file)
@@ -320,6 +320,19 @@ static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx)
 }
 
 
+void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm)
+{
+       if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) {
+               wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for "
+                          MACSTR " (%d seconds)", MAC2STR(sm->addr),
+                          sm->wpa_auth->conf.wpa_ptk_rekey);
+               eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
+               eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0,
+                                      wpa_rekey_ptk, sm->wpa_auth, sm);
+       }
+}
+
+
 static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx)
 {
        if (sm->pmksa == ctx)
@@ -2124,6 +2137,21 @@ SM_STATE(WPA_PTK, PTKSTART)
                        wpa_printf(MSG_DEBUG,
                                   "RSN: No KCK available to derive PMKID for message 1/4");
                        pmkid = NULL;
+#ifdef CONFIG_FILS
+               } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) {
+                       if (sm->pmkid_set) {
+                               wpa_hexdump(MSG_DEBUG,
+                                           "RSN: Message 1/4 PMKID from FILS/ERP",
+                                           sm->pmkid, PMKID_LEN);
+                               os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
+                                         sm->pmkid, PMKID_LEN);
+                       } else {
+                               /* No PMKID available */
+                               wpa_printf(MSG_DEBUG,
+                                          "RSN: No FILS/ERP PMKID available for message 1/4");
+                               pmkid = NULL;
+                       }
+#endif /* CONFIG_FILS */
 #ifdef CONFIG_SAE
                } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
                        if (sm->pmkid_set) {
@@ -2790,6 +2818,12 @@ SM_STATE(WPA_PTK, PTKCALCNEGOTIATING)
                        pmk_len = sm->pmk_len;
                }
 
+               if ((!pmk || !pmk_len) && sm->pmksa) {
+                       wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache");
+                       pmk = sm->pmksa->pmk;
+                       pmk_len = sm->pmksa->pmk_len;
+               }
+
                if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0)
                        break;
 
@@ -3287,12 +3321,7 @@ SM_STATE(WPA_PTK, PTKINITDONE)
                /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */
                sm->pairwise_set = TRUE;
 
-               if (sm->wpa_auth->conf.wpa_ptk_rekey) {
-                       eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm);
-                       eloop_register_timeout(sm->wpa_auth->conf.
-                                              wpa_ptk_rekey, 0, wpa_rekey_ptk,
-                                              sm->wpa_auth, sm);
-               }
+               wpa_auth_set_ptk_rekey_timer(sm);
 
                if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) ||
                    sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP ||
@@ -4840,6 +4869,16 @@ void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
        *fils_kek_len = sm->PTK.kek_len;
 }
 
+
+void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
+                                size_t pmk_len, const u8 *pmkid)
+{
+       os_memcpy(sm->PMK, pmk, pmk_len);
+       sm->pmk_len = pmk_len;
+       os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
+       sm->pmkid_set = 1;
+}
+
 #endif /* CONFIG_FILS */
 
 
index 484e1e5cb73f552169705b3f9fd3f31361d2afc7..df1e17a003f8c3f11c302745c0af4889335f2ec0 100644 (file)
@@ -470,6 +470,8 @@ int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384,
 void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm,
                                   u8 *fils_anonce, u8 *fils_snonce,
                                   u8 *fils_kek, size_t *fils_kek_len);
+void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk,
+                                size_t pmk_len, const u8 *pmkid);
 u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm,
                                   u8 *pos, size_t max_len,
                                   const u8 *req_ies, size_t req_ies_len);
@@ -486,5 +488,6 @@ int wpa_auth_resend_group_m1(struct wpa_state_machine *sm,
                             void (*cb)(void *ctx1, void *ctx2),
                             void *ctx1, void *ctx2);
 int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth);
+void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm);
 
 #endif /* WPA_AUTH_H */