Update AKMP, cipher, PMF for driver-based SME while roaming

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>
This commit is contained in:
Vinay Gannevaram 2021-11-11 12:39:28 +05:30 committed by Jouni Malinen
parent c8b94bc7b3
commit 0b853303ae

View file

@ -2694,6 +2694,8 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
bool found = false; bool found = false;
struct wpa_ie_data ie; struct wpa_ie_data ie;
struct wpa_ssid *ssid = wpa_s->current_ssid; struct wpa_ssid *ssid = wpa_s->current_ssid;
struct wpa_bss *bss = wpa_s->current_bss;
int pmf;
if (!ssid) if (!ssid)
return 0; 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", "WPA: Update cipher suite selection based on IEs in driver-generated WPA/RSNE in AssocReq",
p, l); 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; sel = ie.key_mgmt;
if (ssid->key_mgmt) if (ssid->key_mgmt)
sel &= ssid->key_mgmt; sel &= ssid->key_mgmt;
@ -2740,36 +2750,13 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
return -1; 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_s->key_mgmt = ie.key_mgmt;
wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->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_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_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->wpa_proto),
wpa_s->wpa_proto); wpa_s->wpa_proto);
sel = ie.group_cipher; /* Update pairwise cipher from (Re)Association Request frame info */
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; sel = ie.pairwise_cipher;
if (ssid->pairwise_cipher) if (ssid->pairwise_cipher)
sel &= ssid->pairwise_cipher; sel &= ssid->pairwise_cipher;
@ -2789,7 +2776,109 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s,
wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s", wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s",
wpa_cipher_txt(wpa_s->pairwise_cipher)); wpa_cipher_txt(wpa_s->pairwise_cipher));
wpas_set_mgmt_group_cipher(wpa_s, ssid, &ie); /* 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;
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));
/* 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 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_CIPHER_SUITE_REJECTED);
return -1;
}
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; return 0;
} }