External persistent storage for PMKSA cache entries
This adds new wpa_supplicant control interface commands PMKSA_GET and PMKSA_ADD that can be used to store PMKSA cache entries in an external persistent storage when terminating a wpa_supplicant process and then restore those entries when starting a new process. The previously added PMKSA-CACHE-ADDED/REMOVED events can be used to help in synchronizing the external storage with the memory-only volatile storage within wpa_supplicant. "PMKSA_GET <network_id>" fetches all stored PMKSA cache entries bound to a specific network profile. The network_id of the current profile is available with the STATUS command (id=<network_id). In addition, the network_id is included in the PMKSA-CACHE-ADDED/REMOVED events. The output of the PMKSA_GET command uses the following format: <BSSID> <PMKID> <PMK> <reauth_time in seconds> <expiration in seconds> <akmp> <opportunistic> For example: 02:00:00:00:03:00 113b8b5dc8eda16594e8274df4caa3d4 355e98681d09e0b69d3a342f96998aa765d10c4459ac592459b5efc6b563eff6 30240 43200 1 0 02:00:00:00:04:00 bbdac8607aaaac28e16aacc9152ffe23 e3dd6adc390e685985e5f40e6fe72df846a0acadc59ba15c208d9cb41732a663 30240 43200 1 0 The PMKSA_GET command uses the following format: <network_id> <BSSID> <PMKID> <PMK> <reauth_time in seconds> <expiration in seconds> <akmp> <opportunistic> (i.e., "PMKSA_ADD <network_id> " prefix followed by a line of PMKSA_GET output data; however, the reauth_time and expiration values need to be updated by decrementing them by number of seconds between the PMKSA_GET and PMKSA_ADD commands) For example: PMKSA_ADD 0 02:00:00:00:03:00 113b8b5dc8eda16594e8274df4caa3d4 355e98681d09e0b69d3a342f96998aa765d10c4459ac592459b5efc6b563eff6 30140 43100 1 0 PMKSA_ADD 0 02:00:00:00:04:00 bbdac8607aaaac28e16aacc9152ffe23 e3dd6adc390e685985e5f40e6fe72df846a0acadc59ba15c208d9cb41732a663 30140 43100 1 0 This functionality is disabled be default and can be enabled with CONFIG_PMKSA_CACHE_EXTERNAL=y build configuration option. It should be noted that this allows any process that has access to the wpa_supplicant control interface to use PMKSA_ADD command to fetch keying material (PMK), so this is for environments in which the control interface access is restricted. Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
f0df5afa08
commit
3459381dd2
9 changed files with 222 additions and 8 deletions
|
@ -129,7 +129,7 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|||
const u8 *pmkid, const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, void *network_ctx, int akmp)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *entry, *pos, *prev;
|
||||
struct rsn_pmksa_cache_entry *entry;
|
||||
struct os_reltime now;
|
||||
|
||||
if (pmk_len > PMK_LEN_MAX)
|
||||
|
@ -160,14 +160,25 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|||
os_memcpy(entry->aa, aa, ETH_ALEN);
|
||||
entry->network_ctx = network_ctx;
|
||||
|
||||
return pmksa_cache_add_entry(pmksa, entry);
|
||||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *entry)
|
||||
{
|
||||
struct rsn_pmksa_cache_entry *pos, *prev;
|
||||
|
||||
/* Replace an old entry for the same Authenticator (if found) with the
|
||||
* new entry */
|
||||
pos = pmksa->pmksa;
|
||||
prev = NULL;
|
||||
while (pos) {
|
||||
if (os_memcmp(aa, pos->aa, ETH_ALEN) == 0) {
|
||||
if (pos->pmk_len == pmk_len &&
|
||||
os_memcmp_const(pos->pmk, pmk, pmk_len) == 0 &&
|
||||
if (os_memcmp(entry->aa, pos->aa, ETH_ALEN) == 0) {
|
||||
if (pos->pmk_len == entry->pmk_len &&
|
||||
os_memcmp_const(pos->pmk, entry->pmk,
|
||||
entry->pmk_len) == 0 &&
|
||||
os_memcmp_const(pos->pmkid, entry->pmkid,
|
||||
PMKID_LEN) == 0) {
|
||||
wpa_printf(MSG_DEBUG, "WPA: reusing previous "
|
||||
|
@ -193,8 +204,8 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|||
"the current AP and any PMKSA cache entry "
|
||||
"that was based on the old PMK");
|
||||
if (!pos->opportunistic)
|
||||
pmksa_cache_flush(pmksa, network_ctx, pos->pmk,
|
||||
pos->pmk_len);
|
||||
pmksa_cache_flush(pmksa, entry->network_ctx,
|
||||
pos->pmk, pos->pmk_len);
|
||||
pmksa_cache_free_entry(pmksa, pos, PMKSA_REPLACE);
|
||||
break;
|
||||
}
|
||||
|
@ -245,8 +256,9 @@ pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
|||
}
|
||||
pmksa->pmksa_count++;
|
||||
wpa_printf(MSG_DEBUG, "RSN: Added PMKSA cache entry for " MACSTR
|
||||
" network_ctx=%p", MAC2STR(entry->aa), network_ctx);
|
||||
wpa_sm_add_pmkid(pmksa->sm, network_ctx, entry->aa, entry->pmkid);
|
||||
" network_ctx=%p", MAC2STR(entry->aa), entry->network_ctx);
|
||||
wpa_sm_add_pmkid(pmksa->sm, entry->network_ctx, entry->aa,
|
||||
entry->pmkid);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
@ -514,6 +526,12 @@ int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len)
|
|||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa)
|
||||
{
|
||||
return pmksa->pmksa;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pmksa_cache_init - Initialize PMKSA cache
|
||||
* @free_cb: Callback function to be called when a PMKSA cache entry is freed
|
||||
|
|
|
@ -55,10 +55,14 @@ struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa,
|
|||
const u8 *aa, const u8 *pmkid,
|
||||
const void *network_ctx);
|
||||
int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len);
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_head(struct rsn_pmksa_cache *pmksa);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len,
|
||||
const u8 *pmkid, const u8 *kck, size_t kck_len,
|
||||
const u8 *aa, const u8 *spa, void *network_ctx, int akmp);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
pmksa_cache_add_entry(struct rsn_pmksa_cache *pmksa,
|
||||
struct rsn_pmksa_cache_entry *entry);
|
||||
struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm);
|
||||
void pmksa_cache_clear_current(struct wpa_sm *sm);
|
||||
int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid,
|
||||
|
|
|
@ -3028,6 +3028,20 @@ int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len)
|
|||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm)
|
||||
{
|
||||
return pmksa_cache_head(sm->pmksa);
|
||||
}
|
||||
|
||||
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
|
||||
struct rsn_pmksa_cache_entry * entry)
|
||||
{
|
||||
return pmksa_cache_add_entry(sm->pmksa, entry);
|
||||
}
|
||||
|
||||
|
||||
void wpa_sm_drop_sa(struct wpa_sm *sm)
|
||||
{
|
||||
wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK");
|
||||
|
|
|
@ -149,6 +149,10 @@ int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr,
|
|||
const u8 *buf, size_t len);
|
||||
int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data);
|
||||
int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len);
|
||||
struct rsn_pmksa_cache_entry * wpa_sm_pmksa_cache_head(struct wpa_sm *sm);
|
||||
struct rsn_pmksa_cache_entry *
|
||||
wpa_sm_pmksa_cache_add_entry(struct wpa_sm *sm,
|
||||
struct rsn_pmksa_cache_entry * entry);
|
||||
void wpa_sm_drop_sa(struct wpa_sm *sm);
|
||||
int wpa_sm_has_ptk(struct wpa_sm *sm);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue