]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/sme.c
SAE: Collect list of rejected groups for H2E in STA
[thirdparty/hostap.git] / wpa_supplicant / sme.c
index 17a984d1a17d0d18d40d8e341c1d5e1904f014ba..51d7fed24ed44bba7061e1d6a1dec43759efcd55 100644 (file)
@@ -37,9 +37,7 @@
 static void sme_auth_timer(void *eloop_ctx, void *timeout_ctx);
 static void sme_assoc_timer(void *eloop_ctx, void *timeout_ctx);
 static void sme_obss_scan_timeout(void *eloop_ctx, void *timeout_ctx);
-#ifdef CONFIG_IEEE80211W
 static void sme_stop_sa_query(struct wpa_supplicant *wpa_s);
-#endif /* CONFIG_IEEE80211W */
 
 
 #ifdef CONFIG_SAE
@@ -492,7 +490,6 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
        }
 #endif /* CONFIG_IEEE80211R */
 
-#ifdef CONFIG_IEEE80211W
        wpa_s->sme.mfp = wpas_get_ssid_pmf(wpa_s, ssid);
        if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) {
                const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
@@ -505,7 +502,6 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
                        wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED;
                }
        }
-#endif /* CONFIG_IEEE80211W */
 
 #ifdef CONFIG_P2P
        if (wpa_s->global->p2p) {
@@ -623,7 +619,7 @@ static void sme_send_authentication(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_MBO
        mbo_ie = wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE);
-       if (mbo_ie) {
+       if (!wpa_s->disable_mbo_oce && mbo_ie) {
                int len;
 
                len = wpas_mbo_ie(wpa_s, wpa_s->sme.assoc_req_ie +
@@ -932,21 +928,23 @@ static int sme_external_auth_build_buf(struct wpabuf *buf,
 }
 
 
-static void sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
-                                             const u8 *bssid,
-                                             struct wpa_ssid *ssid)
+static int sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
+                                            const u8 *bssid,
+                                            struct wpa_ssid *ssid)
 {
        struct wpabuf *resp, *buf;
 
        resp = sme_auth_build_sae_commit(wpa_s, ssid, bssid, 1, 0);
-       if (!resp)
-               return;
+       if (!resp) {
+               wpa_printf(MSG_DEBUG, "SAE: Failed to build SAE commit");
+               return -1;
+       }
 
        wpa_s->sme.sae.state = SAE_COMMITTED;
        buf = wpabuf_alloc(4 + SAE_COMMIT_MAX_LEN + wpabuf_len(resp));
        if (!buf) {
                wpabuf_free(resp);
-               return;
+               return -1;
        }
 
        wpa_s->sme.seq_num++;
@@ -955,6 +953,8 @@ static void sme_external_auth_send_sae_commit(struct wpa_supplicant *wpa_s,
        wpa_drv_send_mlme(wpa_s, wpabuf_head(buf), wpabuf_len(buf), 1, 0);
        wpabuf_free(resp);
        wpabuf_free(buf);
+
+       return 0;
 }
 
 
@@ -965,15 +965,17 @@ static void sme_send_external_auth_status(struct wpa_supplicant *wpa_s,
 
        os_memset(&params, 0, sizeof(params));
        params.status = status;
-       params.ssid = wpa_s->sme.ext_auth.ssid;
-       params.ssid_len = wpa_s->sme.ext_auth.ssid_len;
-       params.bssid = wpa_s->sme.ext_auth.bssid;
+       params.ssid = wpa_s->sme.ext_auth_ssid;
+       params.ssid_len = wpa_s->sme.ext_auth_ssid_len;
+       params.bssid = wpa_s->sme.ext_auth_bssid;
+       if (wpa_s->conf->sae_pmkid_in_assoc && status == WLAN_STATUS_SUCCESS)
+               params.pmkid = wpa_s->sme.sae.pmkid;
        wpa_drv_send_external_auth_status(wpa_s, &params);
 }
 
 
-static void sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
-                                          union wpa_event_data *data)
+static int sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
+                                         union wpa_event_data *data)
 {
        struct wpa_ssid *ssid;
        size_t ssid_str_len = data->external_auth.ssid_len;
@@ -987,13 +989,12 @@ static void sme_handle_external_auth_start(struct wpa_supplicant *wpa_s,
                    (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)))
                        break;
        }
