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 */
|
#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 &&
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue