]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
SAE: Reuse previously generated PWE on a retry with the same STA
authorJouni Malinen <jouni@codeaurora.org>
Sun, 3 Mar 2019 14:56:14 +0000 (16:56 +0200)
committerJouni Malinen <j@w1.fi>
Wed, 6 Mar 2019 11:07:20 +0000 (13:07 +0200)
Do not start SAE authentication from scratch if a STA starts a new
attempt for the same group while we still have previously generated PWE
available. Instead, use the previously generated PWE as-is and skip
anti-clogging token exchange since the heavy processing is already
completed. This saves unnecessary processing on the AP side in case the
STA failed to complete authentication on the first attempt (e.g., due to
heavy SAE load on the AP causing a timeout) and makes it more likely for
a valid STA to be able to complete SAE authentication during a DoS
attack.

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

index afa17db249ecadaff961bf3012816566888d0e63..2ea3eabc3bff381d7a3012712617d748c95252b3 100644 (file)
@@ -742,7 +742,7 @@ void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta)
 
 
 static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
-                      const u8 *bssid, u8 auth_transaction)
+                      const u8 *bssid, u8 auth_transaction, int allow_reuse)
 {
        int ret;
 
@@ -755,7 +755,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
        switch (sta->sae->state) {
        case SAE_NOTHING:
                if (auth_transaction == 1) {
-                       ret = auth_sae_send_commit(hapd, sta, bssid, 1);
+                       ret = auth_sae_send_commit(hapd, sta, bssid,
+                                                  !allow_reuse);
                        if (ret)
                                return ret;
                        sae_set_state(sta, SAE_COMMITTED, "Sent Commit");
@@ -844,7 +845,8 @@ static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta,
                         * step to get to Accepted without waiting for
                         * additional events.
                         */
-                       return sae_sm_step(hapd, sta, bssid, auth_transaction);
+                       return sae_sm_step(hapd, sta, bssid, auth_transaction,
+                                          0);
                }
                break;
        case SAE_CONFIRMED:
@@ -1011,6 +1013,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
        if (auth_transaction == 1) {
                const u8 *token = NULL, *pos, *end;
                size_t token_len = 0;
+               int allow_reuse = 0;
+
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                               HOSTAPD_LEVEL_DEBUG,
                               "start SAE authentication (RX commit, status=%u)",
@@ -1088,9 +1092,22 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                         * to use a different group and that would not be
                         * allowed if we remain in Committed state with the
                         * previously set parameters. */
-                       sae_set_state(sta, SAE_NOTHING,
-                                     "Clear existing state to allow restart");
-                       sae_clear_data(sta->sae);
+                       pos = mgmt->u.auth.variable;
+                       end = ((const u8 *) mgmt) + len;
+                       if (end - pos >= (int) sizeof(le16) &&
+                           sae_group_allowed(sta->sae, groups,
+                                             WPA_GET_LE16(pos)) ==
+                           WLAN_STATUS_SUCCESS) {
+                               /* Do not waste resources deriving the same PWE
+                                * again since the same group is reused. */
+                               sae_set_state(sta, SAE_NOTHING,
+                                             "Allow previous PWE to be reused");
+                               allow_reuse = 1;
+                       } else {
+                               sae_set_state(sta, SAE_NOTHING,
+                                             "Clear existing state to allow restart");
+                               sae_clear_data(sta->sae);
+                       }
                }
 
                resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable,
@@ -1126,7 +1143,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                if (resp != WLAN_STATUS_SUCCESS)
                        goto reply;
 
-               if (!token && use_sae_anti_clogging(hapd)) {
+               if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Request anti-clogging token from "
                                   MACSTR, MAC2STR(sta->addr));
@@ -1139,7 +1156,8 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                        goto reply;
                }
 
-               resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
+               resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction,
+                                  allow_reuse);
        } else if (auth_transaction == 2) {
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                               HOSTAPD_LEVEL_DEBUG,
@@ -1180,7 +1198,7 @@ static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta,
                        }
                        sta->sae->rc = peer_send_confirm;
                }
-               resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction);
+               resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0);
        } else {
                hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                               HOSTAPD_LEVEL_DEBUG,