-       if (ssid)
-               sme_external_auth_send_sae_commit(wpa_s,
-                                                 data->external_auth.bssid,
-                                                 ssid);
-       else
-               sme_send_external_auth_status(wpa_s,
-                                             WLAN_STATUS_UNSPECIFIED_FAILURE);
+       if (!ssid ||
+           sme_external_auth_send_sae_commit(wpa_s, data->external_auth.bssid,
+                                             ssid) < 0)
+               return -1;
+
+       return 0;
 }
 
 
@@ -1032,13 +1033,20 @@ void sme_external_auth_trigger(struct wpa_supplicant *wpa_s,
                return;
 
        if (data->external_auth.action == EXT_AUTH_START) {
-               os_memcpy(&wpa_s->sme.ext_auth, data,
-                         sizeof(struct external_auth));
+               if (!data->external_auth.bssid || !data->external_auth.ssid)
+                       return;
+               os_memcpy(wpa_s->sme.ext_auth_bssid, data->external_auth.bssid,
+                         ETH_ALEN);
+               os_memcpy(wpa_s->sme.ext_auth_ssid, data->external_auth.ssid,
+                         data->external_auth.ssid_len);
+               wpa_s->sme.ext_auth_ssid_len = data->external_auth.ssid_len;
                wpa_s->sme.seq_num = 0;
                wpa_s->sme.sae.state = SAE_NOTHING;
                wpa_s->sme.sae.send_confirm = 0;
                wpa_s->sme.sae_group_index = 0;
-               sme_handle_external_auth_start(wpa_s, data);
+               if (sme_handle_external_auth_start(wpa_s, data) < 0)
+                       sme_send_external_auth_status(wpa_s,
+                                             WLAN_STATUS_UNSPECIFIED_FAILURE);
        } else if (data->external_auth.action == EXT_AUTH_ABORT) {
                /* Report failure to driver for the wrong trigger */
                sme_send_external_auth_status(wpa_s,
@@ -1091,7 +1099,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                                                wpa_s->current_ssid, 2);
                else
                        sme_external_auth_send_sae_commit(
-                               wpa_s, wpa_s->sme.ext_auth.bssid,
+                               wpa_s, wpa_s->sme.ext_auth_bssid,
                                wpa_s->current_ssid);
                return 0;
        }
@@ -1101,6 +1109,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
            wpa_s->sme.sae.state == SAE_COMMITTED &&
            (external || wpa_s->current_bss) && wpa_s->current_ssid) {
                wpa_dbg(wpa_s, MSG_DEBUG, "SME: SAE group not supported");
+               int_array_add_unique(&wpa_s->sme.sae_rejected_groups,
+                                    wpa_s->sme.sae.group);
                wpa_s->sme.sae_group_index++;
                if (sme_set_sae_group(wpa_s) < 0)
                        return -1; /* no other groups enabled */
@@ -1110,7 +1120,7 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                                                wpa_s->current_ssid, 1);
                else
                        sme_external_auth_send_sae_commit(
-                               wpa_s, wpa_s->sme.ext_auth.bssid,
+                               wpa_s, wpa_s->sme.ext_auth_bssid,
                                wpa_s->current_ssid);
                return 0;
        }
