[PATCH v2 19/20] AP: Add support for PASN processing to the SME
Ilan Peer
ilan.peer at intel.com
Wed Dec 16 06:00:32 EST 2020
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/ap/ieee802_11.c | 517 +++++++++++++++++++++++++++++++++++++++++++-
src/ap/sta_info.c | 20 ++
src/ap/sta_info.h | 20 ++
3 files changed, 556 insertions(+), 1 deletion(-)
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 114d1f5741..a1f6aa931e 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2296,6 +2296,496 @@ ieee802_11_set_radius_info(struct hostapd_data *hapd, struct sta_info *sta,
}
+#ifdef CONFIG_PASN
+
+static struct wpabuf *pasn_get_wrapped_data(struct hostapd_data *hapd,
+ struct sta_info *sta)
+{
+ switch (sta->pasn->akmp) {
+ case WPA_KEY_MGMT_PASN:
+ /* no wrapped data */
+ return NULL;
+ case WPA_KEY_MGMT_SAE:
+ case WPA_KEY_MGMT_FILS_SHA256:
+ case WPA_KEY_MGMT_FILS_SHA384:
+ case WPA_KEY_MGMT_FT_PSK:
+ case WPA_KEY_MGMT_FT_IEEE8021X:
+ case WPA_KEY_MGMT_FT_IEEE8021X_SHA384:
+ default:
+ wpa_printf(MSG_ERROR,
+ "PASN: TODO: Wrapped data for akmp=0x%x",
+ sta->pasn->akmp);
+ return NULL;
+ }
+}
+
+
+static int
+pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
+ struct rsn_pmksa_cache_entry *pmksa,
+ struct wpa_pasn_params_data *pasn_data,
+ struct wpabuf *wrapped_data,
+ struct wpabuf *secret)
+{
+ static const u8 pasn_default_pmk[] = {'P', 'M', 'K', 'z'};
+ u8 pmk[PMK_LEN_MAX];
+ u8 pmk_len;
+ int ret;
+
+ os_memset(pmk, 0, sizeof(pmk));
+ pmk_len = 0;
+
+ if (!pmksa)
+ wpa_printf(MSG_DEBUG, "PASN: no valid PMKSA entry");
+
+ if (sta->pasn->akmp == WPA_KEY_MGMT_PASN) {
+ wpa_printf(MSG_DEBUG, "PASN: using default PMK");
+
+ pmk_len = WPA_PASN_PMK_LEN;
+ os_memcpy(pmk, pasn_default_pmk, sizeof(pasn_default_pmk));
+ } else if (pmksa) {
+ wpa_printf(MSG_DEBUG, "PASN: using PMKSA entry");
+
+ pmk_len = pmksa->pmk_len;
+ os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len);
+ } else {
+ /* TODO: derive PMK based on wrapped data */
+ wpa_printf(MSG_DEBUG,
+ "PASN: missing implementation to derive PMK");
+
+ return -1;
+ }
+
+ ret = pasn_pmk_to_ptk(pmk, pmk_len,
+ sta->addr, hapd->own_addr,
+ wpabuf_head(secret), wpabuf_len(secret),
+ &sta->pasn->ptk, sta->pasn->akmp,
+ sta->pasn->cipher,
+ WPA_KDK_MAX_LEN);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed to derive PTK");
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "PASN: PTK successfully derived");
+ return 0;
+}
+
+
+static int handle_auth_pasn_resp(struct hostapd_data *hapd,
+ struct sta_info *sta,
+ struct rsn_pmksa_cache_entry *pmksa,
+ u16 status)
+{
+ struct wpabuf *buf, *pubkey = NULL, *wrapped_data_buf = NULL;
+ u8 mic[WPA_PASN_MAX_MIC_LEN];
+ u8 mic_len, data_len;
+ u8 *ptr;
+ const u8 *data, *rsn_ie;
+ size_t rsn_ie_len;
+ int ret;
+
+ wpa_printf(MSG_DEBUG, "PASN: building frame 2: status=%u", status);
+
+ buf = wpabuf_alloc(1500);
+ if (!buf)
+ goto fail;
+
+ wpa_pasn_build_auth_header(buf, hapd->own_addr, hapd->own_addr,
+ sta->addr, 2, status);
+
+ if (status != WLAN_STATUS_SUCCESS)
+ goto done;
+
+ wpa_pasn_add_rsne(buf, pmksa ? pmksa->pmkid : NULL,
+ sta->pasn->akmp, sta->pasn->cipher);
+
+ /* No need to derive PMK if PMKSA is given */
+ if (!pmksa)
+ wrapped_data_buf = pasn_get_wrapped_data(hapd, sta);
+ else
+ sta->pasn->wrapped_data_format = WPA_PASN_NO_WRAPPED_DATA;
+
+ /* Get public key */
+ pubkey = crypto_ecdh_get_pubkey(sta->pasn->ecdh, 0);
+ pubkey = wpabuf_zeropad(pubkey,
+ crypto_ecdh_prime_len(sta->pasn->ecdh));
+ if (!pubkey) {
+ wpa_printf(MSG_DEBUG, "PASN: failed to get pubkey");
+ goto fail;
+ }
+
+ wpa_pasn_add_parameter_ie(buf, sta->pasn->group,
+ sta->pasn->wrapped_data_format,
+ pubkey, NULL, 0);
+
+ wpa_pasn_add_wrapped_data(buf, wrapped_data_buf);
+
+ wpabuf_free(wrapped_data_buf);
+ wrapped_data_buf = NULL;
+ wpabuf_free(pubkey);
+ pubkey = NULL;
+
+ /* Add the mic */
+ mic_len = pasn_mic_len(sta->pasn->akmp, sta->pasn->cipher);
+ wpabuf_put_u8(buf, WLAN_EID_MIC);
+ wpabuf_put_u8(buf, mic_len);
+ ptr = wpabuf_put(buf, mic_len);
+
+ os_memset(ptr, 0, mic_len);
+
+ data = wpabuf_head(buf) + IEEE80211_HDRLEN;
+ data_len = wpabuf_len(buf) - IEEE80211_HDRLEN;
+
+ rsn_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &rsn_ie_len);
+ if (!rsn_ie || !rsn_ie_len)
+ goto fail;
+
+ /*
+ * Note: the wpa_auth_get_wpa_ie() might return not only the RSN IE but
+ * also the MD IE etc. Thus, do not use the returned length but instead
+ * use the length specified in the IE header.
+ */
+ ret = pasn_mic(sta->pasn->ptk.kck, sta->pasn->akmp, sta->pasn->cipher,
+ hapd->own_addr, sta->addr,
+ rsn_ie, rsn_ie[1] + 2,
+ data, data_len,
+ mic);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: frame 3: Failed mic calculation");
+ goto fail;
+ }
+
+ os_memcpy(ptr, mic, mic_len);
+
+done:
+ wpa_printf(MSG_DEBUG, "PASN: building frame 2: success");
+
+ wpa_printf(MSG_DEBUG, "PANS: resp: STA=" MACSTR, MAC2STR(sta->addr));
+
+ ret = hostapd_drv_send_mlme(hapd, wpabuf_head(buf), wpabuf_len(buf), 0,
+ NULL, 0, 0);
+ if (ret)
+ wpa_printf(MSG_INFO, "send_auth_reply: send failed");
+
+ wpabuf_free(buf);
+ return ret;
+fail:
+ wpabuf_free(wrapped_data_buf);
+ wpabuf_free(pubkey);
+ wpabuf_free(buf);
+ return -1;
+}
+
+
+static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
+ const struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct ieee802_11_elems elems;
+ struct wpa_ie_data rsn_data;
+ struct wpa_pasn_params_data pasn_params;
+ struct rsn_pmksa_cache_entry *pmksa;
+ struct wpabuf *wrapped_data = NULL, *secret = NULL;
+ int *groups = hapd->conf->pasn_groups;
+ int default_groups[] = { 19, 0 };
+ u16 status = WLAN_STATUS_SUCCESS;
+ int ret;
+ u32 i;
+
+ if (!groups)
+ groups = default_groups;
+
+ if (ieee802_11_parse_elems(mgmt->u.auth.variable,
+ len - offsetof(struct ieee80211_mgmt,
+ u.auth.variable),
+ &elems, 0) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failed parsing authentication frame");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
+ ret = wpa_parse_wpa_ie_rsn(elems.rsn_ie - 2, elems.rsn_ie_len + 2,
+ &rsn_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed parsing RNSE");
+ status = WLAN_STATUS_INVALID_RSNIE;
+ goto send_resp;
+ }
+
+ ret = wpa_pasn_validate_rsne(&rsn_data);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed validating RSNE");
+ status = WLAN_STATUS_INVALID_RSNIE;
+ goto send_resp;
+ }
+
+ if (!(rsn_data.key_mgmt & hapd->conf->wpa_key_mgmt) ||
+ !(rsn_data.pairwise_cipher & hapd->conf->rsn_pairwise)) {
+ wpa_printf(MSG_DEBUG, "PASN: mismatch in akmp/cipher");
+ status = WLAN_STATUS_INVALID_RSNIE;
+ goto send_resp;
+ }
+
+ sta->pasn->akmp = rsn_data.key_mgmt;
+ sta->pasn->cipher = rsn_data.pairwise_cipher;
+
+ if (!elems.pasn_params || !elems.pasn_params_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: No PASN parameters element found");
+ status = WLAN_STATUS_INVALID_PARAMETERS;
+ goto send_resp;
+ }
+
+ ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
+ elems.pasn_params_len + 3,
+ &pasn_params);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failed validation pasn parameters IE");
+ status = WLAN_STATUS_INVALID_PARAMETERS;
+ goto send_resp;
+ }
+
+ for (i = 0; groups[i] > 0 && groups[i] != pasn_params.group; i++)
+ ;
+
+ if (!pasn_params.group || groups[i] != pasn_params.group) {
+ wpa_printf(MSG_DEBUG, "PASN: requested group=%hu not allowed",
+ pasn_params.group);
+ status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED;
+ goto send_resp;
+ }
+
+ if (!pasn_params.pubkey || !pasn_params.pubkey_len) {
+ wpa_printf(MSG_DEBUG, "PASN: Invalid public key");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
+ sta->pasn->ecdh = crypto_ecdh_init(pasn_params.group);
+ if (!sta->pasn->ecdh) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed init ECDH");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
+ sta->pasn->group = pasn_params.group;
+
+ secret = crypto_ecdh_set_peerkey(sta->pasn->ecdh, 0,
+ pasn_params.pubkey,
+ pasn_params.pubkey_len);
+ if (!secret) {
+ wpa_printf(MSG_DEBUG, "PASN: Failed to derive secret");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
+ if (pasn_params.wrapped_data_format != WPA_PASN_NO_WRAPPED_DATA) {
+ wrapped_data = ieee802_11_defrag(&elems,
+ WLAN_EID_EXTENSION,
+ WLAN_EID_EXT_WRAPPED_DATA);
+
+ if (!wrapped_data) {
+ wpa_printf(MSG_DEBUG, "PASN: missing wrapped data");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+ }
+
+ sta->pasn->wrapped_data_format = pasn_params.wrapped_data_format;
+
+ if (rsn_data.num_pmkid) {
+ wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry");
+
+ pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
+ rsn_data.pmkid);
+ } else {
+ wpa_printf(MSG_DEBUG, "PASN: No PMKID specified");
+ pmksa = NULL;
+ }
+
+ ret = pasn_derive_keys(hapd, sta, pmksa, &pasn_params,
+ wrapped_data, secret);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed to derive keys");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ goto send_resp;
+ }
+
+ ret = pasn_auth_frame_hash(sta->pasn->akmp, sta->pasn->cipher,
+ ((u8 *)mgmt) + IEEE80211_HDRLEN,
+ len - IEEE80211_HDRLEN,
+ sta->pasn->hash);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed to compute hash");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ }
+
+send_resp:
+ ret = handle_auth_pasn_resp(hapd, sta, pmksa, status);
+ if (ret) {
+ wpa_printf(MSG_DEBUG, "PASN: failed to send response");
+ status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "PASN: success handling transaction == 1");
+ }
+
+ wpabuf_free(secret);
+ wpabuf_free(wrapped_data);
+
+ if (status != WLAN_STATUS_SUCCESS)
+ ap_free_sta(hapd, sta);
+}
+
+
+static void handle_auth_pasn_3(struct hostapd_data *hapd, struct sta_info *sta,
+ const struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct ieee802_11_elems elems;
+ struct wpa_pasn_params_data pasn_params;
+ struct wpabuf *wrapped_data = NULL;
+ u8 mic[WPA_PASN_MAX_MIC_LEN], out_mic[WPA_PASN_MAX_MIC_LEN];
+ u8 mic_len;
+ int ret;
+
+ if (ieee802_11_parse_elems(mgmt->u.auth.variable,
+ len - offsetof(struct ieee80211_mgmt,
+ u.auth.variable),
+ &elems, 0) == ParseFailed) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failed parsing authentication frame");
+ goto fail;
+ }
+
+ /* check that the MIC IE exists. Save it and zero out the memory */
+ mic_len = pasn_mic_len(sta->pasn->akmp, sta->pasn->cipher);
+ if (!elems.mic || elems.mic_len != mic_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: invalid mic. Expecting len=%u", mic_len);
+ goto fail;
+ } else {
+ os_memcpy(mic, elems.mic, mic_len);
+ os_memset((u8 *)elems.mic, 0, mic_len);
+ }
+
+ if (!elems.pasn_params || !elems.pasn_params_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: No PASN parameters element found");
+ goto fail;
+ }
+
+ ret = wpa_pasn_parse_parameter_ie(elems.pasn_params - 3,
+ elems.pasn_params_len + 3,
+ &pasn_params);
+ if (ret) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failed validation pasn parameters IE");
+ goto fail;
+ }
+
+ if (pasn_params.pubkey || pasn_params.pubkey_len) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: Public key should not be included");
+ goto fail;
+ }
+
+ /* verify the MIC */
+ ret = pasn_mic(sta->pasn->ptk.kck, sta->pasn->akmp, sta->pasn->cipher,
+ sta->addr, hapd->own_addr,
+ sta->pasn->hash, mic_len * 2,
+ (u8 *)&mgmt->u.auth,
+ len - offsetof(struct ieee80211_mgmt, u.auth),
+ out_mic);
+
+ wpa_hexdump_key(MSG_DEBUG, "PASN: frame MIC: ", mic, mic_len);
+ if (ret || os_memcmp(mic, out_mic, mic_len)) {
+ wpa_printf(MSG_DEBUG, "PASN: failed MIC verification");
+ goto fail;
+ }
+
+ if (pasn_params.wrapped_data_format != WPA_PASN_NO_WRAPPED_DATA) {
+ wrapped_data = ieee802_11_defrag(&elems,
+ WLAN_EID_EXTENSION,
+ WLAN_EID_EXT_WRAPPED_DATA);
+
+ if (!wrapped_data) {
+ wpa_printf(MSG_DEBUG, "PASN: missing wrapped data");
+ goto fail;
+ }
+
+ /* TODO: handle wrapped data */
+ wpabuf_free(wrapped_data);
+ }
+
+ wpa_printf(MSG_INFO,
+ "PASN: success handling transaction == 3. Store PTK");
+
+ ptksa_cache_add(hapd->ptksa, sta->addr, sta->pasn->cipher, 43200,
+ &sta->pasn->ptk);
+fail:
+ ap_free_sta(hapd, sta);
+}
+
+
+static void handle_auth_pasn(struct hostapd_data *hapd, struct sta_info *sta,
+ const struct ieee80211_mgmt *mgmt, size_t len,
+ u16 trans_seq, u16 status)
+{
+ if (hapd->conf->wpa != WPA_PROTO_RSN) {
+ wpa_printf(MSG_INFO, "PASN: RSN is not configured");
+ return;
+ }
+
+ wpa_printf(MSG_INFO, "PASN authentication: sta=" MACSTR,
+ MAC2STR(sta->addr));
+
+ if (trans_seq == 1) {
+ if (sta->pasn) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: not expecting transaction == 1");
+ return;
+ }
+
+ if (status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failure status in transaction == 1");
+ return;
+ }
+
+ sta->pasn = os_zalloc(sizeof(*sta->pasn));
+ if (!sta->pasn) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failed to allocate pasn context");
+ return;
+ }
+
+ handle_auth_pasn_1(hapd, sta, mgmt, len);
+ } else if (trans_seq == 3) {
+ if (!sta->pasn) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: not expecting transaction == 3");
+ return;
+ }
+
+ if (status != WLAN_STATUS_SUCCESS) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: failure status in transaction == 3");
+ ap_free_sta_pasn(hapd, sta);
+ return;
+ }
+
+ handle_auth_pasn_3(hapd, sta, mgmt, len);
+ } else {
+ wpa_printf(MSG_DEBUG,
+ "PASN: invalid transaction. ignore");
+ }
+}
+
+#endif /* CONFIG_PASN */
+
+
static void handle_auth(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len,
int rssi, int from_queue)
@@ -2382,6 +2872,11 @@ static void handle_auth(struct hostapd_data *hapd,
hapd->conf->fils_dh_group &&
auth_alg == WLAN_AUTH_FILS_SK_PFS) ||
#endif /* CONFIG_FILS */
+#ifdef CONFIG_PASN
+ (hapd->conf->wpa &&
+ (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PASN) &&
+ auth_alg == WLAN_AUTH_PASN) ||
+#endif /* CONFIG_PASN*/
((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) &&
auth_alg == WLAN_AUTH_SHARED_KEY))) {
wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)",
@@ -2391,6 +2886,9 @@ static void handle_auth(struct hostapd_data *hapd,
}
if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE ||
+#ifdef CONFIG_PASN
+ (auth_alg == WLAN_AUTH_PASN && auth_transaction == 3) ||
+#endif /* CONFIG_PASN*/
(auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) {
wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)",
auth_transaction);
@@ -2512,6 +3010,14 @@ static void handle_auth(struct hostapd_data *hapd,
return;
}
#endif /* CONFIG_MESH */
+#ifdef CONFIG_PASN
+ if (auth_alg == WLAN_AUTH_PASN && sta->flags & WLAN_STA_ASSOC) {
+ wpa_printf(MSG_DEBUG,
+ "PASN: auth: existing station: " MACSTR,
+ MAC2STR(sta->addr));
+ return;
+ }
+#endif /* CONFIG_PASN */
} else {
#ifdef CONFIG_MESH
if (hapd->conf->mesh & MESH_ENABLED) {
@@ -2572,11 +3078,14 @@ static void handle_auth(struct hostapd_data *hapd,
* to allow the original connection work until the attempt can complete
* (re)association, so that unprotected Authentication frame cannot be
* used to bypass PMF protection.
+ *
+ * PASN authentication does not require adding/removing station to the
+ * driver so skip this flow in case of PASN authentication.
*/
if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) &&
(!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) &&
!(hapd->conf->mesh & MESH_ENABLED) &&
- !(sta->added_unassoc)) {
+ !(sta->added_unassoc) && auth_alg != WLAN_AUTH_PASN) {
if (ap_sta_re_add(hapd, sta) < 0) {
resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA;
goto fail;
@@ -2663,6 +3172,12 @@ static void handle_auth(struct hostapd_data *hapd,
handle_auth_fils_finish);
return;
#endif /* CONFIG_FILS */
+#ifdef CONFIG_PASN
+ case WLAN_AUTH_PASN:
+ handle_auth_pasn(hapd, sta, mgmt, len, auth_transaction,
+ status_code);
+ return;
+#endif /* CONFIG_PASN */
}
fail:
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index 67b5e9885b..b28a2415bc 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -155,6 +155,22 @@ void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta)
sta_ip6addr_del(hapd, sta);
}
+#ifdef CONFIG_PASN
+
+void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta)
+{
+ wpa_printf(MSG_DEBUG, "PASN: Free PASN context: " MACSTR,
+ MAC2STR(sta->addr));
+
+ if (sta->pasn) {
+ if (sta->pasn->ecdh)
+ crypto_ecdh_deinit(sta->pasn->ecdh);
+ os_free(sta->pasn);
+ sta->pasn = NULL;
+ }
+}
+
+#endif /* CONFIG_PASN */
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
{
@@ -371,6 +387,10 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta);
#endif /* CONFIG_WNM_AP */
+#ifdef CONFIG_PASN
+ ap_free_sta_pasn(hapd, sta);
+#endif /* CONFIG_PASN */
+
os_free(sta->ifname_wds);
#ifdef CONFIG_TESTING_OPTIONS
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index ef485618a3..d77d52da10 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -14,6 +14,7 @@
#include "vlan.h"
#include "common/wpa_common.h"
#include "common/ieee802_11_defs.h"
+#include "crypto/sha384.h"
/* STA flags */
#define WLAN_STA_AUTH BIT(0)
@@ -63,6 +64,19 @@ struct pending_eapol_rx {
struct os_reltime rx_time;
};
+struct pasn_data {
+ int akmp;
+ int cipher;
+ u16 group;
+ u8 trans_seq;
+ u8 status;
+ u8 wrapped_data_format;
+
+ u8 hash[SHA384_MAC_LEN];
+ struct wpa_ptk ptk;
+ struct crypto_ecdh *ecdh;
+};
+
struct sta_info {
struct sta_info *next; /* next entry in sta list */
struct sta_info *hnext; /* next entry in hash table list */
@@ -286,6 +300,10 @@ struct sta_info {
unsigned int airtime_weight;
struct os_reltime backlogged_until;
#endif /* CONFIG_AIRTIME_POLICY */
+
+#ifdef CONFIG_PASN
+ struct pasn_data *pasn;
+#endif /* CONFIG_PASN */
};
@@ -363,4 +381,6 @@ int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd,
struct sta_info *sta);
int ap_sta_re_add(struct hostapd_data *hapd, struct sta_info *sta);
+void ap_free_sta_pasn(struct hostapd_data *hapd, struct sta_info *sta);
+
#endif /* STA_INFO_H */
--
2.17.1
More information about the Hostap
mailing list