From: Alexander Wetzel <alexander@xxxxxxxxxxxxxx> Experimental support for Extended Key ID for wpa_supplicant for participation in BSS. Tested for basic functionality and backward compatibility but still WIP. Signed-off-by: Alexander Wetzel <alexander@xxxxxxxxxxxxxx> --- src/rsn_supp/wpa.c | 67 +++++++++++++++++++++++++++++---- src/rsn_supp/wpa.h | 4 +- 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 | 11 ++++++ wpa_supplicant/ibss_rsn.c | 11 +++--- wpa_supplicant/mesh_rsn.c | 3 +- wpa_supplicant/wpa_supplicant.c | 6 +++ wpa_supplicant/wpas_glue.c | 1 + 12 files changed, 107 insertions(+), 14 deletions(-) diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index e0c913074..ea7b68110 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -714,7 +714,8 @@ static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) static int wpa_supplicant_install_ptk(struct wpa_sm *sm, - const struct wpa_eapol_key *key) + const struct wpa_eapol_key *key, + int key_flag) { int keylen, rsclen; enum wpa_alg alg; @@ -749,6 +750,11 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, keylen, (long unsigned int) sm->ptk.tk_len); return -1; } + + if (key_flag && key_flag != KEY_FLAG_RX_ONLY) { + wpa_printf(MSG_DEBUG, "WPA: key_flag=%d invalid", key_flag); + return -1; + } rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { @@ -758,18 +764,47 @@ 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) < 0) { + if (wpa_sm_set_key(sm, alg, sm->bssid, sm->keyidx_active, key_flag, + key_rsc, rsclen, sm->ptk.tk, keylen) < 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)); + "driver (alg=%d extID=%d key_flag=%d keylen=%d bssid=" + MACSTR ")", alg, sm->Ext_Key_ID, key_flag, keylen, + MAC2STR(sm->bssid)); return -1; } /* TK is not needed anymore in supplicant */ os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); sm->ptk.tk_len = 0; + + if (!key_flag) { + 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); + } + } + + return 0; +} + +static int wpa_supplicant_activate_ptk(struct wpa_sm *sm) +{ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Activating PTK in driver"); + + if (wpa_sm_set_key(sm, 0, sm->bssid, sm->keyidx_active, + KEY_FLAG_TX, 0, 0, NULL, 0) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to activate PTK in the " + "driver (idx=%d bssid=" MACSTR ")", + sm->keyidx_active, MAC2STR(sm->bssid)); + return -1; + } + sm->ptk.installed = 1; if (sm->wpa_ptk_rekey) { @@ -781,7 +816,6 @@ static int wpa_supplicant_install_ptk(struct wpa_sm *sm, return 0; } - static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, int group_cipher, int keylen, int maxkeylen, @@ -1367,6 +1401,12 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len); if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) goto failed; + + if (ie.ptk_id && sm->wpa_ext_key_id) { + sm->keyidx_active = ie.ptk_id[0]; + sm->Ext_Key_ID = 1; + } + if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: GTK IE in unencrypted key data"); @@ -1418,6 +1458,11 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, } #endif /* CONFIG_P2P */ + if (sm->Ext_Key_ID) { + if (wpa_supplicant_install_ptk(sm, key, KEY_FLAG_RX_ONLY)) + goto failed; + } + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, &sm->ptk) < 0) { goto failed; @@ -1429,8 +1474,12 @@ 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)) + if (sm->Ext_Key_ID) { + if (wpa_supplicant_activate_ptk(sm)) + goto failed; + } else if (wpa_supplicant_install_ptk(sm, key, 0)) { goto failed; + } } if (key_info & WPA_KEY_INFO_SECURE) { @@ -2464,6 +2513,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; @@ -2847,6 +2897,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_SUPP_EXT_KEY_ID: + sm->wpa_ext_key_id = value; + break; case WPA_PARAM_GROUP: sm->group_cipher = value; break; diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 21f4b1781..e02c68cd8 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -95,7 +95,8 @@ enum wpa_sm_conf_params { WPA_PARAM_KEY_MGMT, WPA_PARAM_MGMT_GROUP, WPA_PARAM_RSN_ENABLED, - WPA_PARAM_MFP + WPA_PARAM_MFP, + WPA_PARAM_SUPP_EXT_KEY_ID }; struct rsn_supp_config { @@ -106,6 +107,7 @@ struct rsn_supp_config { void *eap_conf_ctx; const u8 *ssid; size_t ssid_len; + int wpa_ext_key_id; int wpa_ptk_rekey; int p2p; int wpa_rsc_relaxation; diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index b94b17a85..f1b7e8983 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_ext_key_id; + int Ext_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 a3410d154..358c6d595 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -223,6 +223,9 @@ static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, if (sm->mfp == 2) capab |= WPA_CAPABILITY_MFPR; #endif /* CONFIG_IEEE80211W */ + if (sm->wpa_ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; + WPA_PUT_LE16(pos, capab); pos += 2; @@ -415,6 +418,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->ptk_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 0e72af560..5adc4c8e0 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 *ptk_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 c43960697..840d8be82 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2252,6 +2252,7 @@ static const struct parse_data ssid_fields[] = { { INT(dot11MeshConfirmTimeout) }, { INT(dot11MeshHoldingTimeout) }, #endif /* CONFIG_MESH */ + { INT(wpa_ext_key_id) }, { INT(wpa_ptk_rekey) }, { INT(group_rekey) }, { STR(bgscan) }, @@ -2764,6 +2765,7 @@ void wpa_config_set_network_defaults(struct wpa_ssid *ssid) { ssid->proto = DEFAULT_PROTO; ssid->pairwise_cipher = DEFAULT_PAIRWISE; + ssid->wpa_ext_key_id = DEFAULT_EXT_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 09115e19d..7732b44a3 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -869,6 +869,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_ext_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 d2a52d760..52bd189d2 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_EXT_KEY_ID 1 #define DEFAULT_BG_SCAN_PERIOD -1 #define DEFAULT_MESH_MAX_RETRIES 2 @@ -510,6 +511,16 @@ struct wpa_ssid { unsigned int vht_center_freq1; unsigned int vht_center_freq2; + /** wpa_ext_key_id - Control support for Extended Key ID + * + * IEEE Std 802.11-2016 optionally allows to use key id 0 and 1 for + * PTK keys and shift GTK keys to id 2 and 3. + * default: auto (1) + * 0 = force off. Do not announce or use Extended Key ID. + * 1 = auto. Allow the AP to use Extended Key ID when possible. + */ + int wpa_ext_key_id; + /** * wpa_ptk_rekey - Maximum lifetime for PTK in seconds * diff --git a/wpa_supplicant/ibss_rsn.c b/wpa_supplicant/ibss_rsn.c index 00919d14a..a3b0e91c2 100644 --- a/wpa_supplicant/ibss_rsn.c +++ b/wpa_supplicant/ibss_rsn.c @@ -137,15 +137,15 @@ static void ibss_check_rsn_completed(struct ibss_rsn_peer *peer) static int supp_set_key(void *ctx, enum wpa_alg alg, - const u8 *addr, int key_idx, int set_tx, + const u8 *addr, int key_idx, int key_flag, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct ibss_rsn_peer *peer = ctx; wpa_printf(MSG_DEBUG, "SUPP: %s(alg=%d addr=" MACSTR " key_idx=%d " - "set_tx=%d)", - __func__, alg, MAC2STR(addr), key_idx, set_tx); + "key_flag=%d)", + __func__, alg, MAC2STR(addr), key_idx, key_flag); wpa_hexdump(MSG_DEBUG, "SUPP: set_key - seq", seq, seq_len); wpa_hexdump_key(MSG_DEBUG, "SUPP: set_key - key", key, key_len); @@ -166,7 +166,7 @@ static int supp_set_key(void *ctx, enum wpa_alg alg, if (is_broadcast_ether_addr(addr)) addr = peer->addr; return wpa_drv_set_key(peer->ibss_rsn->wpa_s, alg, addr, key_idx, - set_tx, seq, seq_len, key, key_len); + key_flag, seq, seq_len, key, key_len); } @@ -293,7 +293,8 @@ static int auth_send_eapol(void *ctx, const u8 *addr, const u8 *data, static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, size_t key_len) + const u8 *addr, int idx, u8 *key, size_t key_len, + int key_flag) { struct ibss_rsn *ibss_rsn = ctx; u8 seq[6]; diff --git a/wpa_supplicant/mesh_rsn.c b/wpa_supplicant/mesh_rsn.c index e74cb16b0..62dc0f66e 100644 --- a/wpa_supplicant/mesh_rsn.c +++ b/wpa_supplicant/mesh_rsn.c @@ -98,7 +98,8 @@ static const u8 *auth_get_psk(void *ctx, const u8 *addr, static int auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, size_t key_len) + const u8 *addr, int idx, u8 *key, size_t key_len, + int key_flag) { struct mesh_rsn *mesh_rsn = ctx; u8 seq[6]; diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 6090e0662..341062aa2 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1194,6 +1194,12 @@ int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, int sel, proto; const u8 *bss_wpa, *bss_rsn, *bss_osen; + if (ssid->wpa_ext_key_id && + wpa_s->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID) { + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Enable Extended Key ID support."); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_SUPP_EXT_KEY_ID, 1); + } + 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/wpas_glue.c b/wpa_supplicant/wpas_glue.c index 4634ed7fc..9bc1583bb 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -1263,6 +1263,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_ext_key_id = ssid->wpa_ext_key_id; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; #ifdef CONFIG_P2P if (ssid->p2p_group && wpa_s->current_bss && -- 2.19.1 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap