mirror of
https://git.kernel.org/pub/scm/network/wireless/iwd.git
synced 2024-11-26 10:39:23 +01:00
simauth: new module to handle EAP-SIM/AKA auth
This is the core module that takes care of registering authentication drivers. EAP-SIM/AKA will be able to acquire a driver that supports the required algorithms. The driver implementation (hardcoded/ofono etc.) is isolated into separate plugin modules.
This commit is contained in:
parent
1d119d58c1
commit
46c1e8fa60
185
src/simauth.c
Normal file
185
src/simauth.c
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Wireless daemon for Linux
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ell/ell.h>
|
||||||
|
|
||||||
|
#include "watchlist.h"
|
||||||
|
#include "simauth.h"
|
||||||
|
|
||||||
|
static struct l_queue *auth_providers;
|
||||||
|
|
||||||
|
struct iwd_sim_auth {
|
||||||
|
const struct iwd_sim_auth_driver *driver;
|
||||||
|
void *driver_data;
|
||||||
|
bool aka_supported : 1;
|
||||||
|
bool sim_supported : 1;
|
||||||
|
char *nai;
|
||||||
|
int pending;
|
||||||
|
struct watchlist destory_watches;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iwd_sim_auth *iwd_sim_auth_create(bool sim_supported, bool aka_supported,
|
||||||
|
char *nai, const struct iwd_sim_auth_driver *driver,
|
||||||
|
void *driver_data)
|
||||||
|
{
|
||||||
|
struct iwd_sim_auth *auth = l_new(struct iwd_sim_auth, 1);
|
||||||
|
|
||||||
|
if (!auth)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
auth->aka_supported = aka_supported;
|
||||||
|
auth->sim_supported = sim_supported;
|
||||||
|
auth->nai = l_strdup(nai);
|
||||||
|
auth->driver = driver;
|
||||||
|
auth->driver_data = driver_data;
|
||||||
|
watchlist_init(&auth->destory_watches, NULL);
|
||||||
|
|
||||||
|
l_queue_push_head(auth_providers, auth);
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *iwd_sim_auth_get_data(struct iwd_sim_auth *auth)
|
||||||
|
{
|
||||||
|
return auth->driver_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void destroy_provider(void *data)
|
||||||
|
{
|
||||||
|
struct iwd_sim_auth *auth = data;
|
||||||
|
|
||||||
|
if (auth->driver->cancel_request)
|
||||||
|
auth->driver->cancel_request(auth, auth->pending);
|
||||||
|
|
||||||
|
WATCHLIST_NOTIFY_NO_ARGS(&auth->destory_watches,
|
||||||
|
sim_auth_destroyed_cb_t);
|
||||||
|
|
||||||
|
if (auth->driver->remove)
|
||||||
|
auth->driver->remove(auth);
|
||||||
|
|
||||||
|
l_free(auth->nai);
|
||||||
|
l_free(auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
int iwd_sim_auth_remove(struct iwd_sim_auth *auth)
|
||||||
|
{
|
||||||
|
bool r;
|
||||||
|
|
||||||
|
r = l_queue_remove(auth_providers, auth);
|
||||||
|
if (!r)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
destroy_provider(auth);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *iwd_sim_auth_get_nai(struct iwd_sim_auth *auth)
|
||||||
|
{
|
||||||
|
return auth->nai;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct iwd_sim_auth *iwd_sim_auth_find(bool sim, bool aka)
|
||||||
|
{
|
||||||
|
struct iwd_sim_auth *auth;
|
||||||
|
const struct l_queue_entry *entry;
|
||||||
|
|
||||||
|
for (entry = l_queue_get_entries(auth_providers); entry;
|
||||||
|
entry = entry->next) {
|
||||||
|
auth = entry->data;
|
||||||
|
|
||||||
|
if (sim && !auth->sim_supported)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (aka && !auth->aka_supported)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return auth;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int sim_auth_destroyed_watch_add(struct iwd_sim_auth *auth,
|
||||||
|
sim_auth_destroyed_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
return watchlist_add(&auth->destory_watches, cb, data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sim_auth_destroyed_watch_remove(struct iwd_sim_auth *auth,
|
||||||
|
unsigned int id)
|
||||||
|
{
|
||||||
|
watchlist_remove(&auth->destory_watches, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sim_auth_check_milenage(struct iwd_sim_auth *auth,
|
||||||
|
const uint8_t *rand, const uint8_t *autn,
|
||||||
|
sim_auth_check_milenage_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
if (!auth->aka_supported)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* save ID in case simauth is destroyed */
|
||||||
|
auth->pending = auth->driver->check_milenage(auth, rand, autn,
|
||||||
|
cb, data);
|
||||||
|
|
||||||
|
return auth->pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sim_auth_run_gsm(struct iwd_sim_auth *auth, const uint8_t *rands,
|
||||||
|
int num_rands, sim_auth_run_gsm_cb_t cb, void *data)
|
||||||
|
{
|
||||||
|
if (!auth->sim_supported)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* save ID in case simauth is destroyed */
|
||||||
|
auth->pending = auth->driver->run_gsm(auth, rands, num_rands, cb, data);
|
||||||
|
|
||||||
|
return auth->pending;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sim_auth_cancel_request(struct iwd_sim_auth *auth, int id)
|
||||||
|
{
|
||||||
|
if (auth->driver->cancel_request)
|
||||||
|
auth->driver->cancel_request(auth, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool sim_auth_init(void)
|
||||||
|
{
|
||||||
|
auth_providers = l_queue_new();
|
||||||
|
|
||||||
|
if (!auth_providers)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sim_auth_exit(void)
|
||||||
|
{
|
||||||
|
if (l_queue_length(auth_providers) > 0)
|
||||||
|
l_warn("Auth provider queue was not empty on exit!");
|
||||||
|
|
||||||
|
l_queue_destroy(auth_providers, destroy_provider);
|
||||||
|
}
|
141
src/simauth.h
Normal file
141
src/simauth.h
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* Wireless daemon for Linux
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 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
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define EAP_AKA_KI_LEN 16
|
||||||
|
#define EAP_AKA_OPC_LEN 16
|
||||||
|
#define EAP_AKA_AMF_LEN 2
|
||||||
|
#define EAP_AKA_SQN_LEN 6
|
||||||
|
#define EAP_SIM_KC_LEN 8
|
||||||
|
#define EAP_SIM_SRES_LEN 4
|
||||||
|
|
||||||
|
#define NUM_RANDS_MAX 3
|
||||||
|
|
||||||
|
struct iwd_sim_auth;
|
||||||
|
|
||||||
|
typedef void (*sim_auth_destroyed_cb_t)(void *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback containing Milenage keys.
|
||||||
|
*
|
||||||
|
* @param res RES value
|
||||||
|
* @param ck CK key
|
||||||
|
* @param ik IK key
|
||||||
|
* @param auts AUTS key, if sync failure this will be non NULL. With a
|
||||||
|
* normal success, this should be NULL.
|
||||||
|
* @param data User data
|
||||||
|
*
|
||||||
|
* Note: If there was an error (invalid AUTN or some other error), all the keys
|
||||||
|
* (res/ck/ik/auts) will be NULL. A sync error will result in res, ck, and ik
|
||||||
|
* being NULL but auts should point to a valid AUTS key.
|
||||||
|
*/
|
||||||
|
typedef void (*sim_auth_check_milenage_cb_t)(const uint8_t *res,
|
||||||
|
const uint8_t *ck, const uint8_t *ik, const uint8_t *auts,
|
||||||
|
void *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Callback with GSM data
|
||||||
|
*
|
||||||
|
* @param sres SRES value
|
||||||
|
* @param kc Kc value
|
||||||
|
* @param user_data User data
|
||||||
|
*
|
||||||
|
* Note: If GSM authentication was unsuccessful sres and kc will both be NULL
|
||||||
|
*/
|
||||||
|
typedef void (*sim_auth_run_gsm_cb_t)(const uint8_t *sres,
|
||||||
|
const uint8_t *kc, void *user_data);
|
||||||
|
|
||||||
|
struct iwd_sim_auth_driver {
|
||||||
|
const char *name;
|
||||||
|
int (*check_milenage)(struct iwd_sim_auth *auth, const uint8_t *rand,
|
||||||
|
const uint8_t *autn,
|
||||||
|
sim_auth_check_milenage_cb_t cb, void *data);
|
||||||
|
int (*run_gsm)(struct iwd_sim_auth *auth, const uint8_t *rands,
|
||||||
|
int num_rands, sim_auth_run_gsm_cb_t cb,
|
||||||
|
void *data);
|
||||||
|
void (*cancel_request)(struct iwd_sim_auth *auth, int id);
|
||||||
|
void (*remove)(struct iwd_sim_auth *auth);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new authentication provider. This new provider will be added to
|
||||||
|
* the list of available providers. It is expected that the auth provider
|
||||||
|
* should be immediately available for auth requests.
|
||||||
|
*/
|
||||||
|
struct iwd_sim_auth *iwd_sim_auth_create(bool sim_supported,
|
||||||
|
bool aka_supported, char *nai,
|
||||||
|
const struct iwd_sim_auth_driver *driver, void *driver_data);
|
||||||
|
|
||||||
|
void *iwd_sim_auth_get_data(struct iwd_sim_auth *auth);
|
||||||
|
|
||||||
|
int iwd_sim_auth_remove(struct iwd_sim_auth *auth);
|
||||||
|
|
||||||
|
const char *iwd_sim_auth_get_nai(struct iwd_sim_auth *auth);
|
||||||
|
|
||||||
|
unsigned int sim_auth_destroyed_watch_add(struct iwd_sim_auth *auth,
|
||||||
|
sim_auth_destroyed_cb_t cb, void *data);
|
||||||
|
|
||||||
|
void sim_auth_destroyed_watch_remove(struct iwd_sim_auth *auth,
|
||||||
|
unsigned int id);
|
||||||
|
/*
|
||||||
|
* Find an appropriate driver for running SIM/AKA algorithms
|
||||||
|
*
|
||||||
|
* @param sim True if the driver should support SIM authentication
|
||||||
|
* @param aka True if the driver should support AKA authentication
|
||||||
|
*
|
||||||
|
* @returns Driver handle found, NULL if none available
|
||||||
|
*/
|
||||||
|
struct iwd_sim_auth *iwd_sim_auth_find(bool sim, bool aka);
|
||||||
|
/*
|
||||||
|
* Check that 'rand' and 'autn' are valid from the server.
|
||||||
|
*
|
||||||
|
* @param auth Auth handle found with iwd_sim_auth_find()
|
||||||
|
* @param rand List of RAND's from the server
|
||||||
|
* @param autn AUTN from server
|
||||||
|
* @param cb Callback with milenage values
|
||||||
|
* @param data User data
|
||||||
|
*
|
||||||
|
* @param False if there was an error
|
||||||
|
*/
|
||||||
|
bool sim_auth_check_milenage(struct iwd_sim_auth *auth,
|
||||||
|
const uint8_t *rand, const uint8_t *autn,
|
||||||
|
sim_auth_check_milenage_cb_t cb, void *data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve EAP-SIM Kc and SRES values
|
||||||
|
*
|
||||||
|
* @param Auth Auth handle found with iwd_sim_auth_find()
|
||||||
|
* @param rands Buffer containing N 16 byte RANDs (n == 2 || n == 3)
|
||||||
|
* @param num_rands Number of 16 byte RANDs in 'rand'
|
||||||
|
* @param cb Callback with GSM key values
|
||||||
|
* @param data User data
|
||||||
|
*
|
||||||
|
* @return False if there was an error
|
||||||
|
*/
|
||||||
|
bool sim_auth_run_gsm(struct iwd_sim_auth *auth, const uint8_t *rands,
|
||||||
|
int num_rands, sim_auth_run_gsm_cb_t cb, void *data);
|
||||||
|
|
||||||
|
bool sim_auth_init(void);
|
||||||
|
|
||||||
|
void sim_auth_exit(void);
|
Loading…
Reference in New Issue
Block a user