Add support for Extended Key ID in hostapd based on IEEE 802.11 - 2016 for infrastructure (AP) connections. This also fixes an off by one error for key tracking and deletion: Even within IEEE 802.11w the highest keyid is 5 and not 6. Signed-off-by: Alexander Wetzel <alexander@xxxxxxxxxxxxxx> --- This complements the hostapd Extended Key ID patch and adds support for it also to wpa_supplicant. For now we only have the "client" Extended Key ID support covered in wpa_supplicant. IBSS/TDLS/mesh extensions are also missing for now but besides that it's feature complete. (FILS support is in a separate patch) src/rsn_supp/wpa.c | 126 ++++++++++++++++++++++++++--- src/rsn_supp/wpa.h | 5 +- src/rsn_supp/wpa_ft.c | 7 +- src/rsn_supp/wpa_i.h | 3 + src/rsn_supp/wpa_ie.c | 11 +++ src/rsn_supp/wpa_ie.h | 1 + wpa_supplicant/config.c | 2 + wpa_supplicant/config_file.c | 1 + wpa_supplicant/config_ssid.h | 10 +++ wpa_supplicant/ctrl_iface.c | 3 + wpa_supplicant/driver_i.h | 13 ++- wpa_supplicant/wpa_cli.c | 3 +- wpa_supplicant/wpa_supplicant.c | 27 ++++++- wpa_supplicant/wpa_supplicant.conf | 5 ++ wpa_supplicant/wpas_glue.c | 4 +- 15 files changed, 200 insertions(+), 21 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index 830c74c8f..de463cba6 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -581,6 +581,53 @@ static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, sm->pairwise_cipher, z, z_len); } +static int handle_extended_key_id(struct wpa_sm *sm, + struct wpa_eapol_ie_parse *kde, + const u8 *rsn_ie, size_t rsn_ie_len) +{ + struct wpa_ie_data rsn; + + /* IEEE 802.11 - 2016 requires the Extended Key ID + * bit to be set in the RSN capabilities for both STAs + * to enable the feature + */ + if (sm->wpa_extended_key_id && rsn_ie && + sm->pairwise_cipher != WPA_CIPHER_TKIP && + wpa_parse_wpa_ie_rsn(rsn_ie, rsn_ie_len, &rsn) >= 0 && + rsn.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) { + if (!kde->key_id) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: No KeyID in Extended Key ID handshake"); + return -1; + } else if (kde->key_id[0] & 0xfe) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: Invalid KeyID"); + return -1; + } + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Using Extended Key ID"); + sm->keyidx_active = kde->key_id[0]; + sm->use_extended_key_id = 1; + } else { + if (kde->key_id && kde->key_id[0]) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: Non-zero KeyID in legacy handshake"); + return -1; + } else if (kde->key_id) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: KeyID in legacy handshake"); + } else if (!rsn_ie || sm->pairwise_cipher == WPA_CIPHER_TKIP) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Extended Key ID requires wpa2 and CCMP/GCMP"); + } + if (sm->wpa_extended_key_id) + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Not using Extended Key ID"); + sm->keyidx_active = 0; + sm->use_extended_key_id = 0; + } + return 0; +} static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, const unsigned char *src_addr, @@ -779,6 +826,14 @@ static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) wpa_sm_key_request(sm, 0, 1); } +static void wpa_supplicant_ptk_installed(struct wpa_sm *sm) +{ + if (sm->wpa_ptk_rekey) { + eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); + eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, + sm, NULL); + } +} static int wpa_supplicant_install_ptk(struct wpa_sm *sm, const struct wpa_eapol_key *key, @@ -826,12 +881,14 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); } - if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, - sm->ptk.tk, keylen, key_type) < 0) { + if (wpa_sm_set_key(sm, alg, sm->bssid, sm->keyidx_active, 1, key_rsc, + rsclen, sm->ptk.tk, keylen, key_type) < 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, - "WPA: Failed to set PTK to the " - "driver (alg=%d keylen=%d bssid=" MACSTR ")", - alg, keylen, MAC2STR(sm->bssid)); + "WPA: Failed to set PTK to the driver" + "(alg=%d keylen=%d bssid=" MACSTR + " idx=%d use_extended_key_id=%d key_type=%d)", + alg, keylen, MAC2STR(sm->bssid), + sm->keyidx_active, sm->use_extended_key_id, key_type); return -1; } @@ -840,12 +897,27 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, sm->ptk.tk_len = 0; sm->ptk.installed = 1; - if (sm->wpa_ptk_rekey) { - eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); - eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, - sm, NULL); + if (key_type != KEY_TYPE_NO_AUTO_TX) + wpa_supplicant_ptk_installed(sm); + + return 0; +} + +static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) +{ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Activate PTK (idx=%d bssid=" MACSTR ")", + sm->keyidx_active, MAC2STR(sm->bssid)); + + if (wpa_sm_set_key(sm, 0, sm->bssid, sm->keyidx_active, + 0, 0, 0, NULL, 0, KEY_TYPE_SET_TX) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: Failed to activate PTK for Tx (idx=%d bssid=" + MACSTR ")", sm->keyidx_active, MAC2STR(sm->bssid)); + return -1; } + wpa_supplicant_ptk_installed(sm); return 0; } @@ -1479,6 +1551,9 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) goto failed; + if (handle_extended_key_id(sm, &ie, ie.rsn_ie, ie.rsn_ie_len)) + goto failed; + if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: ANonce from message 1 of 4-Way Handshake " @@ -1523,6 +1598,10 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, } } #endif /* CONFIG_OCV */ + if (sm->use_extended_key_id) { + if (wpa_supplicant_install_ptk(sm, key, KEY_TYPE_NO_AUTO_TX)) + goto failed; + } if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, &sm->ptk) < 0) { @@ -1535,8 +1614,13 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, sm->renew_snonce = 1; if (key_info & WPA_KEY_INFO_INSTALL) { - if (wpa_supplicant_install_ptk(sm, key, KEY_TYPE_PAIRWISE)) + if (sm->use_extended_key_id) { + if (wpa_supplicant_activate_ptk(sm)) + goto failed; + } else if (wpa_supplicant_install_ptk(sm, key, + KEY_TYPE_PAIRWISE)) { goto failed; + } } if (key_info & WPA_KEY_INFO_SECURE) { @@ -2650,6 +2734,7 @@ struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) return NULL; dl_list_init(&sm->pmksa_candidates); sm->renew_snonce = 1; + sm->keyidx_active = 0; sm->ctx = ctx; sm->dot11RSNAConfigPMKLifetime = 43200; @@ -3040,6 +3125,9 @@ int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, case WPA_PARAM_PAIRWISE: sm->pairwise_cipher = value; break; + case WPA_PARAM_EXTENDED_KEY_ID: + sm->wpa_extended_key_id = value; + break; case WPA_PARAM_GROUP: sm->group_cipher = value; break; @@ -3164,6 +3252,9 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, #ifdef CONFIG_TESTING_OPTIONS if (sm->test_assoc_ie) { + struct wpa_eapol_ie_parse ie; + struct wpa_ie_data rsn; + wpa_printf(MSG_DEBUG, "TESTING: Replace association WPA/RSN IE"); if (*wpa_ie_len < wpabuf_len(sm->test_assoc_ie)) @@ -3171,6 +3262,15 @@ int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, os_memcpy(wpa_ie, wpabuf_head(sm->test_assoc_ie), wpabuf_len(sm->test_assoc_ie)); res = wpabuf_len(sm->test_assoc_ie); + + if (wpa_supplicant_parse_ies(wpa_ie, res, &ie) || + wpa_parse_wpa_ie_rsn(ie.rsn_ie, ie.rsn_ie_len, &rsn) || + !(rsn.capabilities & + WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST)) { + wpa_printf(MSG_DEBUG, + "TESTING: Force disable Extended Key ID"); + sm->wpa_extended_key_id = 0; + } } else #endif /* CONFIG_TESTING_OPTIONS */ res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); @@ -3400,6 +3500,10 @@ int wpa_sm_has_ptk(struct wpa_sm *sm) return sm->ptk_set; } +int wpa_sm_extended_key_id(struct wpa_sm *sm) +{ + return sm->wpa_extended_key_id; +} void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) { @@ -4028,6 +4132,8 @@ static int fils_ft_build_assoc_req_rsne(struct wpa_sm *sm, struct wpabuf *buf) #endif /* CONFIG_IEEE80211W */ if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->wpa_extended_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; wpabuf_put_le16(buf, capab); /* PMKID Count */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 698154b94..65ca6262e 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -98,7 +98,8 @@ enum wpa_sm_conf_params { WPA_PARAM_MGMT_GROUP, WPA_PARAM_RSN_ENABLED, WPA_PARAM_MFP, - WPA_PARAM_OCV + WPA_PARAM_OCV, + WPA_PARAM_EXTENDED_KEY_ID }; struct rsn_supp_config { @@ -109,6 +110,7 @@ struct rsn_supp_config { void *eap_conf_ctx; const u8 *ssid; size_t ssid_len; + int wpa_extended_key_id; int wpa_ptk_rekey; int p2p; int wpa_rsc_relaxation; @@ -167,6 +169,7 @@ int wpa_sm_pmksa_exists(struct wpa_sm *sm, const u8 *bssid, const void *network_ctx); void wpa_sm_drop_sa(struct wpa_sm *sm); int wpa_sm_has_ptk(struct wpa_sm *sm); +int wpa_sm_extended_key_id(struct wpa_sm *sm); void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr); diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c index 3b45f669b..4aa862748 100644 --- a/src/rsn_supp/wpa_ft.c +++ b/src/rsn_supp/wpa_ft.c @@ -254,6 +254,8 @@ static u8 * wpa_ft_gen_req_ies(struct wpa_sm *sm, size_t *len, #endif /* CONFIG_IEEE80211W */ if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->wpa_extended_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; WPA_PUT_LE16(pos, capab); pos += 2; @@ -411,8 +413,9 @@ static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid) alg = wpa_cipher_to_alg(sm->pairwise_cipher); keylen = wpa_cipher_key_len(sm->pairwise_cipher); - if (wpa_sm_set_key(sm, alg, bssid, 0, 1, null_rsc, sizeof(null_rsc), - (u8 *) sm->ptk.tk, keylen, KEY_TYPE_PAIRWISE) < 0) { + if (wpa_sm_set_key(sm, alg, bssid, sm->keyidx_active, 1, null_rsc, + sizeof(null_rsc), (u8 *) sm->ptk.tk, keylen, + KEY_TYPE_PAIRWISE) < 0) { wpa_printf(MSG_WARNING, "FT: Failed to set PTK to the driver"); return -1; } diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index 7423e8aee..eee9570ba 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -26,6 +26,7 @@ struct wpa_sm { u8 snonce[WPA_NONCE_LEN]; u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ int renew_snonce; + int keyidx_active; u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; int rx_replay_counter_set; u8 request_counter[WPA_REPLAY_COUNTER_LEN]; @@ -65,6 +66,8 @@ struct wpa_sm { int wpa_ptk_rekey; int p2p; int wpa_rsc_relaxation; + int wpa_extended_key_id; + int use_extended_key_id; u8 own_addr[ETH_ALEN]; const char *ifname; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index ae9f4ca24..4016ec71a 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -225,6 +225,9 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, #endif /* CONFIG_IEEE80211W */ if (sm->ocv) capab |= WPA_CAPABILITY_OCVC; + if (sm->wpa_extended_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; + WPA_PUT_LE16(pos, capab); pos += 2; @@ -417,6 +420,14 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, return 0; } + if (pos[1] > RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_KEYID) { + ie->key_id = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: KeyID in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + if (pos[1] > RSN_SELECTOR_LEN + 2 && RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { ie->gtk = pos + 2 + RSN_SELECTOR_LEN; diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index 9d53973a9..f961e90e4 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -17,6 +17,7 @@ struct wpa_eapol_ie_parse { const u8 *rsn_ie; size_t rsn_ie_len; const u8 *pmkid; + const u8 *key_id; const u8 *gtk; size_t gtk_len; const u8 *mac_addr; diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index fc1ed4f90..19a213398 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2334,6 +2334,7 @@ static const struct parse_data ssid_fields[] = { { INT(dot11MeshConfirmTimeout) }, { INT(dot11MeshHoldingTimeout) }, #endif /* CONFIG_MESH */ + { INT(wpa_extended_key_id) }, { INT(wpa_ptk_rekey) }, { INT(group_rekey) }, { STR(bgscan) }, @@ -2854,6 +2855,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) { ssid->proto = DEFAULT_PROTO; ssid->pairwise_cipher = DEFAULT_PAIRWISE; + ssid->wpa_extended_key_id = DEFAULT_EXTENDED_KEY_ID; ssid->group_cipher = DEFAULT_GROUP; ssid->key_mgmt = DEFAULT_KEY_MGMT; ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 91d5caa3f..dadc503eb 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -882,6 +882,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT_DEF(dot11MeshHoldingTimeout, DEFAULT_MESH_HOLDING_TIMEOUT); INT_DEF(mesh_rssi_threshold, DEFAULT_MESH_RSSI_THRESHOLD); #endif /* CONFIG_MESH */ + INT(wpa_extended_key_id); INT(wpa_ptk_rekey); INT(group_rekey); INT(ignore_broadcast_ssid); diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index d5c5c00a9..968b1c040 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -22,6 +22,7 @@ #define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) #define DEFAULT_FRAGMENT_SIZE 1398 +#define DEFAULT_EXTENDED_KEY_ID 1 #define DEFAULT_BG_SCAN_PERIOD -1 #define DEFAULT_MESH_MAX_RETRIES 2 @@ -528,6 +529,15 @@ struct wpa_ssid { unsigned int vht_center_freq1; unsigned int vht_center_freq2; + /** wpa_extended_key_id - Extended Key ID support + * + * IEEE 802.11-2016 optionally allows to use key id 0 and 1 for PTK keys + * default: auto (1) + * 0 = force off. Do not announce or use Extended Key ID. + * 1 = auto. Use Extended Key ID when possible. + */ + int wpa_extended_key_id; + /** * wpa_ptk_rekey - Maximum lifetime for PTK in seconds * diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index 862f72734..e5f7246d1 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -5254,6 +5254,9 @@ static void wpa_supplicant_ctrl_iface_drop_sa(struct wpa_supplicant *wpa_s) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 0, 0, NULL, 0, NULL, 0, KEY_TYPE_PAIRWISE); + if (wpa_sm_extended_key_id(wpa_s->wpa)) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, wpa_s->bssid, 1, 0, NULL, + 0, NULL, 0, KEY_TYPE_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection(wpa_s, wpa_s->bssid, MLME_SETPROTECTION_PROTECT_TYPE_NONE, diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index efb17c471..a63566b7f 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -156,10 +156,19 @@ static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, enum key_type key_type) { if (alg != WPA_ALG_NONE) { - if (key_idx >= 0 && key_idx <= 6) + if (key_idx == 1 && + (key_type == KEY_TYPE_PAIRWISE || + key_type == KEY_TYPE_NO_AUTO_TX)) { + /* keyidx = 1 can be either a broadcast or - with + * Extended Key ID - an unicast key. Use bit 6 for + * the pairwise keyidx 1. + */ + wpa_s->keys_cleared &= ~BIT(6); + } else if (key_idx >= 0 && key_idx <= 5) { wpa_s->keys_cleared &= ~BIT(key_idx); - else + } else { wpa_s->keys_cleared = 0; + } } if (wpa_s->driver->set_key) { return wpa_s->driver->set_key(wpa_s->ifname, wpa_s->drv_priv, diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c index 43ac42720..1bad63e08 100644 --- a/wpa_supplicant/wpa_cli.c +++ b/wpa_supplicant/wpa_cli.c @@ -1442,7 +1442,8 @@ static const char *network_fields[] = { "dot11MeshRetryTimeout", "dot11MeshConfirmTimeout", "dot11MeshHoldingTimeout", #endif /* CONFIG_MESH */ - "wpa_ptk_rekey", "bgscan", "ignore_broadcast_ssid", + "wpa_extended_key_id", "wpa_ptk_rekey", "bgscan", + "ignore_broadcast_ssid", #ifdef CONFIG_P2P "go_p2p_dev_addr", "p2p_client_list", "psk_list", #endif /* CONFIG_P2P */ diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 56bba65e8..d2be5949c 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -699,7 +699,7 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) int i, max; #ifdef CONFIG_IEEE80211W - max = 6; + max = 5; #else /* CONFIG_IEEE80211W */ max = 4; #endif /* CONFIG_IEEE80211W */ @@ -711,10 +711,15 @@ void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0, NULL, 0, KEY_TYPE_BROADCAST); } - if (!(wpa_s->keys_cleared & BIT(0)) && addr && + /* Pairwise key idx 1 for Extended Key ID is tracked with bit 6 */ + if (~wpa_s->keys_cleared & (BIT(0) | BIT(6)) && addr && !is_zero_ether_addr(addr)) { - wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, - 0, KEY_TYPE_PAIRWISE); + if (!(wpa_s->keys_cleared & (BIT(0)))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, + 0, NULL, 0, KEY_TYPE_PAIRWISE); + if (!(wpa_s->keys_cleared & (BIT(6)))) + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 1, 0, NULL, + 0, NULL, 0, KEY_TYPE_PAIRWISE); /* MLME-SETPROTECTION.request(None) */ wpa_drv_mlme_setprotection( wpa_s, addr, @@ -1237,6 +1242,20 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, int sel, proto; const u8 *bss_wpa, *bss_rsn, *bss_osen; + if (ssid->mode == WPAS_MODE_INFRA && ssid->wpa_extended_key_id && + wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID) { + wpa_msg(wpa_s, MSG_DEBUG, "Enable Extended Key ID support"); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXTENDED_KEY_ID, 1); + } else { + if (ssid->wpa_extended_key_id) + wpa_msg(wpa_s, MSG_INFO, + "Extended Key ID not supported"); + else + wpa_msg(wpa_s, MSG_DEBUG, + "Extended Key ID support disabled"); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_EXTENDED_KEY_ID, 0); + } + if (bss) { bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf index 1159bdcdc..b6a1ed2fd 100644 --- a/wpa_supplicant/wpa_supplicant.conf +++ b/wpa_supplicant/wpa_supplicant.conf @@ -1070,6 +1070,11 @@ fast_reauth=1 # hex without quotation, e.g., 0102030405) # wep_tx_keyidx: Default WEP key index (TX) (0..3) # +# wpa_extended_key_id: +# Support the unicast rekey protocol "Extended Key ID" from IEEE 802.11 - 2016. +# 0 = force off: Do not announce or use Extended Key ID +# 1 = auto: Use Extended Key ID when possible (default) +# # wpa_ptk_rekey: Maximum lifetime for PTK in seconds. This can be used to # enforce rekeying of PTK to mitigate some attacks against TKIP deficiencies. # diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index f96608d72..4b0665826 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -505,7 +505,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_type != KEY_TYPE_SET_TX) { wpa_s->last_tk_alg = alg; os_memcpy(wpa_s->last_tk_addr, addr, ETH_ALEN); wpa_s->last_tk_key_idx = key_idx; @@ -1272,6 +1273,7 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, #endif /* IEEE8021X_EAPOL */ conf.ssid = ssid->ssid; conf.ssid_len = ssid->ssid_len; + conf.wpa_extended_key_id = ssid->wpa_extended_key_id; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; #ifdef CONFIG_P2P if (ssid->p2p_group && wpa_s->current_bss && -- 2.23.0 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap