]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Add support for PMKSA caching on the station side
authorJouni Malinen <j@w1.fi>
Sat, 18 Oct 2014 10:02:02 +0000 (13:02 +0300)
committerJouni Malinen <j@w1.fi>
Sat, 18 Oct 2014 10:02:02 +0000 (13:02 +0300)
This makes wpa_supplicant SME create PMKSA cache entries from SAE
authentication and try to use PMKSA caching if an entry is found for the
AP. If the AP rejects the attempt, fall back to SAE authentication is
used.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/rsn_supp/wpa.c
src/rsn_supp/wpa.h
wpa_supplicant/ibss_rsn.c
wpa_supplicant/sme.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index b17fc88b9adda9526b19de74c4d896ed6cb9de55..4df9e253cab68d737248d9563dd2cc00b64b0ec1 100644 (file)
@@ -2181,10 +2181,12 @@ void wpa_sm_notify_disassoc(struct wpa_sm *sm)
  * @sm: Pointer to WPA state machine data from wpa_sm_init()
  * @pmk: The new PMK
  * @pmk_len: The length of the new PMK in bytes
+ * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK
  *
  * Configure the PMK for WPA state machine.
  */
-void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
+void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+                   const u8 *bssid)
 {
        if (sm == NULL)
                return;
@@ -2197,6 +2199,11 @@ void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len)
        sm->xxkey_len = pmk_len;
        os_memcpy(sm->xxkey, pmk, pmk_len);
 #endif /* CONFIG_IEEE80211R */
+
+       if (bssid) {
+               pmksa_cache_add(sm->pmksa, pmk, pmk_len, bssid, sm->own_addr,
+                               sm->network_ctx, sm->key_mgmt);
+       }
 }
 
 
index 63032b0236e3cd3b23c27b01d50fe5d21dcb536f..595fdf2095576720a92c5cd894fa23ea7600bae8 100644 (file)
@@ -105,7 +105,8 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx);
 void wpa_sm_deinit(struct wpa_sm *sm);
 void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid);
 void wpa_sm_notify_disassoc(struct wpa_sm *sm);
-void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len);
+void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len,
+                   const u8 *bssid);
 void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm);
 void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth);
 void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx);
index 3083dd8093bac7068eb383642dda5b1ae8461de8..0e487d2c08e548ff5933712bd530d504dd5c28e7 100644 (file)
@@ -230,7 +230,7 @@ static int ibss_rsn_supp_init(struct ibss_rsn_peer *peer, const u8 *own_addr,
        wpa_sm_set_param(peer->supp, WPA_PARAM_PAIRWISE, WPA_CIPHER_CCMP);
        wpa_sm_set_param(peer->supp, WPA_PARAM_GROUP, WPA_CIPHER_CCMP);
        wpa_sm_set_param(peer->supp, WPA_PARAM_KEY_MGMT, WPA_KEY_MGMT_PSK);
-       wpa_sm_set_pmk(peer->supp, psk, PMK_LEN);
+       wpa_sm_set_pmk(peer->supp, psk, PMK_LEN, NULL);
 
        peer->supp_ie_len = sizeof(peer->supp_ie);
        if (wpa_sm_set_assoc_wpa_ie_default(peer->supp, peer->supp_ie,
index 36b4f87edb97e0b5d0d85d7dee7d690b8f568d24..9841c10ebe59f3b3b4fbfdf8ec6a3ed1038a665c 100644 (file)
@@ -199,6 +199,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
                        "0x%x", params.auth_alg);
        }
 #ifdef CONFIG_SAE
+       wpa_s->sme.sae_pmksa_caching = 0;
        if (wpa_key_mgmt_sae(ssid->key_mgmt)) {
                const u8 *rsn;
                struct wpa_ie_data ied;
@@ -391,6 +392,15 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
        }
 
 #ifdef CONFIG_SAE
+       if (params.auth_alg == WPA_AUTH_ALG_SAE &&
+           pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, ssid, 0) == 0)
+       {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "PMKSA cache entry found - try to use PMKSA caching instead of new SAE authentication");
+               params.auth_alg = WPA_AUTH_ALG_OPEN;
+               wpa_s->sme.sae_pmksa_caching = 1;
+       }
+
        if (params.auth_alg == WPA_AUTH_ALG_SAE) {
                if (start)
                        resp = sme_auth_build_sae_commit(wpa_s, ssid,
@@ -667,7 +677,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
 
                wpa_printf(MSG_DEBUG, "SME: SAE completed - setting PMK for "
                           "4-way handshake");
-               wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN);
+               wpa_sm_set_pmk(wpa_s->wpa, wpa_s->sme.sae.pmk, PMK_LEN,
+                              wpa_s->pending_bssid);
        }
 #endif /* CONFIG_SAE */
 
