diff options
Diffstat (limited to 'contrib/wpa/wpa_supplicant/wpas_glue.c')
-rw-r--r-- | contrib/wpa/wpa_supplicant/wpas_glue.c | 224 |
1 files changed, 210 insertions, 14 deletions
diff --git a/contrib/wpa/wpa_supplicant/wpas_glue.c b/contrib/wpa/wpa_supplicant/wpas_glue.c index 62af7f6b1013..17fc05bcbdab 100644 --- a/contrib/wpa/wpa_supplicant/wpas_glue.c +++ b/contrib/wpa/wpa_supplicant/wpas_glue.c @@ -16,6 +16,7 @@ #include "config.h" #include "l2_packet/l2_packet.h" #include "common/wpa_common.h" +#include "common/ptksa_cache.h" #include "wpa_supplicant_i.h" #include "driver_i.h" #include "rsn_supp/pmksa_cache.h" @@ -94,8 +95,8 @@ static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, * @len: Frame payload length * Returns: >=0 on success, <0 on failure */ -static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, - u16 proto, const u8 *buf, size_t len) +int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, + u16 proto, const u8 *buf, size_t len) { #ifdef CONFIG_TESTING_OPTIONS if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) { @@ -112,6 +113,14 @@ static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, } #endif /* CONFIG_TESTING_OPTIONS */ + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_CONTROL_PORT) { + int encrypt = wpa_s->wpa && + wpa_sm_has_ptk_installed(wpa_s->wpa); + + return wpa_drv_tx_control_port(wpa_s, dest, proto, buf, len, + !encrypt); + } + if (wpa_s->l2) { return l2_packet_send(wpa_s->l2, dest, proto, buf, len); } @@ -219,6 +228,7 @@ static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, } +#ifdef CONFIG_WEP /** * wpa_eapol_set_wep_key - set WEP key for the driver * @ctx: Pointer to wpa_supplicant data (wpa_s) @@ -242,8 +252,11 @@ static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, } return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, unicast ? wpa_s->bssid : NULL, - keyidx, unicast, NULL, 0, key, keylen); + keyidx, unicast, NULL, 0, key, keylen, + unicast ? KEY_FLAG_PAIRWISE_RX_TX : + KEY_FLAG_GROUP_RX_TX_DEFAULT); } +#endif /* CONFIG_WEP */ static void wpa_supplicant_aborted_cached(void *ctx) @@ -340,8 +353,8 @@ static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " "handshake", pmk, pmk_len); - if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk, - pmk_len)) { + if (wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, NULL, 0, pmk, + pmk_len, KEY_FLAG_PMK)) { wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); } @@ -386,6 +399,13 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) curr = bss; break; } +#ifdef CONFIG_OWE + if (ssid && (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + (bss->flags & WPA_BSS_OWE_TRANSITION)) { + curr = bss; + break; + } +#endif /* CONFIG_OWE */ } if (curr) { @@ -396,6 +416,10 @@ static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) ie = wpa_bss_get_ie(curr, WLAN_EID_RSN); if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) ret = -1; + + ie = wpa_bss_get_ie(curr, WLAN_EID_RSNX); + if (wpa_sm_set_ap_rsnxe(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) + ret = -1; } else { ret = -1; } @@ -472,6 +496,12 @@ static void _wpa_supplicant_deauthenticate(void *wpa_s, u16 reason_code) } +static void _wpa_supplicant_reconnect(void *wpa_s) +{ + wpa_supplicant_reconnect(wpa_s); +} + + static void * wpa_supplicant_get_network_ctx(void *wpa_s) { return wpa_supplicant_get_ssid(wpa_s); @@ -488,7 +518,8 @@ static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid) static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, - const u8 *key, size_t key_len) + const u8 *key, size_t key_len, + enum key_flag key_flag) { struct wpa_supplicant *wpa_s = _wpa_s; if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) { @@ -503,7 +534,8 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, } #endif /* CONFIG_TESTING_GET_GTK */ #ifdef CONFIG_TESTING_OPTIONS - if (addr && !is_broadcast_ether_addr(addr)) { + if (addr && !is_broadcast_ether_addr(addr) && + !(key_flag & KEY_FLAG_MODIFY)) { wpa_s->last_tk_alg = alg; os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); wpa_s->last_tk_key_idx = key_idx; @@ -513,7 +545,7 @@ static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, } #endif /* CONFIG_TESTING_OPTIONS */ return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, - key, key_len); + key, key_len, key_flag); } @@ -543,7 +575,9 @@ static struct wpa_ssid * wpas_get_network_ctx(struct wpa_supplicant *wpa_s, static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, const u8 *bssid, const u8 *pmkid, const u8 *fils_cache_id, - const u8 *pmk, size_t pmk_len) + const u8 *pmk, size_t pmk_len, + u32 pmk_lifetime, u8 pmk_reauth_threshold, + int akmp) { struct wpa_supplicant *wpa_s = _wpa_s; struct wpa_ssid *ssid; @@ -551,9 +585,22 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, os_memset(¶ms, 0, sizeof(params)); ssid = wpas_get_network_ctx(wpa_s, network_ctx); - if (ssid) + if (ssid) { wpa_msg(wpa_s, MSG_INFO, PMKSA_CACHE_ADDED MACSTR " %d", MAC2STR(bssid), ssid->id); + if ((akmp == WPA_KEY_MGMT_FT_IEEE8021X || + akmp == WPA_KEY_MGMT_FT_IEEE8021X_SHA384) && + !ssid->ft_eap_pmksa_caching) { + /* Since we will not be using PMKSA caching for FT-EAP + * within wpa_supplicant to avoid known interop issues + * with APs, do not add this PMKID to the driver either + * so that we won't be hitting those interop issues + * with driver-based RSNE generation. */ + wpa_printf(MSG_DEBUG, + "FT: Do not add PMKID entry to the driver since FT-EAP PMKSA caching is not enabled in configuration"); + return 0; + } + } if (ssid && fils_cache_id) { params.ssid = ssid->ssid; params.ssid_len = ssid->ssid_len; @@ -565,6 +612,8 @@ static int wpa_supplicant_add_pmkid(void *_wpa_s, void *network_ctx, params.pmkid = pmkid; params.pmk = pmk; params.pmk_len = pmk_len; + params.pmk_lifetime = pmk_lifetime; + params.pmk_reauth_threshold = pmk_reauth_threshold; return wpa_drv_add_pmkid(wpa_s, ¶ms); } @@ -729,6 +778,9 @@ static int wpa_supplicant_tdls_peer_addset( const u8 *supp_rates, size_t supp_rates_len, const struct ieee80211_ht_capabilities *ht_capab, const struct ieee80211_vht_capabilities *vht_capab, + const struct ieee80211_he_capabilities *he_capab, + size_t he_capab_len, + const struct ieee80211_he_6ghz_band_cap *he_6ghz_he_capab, u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, const u8 *supp_channels, size_t supp_channels_len, const u8 *supp_oper_classes, size_t supp_oper_classes_len) @@ -752,6 +804,9 @@ static int wpa_supplicant_tdls_peer_addset( params.ht_capabilities = ht_capab; params.vht_capabilities = vht_capab; + params.he_capab = he_capab; + params.he_capab_len = he_capab_len; + params.he_6ghz_capab = he_6ghz_he_capab; params.qosinfo = qosinfo; params.listen_interval = 0; params.supp_rates = supp_rates; @@ -1043,6 +1098,21 @@ static void wpa_supplicant_eap_error_cb(void *ctx, int error_code) } +static int wpa_supplicant_eap_auth_start_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (!wpa_s->new_connection && wpa_s->deny_ptk0_rekey && + !wpa_sm_ext_key_id_active(wpa_s->wpa)) { + wpa_msg(wpa_s, MSG_INFO, + "WPA: PTK0 rekey not allowed, reconnecting"); + wpa_supplicant_reconnect(wpa_s); + return -1; + } + return 0; +} + + static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) { struct wpa_supplicant *wpa_s = ctx; @@ -1098,7 +1168,9 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->preauth = 0; ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; ctx->eapol_send = wpa_supplicant_eapol_send; +#ifdef CONFIG_WEP ctx->set_wep_key = wpa_eapol_set_wep_key; +#endif /* CONFIG_WEP */ #ifndef CONFIG_NO_CONFIG_BLOBS ctx->set_config_blob = wpa_supplicant_set_config_blob; ctx->get_config_blob = wpa_supplicant_get_config_blob; @@ -1121,6 +1193,7 @@ int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) ctx->cert_in_cb = wpa_s->conf->cert_in_cb; ctx->status_cb = wpa_supplicant_status_cb; ctx->eap_error_cb = wpa_supplicant_eap_error_cb; + ctx->confirm_auth_cb = wpa_supplicant_eap_auth_start_cb; ctx->set_anon_id = wpa_supplicant_set_anon_id; ctx->cb_ctx = wpa_s; wpa_s->eapol = eapol_sm_init(ctx); @@ -1156,8 +1229,8 @@ static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, if (wpa_s->conf->key_mgmt_offload && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) - return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, - NULL, 0, pmk, pmk_len); + return wpa_drv_set_key(wpa_s, 0, NULL, 0, 0, + NULL, 0, pmk, pmk_len, KEY_FLAG_PMK); else return 0; } @@ -1189,6 +1262,101 @@ static int wpa_supplicant_channel_info(void *_wpa_s, return wpa_drv_channel_info(wpa_s, ci); } + +static void disable_wpa_wpa2(struct wpa_ssid *ssid) +{ + ssid->proto &= ~WPA_PROTO_WPA; + ssid->proto |= WPA_PROTO_RSN; + ssid->key_mgmt &= ~(WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256); + ssid->group_cipher &= ~WPA_CIPHER_TKIP; + if (!(ssid->group_cipher & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256))) + ssid->group_cipher |= WPA_CIPHER_CCMP; + ssid->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; +} + + +static void wpa_supplicant_transition_disable(void *_wpa_s, u8 bitmap) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + struct wpa_ssid *ssid; + int changed = 0; + + wpa_msg(wpa_s, MSG_INFO, TRANSITION_DISABLE "%02x", bitmap); + + ssid = wpa_s->current_ssid; + if (!ssid) + return; + +#ifdef CONFIG_SAE + if ((bitmap & TRANSITION_DISABLE_WPA3_PERSONAL) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "WPA3-Personal transition mode disabled based on AP notification"); + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_SAE_PK) && + wpa_key_mgmt_sae(wpa_s->key_mgmt) && +#ifdef CONFIG_SME + wpa_s->sme.sae.state == SAE_ACCEPTED && + wpa_s->sme.sae.pk && +#endif /* CONFIG_SME */ + (ssid->key_mgmt & (WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE)) && + (ssid->sae_pk != SAE_PK_MODE_ONLY || + ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + wpa_printf(MSG_DEBUG, + "SAE-PK: SAE authentication without PK disabled based on AP notification"); + disable_wpa_wpa2(ssid); + ssid->sae_pk = SAE_PK_MODE_ONLY; + changed = 1; + } +#endif /* CONFIG_SAE */ + + if ((bitmap & TRANSITION_DISABLE_WPA3_ENTERPRISE) && + wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && + (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_IEEE8021X_SHA256)) && + (ssid->ieee80211w != MGMT_FRAME_PROTECTION_REQUIRED || + (ssid->group_cipher & WPA_CIPHER_TKIP))) { + disable_wpa_wpa2(ssid); + changed = 1; + } + + if ((bitmap & TRANSITION_DISABLE_ENHANCED_OPEN) && + wpa_s->key_mgmt == WPA_KEY_MGMT_OWE && + (ssid->key_mgmt & WPA_KEY_MGMT_OWE) && + !ssid->owe_only) { + ssid->owe_only = 1; + changed = 1; + } + + if (!changed) + return; + +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->conf->update_config && + wpa_config_write(wpa_s->confname, wpa_s->conf)) + wpa_printf(MSG_DEBUG, "Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + + +static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher, + u32 life_time, const struct wpa_ptk *ptk) +{ + struct wpa_supplicant *wpa_s = ctx; + + ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk); +} + #endif /* CONFIG_NO_WPA */ @@ -1196,9 +1364,20 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) { #ifndef CONFIG_NO_WPA struct wpa_sm_ctx *ctx; + + wpa_s->ptksa = ptksa_cache_init(); + if (!wpa_s->ptksa) { + wpa_printf(MSG_ERROR, "Failed to allocate PTKSA"); + return -1; + } + ctx = os_zalloc(sizeof(*ctx)); if (ctx == NULL) { wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); + + ptksa_cache_deinit(wpa_s->ptksa); + wpa_s->ptksa = NULL; + return -1; } @@ -1207,6 +1386,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->set_state = _wpa_supplicant_set_state; ctx->get_state = _wpa_supplicant_get_state; ctx->deauthenticate = _wpa_supplicant_deauthenticate; + ctx->reconnect = _wpa_supplicant_reconnect; ctx->set_key = wpa_supplicant_set_key; ctx->get_network_ctx = wpa_supplicant_get_network_ctx; ctx->get_bssid = wpa_supplicant_get_bssid; @@ -1240,12 +1420,16 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx; ctx->channel_info = wpa_supplicant_channel_info; + ctx->transition_disable = wpa_supplicant_transition_disable; + ctx->store_ptk = wpa_supplicant_store_ptk; wpa_s->wpa = wpa_sm_init(ctx); if (wpa_s->wpa == NULL) { - wpa_printf(MSG_ERROR, "Failed to initialize WPA state " - "machine"); + wpa_printf(MSG_ERROR, + "Failed to initialize WPA state machine"); os_free(ctx); + ptksa_cache_deinit(wpa_s->ptksa); + wpa_s->ptksa = NULL; return -1; } #endif /* CONFIG_NO_WPA */ @@ -1271,6 +1455,8 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.ssid = ssid->ssid; conf.ssid_len = ssid->ssid_len; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; + conf.wpa_deny_ptk0_rekey = ssid->wpa_deny_ptk0_rekey; + conf.owe_ptk_workaround = ssid->owe_ptk_workaround; #ifdef CONFIG_P2P if (ssid->p2p_group && wpa_s->current_bss && !wpa_s->p2p_disable_ip_addr_req) { @@ -1293,6 +1479,16 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.fils_cache_id = wpa_bss_get_fils_cache_id(wpa_s->current_bss); #endif /* CONFIG_FILS */ + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_BEACON_PROTECTION) || + (wpa_s->drv_flags2 & + WPA_DRIVER_FLAGS2_BEACON_PROTECTION_CLIENT)) + conf.beacon_prot = ssid->beacon_prot; + +#ifdef CONFIG_PASN +#ifdef CONFIG_TESTING_OPTIONS + conf.force_kdk_derivation = wpa_s->conf->force_kdk_derivation; +#endif /* CONFIG_TESTING_OPTIONS */ +#endif /* CONFIG_PASN */ } wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); } |