]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Update ciphers to address GTK renewal failures while roaming
authorVinay Gannevaram <vganneva@codeaurora.org>
Thu, 30 Sep 2021 07:18:26 +0000 (12:48 +0530)
committerJouni Malinen <j@w1.fi>
Wed, 6 Oct 2021 18:13:19 +0000 (21:13 +0300)
After roaming from WPA2-AP (group=CCMP) to WPA-AP (group=TKIP) using
driver-based SME and roaming trigger, GTK renewal failures are observed
for the currently associated WPA-AP because of group cipher mismatch,
resulting in deauthentication with the AP.

Update the group cipher and pairwise cipher values in wpa_sm from
association event received from the driver in case of SME offload to the
driver to address GTK renewal failures (and similar issues) that could
happen when the driver/firmware roams between APs with different
security profiles.

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

index 72a2a9c156c53d7e93c620d868a6902c88640d6d..878d9bc741351647846b31fa8f783873ed5b324d 100644 (file)
@@ -2680,6 +2680,91 @@ static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
 #endif /* CONFIG_FST */
 
 
+static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
+                                             union wpa_event_data *data)
+{
+       int sel;
+       const u8 *p;
+       int l, len;
+       bool found = false;
+       struct wpa_ie_data ie;
+       struct wpa_ssid *ssid = wpa_s->current_ssid;
+
+       if (!ssid)
+               return 0;
+
+       p = data->assoc_info.req_ies;
+       l = data->assoc_info.req_ies_len;
+
+       while (p && l >= 2) {
+               len = p[1] + 2;
+               if (len > l) {
+                       wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info",
+                                   p, l);
+                       break;
+               }
+               if (((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 &&
+                     (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) ||
+                    (p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 4 &&
+                     (os_memcmp(&p[2], "\x50\x6F\x9A\x12", 4) == 0)) ||
+                    (p[0] == WLAN_EID_RSN && p[1] >= 2))) {
+                       found = true;
+                       break;
+               }
+               l -= len;
+               p += len;
+       }
+
+       if (!found || wpa_parse_wpa_ie(p, len, &ie) < 0)
+               return 0;
+
+       wpa_hexdump(MSG_DEBUG,
+                   "WPA: Update cipher suite selection based on IEs in driver-generated WPA/RSNE in AssocReq",
+                   p, l);
+
+       sel = ie.group_cipher;
+       if (ssid->group_cipher)
+               sel &= ssid->group_cipher;
+
+       wpa_dbg(wpa_s, MSG_DEBUG,
+               "WPA: AP group cipher 0x%x network group cipher 0x%x; available group cipher 0x%x",
+               ie.group_cipher, ssid->group_cipher, sel);
+       if (ie.group_cipher && !sel) {
+               wpa_supplicant_deauthenticate(
+                       wpa_s, WLAN_REASON_GROUP_CIPHER_NOT_VALID);
+               return -1;
+       }
+
+       wpa_s->group_cipher = ie.group_cipher;
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher);
+       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;
+
+       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));
+
+       wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
+
+       return 0;
+}
+
+
 static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
                                          union wpa_event_data *data)
 {
@@ -3124,6 +3209,10 @@ static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s,
                }
        }
 
+       if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) &&
+           data && wpa_supplicant_use_own_rsne_params(wpa_s, data) < 0)
+               return;
+
        multi_ap_set_4addr_mode(wpa_s);
 
        if (wpa_s->conf->ap_scan == 1 &&
index c9d53a3d749bb1aa7160bb314ecaca8c1bd0aed3..0f9db267fe9d87cbe153abe3f3c08b4f6608cac3 100644 (file)
@@ -1297,6 +1297,47 @@ static int matching_ciphers(struct wpa_ssid *ssid, struct wpa_ie_data *ie,
 }
 
 
+void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
+                               struct wpa_ssid *ssid, struct wpa_ie_data *ie)
+{
+       int sel;
+
+       sel = ie->mgmt_group_cipher;
+       if (ssid->group_mgmt_cipher)
+               sel &= ssid->group_mgmt_cipher;
+       if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
+           !(ie->capabilities & WPA_CAPABILITY_MFPC))
+               sel = 0;
+       wpa_dbg(wpa_s, MSG_DEBUG,
+               "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
+               ie->mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
+       if (sel & WPA_CIPHER_AES_128_CMAC) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: using MGMT group cipher AES-128-CMAC");
+       } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: using MGMT group cipher BIP-GMAC-128");
+       } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: using MGMT group cipher BIP-GMAC-256");
+       } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
+               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
+               wpa_dbg(wpa_s, MSG_DEBUG,
+                       "WPA: using MGMT group cipher BIP-CMAC-256");
+       } else {
+               wpa_s->mgmt_group_cipher = 0;
+               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
+       }
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
+                        wpa_s->mgmt_group_cipher);
+       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
+                        wpas_get_ssid_pmf(wpa_s, ssid));
+}
+
+
 /**
  * wpa_supplicant_set_suites - Set authentication and encryption parameters
  * @wpa_s: Pointer to wpa_supplicant data
@@ -1630,39 +1671,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                return -1;
        }
 
-       sel = ie.mgmt_group_cipher;
-       if (ssid->group_mgmt_cipher)
-               sel &= ssid->group_mgmt_cipher;
-       if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION ||
-           !(ie.capabilities & WPA_CAPABILITY_MFPC))
-               sel = 0;
-       wpa_dbg(wpa_s, MSG_DEBUG,
-               "WPA: AP mgmt_group_cipher 0x%x network profile mgmt_group_cipher 0x%x; available mgmt_group_cipher 0x%x",
-               ie.mgmt_group_cipher, ssid->group_mgmt_cipher, sel);
-       if (sel & WPA_CIPHER_AES_128_CMAC) {
-               wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC;
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-                       "AES-128-CMAC");
-       } else if (sel & WPA_CIPHER_BIP_GMAC_128) {
-               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128;
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-                       "BIP-GMAC-128");
-       } else if (sel & WPA_CIPHER_BIP_GMAC_256) {
-               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256;
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-                       "BIP-GMAC-256");
-       } else if (sel & WPA_CIPHER_BIP_CMAC_256) {
-               wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256;
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher "
-                       "BIP-CMAC-256");
-       } else {
-               wpa_s->mgmt_group_cipher = 0;
-               wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher");
-       }
-       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP,
-                        wpa_s->mgmt_group_cipher);
-       wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP,
-                        wpas_get_ssid_pmf(wpa_s, ssid));
+       wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
 #ifdef CONFIG_OCV
        if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
            (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))
index 47d0cabbef3c3b40521386c6919af013f5ddfe51..cbc955159bbe2ff8008648ad6580fe0aba2b525e 100644 (file)
@@ -1543,6 +1543,8 @@ int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s);
 int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
                                        const char *bridge_ifname);
+void wpas_set_mgmt_group_cipher(struct wpa_supplicant *wpa_s,
+                               struct wpa_ssid *ssid, struct wpa_ie_data *ie);
 int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
                              struct wpa_bss *bss, struct wpa_ssid *ssid,
                              u8 *wpa_ie, size_t *wpa_ie_len);