]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Update AKMP, cipher, PMF for driver-based SME while roaming
authorVinay Gannevaram <vganneva@codeaurora.org>
Thu, 11 Nov 2021 07:09:28 +0000 (12:39 +0530)
committerJouni Malinen <j@w1.fi>
Tue, 16 Nov 2021 21:50:35 +0000 (23:50 +0200)
After roaming to a new AP using driver-based SME and roaming trigger,
update proto type, AKMP suite, and pairwise cipher suite based on the
(Re)Association Request frame. Update PMF, group cipher, and group mgmt
cipher based on the AP's RSNE into wpa_sm. group_mgmt_cipher needs to be
updated based on PMF capabilities of STA and roamed AP.

Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
wpa_supplicant/events.c

index ca366e5904aefb7debe9f9dc80c5737b9f74eb23..5f5c50ba975453e0a42a8b5ae21af62426c4e75f 100644 (file)
@@ -2694,6 +2694,8 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
        bool found = false;
        struct wpa_ie_data ie;
        struct wpa_ssid *ssid = wpa_s->current_ssid;
+       struct wpa_bss *bss = wpa_s->current_bss;
+       int pmf;
 
        if (!ssid)
                return 0;
@@ -2727,6 +2729,14 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
                    "WPA: Update cipher suite selection based on IEs in driver-generated WPA/RSNE in AssocReq",
                    p, l);
 
+       /* Update proto from (Re)Association Request frame info */
+       wpa_s->wpa_proto = ie.proto;
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, wpa_s->wpa_proto);
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
+                        !!(wpa_s->wpa_proto &
+                           (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
+
+       /* Update AKMP suite from (Re)Association Request frame info */
        sel = ie.key_mgmt;
        if (ssid->key_mgmt)
                sel &= ssid->key_mgmt;
@@ -2740,18 +2750,86 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       wpa_s->wpa_proto = ie.proto;
-       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, wpa_s->wpa_proto);
-       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED,
-                        !!(wpa_s->wpa_proto &
-                           (WPA_PROTO_RSN | WPA_PROTO_OSEN)));
-
        wpa_s->key_mgmt = ie.key_mgmt;
        wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt);
        wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT %s and proto %d",
                wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->wpa_proto),
                wpa_s->wpa_proto);
 
+       /* Update pairwise cipher from (Re)Association Request frame info */
+       sel = ie.pairwise_cipher;
+       if (ssid->pairwise_cipher)
+               sel &= ssid->pairwise_cipher;
+
+       wpa_dbg(wpa_s, MSG_DEBUG,
+               "WPA: AP pairwise cipher 0x%x network pairwise cipher 0x%x; available pairwise cipher 0x%x",
+               ie.pairwise_cipher, ssid->pairwise_cipher, sel);
+       if (ie.pairwise_cipher && !sel) {
+               wpa_supplicant_deauthenticate(
+                       wpa_s, WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID);
+               return -1;
+       }
+
+       wpa_s->pairwise_cipher = ie.pairwise_cipher;
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
+                        wpa_s->pairwise_cipher);
+       wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
+               wpa_cipher_txt(wpa_s->pairwise_cipher));
+
+       /* Update other parameters based on AP's WPA IE/RSNE, if available */
+       if (!bss) {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: current_bss == NULL - skip AP IE check");
+               return 0;
+       }
+
+       /* Update GTK and IGTK from AP's RSNE */
+       found = false;
+
+       if (wpa_s->wpa_proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN)) {
+               const u8 *bss_rsn;
+
+               bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN);
+               if (bss_rsn) {
+                       p = bss_rsn;
+                       len = 2 + bss_rsn[1];
+                       found = true;
+               }
+       } else if (wpa_s->wpa_proto & WPA_PROTO_WPA) {
+               const u8 *bss_wpa;
+
+               bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE);
+               if (bss_wpa) {
+                       p = bss_wpa;
+                       len = 2 + bss_wpa[1];
+                       found = true;
+               }
+       }
+
+       if (!found || wpa_parse_wpa_ie(p, len, &ie) < 0)
+               return 0;
+
+       pmf = wpas_get_ssid_pmf(wpa_s, ssid);
+       if (!(ie.capabilities & WPA_CAPABILITY_MFPC) &&
+           pmf == MGMT_FRAME_PROTECTION_REQUIRED) {
+               /* AP does not support MFP, local configuration requires it */
+               wpa_supplicant_deauthenticate(
+                       wpa_s, WLAN_REASON_INVALID_RSN_IE_CAPAB);
+               return -1;
+       }
+       if ((ie.capabilities & WPA_CAPABILITY_MFPR) &&
+           pmf == NO_MGMT_FRAME_PROTECTION) {
+               /* AP requires MFP, local configuration disables it */
+               wpa_supplicant_deauthenticate(
+                       wpa_s, WLAN_REASON_INVALID_RSN_IE_CAPAB);
+               return -1;
+       }
+
+       /* Update PMF from local configuration now that MFP validation was done
+        * above */
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, pmf);
+
+       /* Update GTK from AP's RSNE */
        sel = ie.group_cipher;
        if (ssid->group_cipher)
                sel &= ssid->group_cipher;
@@ -2770,26 +2848,37 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
        wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s",
                wpa_cipher_txt(wpa_s->group_cipher));
 
-       sel = ie.pairwise_cipher;
-       if (ssid->pairwise_cipher)
-               sel &= ssid->pairwise_cipher;
+       /* Update IGTK from AP RSN IE */
+       sel = ie.mgmt_group_cipher;
+       if (ssid->group_mgmt_cipher)
+               sel &= ssid->group_mgmt_cipher;
 
        wpa_dbg(wpa_s, MSG_DEBUG,
-               "WPA: AP pairwise cipher 0x%x network pairwise cipher 0x%x; available pairwise cipher 0x%x",
-               ie.pairwise_cipher, ssid->pairwise_cipher, sel);
-       if (ie.pairwise_cipher && !sel) {
+               "WPA: AP mgmt_group_cipher 0x%x network mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+               ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
+
+       if (pmf == NO_MGMT_FRAME_PROTECTION ||
+           !(ie.capabilities & WPA_CAPABILITY_MFPC)) {
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: STA/AP is not MFP capable; AP RSNE caps 0x%x",
+                       ie.capabilities);
+               ie.mgmt_group_cipher = 0;
+       }
+
+       if (ie.mgmt_group_cipher && !sel) {
                wpa_supplicant_deauthenticate(
-                       wpa_s, WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID);
+                       wpa_s, WLAN_REASON_CIPHER_SUITE_REJECTED);
                return -1;
        }
 
-       wpa_s->pairwise_cipher = ie.pairwise_cipher;
-       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE,
-                        wpa_s->pairwise_cipher);
-       wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
-               wpa_cipher_txt(wpa_s->pairwise_cipher));
-
-       wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
+       wpa_s->mgmt_group_cipher = ie.mgmt_group_cipher;
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+                        wpa_s->mgmt_group_cipher);
+       if (wpa_s->mgmt_group_cipher)
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher %s",
+                       wpa_cipher_txt(wpa_s->mgmt_group_cipher));
+       else
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
 
        return 0;
 }