diff mbox series

[08/14] WPA: Add PTKSA cache to wpa_supplicant for PASN

Message ID 20200224091529.15259-9-ilan.peer@intel.com
State Deferred
Headers show
Series Support base Pre association Security Negotiation (PASN) | expand

Commit Message

Peer, Ilan Feb. 24, 2020, 9:15 a.m. UTC
PASN requires to store the PTK derived during PASN authentication
so it can later be used for secure LTF etc. This is also true
for a PTK derived during regular connection.

Add an instance of a PTKSA cache for each wpa_supplicant
interface when PASN is enabled in build configuration.

Signed-off-by: Ilan Peer <ilan.peer@intel.com>
---
 src/rsn_supp/wpa.c                |  6 ++++++
 src/rsn_supp/wpa.h                |  2 ++
 src/rsn_supp/wpa_ft.c             |  2 ++
 src/rsn_supp/wpa_i.h              |  8 ++++++++
 wpa_supplicant/Makefile           |  2 ++
 wpa_supplicant/ctrl_iface.c       |  3 +++
 wpa_supplicant/events.c           |  3 +++
 wpa_supplicant/wpa_supplicant.c   |  3 +++
 wpa_supplicant/wpa_supplicant_i.h |  2 ++
 wpa_supplicant/wpas_glue.c        | 29 ++++++++++++++++++++++++++---
 10 files changed, 57 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c
index c9ed784765..0781676bde 100644
--- a/src/rsn_supp/wpa.c
+++ b/src/rsn_supp/wpa.c
@@ -870,6 +870,9 @@  static int wpa_supplicant_install_ptk(struct wpa_sm *sm,
 		return -1;
 	}
 
+	wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
+			 sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
+
 	/* TK is not needed anymore in supplicant */
 	os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN);
 	sm->ptk.tk_len = 0;
@@ -4702,6 +4705,9 @@  int fils_process_assoc_resp(struct wpa_sm *sm, const u8 *resp, size_t len)
 		goto fail;
 	}
 
+	wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
+			 sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
+
 	/* TODO: TK could be cleared after auth frame exchange now that driver
 	 * takes care of association frame encryption/decryption. */
 	/* TK is not needed anymore in supplicant */
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 07e4072dec..30e7fad83c 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -85,6 +85,8 @@  struct wpa_sm_ctx {
 	void (*fils_hlp_rx)(void *ctx, const u8 *dst, const u8 *src,
 			    const u8 *pkt, size_t pkt_len);
 	int (*channel_info)(void *ctx, struct wpa_channel_info *ci);
+	void (*store_ptk)(void *ctx, u8 *addr, int cipher,
+			  u32 life_time, struct wpa_ptk *ptk);
 };
 
 
diff --git a/src/rsn_supp/wpa_ft.c b/src/rsn_supp/wpa_ft.c
index 42b85147df..027a24ffcd 100644
--- a/src/rsn_supp/wpa_ft.c
+++ b/src/rsn_supp/wpa_ft.c
@@ -430,6 +430,8 @@  static int wpa_ft_install_ptk(struct wpa_sm *sm, const u8 *bssid)
 		return -1;
 	}
 
+	wpa_sm_store_ptk(sm, sm->bssid, sm->pairwise_cipher,
+			 sm->dot11RSNAConfigPMKLifetime, &sm->ptk);
 	return 0;
 }
 
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index f06dbd6ba4..b9164fa111 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -428,6 +428,14 @@  static inline int wpa_sm_channel_info(struct wpa_sm *sm,
 	return sm->ctx->channel_info(sm->ctx->ctx, ci);
 }
 
+static inline void wpa_sm_store_ptk(struct wpa_sm *sm,
+				    u8 *addr, int cipher,
+				    u32 life_time, struct wpa_ptk *ptk)
+{
+	if (sm->ctx->store_ptk)
+		sm->ctx->store_ptk(sm->ctx->ctx, addr, cipher, life_time,
+				   ptk);
+}
 
 int wpa_eapol_key_send(struct wpa_sm *sm, struct wpa_ptk *ptk,
 		       int ver, const u8 *dest, u16 proto,
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index d40804d528..30c31bd18f 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -392,6 +392,8 @@  NEED_HMAC_SHA256_KDF=y
 NEED_HMAC_SHA384_KDF=y
 NEED_SHA256=y
 NEED_SHA384=y
+OBJS += ../src/common/ptksa_cache.o
+CFLAGS += -DCONFIG_PTKSA_CACHE
 endif
 
 ifdef CONFIG_WIFI_DISPLAY
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 10c0961297..b9a0d206e9 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -56,6 +56,7 @@ 
 #include "mesh.h"
 #include "dpp_supplicant.h"
 #include "sme.h"
+#include "common/ptksa_cache.h"
 
 #ifdef __NetBSD__
 #include <net/if_ether.h>
@@ -8130,6 +8131,7 @@  static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s)
 	wpa_s->conf->auto_interworking = 0;
 	wpa_s->conf->okc = 0;
 
