diff options
Diffstat (limited to 'src/libcharon/sa/authenticators')
-rw-r--r-- | src/libcharon/sa/authenticators/authenticator.c | 7 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/authenticator.h | 6 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/eap_method.c | 20 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/eap_method.h | 15 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/sim_card.h | 125 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/sim_hooks.h | 53 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/sim_manager.c | 534 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/sim_manager.h | 291 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap/sim_provider.h | 124 | ||||
-rw-r--r-- | src/libcharon/sa/authenticators/eap_authenticator.c | 25 |
10 files changed, 53 insertions, 1147 deletions
diff --git a/src/libcharon/sa/authenticators/authenticator.c b/src/libcharon/sa/authenticators/authenticator.c index 83f5fbaad..9ffe661cc 100644 --- a/src/libcharon/sa/authenticators/authenticator.c +++ b/src/libcharon/sa/authenticators/authenticator.c @@ -28,11 +28,12 @@ ENUM_BEGIN(auth_method_names, AUTH_RSA, AUTH_DSS, "RSA signature", "pre-shared key", "DSS signature"); -ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_ECDSA_521, AUTH_DSS, +ENUM_NEXT(auth_method_names, AUTH_ECDSA_256, AUTH_GSPM, AUTH_DSS, "ECDSA-256 signature", "ECDSA-384 signature", - "ECDSA-521 signature"); -ENUM_END(auth_method_names, AUTH_ECDSA_521); + "ECDSA-521 signature", + "secure password method"); +ENUM_END(auth_method_names, AUTH_GSPM); /** * Described in header. diff --git a/src/libcharon/sa/authenticators/authenticator.h b/src/libcharon/sa/authenticators/authenticator.h index d27e006a3..5042e4a73 100644 --- a/src/libcharon/sa/authenticators/authenticator.h +++ b/src/libcharon/sa/authenticators/authenticator.h @@ -67,6 +67,12 @@ enum auth_method_t { * ECDSA with SHA-512 on the P-521 curve as specified in RFC 4754 */ AUTH_ECDSA_521 = 11, + + /** + * Generic Secure Password Authentication Method as specified in RFC 6467 + */ + AUTH_GSPM = 12, + }; /** diff --git a/src/libcharon/sa/authenticators/eap/eap_method.c b/src/libcharon/sa/authenticators/eap/eap_method.c index 0fa4a00c5..a05e8c59a 100644 --- a/src/libcharon/sa/authenticators/eap/eap_method.c +++ b/src/libcharon/sa/authenticators/eap/eap_method.c @@ -15,8 +15,28 @@ #include "eap_method.h" +#include <daemon.h> + ENUM(eap_role_names, EAP_SERVER, EAP_PEER, "EAP_SERVER", "EAP_PEER", ); +/** + * See header + */ +bool eap_method_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data) +{ + if (reg) + { + charon->eap->add_method(charon->eap, feature->arg.eap, 0, + feature->type == FEATURE_EAP_SERVER ? EAP_SERVER : EAP_PEER, + (eap_constructor_t)data); + } + else + { + charon->eap->remove_method(charon->eap, (eap_constructor_t)data); + } + return TRUE; +} diff --git a/src/libcharon/sa/authenticators/eap/eap_method.h b/src/libcharon/sa/authenticators/eap/eap_method.h index 0eab2b5ff..6242a5a6e 100644 --- a/src/libcharon/sa/authenticators/eap/eap_method.h +++ b/src/libcharon/sa/authenticators/eap/eap_method.h @@ -25,6 +25,7 @@ typedef struct eap_method_t eap_method_t; typedef enum eap_role_t eap_role_t; #include <library.h> +#include <plugins/plugin.h> #include <utils/identification.h> #include <eap/eap.h> #include <encoding/payloads/eap_payload.h> @@ -159,4 +160,18 @@ struct eap_method_t { typedef eap_method_t *(*eap_constructor_t)(identification_t *server, identification_t *peer); +/** + * Helper function to (un-)register EAP methods from plugin features. + * + * This function is a plugin_feature_callback_t and can be used with the + * PLUGIN_CALLBACK macro to register a EAP method constructor. + * + * @param plugin plugin registering the EAP method constructor + * @param feature associated plugin feature + * @param reg TRUE to register, FALSE to unregister. + * @param data data passed to callback, an eap_constructor_t + */ +bool eap_method_register(plugin_t *plugin, plugin_feature_t *feature, + bool reg, void *data); + #endif /** EAP_METHOD_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_card.h b/src/libcharon/sa/authenticators/eap/sim_card.h deleted file mode 100644 index 5f5dc580b..000000000 --- a/src/libcharon/sa/authenticators/eap/sim_card.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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. - */ - -/** - * @defgroup sim_card sim_card - * @{ @ingroup eap - */ - -#ifndef SIM_CARD_H_ -#define SIM_CARD_H_ - -typedef struct sim_card_t sim_card_t; - -/** - * Interface for a (U)SIM card (used as EAP client). - * - * The SIM card completes triplets/quintuplets requested in a challenge - * received from the server. - * An implementation supporting only one of SIM/AKA authentication may - * implement the other methods with return_false()/return NOT_SUPPORTED/NULL. - */ -struct sim_card_t { - - /** - * Calculate SRES/KC from a RAND for SIM authentication. - * - * @param id permanent identity to get a triplet for - * @param rand RAND input buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if SRES/KC calculated, FALSE on error/wrong identity - */ - bool (*get_triplet)(sim_card_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Calculate CK/IK/RES from RAND/AUTN for AKA authentication. - * - * If the received sequence number (in autn) is out of sync, INVALID_STATE - * is returned. - * The RES value is the only one with variable length. Pass a buffer - * of at least AKA_RES_MAX, the actual number of bytes is written to the - * res_len value. While the standard would allow any bit length between - * 32 and 128 bits, we support only full bytes for now. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param autn authentication token autn - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param res buffer receiving authentication result res - * @param res_len nubmer of bytes written to res buffer - * @return SUCCESS, FAILED, or INVALID_STATE if out of sync - */ - status_t (*get_quintuplet)(sim_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); - - /** - * Calculate AUTS from RAND for AKA resynchronization. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param auts resynchronization parameter auts - * @return TRUE if parameter generated successfully - */ - bool (*resync)(sim_card_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Set the pseudonym to use for next authentication. - * - * @param id permanent identity of the peer - * @param pseudonym pseudonym identity received from the server - */ - void (*set_pseudonym)(sim_card_t *this, identification_t *id, - identification_t *pseudonym); - - /** - * Get the pseudonym previously stored via set_pseudonym(). - * - * @param id permanent identity of the peer - * @return associated pseudonym identity, NULL if none stored - */ - identification_t* (*get_pseudonym)(sim_card_t *this, identification_t *id); - - /** - * Store parameters to use for the next fast reauthentication. - * - * @param id permanent identity of the peer - * @param next next fast reauthentication identity to use - * @param mk master key MK to store for reauthentication - * @param counter counter value to store, host order - */ - void (*set_reauth)(sim_card_t *this, identification_t *id, - identification_t *next, char mk[HASH_SIZE_SHA1], - u_int16_t counter); - - /** - * Retrieve parameters for fast reauthentication stored via set_reauth(). - * - * @param id permanent identity of the peer - * @param mk buffer receiving master key MK - * @param counter pointer receiving counter value, in host order - * @return fast reauthentication identity, NULL if not found - */ - identification_t* (*get_reauth)(sim_card_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1], u_int16_t *counter); -}; - -#endif /** SIM_CARD_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_hooks.h b/src/libcharon/sa/authenticators/eap/sim_hooks.h deleted file mode 100644 index 0a675e4ab..000000000 --- a/src/libcharon/sa/authenticators/eap/sim_hooks.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -/** - * @defgroup sim_hooks sim_hooks - * @{ @ingroup eap - */ - -#ifndef SIM_HOOKS_H_ -#define SIM_HOOKS_H_ - -typedef struct sim_hooks_t sim_hooks_t; - -/** - * Additional hooks invoked during EAP-SIM/AKA message processing. - */ -struct sim_hooks_t { - - /** - * SIM/AKA message parsing. - * - * As a SIM/AKA optionally contains encrypted attributes, the hook - * might get invoked twice, once before and once after decryption. - * - * @param message SIM/AKA message - * @param inbound TRUE for incoming messages, FALSE for outgoing - * @param decrypted TRUE if AT_ENCR_DATA has been decrypted - */ - void (*message)(sim_hooks_t *this, simaka_message_t *message, - bool inbound, bool decrypted); - - /** - * SIM/AKA encryption/authentication key hooks. - * - * @param k_encr derived SIM/AKA encryption key k_encr - * @param k_auth derived SIM/AKA authentication key k_auth - */ - void (*keys)(sim_hooks_t *this, chunk_t k_encr, chunk_t k_auth); -}; - -#endif /** SIM_HOOKS_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.c b/src/libcharon/sa/authenticators/eap/sim_manager.c deleted file mode 100644 index 9ccaf5298..000000000 --- a/src/libcharon/sa/authenticators/eap/sim_manager.c +++ /dev/null @@ -1,534 +0,0 @@ -/* - * Copyright (C) 2008 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. - */ - -#include "sim_manager.h" - -#include <daemon.h> -#include <utils/linked_list.h> -#include <threading/rwlock.h> - -typedef struct private_sim_manager_t private_sim_manager_t; - -/** - * Private data of an sim_manager_t object. - */ -struct private_sim_manager_t { - - /** - * Public sim_manager_t interface. - */ - sim_manager_t public; - - /** - * list of added cards - */ - linked_list_t *cards; - - /** - * list of added provider - */ - linked_list_t *providers; - - /** - * list of added hooks - */ - linked_list_t *hooks; - - /** - * lock for lists above - */ - rwlock_t *lock; -}; - -METHOD(sim_manager_t, add_card, void, - private_sim_manager_t *this, sim_card_t *card) -{ - this->lock->write_lock(this->lock); - this->cards->insert_last(this->cards, card); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, remove_card, void, - private_sim_manager_t *this, sim_card_t *card) -{ - this->lock->write_lock(this->lock); - this->cards->remove(this->cards, card, NULL); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, card_get_triplet, bool, - private_sim_manager_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) -{ - enumerator_t *enumerator; - sim_card_t *card; - int tried = 0; - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - if (card->get_triplet(card, id, rand, sres, kc)) - { - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return TRUE; - } - tried++; - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'", - tried, id); - return FALSE; -} - -METHOD(sim_manager_t, card_get_quintuplet, status_t, - private_sim_manager_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) -{ - enumerator_t *enumerator; - sim_card_t *card; - status_t status = NOT_FOUND; - int tried = 0; - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - status = card->get_quintuplet(card, id, rand, autn, ck, ik, res, res_len); - switch (status) - { /* try next on error, but not on INVALID_STATE */ - case SUCCESS: - case INVALID_STATE: - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return status; - case NOT_SUPPORTED: - case FAILED: - default: - tried++; - continue; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'", - tried, id); - return status; -} - -METHOD(sim_manager_t, card_resync, bool, - private_sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) -{ - enumerator_t *enumerator; - sim_card_t *card; - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - if (card->resync(card, id, rand, auts)) - { - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return TRUE; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return FALSE; -} - -METHOD(sim_manager_t, card_set_pseudonym, void, - private_sim_manager_t *this, identification_t *id, - identification_t *pseudonym) -{ - enumerator_t *enumerator; - sim_card_t *card; - - DBG1(DBG_IKE, "storing pseudonym '%Y' for '%Y'", pseudonym, id); - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - card->set_pseudonym(card, id, pseudonym); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, card_get_pseudonym, identification_t*, - private_sim_manager_t *this, identification_t *id) -{ - enumerator_t *enumerator; - sim_card_t *card; - identification_t *pseudonym = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - pseudonym = card->get_pseudonym(card, id); - if (pseudonym) - { - DBG1(DBG_IKE, "using stored pseudonym identity '%Y' " - "instead of '%Y'", pseudonym, id); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return pseudonym; -} - -METHOD(sim_manager_t, card_set_reauth, void, - private_sim_manager_t *this, identification_t *id, identification_t *next, - char mk[HASH_SIZE_SHA1], u_int16_t counter) -{ - enumerator_t *enumerator; - sim_card_t *card; - - DBG1(DBG_IKE, "storing next reauthentication identity '%Y' for '%Y'", - next, id); - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - card->set_reauth(card, id, next, mk, counter); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, card_get_reauth, identification_t*, - private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) -{ - enumerator_t *enumerator; - sim_card_t *card; - identification_t *reauth = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->cards->create_enumerator(this->cards); - while (enumerator->enumerate(enumerator, &card)) - { - reauth = card->get_reauth(card, id, mk, counter); - if (reauth) - { - DBG1(DBG_IKE, "using stored reauthentication identity '%Y' " - "instead of '%Y'", reauth, id); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return reauth; -} - -METHOD(sim_manager_t, add_provider, void, - private_sim_manager_t *this, sim_provider_t *provider) -{ - this->lock->write_lock(this->lock); - this->providers->insert_last(this->providers, provider); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, remove_provider, void, - private_sim_manager_t *this, sim_provider_t *provider) -{ - this->lock->write_lock(this->lock); - this->providers->remove(this->providers, provider, NULL); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, provider_get_triplet, bool, - private_sim_manager_t *this, identification_t *id, char rand[SIM_RAND_LEN], - char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - int tried = 0; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->get_triplet(provider, id, rand, sres, kc)) - { - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return TRUE; - } - tried++; - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", - tried, id); - return FALSE; -} - -METHOD(sim_manager_t, provider_get_quintuplet, bool, - private_sim_manager_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]) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - int tried = 0; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->get_quintuplet(provider, id, rand, xres, xres_len, - ck, ik, autn)) - { - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return TRUE; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'", - tried, id); - return FALSE; -} - -METHOD(sim_manager_t, provider_resync, bool, - private_sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->resync(provider, id, rand, auts)) - { - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return TRUE; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return FALSE; -} - -METHOD(sim_manager_t, provider_is_pseudonym, identification_t*, - private_sim_manager_t *this, identification_t *id) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *permanent = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - permanent = provider->is_pseudonym(provider, id); - if (permanent) - { - DBG1(DBG_IKE, "received pseudonym identity '%Y' " - "mapping to '%Y'", id, permanent); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return permanent; -} - -METHOD(sim_manager_t, provider_gen_pseudonym, identification_t*, - private_sim_manager_t *this, identification_t *id) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *pseudonym = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - pseudonym = provider->gen_pseudonym(provider, id); - if (pseudonym) - { - DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return pseudonym; -} - -METHOD(sim_manager_t, provider_is_reauth, identification_t*, - private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *permanent = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - permanent = provider->is_reauth(provider, id, mk, counter); - if (permanent) - { - DBG1(DBG_IKE, "received reauthentication identity '%Y' " - "mapping to '%Y'", id, permanent); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return permanent; -} - -METHOD(sim_manager_t, provider_gen_reauth, identification_t*, - private_sim_manager_t *this, identification_t *id, char mk[HASH_SIZE_SHA1]) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *reauth = NULL; - - this->lock->read_lock(this->lock); - enumerator = this->providers->create_enumerator(this->providers); - while (enumerator->enumerate(enumerator, &provider)) - { - reauth = provider->gen_reauth(provider, id, mk); - if (reauth) - { - DBG1(DBG_IKE, "proposing new reauthentication identity '%Y'", reauth); - break; - } - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); - return reauth; -} - -METHOD(sim_manager_t, add_hooks, void, - private_sim_manager_t *this, sim_hooks_t *hooks) -{ - this->lock->write_lock(this->lock); - this->hooks->insert_last(this->hooks, hooks); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, remove_hooks, void, - private_sim_manager_t *this, sim_hooks_t *hooks) -{ - this->lock->write_lock(this->lock); - this->hooks->remove(this->hooks, hooks, NULL); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, message_hook, void, - private_sim_manager_t *this, simaka_message_t *message, - bool inbound, bool decrypted) -{ - enumerator_t *enumerator; - sim_hooks_t *hooks; - - this->lock->read_lock(this->lock); - enumerator = this->hooks->create_enumerator(this->hooks); - while (enumerator->enumerate(enumerator, &hooks)) - { - hooks->message(hooks, message, inbound, decrypted); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, key_hook, void, - private_sim_manager_t *this, chunk_t k_encr, chunk_t k_auth) -{ - enumerator_t *enumerator; - sim_hooks_t *hooks; - - this->lock->read_lock(this->lock); - enumerator = this->hooks->create_enumerator(this->hooks); - while (enumerator->enumerate(enumerator, &hooks)) - { - hooks->keys(hooks, k_encr, k_auth); - } - enumerator->destroy(enumerator); - this->lock->unlock(this->lock); -} - -METHOD(sim_manager_t, destroy, void, - private_sim_manager_t *this) -{ - this->cards->destroy(this->cards); - this->providers->destroy(this->providers); - this->hooks->destroy(this->hooks); - this->lock->destroy(this->lock); - free(this); -} - -/** - * See header - */ -sim_manager_t *sim_manager_create() -{ - private_sim_manager_t *this; - - INIT(this, - .public = { - .add_card = _add_card, - .remove_card = _remove_card, - .card_get_triplet = _card_get_triplet, - .card_get_quintuplet = _card_get_quintuplet, - .card_resync = _card_resync, - .card_set_pseudonym = _card_set_pseudonym, - .card_get_pseudonym = _card_get_pseudonym, - .card_set_reauth = _card_set_reauth, - .card_get_reauth = _card_get_reauth, - .add_provider = _add_provider, - .remove_provider = _remove_provider, - .provider_get_triplet = _provider_get_triplet, - .provider_get_quintuplet = _provider_get_quintuplet, - .provider_resync = _provider_resync, - .provider_is_pseudonym = _provider_is_pseudonym, - .provider_gen_pseudonym = _provider_gen_pseudonym, - .provider_is_reauth = _provider_is_reauth, - .provider_gen_reauth = _provider_gen_reauth, - .add_hooks = _add_hooks, - .remove_hooks = _remove_hooks, - .message_hook = _message_hook, - .key_hook = _key_hook, - .destroy = _destroy, - }, - .cards = linked_list_create(), - .providers = linked_list_create(), - .hooks = linked_list_create(), - .lock = rwlock_create(RWLOCK_TYPE_DEFAULT), - ); - - return &this->public; -} - diff --git a/src/libcharon/sa/authenticators/eap/sim_manager.h b/src/libcharon/sa/authenticators/eap/sim_manager.h deleted file mode 100644 index db4a65011..000000000 --- a/src/libcharon/sa/authenticators/eap/sim_manager.h +++ /dev/null @@ -1,291 +0,0 @@ -/* - * 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. - */ - -/** - * @defgroup sim_manager sim_manager - * @{ @ingroup eap - */ - -#ifndef SIM_MANAGER_H_ -#define SIM_MANAGER_H_ - -#include <crypto/hashers/hasher.h> -#include <utils/identification.h> -#include <utils/enumerator.h> -#include <sa/authenticators/eap/eap_method.h> - -typedef struct sim_manager_t sim_manager_t; - -/** implemented in libsimaka, but we need it for the message hook */ -typedef struct simaka_message_t simaka_message_t; - -#define SIM_RAND_LEN 16 -#define SIM_SRES_LEN 4 -#define SIM_KC_LEN 8 - -#define AKA_RAND_LEN 16 -#define AKA_RES_MAX 16 -#define AKA_CK_LEN 16 -#define AKA_IK_LEN 16 -#define AKA_AUTN_LEN 16 -#define AKA_AUTS_LEN 14 - -#include <sa/authenticators/eap/sim_card.h> -#include <sa/authenticators/eap/sim_provider.h> -#include <sa/authenticators/eap/sim_hooks.h> - -/** - * The SIM manager handles multiple (U)SIM cards/providers and hooks. - */ -struct sim_manager_t { - - /** - * Register a SIM card (client) at the manager. - * - * @param card sim card to register - */ - void (*add_card)(sim_manager_t *this, sim_card_t *card); - - /** - * Unregister a previously registered card from the manager. - * - * @param card sim card to unregister - */ - void (*remove_card)(sim_manager_t *this, sim_card_t *card); - - /** - * Calculate SIM triplets on one of the registered SIM cards. - * - * @param id permanent identity to get a triplet for - * @param rand RAND input buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if calculated, FALSE if no matching card found - */ - bool (*card_get_triplet)(sim_manager_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Calculate AKA quitpulets on one of the registered SIM cards. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param autn authentication token autn - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param res buffer receiving authentication result res - * @param res_len nubmer of bytes written to res buffer - * @return SUCCESS, FAILED, or INVALID_STATE if out of sync - */ - status_t (*card_get_quintuplet)(sim_manager_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); - - /** - * Calculate resynchronization data on one of the registered SIM cards. - * - * @param id permanent identity to request quintuplet for - * @param rand random value rand - * @param auts resynchronization parameter auts - * @return TRUE if calculated, FALSE if no matcing card found - */ - bool (*card_resync)(sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Store a received pseudonym on one of the registered SIM cards. - * - * @param id permanent identity of the peer - * @param pseudonym pseudonym identity received from the server - */ - void (*card_set_pseudonym)(sim_manager_t *this, identification_t *id, - identification_t *pseudonym); - - /** - * Get a stored pseudonym from one of the registerd SIM cards. - * - * @param id permanent identity of the peer - * @return associated pseudonym identity, NULL if none found - */ - identification_t* (*card_get_pseudonym)(sim_manager_t *this, - identification_t *id); - - /** - * Store fast reauthentication parameters on one of the registered cards. - * - * @param id permanent identity of the peer - * @param next next fast reauthentication identity to use - * @param mk master key MK to store for reauthentication - * @param counter counter value to store, host order - */ - void (*card_set_reauth)(sim_manager_t *this, identification_t *id, - identification_t *next, char mk[HASH_SIZE_SHA1], - u_int16_t counter); - - /** - * Retrieve fast reauthentication parameters from one of the registerd cards. - * - * @param id permanent identity of the peer - * @param mk buffer receiving master key MK - * @param counter pointer receiving counter value, in host order - * @return fast reauthentication identity, NULL if none found - */ - identification_t* (*card_get_reauth)(sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter); - - /** - * Register a triplet provider (server) at the manager. - * - * @param card sim card to register - */ - void (*add_provider)(sim_manager_t *this, sim_provider_t *provider); - - /** - * Unregister a previously registered provider from the manager. - * - * @param card sim card to unregister - */ - void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider); - - /** - * Get a SIM triplet from one of the registered providers. - * - * @param id permanent identity of peer to gen triplet for - * @param rand RAND output buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if triplet received, FALSE if no match found - */ - bool (*provider_get_triplet)(sim_manager_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Get a AKA quintuplet from one of the registered providers. - * - * @param id permanent identity of peer to create challenge for - * @param rand buffer receiving random value rand - * @param xres buffer receiving expected authentication result xres - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param autn authentication token autn - * @return TRUE if quintuplet received, FALSE if no match found - */ - bool (*provider_get_quintuplet)(sim_manager_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]); - - /** - * Pass AKA resynchronization data to one of the registered providers. - * - * @param id permanent identity of peer requesting resynchronisation - * @param rand random value rand - * @param auts synchronization parameter auts - * @return TRUE if resynchronized, FALSE if not handled - */ - bool (*provider_resync)(sim_manager_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Check if a peer uses a pseudonym using one of the registered providers. - * - * @param id pseudonym identity candidate - * @return permanent identity, NULL if id not a pseudonym - */ - identification_t* (*provider_is_pseudonym)(sim_manager_t *this, - identification_t *id); - - /** - * Generate a new pseudonym using one of the registered providers. - * - * @param id permanent identity to generate a pseudonym for - * @return generated pseudonym, NULL to not use a pseudonym identity - */ - identification_t* (*provider_gen_pseudonym)(sim_manager_t *this, - identification_t *id); - - /** - * Check if a peer uses a reauth id using one of the registered providers. - * - * @param id reauthentication identity (candidate) - * @param mk buffer receiving master key MK - * @param counter pointer receiving current counter value, host order - * @return permanent identity, NULL if not a known reauth identity - */ - identification_t* (*provider_is_reauth)(sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1], - u_int16_t *counter); - - /** - * Generate a fast reauth id using one of the registered providers. - * - * @param id permanent peer identity - * @param mk master key to store along with generated identity - * @return fast reauthentication identity, NULL to not use reauth - */ - identification_t* (*provider_gen_reauth)(sim_manager_t *this, - identification_t *id, char mk[HASH_SIZE_SHA1]); - - /** - * Register a set of hooks to the manager. - * - * @param hooks hook interface implementation to register - */ - void (*add_hooks)(sim_manager_t *this, sim_hooks_t *hooks); - - /** - * Unregister a set of hooks from the manager. - * - * @param hooks hook interface implementation to unregister - */ - void (*remove_hooks)(sim_manager_t *this, sim_hooks_t *hooks); - - /** - * Invoke SIM/AKA message hook. - * - * @param message SIM message - * @param inbound TRUE for incoming messages, FALSE for outgoing - * @param decrypted TRUE if AT_ENCR_DATA has been decrypted - */ - void (*message_hook)(sim_manager_t *this, simaka_message_t *message, - bool inbound, bool decrypted); - - /** - * Invoke SIM/AKA key hook. - * - * @param k_encr SIM/AKA encryption key k_encr - * @param k_auth SIM/AKA authentication key k_auth - */ - void (*key_hook)(sim_manager_t *this, chunk_t k_encr, chunk_t k_auth); - - /** - * Destroy a manager instance. - */ - void (*destroy)(sim_manager_t *this); -}; - -/** - * Create an SIM manager to handle multiple (U)SIM cards/providers. - * - * @return sim_t object - */ -sim_manager_t *sim_manager_create(); - -#endif /** SIM_MANAGER_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap/sim_provider.h b/src/libcharon/sa/authenticators/eap/sim_provider.h deleted file mode 100644 index 191e094db..000000000 --- a/src/libcharon/sa/authenticators/eap/sim_provider.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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. - */ - -/** - * @defgroup sim_provider sim_provider - * @{ @ingroup eap - */ - -#ifndef SIM_PROVIDER_H_ -#define SIM_PROVIDER_H_ - -typedef struct sim_provider_t sim_provider_t; - -/** - * Interface for a triplet/quintuplet provider (used as EAP server). - * - * A SIM provider hands out triplets for SIM authentication and quintuplets - * for AKA authentication. Multiple SIM provider instances can serve as - * authentication backend to authenticate clients using SIM/AKA. - * An implementation supporting only one of SIM/AKA authentication may - * implement the other methods with return_false(). - */ -struct sim_provider_t { - - /** - * Create a challenge for SIM authentication. - * - * @param id permanent identity of peer to gen triplet for - * @param rand RAND output buffer, fixed size 16 bytes - * @param sres SRES output buffer, fixed size 4 byte - * @param kc KC output buffer, fixed size 8 bytes - * @return TRUE if triplet received, FALSE otherwise - */ - bool (*get_triplet)(sim_provider_t *this, identification_t *id, - char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], - char kc[SIM_KC_LEN]); - - /** - * Create a challenge for AKA authentication. - * - * The XRES value is the only one with variable length. Pass a buffer - * of at least AKA_RES_MAX, the actual number of bytes is written to the - * xres_len value. While the standard would allow any bit length between - * 32 and 128 bits, we support only full bytes for now. - * - * @param id permanent identity of peer to create challenge for - * @param rand buffer receiving random value rand - * @param xres buffer receiving expected authentication result xres - * @param xres_len nubmer of bytes written to xres buffer - * @param ck buffer receiving encryption key ck - * @param ik buffer receiving integrity key ik - * @param autn authentication token autn - * @return TRUE if quintuplet generated successfully - */ - bool (*get_quintuplet)(sim_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]); - - /** - * Process AKA resynchroniusation request of a peer. - * - * @param id permanent identity of peer requesting resynchronisation - * @param rand random value rand - * @param auts synchronization parameter auts - * @return TRUE if resynchronized successfully - */ - bool (*resync)(sim_provider_t *this, identification_t *id, - char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]); - - /** - * Check if peer uses a pseudonym, get permanent identity. - * - * @param id pseudonym identity candidate - * @return permanent identity, NULL if id not a pseudonym - */ - identification_t* (*is_pseudonym)(sim_provider_t *this, - identification_t *id); - - /** - * Generate a pseudonym identitiy for a given peer identity. - * - * @param id permanent identity to generate a pseudonym for - * @return generated pseudonym, NULL to not use a pseudonym identity - */ - identification_t* (*gen_pseudonym)(sim_provider_t *this, - identification_t *id); - - /** - * Check if peer uses reauthentication, retrieve reauth parameters. - * - * @param id reauthentication identity (candidate) - * @param mk buffer receiving master key MK - * @param counter pointer receiving current counter value, host order - * @return permanent identity, NULL if id not a reauth identity - */ - identification_t* (*is_reauth)(sim_provider_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1], u_int16_t *counter); - - /** - * Generate a fast reauthentication identity, associated to a master key. - * - * @param id permanent peer identity - * @param mk master key to store along with generated identity - * @return fast reauthentication identity, NULL to not use reauth - */ - identification_t* (*gen_reauth)(sim_provider_t *this, identification_t *id, - char mk[HASH_SIZE_SHA1]); -}; - -#endif /** SIM_CARD_H_ @}*/ diff --git a/src/libcharon/sa/authenticators/eap_authenticator.c b/src/libcharon/sa/authenticators/eap_authenticator.c index d442acb00..5c8f0b6ce 100644 --- a/src/libcharon/sa/authenticators/eap_authenticator.c +++ b/src/libcharon/sa/authenticators/eap_authenticator.c @@ -160,7 +160,9 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, { if (this->method->initiate(this->method, &out) == NEED_MORE) { - DBG1(DBG_IKE, "initiating EAP-Identity request"); + DBG1(DBG_IKE, "initiating %N method (id 0x%02X)", + eap_type_names, EAP_IDENTITY, + this->method->get_identifier(this->method)); return out; } this->method->destroy(this->method); @@ -216,23 +218,12 @@ static eap_payload_t* server_initiate_eap(private_eap_authenticator_t *this, */ static void replace_eap_identity(private_eap_authenticator_t *this) { - enumerator_t *enumerator; - auth_rule_t rule; + identification_t *eap_identity; auth_cfg_t *cfg; - void *ptr; + eap_identity = this->eap_identity->clone(this->eap_identity); cfg = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE); - enumerator = cfg->create_enumerator(cfg); - while (enumerator->enumerate(enumerator, &rule, &ptr)) - { - if (rule == AUTH_RULE_EAP_IDENTITY) - { - cfg->replace(cfg, enumerator, AUTH_RULE_EAP_IDENTITY, - this->eap_identity->clone(this->eap_identity)); - break; - } - } - enumerator->destroy(enumerator); + cfg->add(cfg, AUTH_RULE_EAP_IDENTITY, eap_identity); } /** @@ -349,8 +340,8 @@ static eap_payload_t* client_process_eap(private_eap_authenticator_t *this, { id = this->ike_sa->get_my_id(this->ike_sa); } - DBG1(DBG_IKE, "server requested %N, sending '%Y'", - eap_type_names, type, id); + DBG1(DBG_IKE, "server requested %N (id 0x%02X), sending '%Y'", + eap_type_names, type, in->get_identifier(in), id); this->eap_identity = id->clone(id); this->method = load_method(this, type, vendor, EAP_PEER); |