eap-aka-3gpp: Add plugin that implements 3GPP MILENAGE algorithm in software
This is similar to the eap-aka-3gpp2 plugin. K (optionally concatenated with OPc) may be configured as binary EAP secret in ipsec.secrets or swanctl.conf. Based on a patch by Thomas Strangert. Fixes #2326.
This commit is contained in:
parent
7004a59a4c
commit
1aba82bfd7
|
@ -39,7 +39,8 @@ plugins = \
|
|||
plugins/dnscert.opt \
|
||||
plugins/duplicheck.opt \
|
||||
plugins/eap-aka.opt \
|
||||
plugins/eap-aka-3ggp2.opt \
|
||||
plugins/eap-aka-3gpp.opt \
|
||||
plugins/eap-aka-3gpp2.opt \
|
||||
plugins/eap-dynamic.opt \
|
||||
plugins/eap-gtc.opt \
|
||||
plugins/eap-peap.opt \
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
charon.plugins.eap-aka-3ggp2.seq_check =
|
|
@ -0,0 +1,3 @@
|
|||
charon.plugins.eap-aka-3gpp.seq_check =
|
||||
Enable to activate sequence check of the AKA SQN values in order to trigger
|
||||
resync cycles.
|
|
@ -0,0 +1,4 @@
|
|||
charon.plugins.eap-aka-3gpp2.seq_check =
|
||||
Enable to activate sequence check of the AKA SQN values in order to trigger
|
||||
resync cycles.
|
||||
|
|
@ -185,6 +185,7 @@ ARG_ENABL_SET([eap-sim], [enable SIM authentication module for EAP.])
|
|||
ARG_ENABL_SET([eap-sim-file], [enable EAP-SIM backend based on a triplet file.])
|
||||
ARG_ENABL_SET([eap-sim-pcsc], [enable EAP-SIM backend based on a smartcard reader. Requires libpcsclite.])
|
||||
ARG_ENABL_SET([eap-aka], [enable EAP AKA authentication module.])
|
||||
ARG_ENABL_SET([eap-aka-3gpp], [enable EAP AKA backend implementing 3GPP MILENAGE algorithms in software.])
|
||||
ARG_ENABL_SET([eap-aka-3gpp2], [enable EAP AKA backend implementing 3GPP2 algorithms in software. Requires libgmp.])
|
||||
ARG_ENABL_SET([eap-simaka-sql], [enable EAP-SIM/AKA backend based on a triplet/quintuplet SQL database.])
|
||||
ARG_ENABL_SET([eap-simaka-pseudonym], [enable EAP-SIM/AKA pseudonym storage plugin.])
|
||||
|
@ -1399,6 +1400,7 @@ ADD_PLUGIN([eap-sim], [c charon])
|
|||
ADD_PLUGIN([eap-sim-file], [c charon])
|
||||
ADD_PLUGIN([eap-sim-pcsc], [c charon])
|
||||
ADD_PLUGIN([eap-aka], [c charon])
|
||||
ADD_PLUGIN([eap-aka-3gpp], [c charon])
|
||||
ADD_PLUGIN([eap-aka-3gpp2], [c charon])
|
||||
ADD_PLUGIN([eap-simaka-sql], [c charon])
|
||||
ADD_PLUGIN([eap-simaka-pseudonym], [c charon])
|
||||
|
@ -1574,6 +1576,7 @@ AM_CONDITIONAL(USE_EAP_IDENTITY, test x$eap_identity = xtrue)
|
|||
AM_CONDITIONAL(USE_EAP_MD5, test x$eap_md5 = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_GTC, test x$eap_gtc = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_AKA, test x$eap_aka = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_AKA_3GPP, test x$eap_aka_3gpp = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_AKA_3GPP2, test x$eap_aka_3gpp2 = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_MSCHAPV2, test x$eap_mschapv2 = xtrue)
|
||||
AM_CONDITIONAL(USE_EAP_TLS, test x$eap_tls = xtrue)
|
||||
|
@ -1840,6 +1843,7 @@ AC_CONFIG_FILES([
|
|||
src/charon-systemd/Makefile
|
||||
src/libcharon/Makefile
|
||||
src/libcharon/plugins/eap_aka/Makefile
|
||||
src/libcharon/plugins/eap_aka_3gpp/Makefile
|
||||
src/libcharon/plugins/eap_aka_3gpp2/Makefile
|
||||
src/libcharon/plugins/eap_dynamic/Makefile
|
||||
src/libcharon/plugins/eap_identity/Makefile
|
||||
|
|
|
@ -163,6 +163,8 @@ LOCAL_SRC_FILES += $(call add_plugin, p-cscf)
|
|||
|
||||
LOCAL_SRC_FILES += $(call add_plugin, eap-aka)
|
||||
|
||||
LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp)
|
||||
|
||||
LOCAL_SRC_FILES += $(call add_plugin, eap-aka-3gpp2)
|
||||
ifneq ($(call plugin_enabled, eap-aka-3gpp2),)
|
||||
LOCAL_C_INCLUDES += $(libgmp_PATH)
|
||||
|
|
|
@ -370,6 +370,13 @@ if MONOLITHIC
|
|||
endif
|
||||
endif
|
||||
|
||||
if USE_EAP_AKA_3GPP
|
||||
SUBDIRS += plugins/eap_aka_3gpp
|
||||
if MONOLITHIC
|
||||
libcharon_la_LIBADD += plugins/eap_aka_3gpp/libstrongswan-eap-aka-3gpp.la
|
||||
endif
|
||||
endif
|
||||
|
||||
if USE_EAP_AKA_3GPP2
|
||||
SUBDIRS += plugins/eap_aka_3gpp2
|
||||
if MONOLITHIC
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
AM_CPPFLAGS = \
|
||||
-I$(top_srcdir)/src/libstrongswan \
|
||||
-I$(top_srcdir)/src/libcharon \
|
||||
-I$(top_srcdir)/src/libsimaka
|
||||
|
||||
AM_CFLAGS = \
|
||||
$(PLUGIN_CFLAGS)
|
||||
|
||||
libstrongswan_eap_aka_3gpp_la_LDFLAGS = -module -avoid-version
|
||||
|
||||
if MONOLITHIC
|
||||
noinst_LTLIBRARIES = libstrongswan-eap-aka-3gpp.la
|
||||
else
|
||||
plugin_LTLIBRARIES = libstrongswan-eap-aka-3gpp.la
|
||||
libstrongswan_eap_aka_3gpp_la_LIBADD = $(top_builddir)/src/libsimaka/libsimaka.la
|
||||
endif
|
||||
|
||||
libstrongswan_eap_aka_3gpp_la_SOURCES = \
|
||||
eap_aka_3gpp_plugin.h eap_aka_3gpp_plugin.c \
|
||||
eap_aka_3gpp_card.h eap_aka_3gpp_card.c \
|
||||
eap_aka_3gpp_provider.h eap_aka_3gpp_provider.c \
|
||||
eap_aka_3gpp_functions.h eap_aka_3gpp_functions.c
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "eap_aka_3gpp_card.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_aka_3gpp_card_t private_eap_aka_3gpp_card_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_aka_3gpp_card_t object.
|
||||
*/
|
||||
struct private_eap_aka_3gpp_card_t {
|
||||
|
||||
/**
|
||||
* Public eap_aka_3gpp_card_t interface.
|
||||
*/
|
||||
eap_aka_3gpp_card_t public;
|
||||
|
||||
/**
|
||||
* AKA functions
|
||||
*/
|
||||
eap_aka_3gpp_functions_t *f;
|
||||
|
||||
/**
|
||||
* do sequence number checking?
|
||||
*/
|
||||
bool seq_check;
|
||||
|
||||
/**
|
||||
* SQN stored in this pseudo-USIM
|
||||
*/
|
||||
uint8_t sqn[AKA_SQN_LEN];
|
||||
};
|
||||
|
||||
METHOD(simaka_card_t, get_quintuplet, status_t,
|
||||
private_eap_aka_3gpp_card_t *this, identification_t *id,
|
||||
char rand[AKA_RAND_LEN], char autn[AKA_AUTN_LEN], char ck[AKA_CK_LEN],
|
||||
char ik[AKA_IK_LEN], char res[AKA_RES_MAX], int *res_len)
|
||||
{
|
||||
uint8_t *amf, *mac;
|
||||
uint8_t k[AKA_K_LEN], opc[AKA_OPC_LEN], ak[AKA_AK_LEN], sqn[AKA_SQN_LEN],
|
||||
xmac[AKA_MAC_LEN];
|
||||
|
||||
if (!eap_aka_3gpp_get_k_opc(id, k, opc))
|
||||
{
|
||||
DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
|
||||
return FAILED;
|
||||
}
|
||||
DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
|
||||
AKA_K_LEN, opc, AKA_OPC_LEN);
|
||||
|
||||
/* AUTN = SQN xor AK | AMF | MAC */
|
||||
memcpy(sqn, autn, AKA_SQN_LEN);
|
||||
amf = autn + AKA_SQN_LEN;
|
||||
mac = autn + AKA_SQN_LEN + AKA_AMF_LEN;
|
||||
DBG3(DBG_IKE, "received AUTN %b", autn, AKA_AUTN_LEN);
|
||||
DBG3(DBG_IKE, "received AMF %b", amf, AKA_AMF_LEN);
|
||||
DBG3(DBG_IKE, "received MAC %b", mac, AKA_MAC_LEN);
|
||||
|
||||
/* generate RES, CK, IK, AK from received RAND */
|
||||
DBG3(DBG_IKE, "received RAND %b", rand, AKA_RAND_LEN);
|
||||
if (!this->f->f2345(this->f, k, opc, rand, res, ck, ik, ak))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
*res_len = AKA_RES_LEN;
|
||||
DBG3(DBG_IKE, "using RES %b", res, AKA_RES_LEN);
|
||||
DBG3(DBG_IKE, "using CK %b", ck, AKA_CK_LEN);
|
||||
DBG3(DBG_IKE, "using IK %b", ik, AKA_IK_LEN);
|
||||
DBG3(DBG_IKE, "using AK %b", ak, AKA_AK_LEN);
|
||||
|
||||
/* XOR anonymity key AK into SQN to decrypt it */
|
||||
memxor(sqn, ak, AKA_SQN_LEN);
|
||||
DBG3(DBG_IKE, "using SQN %b", sqn, AKA_SQN_LEN);
|
||||
|
||||
/* calculate expected MAC and compare against received one */
|
||||
if (!this->f->f1(this->f, k, opc, rand, sqn, amf, xmac))
|
||||
{
|
||||
return FAILED;
|
||||
}
|
||||
if (!memeq_const(mac, xmac, AKA_MAC_LEN))
|
||||
{
|
||||
DBG1(DBG_IKE, "received MAC does not match XMAC");
|
||||
DBG3(DBG_IKE, "MAC %b\nXMAC %b", mac, AKA_MAC_LEN, xmac, AKA_MAC_LEN);
|
||||
return FAILED;
|
||||
}
|
||||
DBG3(DBG_IKE, "MAC equals XMAC %b", mac, AKA_MAC_LEN);
|
||||
|
||||
if (this->seq_check && memcmp(this->sqn, sqn, AKA_SQN_LEN) >= 0)
|
||||
{
|
||||
DBG3(DBG_IKE, "received SQN %b\ncurrent SQN %b",
|
||||
sqn, AKA_SQN_LEN, this->sqn, AKA_SQN_LEN);
|
||||
return INVALID_STATE;
|
||||
}
|
||||
|
||||
/* update stored SQN to the received one */
|
||||
memcpy(this->sqn, sqn, AKA_SQN_LEN);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
METHOD(simaka_card_t, resync, bool,
|
||||
private_eap_aka_3gpp_card_t *this, identification_t *id,
|
||||
char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
|
||||
{
|
||||
uint8_t amf[AKA_AMF_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN], aks[AKA_AK_LEN],
|
||||
macs[AKA_MAC_LEN];
|
||||
|
||||
if (!eap_aka_3gpp_get_k_opc(id, k, opc))
|
||||
{
|
||||
DBG1(DBG_IKE, "no EAP key found for %Y to resync AKA", id);
|
||||
return FALSE;
|
||||
}
|
||||
DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b to resync AKA",
|
||||
id, k, AKA_K_LEN, opc, AKA_OPC_LEN);
|
||||
|
||||
/* AMF is set to zero in resync */
|
||||
memset(amf, 0, AKA_AMF_LEN);
|
||||
if (!this->f->f5star(this->f, k, opc, rand, aks) ||
|
||||
!this->f->f1star(this->f, k, opc, rand, this->sqn, amf, macs))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* AUTS = SQN xor AKS | MACS */
|
||||
memcpy(auts, this->sqn, AKA_SQN_LEN);
|
||||
memxor(auts, aks, AKA_AK_LEN);
|
||||
memcpy(auts + AKA_AK_LEN, macs, AKA_MAC_LEN);
|
||||
DBG3(DBG_IKE, "generated AUTS %b", auts, AKA_AUTN_LEN);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_card_t, destroy, void,
|
||||
private_eap_aka_3gpp_card_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
eap_aka_3gpp_card_t *eap_aka_3gpp_card_create(eap_aka_3gpp_functions_t *f)
|
||||
{
|
||||
private_eap_aka_3gpp_card_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.card = {
|
||||
.get_triplet = (void*)return_false,
|
||||
.get_quintuplet = _get_quintuplet,
|
||||
.resync = _resync,
|
||||
.get_pseudonym = (void*)return_null,
|
||||
.set_pseudonym = (void*)nop,
|
||||
.get_reauth = (void*)return_null,
|
||||
.set_reauth = (void*)nop,
|
||||
},
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.f = f,
|
||||
.seq_check = lib->settings->get_bool(lib->settings,
|
||||
"%s.plugins.eap-aka-3gpp.seq_check",
|
||||
#ifdef SEQ_CHECK /* handle legacy compile time configuration as default */
|
||||
TRUE,
|
||||
#else /* !SEQ_CHECK */
|
||||
FALSE,
|
||||
#endif /* SEQ_CHECK */
|
||||
lib->ns),
|
||||
);
|
||||
|
||||
eap_aka_3gpp_get_sqn(this->sqn, 0);
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_aka_3gpp_card eap_aka_3gpp_card
|
||||
* @{ @ingroup eap_aka_3gpp
|
||||
*/
|
||||
|
||||
#ifndef EAP_AKA_3GPP_CARD_H_
|
||||
#define EAP_AKA_3GPP_CARD_H_
|
||||
|
||||
#include "eap_aka_3gpp_functions.h"
|
||||
|
||||
#include <simaka_card.h>
|
||||
|
||||
typedef struct eap_aka_3gpp_card_t eap_aka_3gpp_card_t;
|
||||
|
||||
/**
|
||||
* SIM card implementation using a set of AKA functions.
|
||||
*/
|
||||
struct eap_aka_3gpp_card_t {
|
||||
|
||||
/**
|
||||
* Implements simaka_card_t interface
|
||||
*/
|
||||
simaka_card_t card;
|
||||
|
||||
/**
|
||||
* Destroy a eap_aka_3gpp_card_t.
|
||||
*/
|
||||
void (*destroy)(eap_aka_3gpp_card_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a eap_aka_3gpp_card instance.
|
||||
*
|
||||
* @param f AKA functions
|
||||
*/
|
||||
eap_aka_3gpp_card_t *eap_aka_3gpp_card_create(eap_aka_3gpp_functions_t *f);
|
||||
|
||||
#endif /** EAP_AKA_3GPP_CARD_H_ @}*/
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Copyright (C) 2017 Tobias Brunner
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* HSR Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "eap_aka_3gpp_functions.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_aka_3gpp_functions_t private_eap_aka_3gpp_functions_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_aka_3gpp_functions_t object.
|
||||
*/
|
||||
struct private_eap_aka_3gpp_functions_t {
|
||||
|
||||
/**
|
||||
* Public eap_aka_3gpp_functions_t interface.
|
||||
*/
|
||||
eap_aka_3gpp_functions_t public;
|
||||
|
||||
/**
|
||||
* AES instance
|
||||
*/
|
||||
crypter_t *crypter;
|
||||
};
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
bool eap_aka_3gpp_get_k_opc(identification_t *id, uint8_t k[AKA_K_LEN],
|
||||
uint8_t opc[AKA_OPC_LEN])
|
||||
{
|
||||
shared_key_t *shared;
|
||||
chunk_t key;
|
||||
|
||||
shared = lib->credmgr->get_shared(lib->credmgr, SHARED_EAP, id, NULL);
|
||||
if (!shared)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
key = shared->get_key(shared);
|
||||
|
||||
if (key.len == AKA_K_LEN)
|
||||
{
|
||||
memcpy(k, key.ptr, AKA_K_LEN);
|
||||
/* set OPc to a neutral default value, harmless to XOR with */
|
||||
memset(opc, '\0', AKA_OPC_LEN);
|
||||
}
|
||||
else if (key.len == AKA_K_LEN + AKA_OPC_LEN)
|
||||
{
|
||||
memcpy(k, key.ptr, AKA_K_LEN);
|
||||
memcpy(opc, key.ptr + AKA_K_LEN, AKA_OPC_LEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
DBG1(DBG_IKE, "invalid EAP K or K+OPc key found for %Y to authenticate "
|
||||
"with AKA, should be a %d or %d byte long binary value", id,
|
||||
AKA_K_LEN, AKA_K_LEN + AKA_OPC_LEN);
|
||||
shared->destroy(shared);
|
||||
return FALSE;
|
||||
}
|
||||
shared->destroy(shared);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Described in header
|
||||
*/
|
||||
void eap_aka_3gpp_get_sqn(uint8_t sqn[AKA_SQN_LEN], int offset)
|
||||
{
|
||||
timeval_t time;
|
||||
|
||||
gettimeofday(&time, NULL);
|
||||
/* set sqn to an integer containing 4 bytes seconds + 2 bytes usecs */
|
||||
time.tv_sec = htonl(time.tv_sec + offset);
|
||||
/* usec's are never larger than 0x000f423f, so we shift the 12 first bits */
|
||||
time.tv_usec = htonl(time.tv_usec << 12);
|
||||
memcpy(sqn, (uint8_t*)&time.tv_sec + sizeof(time_t) - 4, 4);
|
||||
memcpy(sqn + 4, &time.tv_usec, 2);
|
||||
}
|
||||
|
||||
static bool f1andf1star(private_eap_aka_3gpp_functions_t *this,
|
||||
const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
|
||||
const uint8_t rand[AKA_RAND_LEN], const uint8_t sqn[AKA_SQN_LEN],
|
||||
const uint8_t amf[AKA_AMF_LEN], uint8_t mac[16])
|
||||
{
|
||||
uint8_t i, data[16], in[16], iv[16] = { 0 };
|
||||
|
||||
if (!this->crypter->set_key(this->crypter,
|
||||
chunk_create((uint8_t*)k, AKA_K_LEN)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XOR RAND and OPc */
|
||||
memcpy(data, rand, sizeof(data));
|
||||
memxor(data, opc, sizeof(data));
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* concatenate SQN || AMF ||SQN || AMF */
|
||||
memcpy(in, sqn, 6);
|
||||
memcpy(&in[6], amf, 2);
|
||||
memcpy(&in[8], in, 8);
|
||||
|
||||
/* XOR opc and in, rotate by r1=64, and XOR
|
||||
* on the constant c1 (which is all zeroes) and finally the output above */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
data[(i + 8) % 16] ^= in[i] ^ opc[i];
|
||||
}
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
memxor(data, opc, sizeof(data));
|
||||
memcpy(mac, data, 16);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_functions_t, f1, bool,
|
||||
private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
|
||||
const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
|
||||
const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
|
||||
uint8_t maca[AKA_MAC_LEN])
|
||||
{
|
||||
uint8_t mac[16];
|
||||
|
||||
if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* only diff between f1 and f1* is here:
|
||||
* f1 uses bytes 0-7 as MAC-A
|
||||
* f1* uses bytes 8-15 as MAC-S */
|
||||
memcpy(maca, mac, AKA_MAC_LEN);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_functions_t, f1star, bool,
|
||||
private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
|
||||
const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
|
||||
const uint8_t sqn[AKA_SQN_LEN], const uint8_t amf[AKA_AMF_LEN],
|
||||
uint8_t macs[AKA_MAC_LEN])
|
||||
{
|
||||
uint8_t mac[16];
|
||||
|
||||
if (!f1andf1star(this, k, opc, rand, sqn, amf, mac))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* only diff between f1 and f1* is here:
|
||||
* f1 uses bytes 0-7 as MAC-A
|
||||
* f1* uses bytes 8-15 as MAC-S */
|
||||
memcpy(macs, &mac[8], AKA_MAC_LEN);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_functions_t, f2345, bool,
|
||||
private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
|
||||
const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
|
||||
uint8_t res[AKA_RES_LEN], uint8_t ck[AKA_CK_LEN], uint8_t ik[AKA_IK_LEN],
|
||||
uint8_t ak[AKA_AK_LEN])
|
||||
{
|
||||
uint8_t data[16], iv[16] = { 0 };
|
||||
chunk_t temp;
|
||||
uint8_t i;
|
||||
|
||||
if (!this->crypter->set_key(this->crypter,
|
||||
chunk_create((uint8_t*)k, AKA_K_LEN)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XOR RAND and OPc */
|
||||
memcpy(data, rand, sizeof(data));
|
||||
memxor(data, opc, sizeof(data));
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), &temp))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* to obtain output block OUT2: XOR OPc and TEMP,
|
||||
* rotate by r2=0, and XOR on the constant c2 (which is all zeroes except
|
||||
* that the last bit is 1). */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
data[i] = temp.ptr[i] ^ opc[i];
|
||||
}
|
||||
data[15] ^= 1;
|
||||
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
chunk_free(&temp);
|
||||
return FALSE;
|
||||
}
|
||||
memxor(data, opc, sizeof(data));
|
||||
|
||||
/* f5 output */
|
||||
memcpy(ak, data, 6);
|
||||
/* f2 output */
|
||||
memcpy(res, &data[8], 8);
|
||||
|
||||
/* to obtain output block OUT3: XOR OPc and TEMP,
|
||||
* rotate by r3=32, and XOR on the constant c3 (which
|
||||
* is all zeroes except that the next to last bit is 1) */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
data[(i + 12) % 16] = temp.ptr[i] ^ opc[i];
|
||||
}
|
||||
data[15] ^= 2;
|
||||
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
chunk_free(&temp);
|
||||
return FALSE;
|
||||
}
|
||||
memxor(data, opc, sizeof(data));
|
||||
|
||||
/* f3 output */
|
||||
memcpy(ck, data, 16);
|
||||
|
||||
/* to obtain output block OUT4: XOR OPc and TEMP,
|
||||
* rotate by r4=64, and XOR on the constant c4 (which
|
||||
* is all zeroes except that the 2nd from last bit is 1). */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
data[(i + 8) % 16] = temp.ptr[i] ^ opc[i];
|
||||
}
|
||||
data[15] ^= 4;
|
||||
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
chunk_free(&temp);
|
||||
return FALSE;
|
||||
}
|
||||
memxor(data, opc, sizeof(data));
|
||||
/* f4 output */
|
||||
memcpy(ik, data, 16);
|
||||
chunk_free(&temp);
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_functions_t, f5star, bool,
|
||||
private_eap_aka_3gpp_functions_t *this, const uint8_t k[AKA_K_LEN],
|
||||
const uint8_t opc[AKA_OPC_LEN], const uint8_t rand[AKA_RAND_LEN],
|
||||
uint8_t aks[AKA_AK_LEN])
|
||||
{
|
||||
uint8_t i, data[16], iv[16] = { 0 };
|
||||
chunk_t temp;
|
||||
|
||||
if (!this->crypter->set_key(this->crypter,
|
||||
chunk_create((uint8_t*)k, AKA_K_LEN)))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* XOR RAND and OPc */
|
||||
memcpy(data, rand, sizeof(data));
|
||||
memxor(data, opc, sizeof(data));
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), &temp))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* to obtain output block OUT5: XOR OPc and the output above,
|
||||
* rotate by r5=96, and XOR on the constant c5 (which
|
||||
* is all zeroes except that the 3rd from last bit is 1). */
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
data[(i + 4) % 16] = temp.ptr[i] ^ opc[i];
|
||||
}
|
||||
data[15] ^= 8;
|
||||
chunk_free(&temp);
|
||||
|
||||
if (!this->crypter->encrypt(this->crypter, chunk_create(data, sizeof(data)),
|
||||
chunk_create(iv, sizeof(iv)), NULL))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
memxor(data, opc, sizeof(data));
|
||||
memcpy(aks, data, 6);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_functions_t, destroy, void,
|
||||
private_eap_aka_3gpp_functions_t *this)
|
||||
{
|
||||
this->crypter->destroy(this->crypter);
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
eap_aka_3gpp_functions_t *eap_aka_3gpp_functions_create()
|
||||
{
|
||||
private_eap_aka_3gpp_functions_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.f1 = _f1,
|
||||
.f1star = _f1star,
|
||||
.f2345 = _f2345,
|
||||
.f5star = _f5star,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16),
|
||||
);
|
||||
if (!this->crypter)
|
||||
{
|
||||
DBG1(DBG_IKE, "%N not supported, unable to use 3GPP algorithm",
|
||||
encryption_algorithm_names, ENCR_AES_CBC);
|
||||
free(this);
|
||||
return NULL;
|
||||
}
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_aka_3gpp_functions eap_aka_3gpp_functions
|
||||
* @{ @ingroup eap_aka_3gpp
|
||||
*/
|
||||
|
||||
#ifndef EAP_AKA_3GPP_FUNCTIONS_H_
|
||||
#define EAP_AKA_3GPP_FUNCTIONS_H_
|
||||
|
||||
#include <credentials/keys/shared_key.h>
|
||||
#include <simaka_manager.h>
|
||||
#include "eap_aka_3gpp_plugin.h"
|
||||
|
||||
#define AKA_SQN_LEN 6
|
||||
#define AKA_K_LEN 16
|
||||
#define AKA_OPC_LEN 16
|
||||
#define AKA_MAC_LEN 8
|
||||
#define AKA_AK_LEN 6
|
||||
#define AKA_AMF_LEN 2
|
||||
#define AKA_RES_LEN 8
|
||||
|
||||
typedef struct eap_aka_3gpp_functions_t eap_aka_3gpp_functions_t;
|
||||
|
||||
/**
|
||||
* Get a shared key K and OPc of a particular user from the credential database.
|
||||
*
|
||||
* @param id user identity
|
||||
* @param[out] k (16 byte) scratchpad to receive secret key K
|
||||
* @param[out] opc (16 byte) scratchpad to receive operator variant key
|
||||
* derivate OPc
|
||||
*/
|
||||
bool eap_aka_3gpp_get_k_opc(identification_t *id, uint8_t k[AKA_K_LEN],
|
||||
uint8_t opc[AKA_OPC_LEN]);
|
||||
|
||||
/**
|
||||
* Get SQN using current time. Only used when creating/initializing
|
||||
* an eap_aka_3gpp_card_t or eap_aka_3gpp_provider_t object.
|
||||
*
|
||||
* @param offset time offset to add to current time to avoid initial
|
||||
* SQN resync
|
||||
* @param[out] sqn (6 byte) scratchpad to receive generated SQN
|
||||
*/
|
||||
void eap_aka_3gpp_get_sqn(uint8_t sqn[AKA_SQN_LEN], int offset);
|
||||
|
||||
/**
|
||||
* f1, f1*(), f2345() and f5*() functions from 3GPP as specified
|
||||
* in the TS 35.205, .206, .207, .208 standards.
|
||||
*/
|
||||
struct eap_aka_3gpp_functions_t {
|
||||
|
||||
/**
|
||||
* f1 : Calculate MAC-A from RAND, SQN, AMF using K and OPc
|
||||
*
|
||||
* @param k (128 bit) secret key K
|
||||
* @param opc (128 bit) operator variant key derivate OPc
|
||||
* @param rand (128 bit) random value RAND
|
||||
* @param sqn (48 bit) sequence number SQN
|
||||
* @param amf (16 bit) authentication management field AMF
|
||||
* @param[out] maca (64 bit) scratchpad to receive network auth code MAC-A
|
||||
* @return TRUE if calculations successful
|
||||
*/
|
||||
bool (*f1)(eap_aka_3gpp_functions_t *this,
|
||||
const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
|
||||
const uint8_t rand[AKA_RAND_LEN], const uint8_t sqn[AKA_SQN_LEN],
|
||||
const uint8_t amf[AKA_AMF_LEN],
|
||||
uint8_t maca[AKA_MAC_LEN]);
|
||||
|
||||
|
||||
/**
|
||||
* f1* : Calculate MAC-S from RAND, SQN, AMF using K and OPc
|
||||
*
|
||||
* @param k (128 bit) secret key K
|
||||
* @param opc (128 bit) operator variant key derivate OPc
|
||||
* @param rand (128 bit) random value RAND
|
||||
* @param sqn (48 bit) sequence number SQN
|
||||
* @param amf (16 bit) authentication management field AMF
|
||||
* @param[out] macs (64 bit) scratchpad to receive resync auth code MAC-S
|
||||
* @return TRUE if calculations successful
|
||||
*/
|
||||
bool (*f1star)(eap_aka_3gpp_functions_t *this,
|
||||
const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
|
||||
const uint8_t rand[AKA_RAND_LEN], const uint8_t sqn[AKA_SQN_LEN],
|
||||
const uint8_t amf[AKA_AMF_LEN],
|
||||
uint8_t macs[AKA_MAC_LEN]);
|
||||
|
||||
/**
|
||||
* f2345 : Do f2, f3, f4 and f5 in a single scoop, where:
|
||||
* f2 : Calculates RES from RAND using K and OPc
|
||||
* f3 : Calculates CK from RAND using K and OPc
|
||||
* f4 : Calculates IK from RAND using K and OPc
|
||||
* f5 : Calculates AK from RAND using K and OPc
|
||||
*
|
||||
* @param k (128 bit) secret key K
|
||||
* @param opc (128 bit) operator variant key derivate OPc
|
||||
* @param rand (128 bit) random value RAND
|
||||
* @param[out] res (64 bit) scratchpad to receive signed response RES
|
||||
* @param[out] ck (128 bit) scratchpad to receive encryption key CK
|
||||
* @param[out] ik (128 bit) scratchpad to receive integrity key IK
|
||||
* @param[out] ak (48 bit) scratchpad to receive anonymity key AK
|
||||
* @return TRUE if calculations successful
|
||||
*/
|
||||
bool (*f2345)(eap_aka_3gpp_functions_t *this,
|
||||
const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
|
||||
const uint8_t rand[AKA_RAND_LEN],
|
||||
uint8_t res[AKA_RES_LEN], uint8_t ck[AKA_CK_LEN],
|
||||
uint8_t ik[AKA_IK_LEN], uint8_t ak[AKA_AK_LEN]);
|
||||
|
||||
|
||||
/**
|
||||
* f5* : Calculates resync AKS from RAND using K and OPc
|
||||
*
|
||||
* @param k (128 bit) secret key K
|
||||
* @param opc (128 bit) operator variant key derivate OPc
|
||||
* @param rand (128 bit) random value RAND
|
||||
* @param[out] aks (48 bit) scratchpad to receive resync anonymity key AKS
|
||||
* @return TRUE if calculations successful
|
||||
*/
|
||||
bool (*f5star)(eap_aka_3gpp_functions_t *this,
|
||||
const uint8_t k[AKA_K_LEN], const uint8_t opc[AKA_OPC_LEN],
|
||||
const uint8_t rand[AKA_RAND_LEN],
|
||||
uint8_t aks[AKA_AK_LEN]);
|
||||
|
||||
/**
|
||||
* Destroy a eap_aka_3gpp_functions_t.
|
||||
*/
|
||||
void (*destroy)(eap_aka_3gpp_functions_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a eap_aka_3gpp_functions instance.
|
||||
*
|
||||
* @return function set, NULL on error
|
||||
*/
|
||||
eap_aka_3gpp_functions_t *eap_aka_3gpp_functions_create();
|
||||
|
||||
#endif /** EAP_AKA_3GPP_FUNCTIONS_H_ @}*/
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "eap_aka_3gpp_plugin.h"
|
||||
#include "eap_aka_3gpp_card.h"
|
||||
#include "eap_aka_3gpp_provider.h"
|
||||
#include "eap_aka_3gpp_functions.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_aka_3gpp_t private_eap_aka_3gpp_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_aka_3gpp_t object.
|
||||
*/
|
||||
struct private_eap_aka_3gpp_t {
|
||||
|
||||
/**
|
||||
* Public eap_aka_3gpp_plugin_t interface.
|
||||
*/
|
||||
eap_aka_3gpp_plugin_t public;
|
||||
|
||||
/**
|
||||
* USIM/EAP-AKA card
|
||||
*/
|
||||
eap_aka_3gpp_card_t *card;
|
||||
|
||||
/**
|
||||
* EAP-AKA provider
|
||||
*/
|
||||
eap_aka_3gpp_provider_t *provider;
|
||||
|
||||
/**
|
||||
* AKA functions
|
||||
*/
|
||||
eap_aka_3gpp_functions_t *functions;
|
||||
};
|
||||
|
||||
METHOD(plugin_t, get_name, char*,
|
||||
private_eap_aka_3gpp_t *this)
|
||||
{
|
||||
return "eap-aka-3gpp";
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to instanciate ea_aka_3gpp functions and card/provider backends
|
||||
*/
|
||||
static bool register_functions(private_eap_aka_3gpp_t *this,
|
||||
plugin_feature_t *feature, bool reg, void *data)
|
||||
{
|
||||
if (reg)
|
||||
{
|
||||
this->functions = eap_aka_3gpp_functions_create();
|
||||
if (!this->functions)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
this->card = eap_aka_3gpp_card_create(this->functions);
|
||||
this->provider = eap_aka_3gpp_provider_create(this->functions);
|
||||
return TRUE;
|
||||
}
|
||||
this->card->destroy(this->card);
|
||||
this->provider->destroy(this->provider);
|
||||
this->functions->destroy(this->functions);
|
||||
this->card = NULL;
|
||||
this->provider = NULL;
|
||||
this->functions = NULL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback providing our card to register
|
||||
*/
|
||||
static simaka_card_t* get_card(private_eap_aka_3gpp_t *this)
|
||||
{
|
||||
return &this->card->card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback providing our provider to register
|
||||
*/
|
||||
static simaka_provider_t* get_provider(private_eap_aka_3gpp_t *this)
|
||||
{
|
||||
return &this->provider->provider;
|
||||
}
|
||||
|
||||
METHOD(plugin_t, get_features, int,
|
||||
private_eap_aka_3gpp_t *this, plugin_feature_t *features[])
|
||||
{
|
||||
static plugin_feature_t f[] = {
|
||||
PLUGIN_CALLBACK((void*)register_functions, NULL),
|
||||
PLUGIN_PROVIDE(CUSTOM, "eap-aka-3gpp-functions"),
|
||||
PLUGIN_DEPENDS(CRYPTER, ENCR_AES_CBC, 16),
|
||||
PLUGIN_CALLBACK(simaka_manager_register, get_card),
|
||||
PLUGIN_PROVIDE(CUSTOM, "aka-card"),
|
||||
PLUGIN_DEPENDS(CUSTOM, "aka-manager"),
|
||||
PLUGIN_DEPENDS(CUSTOM, "eap-aka-3gpp-functions"),
|
||||
PLUGIN_CALLBACK(simaka_manager_register, get_provider),
|
||||
PLUGIN_PROVIDE(CUSTOM, "aka-provider"),
|
||||
PLUGIN_DEPENDS(CUSTOM, "aka-manager"),
|
||||
PLUGIN_DEPENDS(CUSTOM, "eap-aka-3gpp-functions"),
|
||||
};
|
||||
*features = f;
|
||||
return countof(f);
|
||||
}
|
||||
|
||||
METHOD(plugin_t, destroy, void, private_eap_aka_3gpp_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
plugin_t *eap_aka_3gpp_plugin_create()
|
||||
{
|
||||
private_eap_aka_3gpp_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.plugin = {
|
||||
.get_name = _get_name,
|
||||
.get_features = _get_features,
|
||||
.destroy = _destroy,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
return &this->public.plugin;
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_aka_3gpp eap_aka_3gpp
|
||||
* @ingroup cplugins
|
||||
*
|
||||
* @defgroup eap_aka_3gpp_plugin eap_aka_3gpp_plugin
|
||||
* @{ @ingroup eap_aka_3gpp
|
||||
*/
|
||||
|
||||
#ifndef EAP_AKA_3GPP_PLUGIN_H_
|
||||
#define EAP_AKA_3GPP_PLUGIN_H_
|
||||
|
||||
#include <plugins/plugin.h>
|
||||
|
||||
typedef struct eap_aka_3gpp_plugin_t eap_aka_3gpp_plugin_t;
|
||||
|
||||
/**
|
||||
* Plugin to provide a USIM card/provider according to the 3GPP standard.
|
||||
*
|
||||
* This plugin implements the 3GPP standards TS 35.205, .206, .207, .208
|
||||
* completely in software using the MILENAGE algorithm.
|
||||
* The shared keys used for authentication (K, OPc) are from ipsec.secrets.
|
||||
* The peers ID is used to query it.
|
||||
*
|
||||
* To enable SEQ sequence check by default define SEQ_CHECK. Left undefined/off,
|
||||
* it makes the USIM 'card' to accept any SEQ number, not comparing received
|
||||
* SQN with its own locally stored value. This potentially allows an attacker
|
||||
* to do replay attacks. But since the server has proven his identity via IKE,
|
||||
* such an attack is only possible between server and AAA (if any).
|
||||
* Note that SEQ_CHECK only controls the compile-time default behaviour,
|
||||
* but the run-time behaviour can always be controlled by setting the
|
||||
* charon.plugins.eap-aka-3gpp.seq_check config variable.
|
||||
*/
|
||||
struct eap_aka_3gpp_plugin_t {
|
||||
|
||||
/**
|
||||
* implements plugin interface
|
||||
*/
|
||||
plugin_t plugin;
|
||||
};
|
||||
|
||||
/**
|
||||
* The AKA mechanism uses sequence numbers to detect replay attacks. The
|
||||
* peer stores the sequence number normally in a USIM and accepts
|
||||
* incremental sequence numbers (incremental for lifetime of the USIM). To
|
||||
* prevent a complex sequence number management, this implementation uses
|
||||
* a sequence number derived from time. It is initialized to the startup
|
||||
* time of the daemon. On the provider side, an offset can optionally be
|
||||
* added to allow for a time sqew towards the card side.
|
||||
*/
|
||||
#define SQN_TIME_OFFSET 180
|
||||
|
||||
#endif /** EAP_AKA_3GPP_PLUGIN_H_ @}*/
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "eap_aka_3gpp_provider.h"
|
||||
|
||||
#include <daemon.h>
|
||||
|
||||
typedef struct private_eap_aka_3gpp_provider_t private_eap_aka_3gpp_provider_t;
|
||||
|
||||
/**
|
||||
* Private data of an eap_aka_3gpp_provider_t object.
|
||||
*/
|
||||
struct private_eap_aka_3gpp_provider_t {
|
||||
|
||||
/**
|
||||
* Public eap_aka_3gpp_provider_t interface.
|
||||
*/
|
||||
eap_aka_3gpp_provider_t public;
|
||||
|
||||
/**
|
||||
* AKA functions
|
||||
*/
|
||||
eap_aka_3gpp_functions_t *f;
|
||||
|
||||
/**
|
||||
* time based SQN, we use the same for all peers
|
||||
*/
|
||||
uint8_t sqn[AKA_SQN_LEN];
|
||||
};
|
||||
|
||||
/** Authentication management field, AMF, as defined in 3GPP TS 33.102 V12.2.0
|
||||
*
|
||||
* The 16 bits in the AMF are numbered from "0" to "15" where bit "0" is
|
||||
* the most significant bit and bit "15" is the least significant bit.
|
||||
* Bit "0" is called the "AMF separation bit". It is used for the purposes
|
||||
* of EPS (Evolved Packet System) and is specified in
|
||||
* - TS 33.401 [28] for E-UTRAN access to EPS;
|
||||
* - TS 33.402 [29] for non-3GPP access to EPS.
|
||||
* Bits "1" to "7" are reserved for future standardization use.
|
||||
* Bits "1" to "7" shall be set to 0 while not yet specified for a particular use.
|
||||
* Bits "8" to "15" can be used for proprietary purposes.
|
||||
*/
|
||||
static const uint8_t amf[AKA_AMF_LEN] = {0x80, 0x00};
|
||||
|
||||
METHOD(simaka_provider_t, get_quintuplet, bool,
|
||||
private_eap_aka_3gpp_provider_t *this, identification_t *id,
|
||||
char rand[AKA_RAND_LEN], char xres[AKA_RES_MAX], int *xres_len,
|
||||
char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN])
|
||||
{
|
||||
rng_t *rng;
|
||||
uint8_t maca[AKA_MAC_LEN], ak[AKA_AK_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN];
|
||||
|
||||
/* generate RAND: we use a RNG already registered as f0(). */
|
||||
rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
|
||||
if (!rng || !rng->get_bytes(rng, AKA_RAND_LEN, rand))
|
||||
{
|
||||
DBG1(DBG_IKE, "generating RAND for AKA failed");
|
||||
DESTROY_IF(rng);
|
||||
return FALSE;
|
||||
}
|
||||
rng->destroy(rng);
|
||||
DBG3(DBG_IKE, "generated rand %b", rand, AKA_RAND_LEN);
|
||||
|
||||
if (!eap_aka_3gpp_get_k_opc(id, k, opc))
|
||||
{
|
||||
DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
|
||||
return FALSE;
|
||||
}
|
||||
DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
|
||||
AKA_K_LEN, opc, AKA_OPC_LEN);
|
||||
|
||||
/* generate MAC and XRES, CK, IK, AK */
|
||||
if (!this->f->f1(this->f, k, opc, rand, this->sqn, amf, maca) ||
|
||||
!this->f->f2345(this->f, k, opc, rand, xres, ck, ik, ak))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
*xres_len = AKA_RES_LEN;
|
||||
|
||||
/* create AUTN = (SQN xor AK) || AMF || MAC */
|
||||
memcpy(autn, this->sqn, AKA_SQN_LEN);
|
||||
memxor(autn, ak, AKA_AK_LEN);
|
||||
memcpy(autn + AKA_SQN_LEN, amf, AKA_AMF_LEN);
|
||||
memcpy(autn + AKA_SQN_LEN + AKA_AMF_LEN, maca, AKA_MAC_LEN);
|
||||
DBG3(DBG_IKE, "AUTN %b", autn, AKA_AUTN_LEN);
|
||||
|
||||
chunk_increment(chunk_create(this->sqn, AKA_SQN_LEN));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(simaka_provider_t, resync, bool,
|
||||
private_eap_aka_3gpp_provider_t *this, identification_t *id,
|
||||
char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN])
|
||||
{
|
||||
uint8_t *sqn, *macs;
|
||||
uint8_t aks[AKA_AK_LEN], k[AKA_K_LEN], opc[AKA_OPC_LEN], amfs[AKA_AMF_LEN],
|
||||
xmacs[AKA_MAC_LEN];
|
||||
|
||||
if (!eap_aka_3gpp_get_k_opc(id, k, opc))
|
||||
{
|
||||
DBG1(DBG_IKE, "no EAP key found for %Y to authenticate with AKA", id);
|
||||
return FALSE;
|
||||
}
|
||||
DBG4(DBG_IKE, "EAP key found for id %Y, using K %b and OPc %b", id, k,
|
||||
AKA_K_LEN, opc, AKA_OPC_LEN);
|
||||
|
||||
/* get SQNms out of the AUTS the card created as:
|
||||
* AUTS = (SQNms xor AKS) || MAC-S */
|
||||
sqn = auts;
|
||||
macs = auts + AKA_SQN_LEN;
|
||||
if (!this->f->f5star(this->f, k, opc, rand, aks))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
memxor(sqn, aks, AKA_AK_LEN);
|
||||
|
||||
/* generate resync XMAC-S... */
|
||||
memset(amfs, 0, AKA_AMF_LEN);
|
||||
if (!this->f->f1star(this->f, k, opc, rand, sqn, amfs, xmacs))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
/* ...and compare it with the card's MAC-S */
|
||||
if (!memeq_const(xmacs, macs, AKA_MAC_LEN))
|
||||
{
|
||||
DBG1(DBG_IKE, "received MACS does not match XMACS");
|
||||
DBG3(DBG_IKE, "MACS %b XMACS %b",
|
||||
macs, AKA_MAC_LEN, xmacs, AKA_MAC_LEN);
|
||||
return FALSE;
|
||||
}
|
||||
/* update stored SQN to received SQN + 1 */
|
||||
memcpy(this->sqn, sqn, AKA_SQN_LEN);
|
||||
chunk_increment(chunk_create(this->sqn, AKA_SQN_LEN));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
METHOD(eap_aka_3gpp_provider_t, destroy, void,
|
||||
private_eap_aka_3gpp_provider_t *this)
|
||||
{
|
||||
free(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* See header
|
||||
*/
|
||||
eap_aka_3gpp_provider_t *eap_aka_3gpp_provider_create(
|
||||
eap_aka_3gpp_functions_t *f)
|
||||
{
|
||||
private_eap_aka_3gpp_provider_t *this;
|
||||
|
||||
INIT(this,
|
||||
.public = {
|
||||
.provider = {
|
||||
.get_triplet = (void*)return_false,
|
||||
.get_quintuplet = _get_quintuplet,
|
||||
.resync = _resync,
|
||||
.is_pseudonym = (void*)return_null,
|
||||
.gen_pseudonym = (void*)return_null,
|
||||
.is_reauth = (void*)return_null,
|
||||
.gen_reauth = (void*)return_null,
|
||||
},
|
||||
.destroy = _destroy,
|
||||
},
|
||||
.f = f,
|
||||
);
|
||||
/* use an offset to accept clock skew between client/server without resync */
|
||||
eap_aka_3gpp_get_sqn(this->sqn, SQN_TIME_OFFSET);
|
||||
|
||||
return &this->public;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2008-2009 Martin Willi
|
||||
* Hochschule fuer Technik Rapperswil
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
|
||||
*
|
||||
* This program 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 General Public License
|
||||
* for more details.
|
||||
*/
|
||||
/*
|
||||
* Copyright (C) 2015 Thomas Strangert
|
||||
* Polystar System AB, Sweden
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup eap_aka_3gpp_provider eap_aka_3gpp_provider
|
||||
* @{ @ingroup eap_aka_3gpp
|
||||
*/
|
||||
|
||||
#ifndef EAP_AKA_3GPP_PROVIDER_H_
|
||||
#define EAP_AKA_3GPP_PROVIDER_H_
|
||||
|
||||
#include "eap_aka_3gpp_functions.h"
|
||||
|
||||
#include <simaka_provider.h>
|
||||
|
||||
typedef struct eap_aka_3gpp_provider_t eap_aka_3gpp_provider_t;
|
||||
|
||||
/**
|
||||
* SIM provider implementation using a set of AKA functions.
|
||||
*/
|
||||
struct eap_aka_3gpp_provider_t {
|
||||
|
||||
/**
|
||||
* Implements simaka_provider_t interface.
|
||||
*/
|
||||
simaka_provider_t provider;
|
||||
|
||||
/**
|
||||
* Destroy a eap_aka_3gpp_provider_t.
|
||||
*/
|
||||
void (*destroy)(eap_aka_3gpp_provider_t *this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a eap_aka_3gpp_provider instance.
|
||||
*/
|
||||
eap_aka_3gpp_provider_t *eap_aka_3gpp_provider_create(
|
||||
eap_aka_3gpp_functions_t *f);
|
||||
|
||||
#endif /** EAP_AKA_3GPP_PROVIDER_H_ @}*/
|
Loading…
Reference in New Issue