+	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 	rsn_preauth_deinit(wpa_s->wpa);
 
@@ -9783,6 +9785,7 @@  static int wpas_ctrl_iface_pmksa(struct wpa_supplicant *wpa_s,
 
 static void wpas_ctrl_iface_pmksa_flush(struct wpa_supplicant *wpa_s)
 {
+	ptksa_cache_flush(wpa_s->ptksa, NULL, WPA_CIPHER_NONE);
 	wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL);
 #ifdef CONFIG_AP
 	wpas_ap_pmksa_cache_flush(wpa_s);
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 2851ffc810..5b09ec54e4 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -49,6 +49,7 @@ 
 #include "mesh_mpm.h"
 #include "wmm_ac.h"
 #include "dpp_supplicant.h"
+#include "common/ptksa_cache.h"
 
 
 #define MAX_OWE_TRANSITION_BSS_SELECT_COUNT 5
@@ -3289,6 +3290,8 @@  static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s,
 	if (wpa_s->wpa_state >= WPA_AUTHENTICATING)
 		wpas_connection_failed(wpa_s, bssid);
 	wpa_sm_notify_disassoc(wpa_s->wpa);
+	ptksa_cache_flush(wpa_s->ptksa, wpa_s->bssid, WPA_CIPHER_NONE);
+
 	if (locally_generated)
 		wpa_s->disconnect_reason = -reason_code;
 	else
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 634fb290e0..d357633e63 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -63,6 +63,7 @@ 
 #include "wpas_kay.h"
 #include "mesh.h"
 #include "dpp_supplicant.h"
+#include "common/ptksa_cache.h"
 #ifdef CONFIG_MESH
 #include "ap/ap_config.h"
 #include "ap/hostapd.h"
@@ -565,6 +566,8 @@  static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
 
 	wmm_ac_clear_saved_tspecs(wpa_s);
 	pmksa_candidate_free(wpa_s->wpa);
+	ptksa_cache_deinit(wpa_s->ptksa);
+	wpa_s->ptksa = NULL;
 	wpa_sm_deinit(wpa_s->wpa);
 	wpa_s->wpa = NULL;
 	wpa_blacklist_clear(wpa_s);
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index de2e6350b8..f4ffba2934 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -615,6 +615,8 @@  struct wpa_supplicant {
 	int interface_removed; /* whether the network interface has been
 				* removed */
 	struct wpa_sm *wpa;
+	struct ptksa_cache *ptksa;
+
 	struct eapol_sm *eapol;
 
 	struct ctrl_iface_priv *ctrl_iface;
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 29257b9873..eee365748b 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -28,7 +28,7 @@ 
 #include "scan.h"
 #include "notify.h"
 #include "wpas_kay.h"
-
+#include "common/ptksa_cache.h"
 
 #ifndef CONFIG_NO_CONFIG_BLOBS
 #if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA)
@@ -1225,6 +1225,15 @@  static int wpa_supplicant_channel_info(void *_wpa_s,
 	return wpa_drv_channel_info(wpa_s, ci);
 }
 
+
+static void wpa_supplicant_store_ptk(void *ctx, u8 *addr, int cipher,
+				     u32 life_time, struct wpa_ptk *ptk)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	ptksa_cache_add(wpa_s->ptksa, addr, cipher, life_time, ptk);
+}
+
 #endif /* CONFIG_NO_WPA */
 
 
@@ -1232,9 +1241,20 @@  int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
 {
 #ifndef CONFIG_NO_WPA
 	struct wpa_sm_ctx *ctx;
+
+	wpa_s->ptksa = ptksa_cache_init();
+	if (!wpa_s->ptksa) {
+		wpa_printf(MSG_ERROR, "Failed to allocate PTKSA");
+		return -1;
+	}
+
 	ctx = os_zalloc(sizeof(*ctx));
 	if (ctx == NULL) {
 		wpa_printf(MSG_ERROR, "Failed to allocate WPA context.");
+
+		ptksa_cache_deinit(wpa_s->ptksa);
+		wpa_s->ptksa = NULL;
+
 		return -1;
 	}
 
@@ -1277,12 +1297,15 @@  int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
 	ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk;
 	ctx->fils_hlp_rx = wpa_supplicant_fils_hlp_rx;
 	ctx->channel_info = wpa_supplicant_channel_info;
+	ctx->store_ptk = wpa_supplicant_store_ptk;
 
 	wpa_s->wpa = wpa_sm_init(ctx);
 	if (wpa_s->wpa == NULL) {
-		wpa_printf(MSG_ERROR, "Failed to initialize WPA state "
-			   "machine");
+		wpa_printf(MSG_ERROR,
+			   "Failed to initialize WPA state machine");
 		os_free(ctx);
+		ptksa_cache_deinit(wpa_s->ptksa);
+		wpa_s->ptksa = NULL;
 		return -1;
 	}
 #endif /* CONFIG_NO_WPA */