@@ -881,6 +892,27 @@ void sme_event_assoc_reject(struct wpa_supplicant *wpa_s,
 
        eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
 
+#ifdef CONFIG_SAE
+       if (wpa_s->sme.sae_pmksa_caching && wpa_s->current_ssid &&
+           wpa_key_mgmt_sae(wpa_s->current_ssid->key_mgmt)) {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "PMKSA caching attempt rejected - drop PMKSA cache entry and fall back to SAE authentication");
+               wpa_sm_aborted_cached(wpa_s->wpa);
+               wpa_sm_pmksa_cache_flush(wpa_s->wpa, wpa_s->current_ssid);
+               if (wpa_s->current_bss) {
+                       struct wpa_bss *bss = wpa_s->current_bss;
+                       struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+                       wpa_drv_deauthenticate(wpa_s, wpa_s->pending_bssid,
+                                              WLAN_REASON_DEAUTH_LEAVING);
+                       wpas_connect_work_done(wpa_s);
+                       wpa_supplicant_mark_disassoc(wpa_s);
+                       wpa_supplicant_connect(wpa_s, bss, ssid);
+                       return;
+               }
+       }
+#endif /* CONFIG_SAE */
+
        /*
         * For now, unconditionally terminate the previous authentication. In
         * theory, this should not be needed, but mac80211 gets quite confused
index e7aeeacfe5d77fb48e3b0e569106632c87c496cc..028e034bb4b562d2b55fb18356211e3cbe7f4f53 100644 (file)
@@ -1177,7 +1177,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
        }
 
        if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) {
-               wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN);
+               wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL);
 #ifndef CONFIG_NO_PBKDF2
                if (bss && ssid->bssid_set && ssid->ssid_len == 0 &&
                    ssid->passphrase) {
@@ -1186,7 +1186,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                                    4096, psk, PMK_LEN);
                        wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)",
                                        psk, PMK_LEN);
-                       wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
+                       wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
                }
 #endif /* CONFIG_NO_PBKDF2 */
 #ifdef CONFIG_EXT_PASSWORD
@@ -1222,7 +1222,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                                wpa_hexdump_key(MSG_MSGDUMP, "PSK (from "
                                                "external passphrase)",
                                                psk, PMK_LEN);
-                               wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
+                               wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
                        } else
 #endif /* CONFIG_NO_PBKDF2 */
                        if (wpabuf_len(pw) == 2 * PMK_LEN) {
@@ -1233,7 +1233,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                                        ext_password_free(pw);
                                        return -1;
                                }
-                               wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN);
+                               wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL);
                        } else {
                                wpa_msg(wpa_s, MSG_INFO, "EXT PW: No suitable "
                                        "PSK available");
index ba9df624f903840e2c16c5b081be43911272b16a..f968c96c5e4ae3c9d38b1cb26ef383c3a5d2266a 100644 (file)
@@ -651,6 +651,7 @@ struct wpa_supplicant {
                struct sae_data sae;
                struct wpabuf *sae_token;
                int sae_group_index;
+               unsigned int sae_pmksa_caching:1;
 #endif /* CONFIG_SAE */
        } sme;
 #endif /* CONFIG_SME */