]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
Moved card/provider enumeration to SIM manager, providing wrapped functions for both...
authorMartin Willi <martin@strongswan.org>
Thu, 29 Oct 2009 13:56:45 +0000 (14:56 +0100)
committerMartin Willi <martin@strongswan.org>
Thu, 12 Nov 2009 09:34:01 +0000 (10:34 +0100)
src/charon/plugins/eap_aka/eap_aka_peer.c
src/charon/plugins/eap_aka/eap_aka_server.c
src/charon/plugins/eap_sim/eap_sim_peer.c
src/charon/plugins/eap_sim/eap_sim_server.c
src/charon/sa/authenticators/eap/sim_manager.c
src/charon/sa/authenticators/eap/sim_manager.h

index 136a774db9c93a363193002b6555cffe500492d1..1ff445c910c6b323a56de1230bd867c13013bdfc 100644 (file)
@@ -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);
index 9f6e71ad7833f6a1b57e8ee18714e1d77c6ead45..87c718baa97c95f94cd591b823aa19ea773f607d 100644 (file)
@@ -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);
index 8574f7da7135232a23351544420ef43e85a2aaaf..bd78c516a14003005892ca98f60be4afe756aea4 100644 (file)
@@ -94,124 +94,34 @@ struct private_eap_sim_peer_t {
 /* version of SIM protocol we speak */
 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),
index fbc9daf4f65760e28a9b31f1b3147fcd0e7999a1..33c59a570ef9e0c56ffa30502e4c5a588fc8a984 100644 (file)
@@ -107,126 +107,6 @@ struct private_eap_sim_server_t {
 /* version of SIM protocol we speak */
 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
  */
@@ -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,
index b5edb75e218b674074bbf5b3327644ec1d895293..5195f8f9102419b4135a016033022f677fc52f16 100644 (file)
@@ -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;
 }
index cc109f7652e9a9f259096990586f58ed64733660..a4dbffa6ba0a6380f200fb4c0a8e13882f705330 100644 (file)
@@ -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.