From patchwork Sun Nov 11 11:54:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Wetzel X-Patchwork-Id: 996111 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.infradead.org (client-ip=2607:7c80:54:e::133; helo=bombadil.infradead.org; envelope-from=hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=web.de Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="ptckDORJ"; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=infradead.org header.i=@infradead.org header.b="oa57rjXR"; dkim-atps=neutral Received: from bombadil.infradead.org (bombadil.infradead.org [IPv6:2607:7c80:54:e::133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 42tC6L0zK9z9s9G for ; Sun, 11 Nov 2018 22:56:42 +1100 (AEDT) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-Id:Date:Subject:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=nTcgeRew3yRQGh9xYxP0BCigryNcBqKxZ4pzVpiNxCs=; b=ptckDORJ5ujarP zkcDafSnteAkJNG77T+RgqTvnA0Mfp88izZUUkJzn8k5vuHgmfBNjAzKyCZFuIdDCDI80OTdIvvGr 4C2zKMfTZklZnrafD2MBa+ga8FD3HgPuimRk/LXY7lCz1V5aqV/Qv+Rmr8H3eBhrn+8ufHrb3sWmd l09KaiRm8U9Hxq0AdruwZ2iutXHdHOKQC9APKRKCNiV0Bsm13DKxmHfqJ3qF3OKLmtQ51VvLaEQuh NT9AYcSVbrWLhRV+PKLOT4A3kc+NX9dYUQLSwGgxrRwCYYFEWXHJ0SuLYgp3Q067hikCdIPgsd48b eGkWS0KatVmJgTSj3H7g==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gLoLn-00085q-A4; Sun, 11 Nov 2018 11:56:23 +0000 Received: from casper.infradead.org ([2001:8b0:10b:1236::1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gLoLi-00083h-RW for hostap@bombadil.infradead.org; Sun, 11 Nov 2018 11:56:19 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=casper.20170209; h=Content-Transfer-Encoding:MIME-Version: References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=MchPfUVkJaVgOOlIx9pMZrY6DlySr/v/jWff/7UE7q8=; b=oa57rjXRnVuvu9+jfqcIb9hwYT jtsT1brGevs/N84mysvuwlNp+ZuCKgd5C4XPSV2bfILJUknKURqV7+PHkDzeX+4PPEM7h1Dkt7E+D 7J4CRMM/sIVCxXhdaE0zYMiO7XWi07NFQ1BhHNizEMyH86UTKbWggBDzpy5yBtZyKcn/+g/xtaSCI 4UqUQxHR/Zrp7Pd/uNLelKMRvOHqMqBvHWMctwl7cS6OM+tSmr+5uuwQJfqnVA45DDtuKmD+kP9Sp +3DXER1cJ9pq4o63FLa6UKk/0QTJwdE21LbbyTWHSpSlCpSxCQjeoMHJfXtNPVHW4gQXiQShhcgRQ UBtTsqmQ==; Received: from 4.mo69.mail-out.ovh.net ([46.105.42.102]) by casper.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1gLoLe-0005nS-Tb for hostap@lists.infradead.org; Sun, 11 Nov 2018 11:56:17 +0000 Received: from player786.ha.ovh.net (unknown [10.109.143.24]) by mo69.mail-out.ovh.net (Postfix) with ESMTP id 0B8E831A81 for ; Sun, 11 Nov 2018 12:56:03 +0100 (CET) Received: from awhome.eu (p4FF91EF0.dip0.t-ipconnect.de [79.249.30.240]) (Authenticated sender: postmaster@awhome.eu) by player786.ha.ovh.net (Postfix) with ESMTPSA id BA36B380093 for ; Sun, 11 Nov 2018 12:56:02 +0100 (CET) From: alexander.wetzel@web.de To: hostap@lists.infradead.org Subject: [RFC PATCH 2/3] hostapd support for Extended Key ID Date: Sun, 11 Nov 2018 12:54:40 +0100 Message-Id: <20181111115441.15015-3-alexander.wetzel@web.de> X-Mailer: git-send-email 2.19.1 In-Reply-To: <20181111115441.15015-1-alexander.wetzel@web.de> References: <20181111115441.15015-1-alexander.wetzel@web.de> MIME-Version: 1.0 X-Ovh-Tracer-Id: 1788492003570086336 X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: -100 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrgedtkedrkeejgdefgecutefuodetggdotefrodftvfcurfhrohhfihhlvgemucfqggfjpdevjffgvefmvefgnecuuegrihhlohhuthemucehtddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmd X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181111_115614_974696_24057A75 X-CRM114-Status: GOOD ( 24.37 ) X-Spam-Score: -0.4 (/) X-Spam-Report: SpamAssassin version 3.4.1 on casper.infradead.org summary: Content analysis details: (-0.4 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [46.105.42.102 listed in list.dnswl.org] 0.0 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (alexander.wetzel[at]web.de) 0.2 FREEMAIL_FORGED_FROMDOMAIN 2nd level domains in From and EnvelopeFrom freemail headers are different X-BeenThere: hostap@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Alexander Wetzel Sender: "Hostap" Errors-To: hostap-bounces+incoming=patchwork.ozlabs.org@lists.infradead.org From: Alexander Wetzel Experimental support for Extended Key ID for APs. Tested for basic functionality and backward compatibility but still WIP. Signed-off-by: Alexander Wetzel --- hostapd/config_file.c | 2 + hostapd/hostapd.conf | 9 +++++ src/ap/ap_config.c | 1 + src/ap/ap_config.h | 1 + src/ap/ap_drv_ops.c | 4 +- src/ap/wpa_auth.c | 84 +++++++++++++++++++++++++++++++----------- src/ap/wpa_auth.h | 5 ++- src/ap/wpa_auth_ft.c | 6 +-- src/ap/wpa_auth_glue.c | 13 ++++++- src/ap/wpa_auth_i.h | 2 + src/ap/wpa_auth_ie.c | 7 ++++ 11 files changed, 104 insertions(+), 30 deletions(-) diff --git a/hostapd/config_file.c b/hostapd/config_file.c index b26da71a8..2e164e1d0 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2790,6 +2790,8 @@ static int hostapd_config_fill(struct hostapd_config *conf, bss->wpa_strict_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { bss->wpa_gmk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_ext_key_id") == 0) { + bss->wpa_ext_key_id = atoi(pos); } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { bss->wpa_ptk_rekey = atoi(pos); } else if (os_strcmp(buf, "wpa_group_update_count") == 0) { diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index a00521711..4ae7a4617 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -1342,8 +1342,17 @@ own_ip_addr=127.0.0.1 # (in seconds). #wpa_gmk_rekey=86400 +# Control Extended Key ID support from IEEE802.11-2016. +# 0 = force off +# 1 = use Extended Key ID for PTK keys when supported by driver (Default) +# When supported this will use KeyID 0 and 1 for PTK keys and shift GTK +# keys to 2 and 3. +#wpa_ext_key_id=1 + # Maximum lifetime for PTK in seconds. This can be used to enforce rekeying of # PTK to mitigate some attacks against TKIP deficiencies. +# WARNING: PTK rekeys without also using Extended Key ID is broken in many +# implementations. (Linux versions before 4.20 are known to be problematic.) #wpa_ptk_rekey=600 # The number of times EAPOL-Key Message 1/4 and Message 3/4 in the RSN 4-Way diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index f9b6f2959..f37ec6f1a 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -62,6 +62,7 @@ void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) bss->wpa_group_rekey = 600; bss->wpa_gmk_rekey = 86400; bss->wpa_group_update_count = 4; + bss->wpa_ext_key_id = 1; bss->wpa_pairwise_update_count = 4; bss->wpa_disable_eapol_key_retries = DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 778366d49..61db24a04 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -347,6 +347,7 @@ struct hostapd_bss_config { int wpa_group_rekey_set; int wpa_strict_rekey; int wpa_gmk_rekey; + int wpa_ext_key_id; int wpa_ptk_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index 067cf863e..ff8124cc7 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -658,14 +658,14 @@ int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, enum wpa_alg alg, const u8 *addr, - int key_idx, int set_tx, + int key_idx, int key_flag, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { if (hapd->driver == NULL || hapd->driver->set_key == NULL) return 0; return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, - key_idx, set_tx, seq, seq_len, key, + key_idx, key_flag, seq, seq_len, key, key_len); } diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 34969e79e..9f63bd424 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -133,12 +133,12 @@ static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, - u8 *key, size_t key_len) + u8 *key, size_t key_len, int key_flag) { if (wpa_auth->cb->set_key == NULL) return -1; return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, - key, key_len); + key, key_len, key_flag); } @@ -711,6 +711,9 @@ static void wpa_request_new_ptk(struct wpa_state_machine *sm) if (sm == NULL) return; + if (sm->Ext_Key_ID) + sm->keyidx_active ^= 1; /* flip keyID */ + sm->PTKRequest = TRUE; sm->PTK_valid = 0; } @@ -1637,7 +1640,7 @@ void wpa_remove_ptk(struct wpa_state_machine *sm) sm->PTK_valid = FALSE; os_memset(&sm->PTK, 0, sizeof(sm->PTK)); if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, - 0)) + 0, 0)) wpa_printf(MSG_DEBUG, "RSN: PTK removal from the driver failed"); sm->pairwise_set = FALSE; @@ -2582,7 +2585,7 @@ int fils_set_tk(struct wpa_state_machine *sm) wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver"); if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk, klen)) { + sm->PTK.tk, klen, 0)) { wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); return -1; } @@ -2885,11 +2888,11 @@ static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) SM_STATE(WPA_PTK, PTKINITNEGOTIATING) { - u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32], hdr[2]; size_t gtk_len, kde_len; struct wpa_group *gsm = sm->group; u8 *wpa_ie; - int wpa_ie_len, secure, keyidx, encr = 0; + int wpa_ie_len, secure, gtkidx, encr = 0; SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); sm->TimeoutEvt = FALSE; @@ -2926,6 +2929,19 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, "sending 3/4 msg of 4-Way Handshake"); if (sm->wpa == WPA_VERSION_WPA2) { + if (sm->Ext_Key_ID && sm->TimeoutCtr == 1) { + if (wpa_auth_set_key(sm->wpa_auth, 0, + wpa_cipher_to_alg(sm->pairwise), + sm->addr, + sm->keyidx_active, sm->PTK.tk, + wpa_cipher_key_len(sm->pairwise), + KEY_FLAG_RX_ONLY)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + } + /* WPA2 send GTK in the 4-way handshake */ secure = 1; gtk = gsm->GTK[gsm->GN - 1]; @@ -2940,7 +2956,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) return; gtk = dummy_gtk; } - keyidx = gsm->GN; + gtkidx = gsm->GN; _rsc = rsc; encr = 1; } else { @@ -2948,7 +2964,6 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) secure = 0; gtk = NULL; gtk_len = 0; - keyidx = 0; _rsc = NULL; if (sm->rx_eapol_key_secure) { /* @@ -2967,6 +2982,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) } kde_len = wpa_ie_len + ieee80211w_kde_len(sm); + + if (sm->Ext_Key_ID) + kde_len += 2 + RSN_SELECTOR_LEN + 2; + if (gtk) kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; #ifdef CONFIG_IEEE80211R_AP @@ -3003,10 +3022,15 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos += elen; } #endif /* CONFIG_IEEE80211R_AP */ + hdr[1] = 0; + + if (sm->Ext_Key_ID) { + hdr[0] = sm->keyidx_active & 0x03; + pos = wpa_add_kde(pos, RSN_KEY_DATA_KEYID, hdr, 2, NULL, 0); + } + if (gtk) { - u8 hdr[2]; - hdr[0] = keyidx & 0x03; - hdr[1] = 0; + hdr[0] = gtkidx & 0x03; pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, gtk, gtk_len); } @@ -3073,7 +3097,7 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) WPA_KEY_INFO_MIC : 0) | WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | WPA_KEY_INFO_KEY_TYPE, - _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); + _rsc, sm->ANonce, kde, pos - kde, 0, encr); os_free(kde); } @@ -3085,11 +3109,22 @@ SM_STATE(WPA_PTK, PTKINITDONE) if (sm->Pair) { enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); int klen = wpa_cipher_key_len(sm->pairwise); - if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk, klen)) { - wpa_sta_disconnect(sm->wpa_auth, sm->addr, - WLAN_REASON_PREV_AUTH_NOT_VALID); - return; + if (sm->Ext_Key_ID) { + if (wpa_auth_set_key(sm->wpa_auth, 0, 0, sm->addr, + sm->keyidx_active, NULL, 0, + KEY_FLAG_TX)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + } else { + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, + sm->keyidx_active, sm->PTK.tk, + klen, 0)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } } /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ sm->pairwise_set = TRUE; @@ -3457,8 +3492,13 @@ static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, /* GTK[0..N] = 0 */ os_memset(group->GTK, 0, sizeof(group->GTK)); - group->GN = 1; - group->GM = 2; + if (wpa_auth->conf.wpa_ext_key_id) { + group->GN = 2; + group->GM = 3; + } else { + group->GN = 1; + group->GM = 2; + } #ifdef CONFIG_IEEE80211W group->GN_igtk = 4; group->GM_igtk = 5; @@ -3627,7 +3667,8 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, if (wpa_auth_set_key(wpa_auth, group->vlan_id, wpa_cipher_to_alg(wpa_auth->conf.wpa_group), broadcast_ether_addr, group->GN, - group->GTK[group->GN - 1], group->GTK_len) < 0) + group->GTK[group->GN - 1], group->GTK_len, + KEY_FLAG_DEFAULT_KEY) < 0) ret = -1; #ifdef CONFIG_IEEE80211W @@ -3641,7 +3682,8 @@ static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, if (ret == 0 && wpa_auth_set_key(wpa_auth, group->vlan_id, alg, broadcast_ether_addr, group->GN_igtk, - group->IGTK[group->GN_igtk - 4], len) < 0) + group->IGTK[group->GN_igtk - 4], len, + KEY_FLAG_DEFAULT_KEY) < 0) ret = -1; } #endif /* CONFIG_IEEE80211W */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index fad5536f7..e60a7da57 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -174,6 +174,7 @@ struct wpa_auth_config { int wpa_group_rekey; int wpa_strict_rekey; int wpa_gmk_rekey; + int wpa_ext_key_id; int wpa_ptk_rekey; u32 wpa_group_update_count; u32 wpa_pairwise_update_count; @@ -252,8 +253,8 @@ struct wpa_auth_callbacks { const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr, const u8 *prev_psk, size_t *psk_len); int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); - int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, - const u8 *addr, int idx, u8 *key, size_t key_len); + int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, const u8 *addr, + int idx, u8 *key, size_t key_len, int key_flag); int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, size_t data_len, int encrypt); diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c index e8d46ab0d..f4c220935 100644 --- a/src/ap/wpa_auth_ft.c +++ b/src/ap/wpa_auth_ft.c @@ -2504,12 +2504,12 @@ u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, - u8 *key, size_t key_len) + u8 *key, size_t key_len, int key_flag) { if (wpa_auth->cb->set_key == NULL) return -1; return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, - key, key_len); + key, key_len, key_flag); } @@ -2542,7 +2542,7 @@ void wpa_ft_install_ptk(struct wpa_state_machine *sm) * optimized by adding the STA entry earlier. */ if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, - sm->PTK.tk, klen)) + sm->PTK.tk, klen, 0)) return; /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 812740301..99107d292 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -44,6 +44,7 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->wpa_group_rekey = conf->wpa_group_rekey; wconf->wpa_strict_rekey = conf->wpa_strict_rekey; wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; + wconf->wpa_ext_key_id = conf->wpa_ext_key_id; wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; wconf->wpa_group_update_count = conf->wpa_group_update_count; wconf->wpa_disable_eapol_key_retries = @@ -342,7 +343,7 @@ static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, const u8 *addr, int idx, u8 *key, - size_t key_len) + size_t key_len, int key_flag) { struct hostapd_data *hapd = ctx; const char *ifname = hapd->conf->iface; @@ -384,7 +385,7 @@ static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, hapd->last_gtk_len = key_len; } #endif /* CONFIG_TESTING_OPTIONS */ - return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, + return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, key_flag, NULL, 0, key, key_len); } @@ -1211,6 +1212,14 @@ int hostapd_setup_wpa(struct hostapd_data *hapd) _conf.tx_status = 1; if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) _conf.ap_mlme = 1; + + if (_conf.wpa_ext_key_id && + !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EXTENDED_KEY_ID)) { + wpa_printf(MSG_INFO, "Extended Key ID disabled, not " + "supported by driver."); + _conf.wpa_ext_key_id = 0; + } + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); if (hapd->wpa_auth == NULL) { wpa_printf(MSG_ERROR, "WPA initialization failed."); diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index b1cea1b49..2df37a4e2 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -60,6 +60,8 @@ struct wpa_state_machine { unsigned int pmk_len; u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ struct wpa_ptk PTK; + u8 keyidx_active; + Boolean Ext_Key_ID; Boolean PTK_valid; Boolean pairwise_set; Boolean tk_already_set; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index 253fe6e10..21efdc5f4 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -280,6 +280,8 @@ int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, /* RSN Capabilities */ capab = 0; + if (conf->wpa_ext_key_id) + capab |= WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST; if (conf->rsn_preauth) capab |= WPA_CAPABILITY_PREAUTH; if (conf->wmm_enabled) { @@ -773,6 +775,11 @@ int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, } #endif /* CONFIG_IEEE80211W */ + /* Enable Extended Key ID if possible */ + if (wpa_auth->conf.wpa_ext_key_id && + data.capabilities & WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST) + sm->Ext_Key_ID = TRUE; + #ifdef CONFIG_IEEE80211R_AP if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) {