From 0b853303ae3196e8b23ed79021ad98c1755a86aa Mon Sep 17 00:00:00 2001 From: Vinay Gannevaram Date: Thu, 11 Nov 2021 12:39:28 +0530 Subject: [PATCH] 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 --- wpa_supplicant/events.c | 139 ++++++++++++++++++++++++++++++++-------- 1 file changed, 114 insertions(+), 25 deletions(-) diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index ca366e590..5f5c50ba9 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -2694,6 +2694,8 @@ static int wpa_supplicant_use_own_rsne_params(struct wpa_supplicant *wpa_s, bool found = false; struct wpa_ie_data ie; struct wpa_ssid *ssid = wpa_s->current_ssid; + struct wpa_bss *bss = wpa_s->current_bss; + int pmf; if (!ssid) 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", 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; if (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; } - 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_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_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->wpa_proto), wpa_s->wpa_proto); - 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 pairwise cipher from (Re)Association Request frame info */ sel = ie.pairwise_cipher; if (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_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; }