]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - wpa_supplicant/wpa_supplicant.c
SAE: Support external authentication offload for driver-SME cases
[thirdparty/hostap.git] / wpa_supplicant / wpa_supplicant.c
index 1820a43f22b304c75c0e4aa8fd941efdcee61bf6..4209c41452a4f192080b7750f81c813a589c3ace 100644 (file)
@@ -120,6 +120,9 @@ const char *const wpa_supplicant_full_license5 =
 
 
 static void wpa_bss_tmp_disallow_timeout(void *eloop_ctx, void *timeout_ctx);
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
 
 
 /* Configure default/group WEP keys for static WEP */
@@ -888,6 +891,11 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
                wpas_p2p_completed(wpa_s);
 
                sme_sched_obss_scan(wpa_s, 1);
+
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+               if (!fils_hlp_sent && ssid && ssid->eap.erp)
+                       wpas_update_fils_connect_params(wpa_s);
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
        } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING ||
                   state == WPA_ASSOCIATED) {
                wpa_s->new_connection = 1;
@@ -1253,6 +1261,15 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                                                WPA_CIPHER_AES_128_CMAC;
                        }
 #endif /* CONFIG_IEEE80211W */
+#ifdef CONFIG_OWE
+                       if ((ssid->key_mgmt & WPA_KEY_MGMT_OWE) &&
+                           !ssid->owe_only &&
+                           !bss_wpa && !bss_rsn && !bss_osen) {
+                               wpa_supplicant_set_non_wpa_policy(wpa_s, ssid);
+                               wpa_s->wpa_proto = 0;
+                               return 0;
+                       }
+#endif /* CONFIG_OWE */
                        wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites "
                                "based on configuration");
                } else
@@ -1598,7 +1615,8 @@ static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx)
                break;
        case 9: /* Bits 72-79 */
 #ifdef CONFIG_FILS
-               *pos |= 0x01;
+               if (!wpa_s->disable_fils)
+                       *pos |= 0x01;
 #endif /* CONFIG_FILS */
                break;
        }
