]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Fix PMKID in EAPOL-Key msg 1/4
authorJouni Malinen <jouni@codeaurora.org>
Fri, 23 Mar 2018 15:45:44 +0000 (17:45 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 23 Mar 2018 16:44:48 +0000 (18:44 +0200)
Previously, the association that used SAE authentication ended up
recalculating the PMKID for EAPOL-Key msg 1/4 using incorrect
PMK-to-PMKID derivation instead of using the previously derived PMKID
from SAE. The correct PMKID was used only when going through PMKSA
caching exchange with a previously derived PMKSA from SAE.

Fix this by storing the SAE PMKID into the state machine entry for the
initial SAE authentication case when there is no explicit PMKSA entry
attached to the station.

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

index 71b6c4366c4e845cc639f46f94165f94542c650f..68bc333033e678d08c134556e63810da595a7e84 100644 (file)
@@ -2538,6 +2538,10 @@ static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta,
 #endif /* CONFIG_IEEE80211R_AP */
 
 #ifdef CONFIG_SAE
+               if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae &&
+                   sta->sae->state == SAE_ACCEPTED)
+                       wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid);
+
                if (wpa_auth_uses_sae(sta->wpa_sm) &&
                    sta->auth_alg == WLAN_AUTH_OPEN) {
                        struct rsn_pmksa_cache_entry *sa;
index 203329eeb2e55951bbcc6e3dc0fd059c0675d349..8dde1d0aa780b7ba5abc87413fe4bffe47f54057 100644 (file)
@@ -2035,11 +2035,31 @@ SM_STATE(WPA_PTK, PTKSTART)
                pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN;
                RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID);
                if (sm->pmksa) {
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Message 1/4 PMKID from PMKSA entry",
+                                   sm->pmksa->pmkid, PMKID_LEN);
                        os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN],
                                  sm->pmksa->pmkid, PMKID_LEN);
                } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) {
                        /* No KCK available to derive PMKID */
+                       wpa_printf(MSG_DEBUG,
+                                  "RSN: No KCK available to derive PMKID for message 1/4");
                        pmkid = NULL;
+#ifdef CONFIG_SAE
+               } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) {
+                       if (sm->pmkid_set) {
+                               wpa_hexdump(MSG_DEBUG,
+                                           "RSN: Message 1/4 PMKID from SAE",
+                                           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 SAE PMKID available for message 1/4");
+                               pmkid = NULL;
+                       }
+#endif /* CONFIG_SAE */
                } else {
                        /*
                         * Calculate PMKID since no PMKSA cache entry was
@@ -2048,6 +2068,9 @@ SM_STATE(WPA_PTK, PTKSTART)
                        rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr,
                                  sm->addr, &pmkid[2 + RSN_SELECTOR_LEN],
                                  sm->wpa_key_mgmt);
+                       wpa_hexdump(MSG_DEBUG,
+                                   "RSN: Message 1/4 PMKID derived from PMK",
+                                   &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN);
                }
        }
        wpa_send_eapol(sm->wpa_auth, sm,
@@ -4040,6 +4063,13 @@ int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
 }
 
 
+void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid)
+{
+       os_memcpy(sm->pmkid, pmkid, PMKID_LEN);
+       sm->pmkid_set = 1;
+}
+
+
 int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
                        const u8 *pmk, size_t pmk_len, const u8 *pmkid,
                        int session_timeout, int akmp)
index 1bfacdc7a2ae60a4770ecf8b9bd0f12920820e7f..6b1887bdc0a79945f218d017f0a1e5896e249ae0 100644 (file)
@@ -332,6 +332,7 @@ int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth,
                               struct eapol_state_machine *eapol);
 int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr,
                           const u8 *pmk, const u8 *pmkid);
+void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid);
 int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr,
                        const u8 *pmk, size_t pmk_len, const u8 *pmkid,
                        int session_timeout, int akmp);
index befa8007fdb27f18c2be9db307de161ca8b91e55..609405a26465182f04e5448009379582a125c3ab 100644 (file)
@@ -58,6 +58,7 @@ struct wpa_state_machine {
        u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN];
        u8 PMK[PMK_LEN_MAX];
        unsigned int pmk_len;
+       u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */
        struct wpa_ptk PTK;
        Boolean PTK_valid;
        Boolean pairwise_set;
@@ -90,6 +91,7 @@ struct wpa_state_machine {
        unsigned int pmk_r1_name_valid:1;
 #endif /* CONFIG_IEEE80211R_AP */
        unsigned int is_wnmsleep:1;
+       unsigned int pmkid_set:1;
 
        u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN];
        int req_replay_counter_used;