@@ -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 */
@@ -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);
};
@@ -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;
}
@@ -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,
@@ -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
@@ -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);
@@ -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
@@ -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);
@@ -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;
@@ -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 */
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(-)