@@ -2325,7 +2343,8 @@ static size_t wpas_add_fils_hlp_req(struct wpa_supplicant *wpa_s, u8 *ie_buf,
 static u8 * wpas_populate_assoc_ies(
        struct wpa_supplicant *wpa_s,
        struct wpa_bss *bss, struct wpa_ssid *ssid,
-       struct wpa_driver_associate_params *params)
+       struct wpa_driver_associate_params *params,
+       enum wpa_drv_update_connect_params_mask *mask)
 {
        u8 *wpa_ie;
        size_t max_wpa_ie_len = 500;
@@ -2448,9 +2467,16 @@ static u8 * wpas_populate_assoc_ies(
                params->fils_erp_next_seq_num = next_seq_num;
                params->fils_erp_rrk = rrk;
                params->fils_erp_rrk_len = rrk_len;
+
+               if (mask)
+                       *mask |= WPA_DRV_UPDATE_FILS_ERP_INFO;
        }
 #endif /* CONFIG_FILS */
 #endif /* IEEE8021X_EAPOL */
+#ifdef CONFIG_SAE
+       if (wpa_s->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE))
+               algs = WPA_AUTH_ALG_SAE;
+#endif /* CONFIG_SAE */
 
        wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs);
        if (ssid->auth_alg) {
@@ -2596,13 +2622,28 @@ static u8 * wpas_populate_assoc_ies(
 #endif /* CONFIG_FILS */
 
 #ifdef CONFIG_OWE
+#ifdef CONFIG_TESTING_OPTIONS
+       if (get_ie_ext(wpa_ie, wpa_ie_len, WLAN_EID_EXT_OWE_DH_PARAM)) {
+               wpa_printf(MSG_INFO, "TESTING: Override OWE DH element");
+       } else
+#endif /* CONFIG_TESTING_OPTIONS */
        if (algs == WPA_AUTH_ALG_OPEN &&
            ssid->key_mgmt == WPA_KEY_MGMT_OWE) {
                struct wpabuf *owe_ie;
-               u16 group = OWE_DH_GROUP;
+               u16 group;
 
-               if (ssid->owe_group)
+               if (ssid->owe_group) {
                        group = ssid->owe_group;
+               } else {
+                       if (wpa_s->last_owe_group == 19)
+                               group = 20;
+                       else if (wpa_s->last_owe_group == 20)
+                               group = 21;
+                       else
+                               group = OWE_DH_GROUP;
+               }
+               wpa_s->last_owe_group = group;
+               wpa_printf(MSG_DEBUG, "OWE: Try to use group %u", group);
                owe_ie = owe_build_assoc_req(wpa_s->wpa, group);
                if (owe_ie &&
                    wpabuf_len(owe_ie) <= max_wpa_ie_len - wpa_ie_len) {
@@ -2617,11 +2658,41 @@ static u8 * wpas_populate_assoc_ies(
        params->wpa_ie = wpa_ie;
        params->wpa_ie_len = wpa_ie_len;
        params->auth_alg = algs;
+       if (mask)
+               *mask |= WPA_DRV_UPDATE_ASSOC_IES | WPA_DRV_UPDATE_AUTH_TYPE;
 
        return wpa_ie;
 }
 
 
+#if defined(CONFIG_FILS) && defined(IEEE8021X_EAPOL)
+static void wpas_update_fils_connect_params(struct wpa_supplicant *wpa_s)
+{
+       struct wpa_driver_associate_params params;
+       enum wpa_drv_update_connect_params_mask mask = 0;
+       u8 *wpa_ie;
+
+       if (wpa_s->auth_alg != WPA_AUTH_ALG_OPEN)
+               return; /* nothing to do */
+
+       os_memset(&params, 0, sizeof(params));
+       wpa_ie = wpas_populate_assoc_ies(wpa_s, wpa_s->current_bss,
+                                        wpa_s->current_ssid, &params, &mask);
+       if (!wpa_ie)
+               return;
+
+       if (params.auth_alg != WPA_AUTH_ALG_FILS) {
+               os_free(wpa_ie);
+               return;
+       }
+
+       wpa_s->auth_alg = params.auth_alg;
+       wpa_drv_update_connect_params(wpa_s, &params, mask);
+       os_free(wpa_ie);
+}
+#endif /* CONFIG_FILS && IEEE8021X_EAPOL */
+
+
 static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
 {
        struct wpa_connect_work *cwork = work->ctx;
@@ -2722,7 +2793,7 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit)
         * previous association. */
        wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0);
 
-       wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params);
+       wpa_ie = wpas_populate_assoc_ies(wpa_s, bss, ssid, &params, NULL);
        if (!wpa_ie) {
                wpas_connect_work_done(wpa_s);
                return;
@@ -3357,6 +3428,7 @@ void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s,
 
        wpa_s->disconnected = 0;
        wpa_s->reassociate = 1;
+       wpa_s->last_owe_group = 0;
 
        if (wpa_s->connect_without_scan ||
            wpa_supplicant_fast_associate(wpa_s) != 1) {
@@ -4669,7 +4741,7 @@ static void radio_work_free(struct wpa_radio_work *work)
        if (work->started) {
                work->wpa_s->radio->num_active_works--;
                wpa_dbg(work->wpa_s, MSG_DEBUG,
-                       "radio_work_free('%s'@%p: num_active_works --> %u",
+                       "radio_work_free('%s'@%p): num_active_works --> %u",
                        work->type, work,
                        work->wpa_s->radio->num_active_works);
        }
@@ -6611,6 +6683,7 @@ void wpas_request_connection(struct wpa_supplicant *wpa_s)
        wpa_s->extra_blacklist_count = 0;
        wpa_s->disconnected = 0;
        wpa_s->reassociate = 1;
+       wpa_s->last_owe_group = 0;
 
        if (wpa_supplicant_fast_associate(wpa_s) != 1)
                wpa_supplicant_req_scan(wpa_s, 0, 0);