diff options
Diffstat (limited to 'src/libstrongswan/crypto/crypto_factory.c')
-rw-r--r-- | src/libstrongswan/crypto/crypto_factory.c | 281 |
1 files changed, 187 insertions, 94 deletions
diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index 46fa983b2..9836ed468 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -12,7 +12,7 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * - * $Id: crypto_factory.c 3806 2008-04-15 05:56:35Z martin $ + * $Id: crypto_factory.c 4307 2008-08-28 09:24:42Z martin $ */ #include "crypto_factory.h" @@ -20,52 +20,19 @@ #include <utils/linked_list.h> #include <utils/mutex.h> -typedef struct crypter_entry_t crypter_entry_t; -struct crypter_entry_t { - /** encryption algorithm */ - encryption_algorithm_t algo; - /** associated constructor */ - crypter_constructor_t create; -}; - -typedef struct signer_entry_t signer_entry_t; -struct signer_entry_t { - /** integrity algorithm */ - integrity_algorithm_t algo; - /** associated constructor */ - signer_constructor_t create; -}; - -typedef struct hasher_entry_t hasher_entry_t; -struct hasher_entry_t { - /** hash algorithm */ - hash_algorithm_t algo; - /** associated constructor */ - hasher_constructor_t create; -}; - -typedef struct prf_entry_t prf_entry_t; -struct prf_entry_t { - /** hash algorithm */ - pseudo_random_function_t algo; - /** associated constructor */ - prf_constructor_t create; -}; - -typedef struct rng_entry_t rng_entry_t; -struct rng_entry_t { - /** quality of randomness */ - rng_quality_t quality; - /** associated constructor */ - rng_constructor_t create; -}; - -typedef struct dh_entry_t dh_entry_t; -struct dh_entry_t { - /** hash algorithm */ - diffie_hellman_group_t group; - /** associated constructor */ - dh_constructor_t create; +typedef struct entry_t entry_t; +struct entry_t { + /** algorithm */ + u_int algo; + /* constructor */ + union { + crypter_constructor_t create_crypter; + signer_constructor_t create_signer; + hasher_constructor_t create_hasher; + prf_constructor_t create_prf; + rng_constructor_t create_rng; + dh_constructor_t create_dh; + }; }; typedef struct private_crypto_factory_t private_crypto_factory_t; @@ -81,32 +48,32 @@ struct private_crypto_factory_t { crypto_factory_t public; /** - * registered crypters, as crypter_entry_t + * registered crypters, as entry_t */ linked_list_t *crypters; /** - * registered signers, as signer_entry_t + * registered signers, as entry_t */ linked_list_t *signers; /** - * registered hashers, as hasher_entry_t + * registered hashers, as entry_t */ linked_list_t *hashers; /** - * registered prfs, as prf_entry_t + * registered prfs, as entry_t */ linked_list_t *prfs; /** - * registered rngs, as rng_entry_t + * registered rngs, as entry_t */ linked_list_t *rngs; /** - * registered diffie hellman, as dh_entry_t + * registered diffie hellman, as entry_t */ linked_list_t *dhs; @@ -123,7 +90,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size) { enumerator_t *enumerator; - crypter_entry_t *entry; + entry_t *entry; crypter_t *crypter = NULL; this->mutex->lock(this->mutex); @@ -132,7 +99,7 @@ static crypter_t* create_crypter(private_crypto_factory_t *this, { if (entry->algo == algo) { - crypter = entry->create(algo, key_size); + crypter = entry->create_crypter(algo, key_size); if (crypter) { break; @@ -151,7 +118,7 @@ static signer_t* create_signer(private_crypto_factory_t *this, integrity_algorithm_t algo) { enumerator_t *enumerator; - signer_entry_t *entry; + entry_t *entry; signer_t *signer = NULL; this->mutex->lock(this->mutex); @@ -160,7 +127,7 @@ static signer_t* create_signer(private_crypto_factory_t *this, { if (entry->algo == algo) { - signer = entry->create(algo); + signer = entry->create_signer(algo); if (signer) { break; @@ -180,7 +147,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this, hash_algorithm_t algo) { enumerator_t *enumerator; - hasher_entry_t *entry; + entry_t *entry; hasher_t *hasher = NULL; this->mutex->lock(this->mutex); @@ -189,7 +156,7 @@ static hasher_t* create_hasher(private_crypto_factory_t *this, { if (algo == HASH_PREFERRED || entry->algo == algo) { - hasher = entry->create(entry->algo); + hasher = entry->create_hasher(entry->algo); if (hasher) { break; @@ -208,7 +175,7 @@ static prf_t* create_prf(private_crypto_factory_t *this, pseudo_random_function_t algo) { enumerator_t *enumerator; - prf_entry_t *entry; + entry_t *entry; prf_t *prf = NULL; this->mutex->lock(this->mutex); @@ -217,7 +184,7 @@ static prf_t* create_prf(private_crypto_factory_t *this, { if (entry->algo == algo) { - prf = entry->create(algo); + prf = entry->create_prf(algo); if (prf) { break; @@ -235,7 +202,7 @@ static prf_t* create_prf(private_crypto_factory_t *this, static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) { enumerator_t *enumerator; - rng_entry_t *entry; + entry_t *entry; u_int diff = ~0; rng_constructor_t constr = NULL; @@ -243,10 +210,10 @@ static rng_t* create_rng(private_crypto_factory_t *this, rng_quality_t quality) enumerator = this->rngs->create_enumerator(this->rngs); while (enumerator->enumerate(enumerator, &entry)) { /* find the best matching quality, but at least as good as requested */ - if (entry->quality >= quality && diff > entry->quality - quality) + if (entry->algo >= quality && diff > entry->algo - quality) { - diff = entry->quality - quality; - constr = entry->create; + diff = entry->algo - quality; + constr = entry->create_rng; if (diff == 0) { /* perfect match, won't get better */ break; @@ -269,16 +236,16 @@ static diffie_hellman_t* create_dh(private_crypto_factory_t *this, diffie_hellman_group_t group) { enumerator_t *enumerator; - dh_entry_t *entry; + entry_t *entry; diffie_hellman_t *diffie_hellman = NULL; this->mutex->lock(this->mutex); enumerator = this->dhs->create_enumerator(this->dhs); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->group == group) + if (entry->algo == group) { - diffie_hellman = entry->create(group); + diffie_hellman = entry->create_dh(group); if (diffie_hellman) { break; @@ -297,10 +264,10 @@ static void add_crypter(private_crypto_factory_t *this, encryption_algorithm_t algo, crypter_constructor_t create) { - crypter_entry_t *entry = malloc_thing(crypter_entry_t); + entry_t *entry = malloc_thing(entry_t); entry->algo = algo; - entry->create = create; + entry->create_crypter = create; this->mutex->lock(this->mutex); this->crypters->insert_last(this->crypters, entry); this->mutex->unlock(this->mutex); @@ -312,14 +279,14 @@ static void add_crypter(private_crypto_factory_t *this, static void remove_crypter(private_crypto_factory_t *this, crypter_constructor_t create) { - crypter_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->crypters->create_enumerator(this->crypters); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_crypter == create) { this->crypters->remove_at(this->crypters, enumerator); free(entry); @@ -335,10 +302,10 @@ static void remove_crypter(private_crypto_factory_t *this, static void add_signer(private_crypto_factory_t *this, integrity_algorithm_t algo, signer_constructor_t create) { - signer_entry_t *entry = malloc_thing(signer_entry_t); + entry_t *entry = malloc_thing(entry_t); entry->algo = algo; - entry->create = create; + entry->create_signer = create; this->mutex->lock(this->mutex); this->signers->insert_last(this->signers, entry); this->mutex->unlock(this->mutex); @@ -350,14 +317,14 @@ static void add_signer(private_crypto_factory_t *this, static void remove_signer(private_crypto_factory_t *this, signer_constructor_t create) { - signer_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->signers->create_enumerator(this->signers); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_signer == create) { this->signers->remove_at(this->signers, enumerator); free(entry); @@ -373,10 +340,10 @@ static void remove_signer(private_crypto_factory_t *this, static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo, hasher_constructor_t create) { - hasher_entry_t *entry = malloc_thing(hasher_entry_t); + entry_t *entry = malloc_thing(entry_t); entry->algo = algo; - entry->create = create; + entry->create_hasher = create; this->mutex->lock(this->mutex); this->hashers->insert_last(this->hashers, entry); this->mutex->unlock(this->mutex); @@ -388,14 +355,14 @@ static void add_hasher(private_crypto_factory_t *this, hash_algorithm_t algo, static void remove_hasher(private_crypto_factory_t *this, hasher_constructor_t create) { - hasher_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->hashers->create_enumerator(this->hashers); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_hasher == create) { this->hashers->remove_at(this->hashers, enumerator); free(entry); @@ -411,10 +378,10 @@ static void remove_hasher(private_crypto_factory_t *this, static void add_prf(private_crypto_factory_t *this, pseudo_random_function_t algo, prf_constructor_t create) { - prf_entry_t *entry = malloc_thing(prf_entry_t); + entry_t *entry = malloc_thing(entry_t); entry->algo = algo; - entry->create = create; + entry->create_prf = create; this->mutex->lock(this->mutex); this->prfs->insert_last(this->prfs, entry); this->mutex->unlock(this->mutex); @@ -425,14 +392,14 @@ static void add_prf(private_crypto_factory_t *this, */ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) { - prf_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->prfs->create_enumerator(this->prfs); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_prf == create) { this->prfs->remove_at(this->prfs, enumerator); free(entry); @@ -448,10 +415,10 @@ static void remove_prf(private_crypto_factory_t *this, prf_constructor_t create) static void add_rng(private_crypto_factory_t *this, rng_quality_t quality, rng_constructor_t create) { - rng_entry_t *entry = malloc_thing(rng_entry_t); + entry_t *entry = malloc_thing(entry_t); - entry->quality = quality; - entry->create = create; + entry->algo = quality; + entry->create_rng = create; this->mutex->lock(this->mutex); this->rngs->insert_last(this->rngs, entry); this->mutex->unlock(this->mutex); @@ -462,14 +429,14 @@ static void add_rng(private_crypto_factory_t *this, rng_quality_t quality, */ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) { - rng_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->rngs->create_enumerator(this->rngs); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_rng == create) { this->rngs->remove_at(this->rngs, enumerator); free(entry); @@ -485,10 +452,10 @@ static void remove_rng(private_crypto_factory_t *this, rng_constructor_t create) static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group, dh_constructor_t create) { - dh_entry_t *entry = malloc_thing(dh_entry_t); + entry_t *entry = malloc_thing(entry_t); - entry->group = group; - entry->create = create; + entry->algo = group; + entry->create_dh = create; this->mutex->lock(this->mutex); this->dhs->insert_last(this->dhs, entry); this->mutex->unlock(this->mutex); @@ -499,14 +466,14 @@ static void add_dh(private_crypto_factory_t *this, diffie_hellman_group_t group, */ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create) { - dh_entry_t *entry; + entry_t *entry; enumerator_t *enumerator; this->mutex->lock(this->mutex); enumerator = this->dhs->create_enumerator(this->dhs); while (enumerator->enumerate(enumerator, &entry)) { - if (entry->create == create) + if (entry->create_dh == create) { this->dhs->remove_at(this->dhs, enumerator); free(entry); @@ -517,6 +484,127 @@ static void remove_dh(private_crypto_factory_t *this, dh_constructor_t create) } /** + * match algorithms of an entry? + */ +static bool entry_match(entry_t *a, entry_t *b) +{ + return a->algo == b->algo; +} + +/** + * check for uniqueness of an entry + */ +static bool unique_check(linked_list_t *list, entry_t **in, entry_t **out) +{ + if (list->find_first(list, (void*)entry_match, NULL, *in) == SUCCESS) + { + return FALSE; + } + *out = *in; + list->insert_last(list, *in); + return TRUE; +} + +/** + * create an enumerator over entry->algo in list with locking and unique check + */ +static enumerator_t *create_enumerator(private_crypto_factory_t *this, + linked_list_t *list, void *filter) +{ + this->mutex->lock(this->mutex); + return enumerator_create_filter( + enumerator_create_filter( + list->create_enumerator(list), (void*)unique_check, + linked_list_create(), (void*)list->destroy), + filter, this->mutex, (void*)this->mutex->unlock); +} + +/** + * Filter function to enumerate algorithm, not entry + */ +static bool crypter_filter(void *n, entry_t **entry, encryption_algorithm_t *algo) +{ + *algo = (*entry)->algo; + return TRUE; +} + +/** + * Implementation of crypto_factory_t.create_crypter_enumerator + */ +static enumerator_t* create_crypter_enumerator(private_crypto_factory_t *this) +{ + return create_enumerator(this, this->crypters, crypter_filter); +} + +/** + * Filter function to enumerate algorithm, not entry + */ +static bool signer_filter(void *n, entry_t **entry, integrity_algorithm_t *algo) +{ + *algo = (*entry)->algo; + return TRUE; +} + +/** + * Implementation of crypto_factory_t.create_signer_enumerator + */ +static enumerator_t* create_signer_enumerator(private_crypto_factory_t *this) +{ + return create_enumerator(this, this->signers, signer_filter); +} + +/** + * Filter function to enumerate algorithm, not entry + */ +static bool hasher_filter(void *n, entry_t **entry, hash_algorithm_t *algo) +{ + *algo = (*entry)->algo; + return TRUE; +} + +/** + * Implementation of crypto_factory_t.create_hasher_enumerator + */ +static enumerator_t* create_hasher_enumerator(private_crypto_factory_t *this) +{ + return create_enumerator(this, this->hashers, hasher_filter); +} + +/** + * Filter function to enumerate algorithm, not entry + */ +static bool prf_filter(void *n, entry_t **entry, pseudo_random_function_t *algo) +{ + *algo = (*entry)->algo; + return TRUE; +} + +/** + * Implementation of crypto_factory_t.create_prf_enumerator + */ +static enumerator_t* create_prf_enumerator(private_crypto_factory_t *this) +{ + return create_enumerator(this, this->prfs, prf_filter); +} + +/** + * Filter function to enumerate algorithm, not entry + */ +static bool dh_filter(void *n, entry_t **entry, diffie_hellman_group_t *group) +{ + *group = (*entry)->algo; + return TRUE; +} + +/** + * Implementation of crypto_factory_t.create_dh_enumerator + */ +static enumerator_t* create_dh_enumerator(private_crypto_factory_t *this) +{ + return create_enumerator(this, this->dhs, dh_filter); +} + +/** * Implementation of crypto_factory_t.destroy */ static void destroy(private_crypto_factory_t *this) @@ -556,6 +644,11 @@ crypto_factory_t *crypto_factory_create() this->public.remove_rng = (void(*)(crypto_factory_t*, rng_constructor_t create))remove_rng; this->public.add_dh = (void(*)(crypto_factory_t*, diffie_hellman_group_t algo, dh_constructor_t create))add_dh; this->public.remove_dh = (void(*)(crypto_factory_t*, dh_constructor_t create))remove_dh; + this->public.create_crypter_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_crypter_enumerator; + this->public.create_signer_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_signer_enumerator; + this->public.create_hasher_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_hasher_enumerator; + this->public.create_prf_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_prf_enumerator; + this->public.create_dh_enumerator = (enumerator_t*(*)(crypto_factory_t*))create_dh_enumerator; this->public.destroy = (void(*)(crypto_factory_t*))destroy; this->crypters = linked_list_create(); |