Update ciphers to address GTK renewal failures while roaming

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>
This commit is contained in:
Vinay Gannevaram 2021-09-30 12:48:26 +05:30 committed by Jouni Malinen
parent 19307ef69a
commit 2b3e64a0fb
3 changed files with 133 additions and 33 deletions

View file

@ -2680,6 +2680,91 @@ static int wpas_fst_update_mbie(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_FST */ #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, static int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s,
union wpa_event_data *data) 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); multi_ap_set_4addr_mode(wpa_s);
if (wpa_s->conf->ap_scan == 1 && if (wpa_s->conf->ap_scan == 1 &&

View 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_supplicant_set_suites - Set authentication and encryption parameters
* @wpa_s: Pointer to wpa_supplicant data * @wpa_s: Pointer to wpa_supplicant data
@ -1630,39 +1671,7 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
return -1; return -1;
} }
sel = ie.mgmt_group_cipher; wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie);
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));
#ifdef CONFIG_OCV #ifdef CONFIG_OCV
if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) || if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) ||
(wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV)) (wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_OCV))

View 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_driver_init(struct wpa_supplicant *wpa_s);
int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s, int wpa_supplicant_update_bridge_ifname(struct wpa_supplicant *wpa_s,
const char *bridge_ifname); 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, int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s,
struct wpa_bss *bss, struct wpa_ssid *ssid, struct wpa_bss *bss, struct wpa_ssid *ssid,
u8 *wpa_ie, size_t *wpa_ie_len); u8 *wpa_ie, size_t *wpa_ie_len);