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:
parent
19307ef69a
commit
2b3e64a0fb
3 changed files with 133 additions and 33 deletions
|
@ -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 &&
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue