diff options
author | Martin Willi <martin@strongswan.org> | 2009-10-29 14:56:45 +0100 |
---|---|---|
committer | Martin Willi <martin@strongswan.org> | 2009-11-12 10:34:01 +0100 |
commit | 0109846aa13e46f0d96e4c382621130337ebbc61 (patch) | |
tree | 6b67aeb411725ee146c8e8a37fbaf368eb14d6bb | |
parent | eb7bf91e1259c6e8ea9e5b2c6eedf88f627f8af5 (diff) | |
download | strongswan-0109846aa13e46f0d96e4c382621130337ebbc61.tar.bz2 strongswan-0109846aa13e46f0d96e4c382621130337ebbc61.tar.xz |
Moved card/provider enumeration to SIM manager, providing wrapped functions for both SIM and AKA plugins
-rw-r--r-- | src/charon/plugins/eap_aka/eap_aka_peer.c | 17 | ||||
-rw-r--r-- | src/charon/plugins/eap_aka/eap_aka_server.c | 34 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_peer.c | 105 | ||||
-rw-r--r-- | src/charon/plugins/eap_sim/eap_sim_server.c | 134 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/sim_manager.c | 364 | ||||
-rw-r--r-- | src/charon/sa/authenticators/eap/sim_manager.h | 161 |
6 files changed, 527 insertions, 288 deletions
diff --git a/src/charon/plugins/eap_aka/eap_aka_peer.c b/src/charon/plugins/eap_aka/eap_aka_peer.c index 136a774db..1ff445c91 100644 --- a/src/charon/plugins/eap_aka/eap_aka_peer.c +++ b/src/charon/plugins/eap_aka/eap_aka_peer.c @@ -81,7 +81,6 @@ static status_t process_challenge(private_eap_aka_peer_t *this, simaka_message_t *message; enumerator_t *enumerator; simaka_attribute_t type; - sim_card_t *card; chunk_t data, rand = chunk_empty, autn = chunk_empty, mk; u_char res[AKA_RES_LEN], ck[AKA_CK_LEN], ik[AKA_IK_LEN], auts[AKA_AUTS_LEN]; status_t status = NOT_FOUND; @@ -116,20 +115,10 @@ static status_t process_challenge(private_eap_aka_peer_t *this, return NEED_MORE; } - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - status = card->get_quintuplet(card, this->peer, rand.ptr, autn.ptr, - ck, ik, res); - if (status != FAILED) - { /* try next on error */ - break; - } - } - enumerator->destroy(enumerator); - + status = charon->sim->card_get_quintuplet(charon->sim, this->peer, + rand.ptr, autn.ptr, ck, ik, res); if (status == INVALID_STATE && - card->resync(card, this->peer, rand.ptr, auts)) + charon->sim->card_resync(charon->sim, this->peer, rand.ptr, auts)) { DBG1(DBG_IKE, "received SQN invalid, sending %N", simaka_subtype_names, AKA_SYNCHRONIZATION_FAILURE); diff --git a/src/charon/plugins/eap_aka/eap_aka_server.c b/src/charon/plugins/eap_aka/eap_aka_server.c index 9f6e71ad7..87c718baa 100644 --- a/src/charon/plugins/eap_aka/eap_aka_server.c +++ b/src/charon/plugins/eap_aka/eap_aka_server.c @@ -94,31 +94,17 @@ static bool attribute_skippable(simaka_attribute_t attribute) static status_t initiate(private_eap_aka_server_t *this, eap_payload_t **out) { simaka_message_t *message; - enumerator_t *enumerator; - sim_provider_t *provider; char rand[AKA_RAND_LEN], xres[AKA_RES_LEN]; char ck[AKA_CK_LEN], ik[AKA_IK_LEN], autn[AKA_AUTN_LEN]; chunk_t data, mk; - bool found = FALSE; - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->get_quintuplet(provider, this->peer, - rand, xres, ck, ik, autn)) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - if (!found) + if (!charon->sim->provider_get_quintuplet(charon->sim, this->peer, + rand, xres, ck, ik, autn)) { DBG1(DBG_IKE, "no AKA provider found with quintuplets for '%Y'", this->peer); return FAILED; } - data = chunk_cata("cc", chunk_create(ik, AKA_IK_LEN), chunk_create(ck, AKA_CK_LEN)); free(this->msk.ptr); @@ -197,11 +183,9 @@ static status_t process_challenge(private_eap_aka_server_t *this, static status_t process_synchronize(private_eap_aka_server_t *this, simaka_message_t *in, eap_payload_t **out) { - sim_provider_t *provider; enumerator_t *enumerator; simaka_attribute_t type; chunk_t data, auts = chunk_empty; - bool found = FALSE; if (this->synchronized) { @@ -239,18 +223,8 @@ static status_t process_synchronize(private_eap_aka_server_t *this, return FAILED; } - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->resync(provider, this->peer, this->rand.ptr, auts.ptr)) - { - found = TRUE; - break; - } - } - enumerator->destroy(enumerator); - - if (!found) + if (!charon->sim->provider_resync(charon->sim, this->peer, + this->rand.ptr, auts.ptr)) { DBG1(DBG_IKE, "no AKA provider found supporting " "resynchronization for '%Y'", this->peer); diff --git a/src/charon/plugins/eap_sim/eap_sim_peer.c b/src/charon/plugins/eap_sim/eap_sim_peer.c index 8574f7da7..bd78c516a 100644 --- a/src/charon/plugins/eap_sim/eap_sim_peer.c +++ b/src/charon/plugins/eap_sim/eap_sim_peer.c @@ -95,123 +95,33 @@ struct private_eap_sim_peer_t { static chunk_t version = chunk_from_chars(0x00,0x01); /** - * Read a triplet from the SIM card - */ -static bool get_triplet(private_eap_sim_peer_t *this, identification_t *peer, - char *rand, char *sres, char *kc) -{ - enumerator_t *enumerator; - sim_card_t *card; - bool success = FALSE; - - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - if (card->get_triplet(card, peer, rand, sres, kc)) - { - success = TRUE; - break; - } - } - enumerator->destroy(enumerator); - if (!success) - { - DBG1(DBG_IKE, "no SIM card found with triplets for '%Y'", peer); - } - return success; -} - -/** - * Find a stored reauthentication identity on a SIM card - */ -static identification_t *get_reauth(private_eap_sim_peer_t *this) -{ - enumerator_t *enumerator; - sim_card_t *card; - identification_t *reauth = NULL; - - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - reauth = card->get_reauth(card, this->permanent, - this->mk, &this->counter); - if (reauth) - { - DBG1(DBG_IKE, "using stored reauthentication identity '%Y' " - "instead of '%Y'", reauth, this->permanent); - break; - } - } - enumerator->destroy(enumerator); - return reauth; -} - -/** * Store received next fast reauthentication identity, along with mk/counter */ static void set_reauth(private_eap_sim_peer_t *this, chunk_t data) { - enumerator_t *enumerator; - sim_card_t *card; identification_t *reauth; char buf[data.len + 1]; snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr); reauth = identification_create_from_string(buf); DBG1(DBG_IKE, "received next reauthentication identity '%Y'", reauth); - - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - card->set_reauth(card, this->permanent, reauth, this->mk, this->counter); - } - enumerator->destroy(enumerator); + charon->sim->card_set_reauth(charon->sim, this->permanent, reauth, + this->mk, this->counter); reauth->destroy(reauth); } /** - * Find a stored pseudonym on a SIM card - */ -static identification_t *get_pseudonym(private_eap_sim_peer_t *this) -{ - enumerator_t *enumerator; - sim_card_t *card; - identification_t *pseudonym = NULL; - - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - pseudonym = card->get_pseudonym(card, this->permanent); - if (pseudonym) - { - DBG1(DBG_IKE, "using stored pseudonym identity '%Y' " - "instead of '%Y'", pseudonym, this->permanent); - break; - } - } - enumerator->destroy(enumerator); - return pseudonym; -} - -/** * Store a pseudonym in a SIM card */ static void set_pseudonym(private_eap_sim_peer_t *this, chunk_t data) { - enumerator_t *enumerator; - sim_card_t *card; identification_t *pseudonym; char buf[data.len + 1]; snprintf(buf, sizeof(buf), "%.*s", data.len, data.ptr); pseudonym = identification_create_from_string(buf); DBG1(DBG_IKE, "received pseudonym '%Y' for next authentication", pseudonym); - enumerator = charon->sim->create_card_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &card)) - { - card->set_pseudonym(card, this->permanent, pseudonym); - } - enumerator->destroy(enumerator); + charon->sim->card_set_pseudonym(charon->sim, this->permanent, pseudonym); pseudonym->destroy(pseudonym); } @@ -306,7 +216,8 @@ static status_t process_start(private_eap_sim_peer_t *this, switch (id_req) { case AT_ANY_ID_REQ: - this->reauth = get_reauth(this); + this->reauth = charon->sim->card_get_reauth(charon->sim, + this->permanent, this->mk, &this->counter); if (this->reauth) { id = this->reauth->get_encoding(this->reauth); @@ -314,7 +225,8 @@ static status_t process_start(private_eap_sim_peer_t *this, } /* FALL */ case AT_FULLAUTH_ID_REQ: - this->pseudonym = get_pseudonym(this); + this->pseudonym = charon->sim->card_get_pseudonym(charon->sim, + this->permanent); if (this->pseudonym) { id = this->pseudonym->get_encoding(this->pseudonym); @@ -405,7 +317,8 @@ static status_t process_challenge(private_eap_sim_peer_t *this, sreses = sres = chunk_alloca(rands.len / 4); while (rands.len >= SIM_RAND_LEN) { - if (!get_triplet(this, this->permanent, rands.ptr, sres.ptr, kc.ptr)) + if (!charon->sim->card_get_triplet(charon->sim, this->permanent, + rands.ptr, sres.ptr, kc.ptr)) { DBG1(DBG_IKE, "unable to get EAP-SIM triplet"); *out = create_client_error(this, in->get_identifier(in), diff --git a/src/charon/plugins/eap_sim/eap_sim_server.c b/src/charon/plugins/eap_sim/eap_sim_server.c index fbc9daf4f..33c59a570 100644 --- a/src/charon/plugins/eap_sim/eap_sim_server.c +++ b/src/charon/plugins/eap_sim/eap_sim_server.c @@ -108,126 +108,6 @@ struct private_eap_sim_server_t { static chunk_t version = chunk_from_chars(0x00,0x01); /** - * Fetch a triplet from a provider - */ -static bool get_triplet(private_eap_sim_server_t *this, identification_t *peer, - char *rand, char *sres, char *kc) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - int tried = 0; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - if (provider->get_triplet(provider, peer, rand, sres, kc)) - { - enumerator->destroy(enumerator); - return TRUE; - } - tried++; - } - enumerator->destroy(enumerator); - DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", - tried, peer); - return FALSE; -} - -/** - * Generate a new reauthentication identity for next fast reauthentication - */ -static identification_t* gen_reauth(private_eap_sim_server_t *this, - char mk[HASH_SIZE_SHA1]) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *reauth = NULL; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - reauth = provider->gen_reauth(provider, this->permanent, mk); - if (reauth) - { - DBG1(DBG_IKE, "proposing new reauthentication identity '%Y'", reauth); - break; - } - } - enumerator->destroy(enumerator); - return reauth; -} - -/** - * Check if an identity is a known reauthentication identity - */ -static identification_t* is_reauth(private_eap_sim_server_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; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - permanent = provider->is_reauth(provider, id, mk, counter); - if (permanent) - { - break; - } - } - enumerator->destroy(enumerator); - return permanent; -} - -/** - * Generate a new pseudonym for next authentication - */ -static identification_t* gen_pseudonym(private_eap_sim_server_t *this) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *pseudonym = NULL; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - pseudonym = provider->gen_pseudonym(provider, this->permanent); - if (pseudonym) - { - DBG1(DBG_IKE, "proposing new pseudonym '%Y'", pseudonym); - break; - } - } - enumerator->destroy(enumerator); - return pseudonym; -} - -/** - * Check if an identity is a known pseudonym - */ -static identification_t* is_pseudonym(private_eap_sim_server_t *this, - identification_t *pseudonym) -{ - enumerator_t *enumerator; - sim_provider_t *provider; - identification_t *permanent = NULL; - - enumerator = charon->sim->create_provider_enumerator(charon->sim); - while (enumerator->enumerate(enumerator, &provider)) - { - permanent = provider->is_pseudonym(provider, pseudonym); - if (permanent) - { - break; - } - } - enumerator->destroy(enumerator); - return permanent; -} - -/** * Implementation of eap_method_t.initiate */ static status_t initiate(private_eap_sim_server_t *this, eap_payload_t **out) @@ -285,7 +165,7 @@ static status_t reauthenticate(private_eap_sim_server_t *this, SIM_REAUTHENTICATION, this->crypto); message->add_attribute(message, AT_COUNTER, this->counter); message->add_attribute(message, AT_NONCE_S, this->nonce); - next = gen_reauth(this, mk); + next = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk); if (next) { message->add_attribute(message, AT_NEXT_REAUTH_ID, @@ -424,7 +304,8 @@ static status_t process_start(private_eap_sim_server_t *this, char mk[HASH_SIZE_SHA1]; u_int16_t counter; - permanent = is_reauth(this, id, mk, &counter); + permanent = charon->sim->provider_is_reauth(charon->sim, id, + mk, &counter); if (permanent) { DBG1(DBG_IKE, "received reauthentication identity '%Y' " @@ -442,7 +323,7 @@ static status_t process_start(private_eap_sim_server_t *this, } if (this->use_pseudonym) { - permanent = is_pseudonym(this, id); + permanent = charon->sim->provider_is_pseudonym(charon->sim, id); if (permanent) { DBG1(DBG_IKE, "received pseudonym identity '%Y' " @@ -477,7 +358,8 @@ static status_t process_start(private_eap_sim_server_t *this, rands.len = kcs.len = sreses.len = 0; for (i = 0; i < TRIPLET_COUNT; i++) { - if (!get_triplet(this, this->permanent, rand.ptr, sres.ptr, kc.ptr)) + if (!charon->sim->provider_get_triplet(charon->sim, this->permanent, + rand.ptr, sres.ptr, kc.ptr)) { if (this->use_pseudonym) { @@ -514,7 +396,7 @@ static status_t process_start(private_eap_sim_server_t *this, message = simaka_message_create(TRUE, this->identifier++, EAP_SIM, SIM_CHALLENGE, this->crypto); message->add_attribute(message, AT_RAND, rands); - id = gen_reauth(this, mk.ptr); + id = charon->sim->provider_gen_reauth(charon->sim, this->permanent, mk.ptr); if (id) { message->add_attribute(message, AT_NEXT_REAUTH_ID, @@ -523,7 +405,7 @@ static status_t process_start(private_eap_sim_server_t *this, } else { - id = gen_pseudonym(this); + id = charon->sim->provider_gen_pseudonym(charon->sim, this->permanent); if (id) { message->add_attribute(message, AT_NEXT_PSEUDONYM, diff --git a/src/charon/sa/authenticators/eap/sim_manager.c b/src/charon/sa/authenticators/eap/sim_manager.c index b5edb75e2..5195f8f91 100644 --- a/src/charon/sa/authenticators/eap/sim_manager.c +++ b/src/charon/sa/authenticators/eap/sim_manager.c @@ -15,6 +15,7 @@ #include "sim_manager.h" +#include <daemon.h> #include <utils/linked_list.h> typedef struct private_sim_manager_t private_sim_manager_t; @@ -37,7 +38,7 @@ struct private_sim_manager_t { /** * list of added provider */ - linked_list_t *provider; + linked_list_t *providers; }; /** @@ -57,37 +58,356 @@ static void remove_card(private_sim_manager_t *this, sim_card_t *card) } /** - * Implementation of sim_manager_t.create_card_enumerator + * Implementation of sim_manager_t.card_get_triplet */ -static enumerator_t* create_card_enumerator(private_sim_manager_t *this) +static bool card_get_triplet(private_sim_manager_t *this, identification_t *id, + char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], + char kc[SIM_KC_LEN]) { - return this->cards->create_enumerator(this->cards); + enumerator_t *enumerator; + sim_card_t *card; + int tried = 0; + + enumerator = this->cards->create_enumerator(this->cards); + while (enumerator->enumerate(enumerator, &card)) + { + if (card->get_triplet(card, id, rand, sres, kc)) + { + enumerator->destroy(enumerator); + return TRUE; + } + tried++; + } + enumerator->destroy(enumerator); + DBG1(DBG_IKE, "tried %d SIM cards, but none has triplets for '%Y'", + tried, id); + return FALSE; +} + +/** + * Implementation of sim_manager_t.card_get_quintuplet + */ +static status_t card_get_quintuplet(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_LEN]) +{ + enumerator_t *enumerator; + sim_card_t *card; + status_t status = NOT_FOUND; + int tried = 0; + + enumerator = this->cards->create_enumerator(this->cards); + while (enumerator->enumerate(enumerator, &card)) + { + status = card->get_quintuplet(card, id, rand, autn, ck, ik, res); + if (status != FAILED) + { /* try next on error, but not on INVALID_STATE */ + enumerator->destroy(enumerator); + return status; + } + tried++; + } + enumerator->destroy(enumerator); + DBG1(DBG_IKE, "tried %d SIM cards, but none has quintuplets for '%Y'", + tried, id); + return status; +} + +/** + * Implementation of sim_manager_t.card_resync + */ +static bool card_resync(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; + + enumerator = this->cards->create_enumerator(this->cards); + while (enumerator->enumerate(enumerator, &card)) + { + if (card->resync(card, id, rand, auts)) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +/** + * Implementation of sim_manager_t.card_set_pseudonym + */ +static void card_set_pseudonym(private_sim_manager_t *this, + identification_t *id, identification_t *pseudonym) +{ + enumerator_t *enumerator; + sim_card_t *card; + + enumerator = this->cards->create_enumerator(this->cards); + while (enumerator->enumerate(enumerator, &card)) + { + card->set_pseudonym(card, id, pseudonym); + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of sim_manager_t.card_get_pseudonym + */ +static identification_t* card_get_pseudonym(private_sim_manager_t *this, + identification_t *id) +{ + enumerator_t *enumerator; + sim_card_t *card; + identification_t *pseudonym = NULL; + + 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); + return pseudonym; +} + +/** + * Implementation of sim_manager_t.card_set_reauth + */ +static void card_set_reauth(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; + + enumerator = this->cards->create_enumerator(this->cards); + while (enumerator->enumerate(enumerator, &card)) + { + card->set_reauth(card, id, next, mk, counter); + } + enumerator->destroy(enumerator); +} + +/** + * Implementation of sim_manager_t.card_get_reauth + */ +static identification_t* card_get_reauth(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; + + 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); + return reauth; } /** * Implementation of sim_manager_t.add_provider */ -static void add_provider(private_sim_manager_t *this, - sim_provider_t *provider) +static void add_provider(private_sim_manager_t *this, sim_provider_t *provider) { - this->provider->insert_last(this->provider, provider); + this->providers->insert_last(this->providers, provider); } /** * Implementation of sim_manager_t.remove_provider */ static void remove_provider(private_sim_manager_t *this, - sim_provider_t *provider) + sim_provider_t *provider) { - this->provider->remove(this->provider, provider, NULL); + this->providers->remove(this->providers, provider, NULL); } /** - * Implementation of sim_manager_t.create_provider_enumerator + * Implementation of sim_manager_t.provider_get_triplet */ -static enumerator_t* create_provider_enumerator(private_sim_manager_t *this) +static bool provider_get_triplet(private_sim_manager_t *this, + identification_t *id, char rand[SIM_RAND_LEN], + char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]) { - return this->provider->create_enumerator(this->provider); + enumerator_t *enumerator; + sim_provider_t *provider; + int tried = 0; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->get_triplet(provider, id, rand, sres, kc)) + { + enumerator->destroy(enumerator); + return TRUE; + } + tried++; + } + enumerator->destroy(enumerator); + DBG1(DBG_IKE, "tried %d SIM providers, but none had a triplet for '%Y'", + tried, id); + return FALSE; +} + +/** + * Implementation of sim_manager_t.provider_get_quintuplet + */ +static bool provider_get_quintuplet(private_sim_manager_t *this, + identification_t *id, char rand[AKA_RAND_LEN], + char xres[AKA_RES_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; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->get_quintuplet(provider, id, rand, xres, ck, ik, autn)) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + DBG1(DBG_IKE, "tried %d SIM providers, but none had a quintuplet for '%Y'", + tried, id); + return FALSE; +} + +/** + * Implementation of sim_manager_t.provider_resync + */ +static bool provider_resync(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; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + if (provider->resync(provider, id, rand, auts)) + { + enumerator->destroy(enumerator); + return TRUE; + } + } + enumerator->destroy(enumerator); + return FALSE; +} + +/** + * Implementation of sim_manager_t.provider_is_pseudonym + */ +static identification_t* provider_is_pseudonym(private_sim_manager_t *this, + identification_t *id) +{ + enumerator_t *enumerator; + sim_provider_t *provider; + identification_t *permanent = NULL; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + permanent = provider->is_pseudonym(provider, id); + if (permanent) + { + break; + } + } + enumerator->destroy(enumerator); + return permanent; +} + +/** + * Implementation of sim_manager_t.provider_gen_pseudonym + */ +static identification_t* provider_gen_pseudonym(private_sim_manager_t *this, + identification_t *id) +{ + enumerator_t *enumerator; + sim_provider_t *provider; + identification_t *pseudonym = NULL; + + 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); + return pseudonym; +} + +/** + * Implementation of sim_manager_t.provider_is_reauth + */ +static identification_t* provider_is_reauth(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; + + enumerator = this->providers->create_enumerator(this->providers); + while (enumerator->enumerate(enumerator, &provider)) + { + permanent = provider->is_reauth(provider, id, mk, counter); + if (permanent) + { + break; + } + } + enumerator->destroy(enumerator); + return permanent; +} + +/** + * Implementation of sim_manager_t.provider_gen_reauth + */ +static identification_t* provider_gen_reauth(private_sim_manager_t *this, + identification_t *id, char mk[HASH_SIZE_SHA1]) +{ + enumerator_t *enumerator; + sim_provider_t *provider; + identification_t *reauth = NULL; + + 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); + return reauth; } /** @@ -96,7 +416,7 @@ static enumerator_t* create_provider_enumerator(private_sim_manager_t *this) static void destroy(private_sim_manager_t *this) { this->cards->destroy(this->cards); - this->provider->destroy(this->provider); + this->providers->destroy(this->providers); free(this); } @@ -109,14 +429,26 @@ sim_manager_t *sim_manager_create() this->public.add_card = (void(*)(sim_manager_t*, sim_card_t *card))add_card; this->public.remove_card = (void(*)(sim_manager_t*, sim_card_t *card))remove_card; - this->public.create_card_enumerator = (enumerator_t*(*)(sim_manager_t*))create_card_enumerator; + this->public.card_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))card_get_triplet; + this->public.card_get_quintuplet = (status_t(*)(sim_manager_t*, 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_LEN]))card_get_quintuplet; + this->public.card_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))card_resync; + this->public.card_set_pseudonym = (void(*)(sim_manager_t*, identification_t *id, identification_t *pseudonym))card_set_pseudonym; + this->public.card_get_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))card_get_pseudonym; + this->public.card_set_reauth = (void(*)(sim_manager_t*, identification_t *id, identification_t *next, char mk[HASH_SIZE_SHA1], u_int16_t counter))card_set_reauth; + this->public.card_get_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))card_get_reauth; this->public.add_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))add_provider; this->public.remove_provider = (void(*)(sim_manager_t*, sim_provider_t *provider))remove_provider; - this->public.create_provider_enumerator = (enumerator_t*(*)(sim_manager_t*))create_provider_enumerator; + this->public.provider_get_triplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[SIM_RAND_LEN], char sres[SIM_SRES_LEN], char kc[SIM_KC_LEN]))provider_get_triplet; + this->public.provider_get_quintuplet = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char xres[AKA_RES_LEN], char ck[AKA_CK_LEN], char ik[AKA_IK_LEN], char autn[AKA_AUTN_LEN]))provider_get_quintuplet; + this->public.provider_resync = (bool(*)(sim_manager_t*, identification_t *id, char rand[AKA_RAND_LEN], char auts[AKA_AUTS_LEN]))provider_resync; + this->public.provider_is_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_is_pseudonym; + this->public.provider_gen_pseudonym = (identification_t*(*)(sim_manager_t*, identification_t *id))provider_gen_pseudonym; + this->public.provider_is_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1], u_int16_t *counter))provider_is_reauth; + this->public.provider_gen_reauth = (identification_t*(*)(sim_manager_t*, identification_t *id, char mk[HASH_SIZE_SHA1]))provider_gen_reauth; this->public.destroy = (void(*)(sim_manager_t*))destroy; this->cards = linked_list_create(); - this->provider = linked_list_create(); + this->providers = linked_list_create(); return &this->public; } diff --git a/src/charon/sa/authenticators/eap/sim_manager.h b/src/charon/sa/authenticators/eap/sim_manager.h index cc109f765..a4dbffa6b 100644 --- a/src/charon/sa/authenticators/eap/sim_manager.h +++ b/src/charon/sa/authenticators/eap/sim_manager.h @@ -128,6 +128,7 @@ struct sim_card_t { * @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); @@ -244,11 +245,86 @@ struct sim_manager_t { void (*remove_card)(sim_manager_t *this, sim_card_t *card); /** - * Create an enumerator over all registered cards. + * Calculate SIM triplets on one of the registered SIM cards. * - * @return enumerator over sim_card_t's + * @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 + * @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_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 */ - enumerator_t* (*create_card_enumerator)(sim_manager_t *this); + 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. @@ -265,11 +341,84 @@ struct sim_manager_t { void (*remove_provider)(sim_manager_t *this, sim_provider_t *provider); /** - * Create an enumerator over all registered provider. + * Get a SIM triplet from one of the registered providers. * - * @return enumerator over sim_provider_t's + * @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_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 */ - enumerator_t* (*create_provider_enumerator)(sim_manager_t *this); + identification_t* (*provider_gen_reauth)(sim_manager_t *this, + identification_t *id, char mk[HASH_SIZE_SHA1]); /** * Destroy a manager instance. |