[13/14] AP: Support PASN with FT key derivation
diff mbox series

Message ID 20200224091602.15306-14-ilan.peer@intel.com
State Deferred
Headers show
Series
  • Support PASN with SAE, FILS and FT
Related show

Commit Message

Peer, Ilan Feb. 24, 2020, 9:16 a.m. UTC
Note that the implementation is not complete as it is missing
support for the FT wrapped data (which is optional for the
station, but must be supported by the AP in case the station
included it).

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
---
 src/ap/ieee802_11.c  | 56 +++++++++++++++++++++++++++++++++++---------
 src/ap/wpa_auth.h    |  8 +++++++
 src/ap/wpa_auth_ft.c | 14 +++++------
 3 files changed, 60 insertions(+), 18 deletions(-)

Patch
diff mbox series

diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 92bad982a9..2f2971ec05 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -2747,7 +2747,7 @@  static struct wpabuf *pasn_get_wrapped_data(struct hostapd_data *hapd,
 
 static int
 pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
-		 struct rsn_pmksa_cache_entry *pmksa,
+		 const u8 *cached_pmk, size_t cached_pmk_len,
 		 struct wpa_pasn_params_data *pasn_data,
 		 struct wpabuf *wrapped_data,
 		 struct wpabuf *secret)
@@ -2760,7 +2760,7 @@  pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
 	os_memset(pmk, 0, sizeof(pmk));
 	pmk_len = 0;
 
-	if (!pmksa)
+	if (!cached_pmk || !cached_pmk_len)
 		wpa_printf(MSG_DEBUG, "PASN: no valid PMKSA entry");
 
 	if (sta->pasn->akmp == WPA_KEY_MGMT_PASN) {
@@ -2768,11 +2768,11 @@  pasn_derive_keys(struct hostapd_data *hapd, struct sta_info *sta,
 
 		pmk_len = WPA_PASN_PMK_LEN;
 		os_memcpy(pmk, pasn_default_pmk, sizeof(pasn_default_pmk));
-	} else if (pmksa) {
+	} else if (cached_pmk && cached_pmk_len) {
 		wpa_printf(MSG_DEBUG, "PASN: using PMKSA entry");
 
-		pmk_len = pmksa->pmk_len;
-		os_memcpy(pmk, pmksa->pmk, pmksa->pmk_len);
+		pmk_len = cached_pmk_len;
+		os_memcpy(pmk, cached_pmk, cached_pmk_len);
 	} else {
 		switch (sta->pasn->akmp) {
 #ifdef CONFIG_SAE
@@ -2965,6 +2965,12 @@  static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
 	struct wpa_ie_data rsn_data;
 	struct wpa_pasn_params_data pasn_params;
 	struct rsn_pmksa_cache_entry *pmksa = NULL;
+	const u8 *cached_pmk = NULL;
+	size_t cached_pmk_len = 0;
+#ifdef CONFIG_IEEE80211R_AP
+	u8 pmk_r1[PMK_LEN_MAX];
+	size_t pmk_r1_len;
+#endif /* CONFIG_IEEE80211R_AP */
 	struct wpabuf *wrapped_data = NULL, *secret = NULL;
 	int *groups = hapd->conf->pasn_groups;
 	int default_groups[] = { 19, 0 };
@@ -3151,17 +3157,45 @@  static void handle_auth_pasn_1(struct hostapd_data *hapd, struct sta_info *sta,
 	}
 
 	if (rsn_data.num_pmkid) {
-		wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry");
+		if (wpa_key_mgmt_ft(sta->pasn->akmp)) {
+#ifdef CONFIG_IEEE80211R_AP
+			wpa_printf(MSG_DEBUG, "PASN: FT: Fetch PMK R1");
+
+			ret = wpa_ft_fetch_pmk_r1(hapd->wpa_auth, sta->addr,
+						  rsn_data.pmkid,
+						  pmk_r1, &pmk_r1_len,
+						  NULL,
+						  NULL, NULL, NULL,
+						  NULL, NULL, NULL);
+			if (ret) {
+				wpa_printf(MSG_DEBUG,
+					   "PASN: FT: failed getting PMK R1");
+				status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+				goto send_resp;
+			}
+			cached_pmk = pmk_r1;
+			cached_pmk_len = pmk_r1_len;
+#else
+			wpa_printf(MSG_DEBUG, "PASN: FT: not supported");
+			status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+			goto send_resp;
+#endif /* CONFIG_IEEE80211R_AP */
+		} else {
+			wpa_printf(MSG_DEBUG, "PASN: Try to find PMKSA entry");
 
-		pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
-					   rsn_data.pmkid);
+			pmksa = wpa_auth_pmksa_get(hapd->wpa_auth, sta->addr,
+						   rsn_data.pmkid);
+			if (pmksa) {
+				cached_pmk = pmksa->pmk;
+				cached_pmk_len = pmksa->pmk_len;
+			}
+		}
 	} else {
 		wpa_printf(MSG_DEBUG, "PASN: No PMKID specified");
-		pmksa = NULL;
 	}
 
-	ret = pasn_derive_keys(hapd, sta, pmksa, &pasn_params,
-			       wrapped_data, secret);
+	ret = pasn_derive_keys(hapd, sta, cached_pmk, cached_pmk_len,
+			       &pasn_params, wrapped_data, secret);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "PASN: failed to derive keys");
 		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h
index 56abfab141..54f0a75f77 100644
--- a/src/ap/wpa_auth.h
+++ b/src/ap/wpa_auth.h
@@ -442,6 +442,14 @@  void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr,
 void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr);
 void wpa_ft_deinit(struct wpa_authenticator *wpa_auth);
 void wpa_ft_sta_deinit(struct wpa_state_machine *sm);
+int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
+			const u8 *spa, const u8 *pmk_r1_name,
+			u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
+			struct vlan_description *vlan,
+			const u8 **identity, size_t *identity_len,
+			const u8 **radius_cui, size_t *radius_cui_len,
+			int *session_timeout);
+
 #endif /* CONFIG_IEEE80211R_AP */
 
 void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm);
diff --git a/src/ap/wpa_auth_ft.c b/src/ap/wpa_auth_ft.c
index fd654ecd0f..e6d92dd8e5 100644
--- a/src/ap/wpa_auth_ft.c
+++ b/src/ap/wpa_auth_ft.c
@@ -1472,13 +1472,13 @@  static int wpa_ft_store_pmk_r1(struct wpa_authenticator *wpa_auth,
 }
 
 
-static int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
-			       const u8 *spa, const u8 *pmk_r1_name,
-			       u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
-			       struct vlan_description *vlan,
-			       const u8 **identity, size_t *identity_len,
-			       const u8 **radius_cui, size_t *radius_cui_len,
-			       int *session_timeout)
+int wpa_ft_fetch_pmk_r1(struct wpa_authenticator *wpa_auth,
+			const u8 *spa, const u8 *pmk_r1_name,
+			u8 *pmk_r1, size_t *pmk_r1_len, int *pairwise,
+			struct vlan_description *vlan,
+			const u8 **identity, size_t *identity_len,
+			const u8 **radius_cui, size_t *radius_cui_len,
+			int *session_timeout)
 {
 	struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
 	struct wpa_ft_pmk_r1_sa *r1;