aboutsummaryrefslogtreecommitdiff
path: root/contrib/wpa/wpa_supplicant/wpas_glue.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/wpa/wpa_supplicant/wpas_glue.c')
-rw-r--r--contrib/wpa/wpa_supplicant/wpas_glue.c224
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(&params, 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, &params);
}
@@ -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);
}