erpcache: implementation for ERP key cache

This allows IWD to cache ERP keys after a full EAP run. Caching
allows IWD to quickly connect to the network later on using ERP or
FILS.

The cache will contain the EAP Identity, Session ID, EMSK, SSID and
optionally the ERP domain. For the time being, the cache entry
lifetimes are hard coded to 24 hours. Eventually the cache should
be written to disk to allow ERP/FILS to work after a reboot or
IWD restart.
This commit is contained in:
James Prestwood 2019-04-10 10:48:08 -07:00 committed by Denis Kenzior
parent b30b84373d
commit 5df84a6933
3 changed files with 206 additions and 1 deletions

View File

@ -167,7 +167,8 @@ eap_sources = src/eap.c src/eap.h src/eap-private.h \
src/simauth.h src/simauth.c \
src/watchlist.h src/watchlist.c \
src/eap-tls-common.h src/eap-tls-common.c \
src/mschaputil.h src/mschaputil.c
src/mschaputil.h src/mschaputil.c \
src/erpcache.h src/erpcache.c
if DAEMON
libexec_PROGRAMS += src/iwd

166
src/erpcache.c Normal file
View File

@ -0,0 +1,166 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdint.h>
#include <ell/ell.h>
#include "erpcache.h"
#define ERP_DEFAULT_KEY_LIFETIME 86400000000
struct erp_cache_entry {
char *id;
void *emsk;
size_t emsk_len;
void *session_id;
size_t session_len;
char *erp_domain;
char *ssid;
uint64_t expire_time;
};
static struct l_queue *key_cache;
static void destroy_entry(void *data)
{
struct erp_cache_entry *entry = data;
l_free(entry->id);
l_free(entry->emsk);
l_free(entry->session_id);
l_free(entry->ssid);
if (entry->erp_domain)
l_free(entry->erp_domain);
l_free(entry);
}
void erp_add_key(const char *id, const void *session_id,
size_t session_len, const void *emsk, size_t emsk_len,
const char *ssid, const char *erp_domain)
{
struct erp_cache_entry *entry;
if (!unlikely(id || session_id || emsk))
return;
entry = l_new(struct erp_cache_entry, 1);
entry->id = l_strdup(id);
entry->emsk = l_memdup(emsk, emsk_len);
entry->emsk_len = emsk_len;
entry->session_id = l_memdup(session_id, session_len);
entry->session_len = session_len;
entry->ssid = l_strdup(ssid);
entry->expire_time = l_time_offset(l_time_now(),
ERP_DEFAULT_KEY_LIFETIME);
if (erp_domain)
entry->erp_domain = l_strdup(erp_domain);
l_queue_push_head(key_cache, entry);
}
static struct erp_cache_entry *find_keycache(const char *id, const char *ssid)
{
const struct l_queue_entry *entry;
for (entry = l_queue_get_entries(key_cache); entry;
entry = entry->next) {
struct erp_cache_entry *cache = entry->data;
if (l_time_after(l_time_now(), cache->expire_time)) {
l_queue_remove(key_cache, cache);
destroy_entry(cache);
continue;
}
if (id) {
if (strcmp(cache->id, id))
continue;
} else if (ssid) {
if (strcmp(cache->ssid, ssid))
continue;
} else
return NULL;
return cache;
}
return NULL;
}
void erp_remove_key(const char *id)
{
struct erp_cache_entry *entry = find_keycache(id, NULL);
if (!entry)
return;
l_queue_remove(key_cache, entry);
destroy_entry(entry);
}
bool erp_find_key_by_identity(const char *id, void *session,
size_t *session_len, void *emsk, size_t *emsk_len,
const char **erp_domain)
{
struct erp_cache_entry *cache = find_keycache(id, NULL);
if (!cache)
return false;
memcpy(emsk, cache->emsk, cache->emsk_len);
*emsk_len = cache->emsk_len;
memcpy(session, cache->session_id, cache->session_len);
*session_len = cache->session_len;
*erp_domain = cache->erp_domain;
return true;
}
bool erp_has_key_for_ssid(const char *ssid)
{
return find_keycache(NULL, ssid) != NULL;
}
bool erp_has_key_for_identity(const char *id)
{
return find_keycache(id, NULL) != NULL;
}
void erp_init(void)
{
key_cache = l_queue_new();
}
void erp_exit(void)
{
l_queue_destroy(key_cache, destroy_entry);
}

38
src/erpcache.h Normal file
View File

@ -0,0 +1,38 @@
/*
*
* Wireless daemon for Linux
*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
void erp_add_key(const char *id, const void *session_id, size_t session_len,
const void *emsk, size_t emsk_len,
const char *ssid, const char *erp_domain);
void erp_remove_key(const char *id);
bool erp_find_key_by_identity(const char *id, void *session,
size_t *session_len, void *emsk, size_t *emsk_len,
const char **erp_domain);
bool erp_has_key_for_ssid(const char *ssid);
bool erp_has_key_for_identity(const char *id);
void erp_init(void);
void erp_exit(void);