@@ -1142,7 +1152,8 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
                if (groups && groups[0] <= 0)
                        groups = NULL;
                res = sae_parse_commit(&wpa_s->sme.sae, data, len, NULL, NULL,
-                                      groups);
+                                      groups, status_code ==
+                                      WLAN_STATUS_SAE_HASH_TO_ELEMENT);
                if (res == SAE_SILENTLY_DISCARD) {
                        wpa_printf(MSG_DEBUG,
                                   "SAE: Drop commit message due to reflection attack");
@@ -1187,6 +1198,37 @@ static int sme_sae_auth(struct wpa_supplicant *wpa_s, u16 auth_transaction,
 }
 
 
+static int sme_sae_set_pmk(struct wpa_supplicant *wpa_s, const u8 *bssid)
+{
+       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_s->sme.sae.pmkid, bssid);
+       if (wpa_s->conf->sae_pmkid_in_assoc) {
+               /* Update the own RSNE contents now that we have set the PMK
+                * and added a PMKSA cache entry based on the successfully
+                * completed SAE exchange. In practice, this will add the PMKID
+                * into RSNE. */
+               if (wpa_s->sme.assoc_req_ie_len + 2 + PMKID_LEN >
+                   sizeof(wpa_s->sme.assoc_req_ie)) {
+                       wpa_msg(wpa_s, MSG_WARNING,
+                               "RSN: Not enough room for inserting own PMKID into RSNE");
+                       return -1;
+               }
+               if (wpa_insert_pmkid(wpa_s->sme.assoc_req_ie,
+                                    &wpa_s->sme.assoc_req_ie_len,
+                                    wpa_s->sme.sae.pmkid) < 0)
+                       return -1;
+               wpa_hexdump(MSG_DEBUG,
+                           "SME: Updated Association Request IEs",
+                           wpa_s->sme.assoc_req_ie,
+                           wpa_s->sme.assoc_req_ie_len);
+       }
+
+       return 0;
+}
+
+
 void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
                               const u8 *auth_frame, size_t len)
 {
@@ -1220,10 +1262,8 @@ void sme_external_auth_mgmt_rx(struct wpa_supplicant *wpa_s,
                if (res != 1)
                        return;
 
-               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_s->sme.sae.pmkid, wpa_s->pending_bssid);
+               if (sme_sae_set_pmk(wpa_s, wpa_s->sme.ext_auth_bssid) < 0)
+                       return;
        }
 }
 
@@ -1276,10 +1316,8 @@ void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data)
                if (res != 1)
                        return;
 
-               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_s->sme.sae.pmkid, wpa_s->pending_bssid);
+               if (sme_sae_set_pmk(wpa_s, wpa_s->pending_bssid) < 0)
+                       return;
        }
 #endif /* CONFIG_SAE */
 
@@ -1985,15 +2023,17 @@ void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s)
        if (wpa_s->sme.ft_ies || wpa_s->sme.ft_used)
                sme_update_ft_ies(wpa_s, NULL, NULL, 0);
 #endif /* CONFIG_IEEE80211R */
-#ifdef CONFIG_IEEE80211W
        sme_stop_sa_query(wpa_s);
-#endif /* CONFIG_IEEE80211W */
 }
 
 
 void sme_deinit(struct wpa_supplicant *wpa_s)
 {
        sme_clear_on_disassoc(wpa_s);
+#ifdef CONFIG_SAE
+       os_free(wpa_s->sme.sae_rejected_groups);
+       wpa_s->sme.sae_rejected_groups = NULL;
+#endif /* CONFIG_SAE */
 
        eloop_cancel_timeout(sme_assoc_timer, wpa_s, NULL);
        eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL);
@@ -2236,7 +2276,7 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
         */
        if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
              (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) ||
-           ssid == NULL || ssid->mode != IEEE80211_MODE_INFRA)
+           ssid == NULL || ssid->mode != WPAS_MODE_INFRA)
                return;
 
        if (!wpa_s->hw.modes)
@@ -2282,8 +2322,6 @@ void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable)
 }
 
 
-#ifdef CONFIG_IEEE80211W
-
 static const unsigned int sa_query_max_timeout = 1000;
 static const unsigned int sa_query_retry_timeout = 201;
 static const unsigned int sa_query_ch_switch_max_delay = 5000; /* in usec */
@@ -2572,5 +2610,3 @@ void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa,
        else if (data[0] == WLAN_SA_QUERY_RESPONSE)
                sme_process_sa_query_response(wpa_s, sa, data, len);
 }
-
-#endif /* CONFIG_IEEE80211W */