diff options
Diffstat (limited to 'src/libstrongswan/crypto')
-rw-r--r-- | src/libstrongswan/crypto/aead.c | 4 | ||||
-rw-r--r-- | src/libstrongswan/crypto/aead.h | 3 | ||||
-rw-r--r-- | src/libstrongswan/crypto/crypto_factory.c | 182 | ||||
-rw-r--r-- | src/libstrongswan/crypto/crypto_factory.h | 21 | ||||
-rw-r--r-- | src/libstrongswan/crypto/crypto_tester.c | 193 | ||||
-rw-r--r-- | src/libstrongswan/crypto/crypto_tester.h | 41 | ||||
-rw-r--r-- | src/libstrongswan/crypto/diffie_hellman.h | 12 | ||||
-rw-r--r-- | src/libstrongswan/crypto/iv/iv_gen.c | 61 | ||||
-rw-r--r-- | src/libstrongswan/crypto/iv/iv_gen.h | 8 | ||||
-rw-r--r-- | src/libstrongswan/crypto/iv/iv_gen_seq.c | 24 | ||||
-rw-r--r-- | src/libstrongswan/crypto/iv/iv_gen_seq.h | 3 | ||||
-rw-r--r-- | src/libstrongswan/crypto/signers/mac_signer.c | 3 | ||||
-rw-r--r-- | src/libstrongswan/crypto/transform.c | 32 | ||||
-rw-r--r-- | src/libstrongswan/crypto/transform.h | 8 |
14 files changed, 522 insertions, 73 deletions
diff --git a/src/libstrongswan/crypto/aead.c b/src/libstrongswan/crypto/aead.c index afcc11fbe..d50bd4d22 100644 --- a/src/libstrongswan/crypto/aead.c +++ b/src/libstrongswan/crypto/aead.c @@ -172,7 +172,7 @@ METHOD(aead_t, destroy, void, /** * See header */ -aead_t *aead_create(crypter_t *crypter, signer_t *signer) +aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen) { private_aead_t *this; @@ -190,7 +190,7 @@ aead_t *aead_create(crypter_t *crypter, signer_t *signer) }, .crypter = crypter, .signer = signer, - .iv_gen = iv_gen_rand_create(), + .iv_gen = iv_gen, ); return &this->public; diff --git a/src/libstrongswan/crypto/aead.h b/src/libstrongswan/crypto/aead.h index 43f71b65e..9d1b8df55 100644 --- a/src/libstrongswan/crypto/aead.h +++ b/src/libstrongswan/crypto/aead.h @@ -135,8 +135,9 @@ struct aead_t { * * @param crypter encryption transform for this aead * @param signer integrity transform for this aead + * @param iv_gen suitable IV generator for encryption algorithm * @return aead transform */ -aead_t *aead_create(crypter_t *crypter, signer_t *signer); +aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen); #endif /** AEAD_H_ @}*/ diff --git a/src/libstrongswan/crypto/crypto_factory.c b/src/libstrongswan/crypto/crypto_factory.c index 96fbc0d87..b0b86372c 100644 --- a/src/libstrongswan/crypto/crypto_factory.c +++ b/src/libstrongswan/crypto/crypto_factory.c @@ -377,6 +377,12 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*, { if (entry->algo == group) { + if (this->test_on_create && group != MODP_CUSTOM && + !this->tester->test_dh(this->tester, group, + entry->create_dh, NULL, default_plugin_name)) + { + continue; + } diffie_hellman = entry->create_dh(group, g, p); if (diffie_hellman) { @@ -439,14 +445,14 @@ static void add_entry(private_crypto_factory_t *this, linked_list_t *list, } METHOD(crypto_factory_t, add_crypter, bool, - private_crypto_factory_t *this, encryption_algorithm_t algo, + private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size, const char *plugin_name, crypter_constructor_t create) { u_int speed = 0; if (!this->test_on_add || - this->tester->test_crypter(this->tester, algo, 0, create, - this->bench ? &speed : NULL, plugin_name)) + this->tester->test_crypter(this->tester, algo, key_size, create, + this->bench ? &speed : NULL, plugin_name)) { add_entry(this, this->crypters, algo, plugin_name, speed, create); return TRUE; @@ -476,13 +482,13 @@ METHOD(crypto_factory_t, remove_crypter, void, } METHOD(crypto_factory_t, add_aead, bool, - private_crypto_factory_t *this, encryption_algorithm_t algo, + private_crypto_factory_t *this, encryption_algorithm_t algo, size_t key_size, const char *plugin_name, aead_constructor_t create) { u_int speed = 0; if (!this->test_on_add || - this->tester->test_aead(this->tester, algo, 0, 0, create, + this->tester->test_aead(this->tester, algo, key_size, 0, create, this->bench ? &speed : NULL, plugin_name)) { add_entry(this, this->aeads, algo, plugin_name, speed, create); @@ -692,8 +698,17 @@ METHOD(crypto_factory_t, add_dh, bool, private_crypto_factory_t *this, diffie_hellman_group_t group, const char *plugin_name, dh_constructor_t create) { - add_entry(this, this->dhs, group, plugin_name, 0, create); - return TRUE; + u_int speed = 0; + + if (!this->test_on_add || + this->tester->test_dh(this->tester, group, create, + this->bench ? &speed : NULL, plugin_name)) + { + add_entry(this, this->dhs, group, plugin_name, 0, create); + return TRUE; + } + this->test_failures++; + return FALSE; } METHOD(crypto_factory_t, remove_dh, void, @@ -892,16 +907,125 @@ METHOD(crypto_factory_t, add_test_vector, void, return this->tester->add_prf_vector(this->tester, vector); case RANDOM_NUMBER_GENERATOR: return this->tester->add_rng_vector(this->tester, vector); + case DIFFIE_HELLMAN_GROUP: + return this->tester->add_dh_vector(this->tester, vector); default: DBG1(DBG_LIB, "%N test vectors not supported, ignored", transform_type_names, type); } } -METHOD(crypto_factory_t, get_test_vector_failures, u_int, - private_crypto_factory_t *this) +/** + * Private enumerator for create_verify_enumerator() + */ +typedef struct { + enumerator_t public; + enumerator_t *inner; + transform_type_t type; + crypto_tester_t *tester; + rwlock_t *lock; +} verify_enumerator_t; + +METHOD(enumerator_t, verify_enumerate, bool, + verify_enumerator_t *this, u_int *alg, const char **plugin, bool *valid) { - return this->test_failures; + entry_t *entry; + + if (!this->inner->enumerate(this->inner, &entry)) + { + return FALSE; + } + switch (this->type) + { + case ENCRYPTION_ALGORITHM: + *valid = this->tester->test_crypter(this->tester, entry->algo, 0, + entry->create_crypter, NULL, entry->plugin_name); + break; + case AEAD_ALGORITHM: + *valid = this->tester->test_aead(this->tester, entry->algo, 0, 0, + entry->create_aead, NULL, entry->plugin_name); + break; + case INTEGRITY_ALGORITHM: + *valid = this->tester->test_signer(this->tester, entry->algo, + entry->create_signer, NULL, entry->plugin_name); + break; + case HASH_ALGORITHM: + *valid = this->tester->test_hasher(this->tester, entry->algo, + entry->create_hasher, NULL, entry->plugin_name); + break; + case PSEUDO_RANDOM_FUNCTION: + *valid = this->tester->test_prf(this->tester, entry->algo, + entry->create_prf, NULL, entry->plugin_name); + break; + case RANDOM_NUMBER_GENERATOR: + *valid = this->tester->test_rng(this->tester, entry->algo, + entry->create_rng, NULL, entry->plugin_name); + break; + case DIFFIE_HELLMAN_GROUP: + *valid = this->tester->test_dh(this->tester, entry->algo, + entry->create_dh, NULL, entry->plugin_name); + break; + default: + return FALSE; + } + *plugin = entry->plugin_name; + *alg = entry->algo; + return TRUE; +} + +METHOD(enumerator_t, verify_destroy, void, + verify_enumerator_t *this) +{ + this->inner->destroy(this->inner); + this->lock->unlock(this->lock); + free(this); +} + +METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*, + private_crypto_factory_t *this, transform_type_t type) +{ + verify_enumerator_t *enumerator; + enumerator_t *inner; + + this->lock->read_lock(this->lock); + switch (type) + { + case ENCRYPTION_ALGORITHM: + inner = this->crypters->create_enumerator(this->crypters); + break; + case AEAD_ALGORITHM: + inner = this->aeads->create_enumerator(this->aeads); + break; + case INTEGRITY_ALGORITHM: + inner = this->signers->create_enumerator(this->signers); + break; + case HASH_ALGORITHM: + inner = this->hashers->create_enumerator(this->hashers); + break; + case PSEUDO_RANDOM_FUNCTION: + inner = this->prfs->create_enumerator(this->prfs); + break; + case RANDOM_NUMBER_GENERATOR: + inner = this->rngs->create_enumerator(this->rngs); + break; + case DIFFIE_HELLMAN_GROUP: + inner = this->dhs->create_enumerator(this->dhs); + break; + default: + this->lock->unlock(this->lock); + return enumerator_create_empty(); + } + INIT(enumerator, + .public = { + .enumerate = (void*)_verify_enumerate, + .destroy = _verify_destroy, + }, + .inner = inner, + .type = type, + .tester = this->tester, + .lock = this->lock, + ); + return &enumerator->public; } METHOD(crypto_factory_t, destroy, void, @@ -962,7 +1086,7 @@ crypto_factory_t *crypto_factory_create() .create_rng_enumerator = _create_rng_enumerator, .create_nonce_gen_enumerator = _create_nonce_gen_enumerator, .add_test_vector = _add_test_vector, - .get_test_vector_failures = _get_test_vector_failures, + .create_verify_enumerator = _create_verify_enumerator, .destroy = _destroy, }, .crypters = linked_list_create(), @@ -985,39 +1109,3 @@ crypto_factory_t *crypto_factory_create() return &this->public; } - -/** - * Manually verify all registered algorithms against test vectors - */ -static u_int verify_registered_algorithms(crypto_factory_t *factory) -{ - private_crypto_factory_t *this = (private_crypto_factory_t*)factory; - enumerator_t *enumerator; - entry_t *entry; - u_int failures = 0; - -#define TEST_ALGORITHMS(test, ...) do { \ - enumerator = this->test##s->create_enumerator(this->test##s); \ - while (enumerator->enumerate(enumerator, &entry)) \ - { \ - if (!this->tester->test_##test(this->tester, entry->algo, ##__VA_ARGS__, \ - entry->create_##test, NULL, entry->plugin_name)) \ - { \ - failures++; \ - } \ - } \ - enumerator->destroy(enumerator); \ -} while (0) - - this->lock->read_lock(this->lock); - TEST_ALGORITHMS(crypter, 0); - TEST_ALGORITHMS(aead, 0, 0); - TEST_ALGORITHMS(signer); - TEST_ALGORITHMS(hasher); - TEST_ALGORITHMS(prf); - TEST_ALGORITHMS(rng); - this->lock->unlock(this->lock); - return failures; -} - -EXPORT_FUNCTION_FOR_TESTS(crypto, verify_registered_algorithms); diff --git a/src/libstrongswan/crypto/crypto_factory.h b/src/libstrongswan/crypto/crypto_factory.h index 7865bcb15..e03915603 100644 --- a/src/libstrongswan/crypto/crypto_factory.h +++ b/src/libstrongswan/crypto/crypto_factory.h @@ -162,12 +162,14 @@ struct crypto_factory_t { * Register a crypter constructor. * * @param algo algorithm to constructor + * @param key size key size to peform benchmarking for * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return TRUE if registered, FALSE if test vector failed */ bool (*add_crypter)(crypto_factory_t *this, encryption_algorithm_t algo, - const char *plugin_name, crypter_constructor_t create); + size_t key_size, const char *plugin_name, + crypter_constructor_t create); /** * Unregister a crypter constructor. @@ -187,12 +189,14 @@ struct crypto_factory_t { * Register a aead constructor. * * @param algo algorithm to constructor + * @param key size key size to peform benchmarking for * @param plugin_name plugin that registered this algorithm * @param create constructor function for that algorithm * @return TRUE if registered, FALSE if test vector failed */ bool (*add_aead)(crypto_factory_t *this, encryption_algorithm_t algo, - const char *plugin_name, aead_constructor_t create); + size_t key_size, const char *plugin_name, + aead_constructor_t create); /** * Register a signer constructor. @@ -368,14 +372,17 @@ struct crypto_factory_t { void *vector); /** - * Get the number of test vector failures encountered during add. + * Create an enumerator verifying transforms using known test vectors. * - * This counter gets incremented only if transforms get tested during - * registration. + * The resulting enumerator enumerates over an u_int with the type + * specific transform identifier, the plugin name providing the transform, + * and a boolean value indicating success/failure for the given transform. * - * @return number of failed test vectors + * @param type transform type to test + * @return enumerator over (u_int, char*, bool) */ - u_int (*get_test_vector_failures)(crypto_factory_t *this); + enumerator_t* (*create_verify_enumerator)(crypto_factory_t *this, + transform_type_t type); /** * Destroy a crypto_factory instance. diff --git a/src/libstrongswan/crypto/crypto_tester.c b/src/libstrongswan/crypto/crypto_tester.c index 15ed17381..5607d35b9 100644 --- a/src/libstrongswan/crypto/crypto_tester.c +++ b/src/libstrongswan/crypto/crypto_tester.c @@ -68,6 +68,11 @@ struct private_crypto_tester_t { linked_list_t *rng; /** + * List of Diffie-Hellman test vectors + */ + linked_list_t *dh; + + /** * Is a test vector required to pass a test? */ bool required; @@ -138,11 +143,11 @@ static u_int end_timing(struct timespec *start) * Benchmark a crypter */ static u_int bench_crypter(private_crypto_tester_t *this, - encryption_algorithm_t alg, crypter_constructor_t create) + encryption_algorithm_t alg, crypter_constructor_t create, size_t key_size) { crypter_t *crypter; - crypter = create(alg, 0); + crypter = create(alg, key_size); if (crypter) { char iv[crypter->get_iv_size(crypter)]; @@ -280,8 +285,8 @@ failure: { if (failed) { - DBG1(DBG_LIB,"disable %N[%s]: no key size supported", - encryption_algorithm_names, alg, plugin_name); + DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported", + encryption_algorithm_names, alg, plugin_name, key_size); return FALSE; } else @@ -296,9 +301,10 @@ failure: { if (speed) { - *speed = bench_crypter(this, alg, create); - DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", - encryption_algorithm_names, alg, plugin_name, tested, *speed); + *speed = bench_crypter(this, alg, create, key_size); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points " + "(%zd bit key)", encryption_algorithm_names, alg, + plugin_name, tested, *speed, key_size * 8); } else { @@ -313,11 +319,11 @@ failure: * Benchmark an aead transform */ static u_int bench_aead(private_crypto_tester_t *this, - encryption_algorithm_t alg, aead_constructor_t create) + encryption_algorithm_t alg, aead_constructor_t create, size_t key_size) { aead_t *aead; - aead = create(alg, 0, 0); + aead = create(alg, key_size, 0); if (aead) { char iv[aead->get_iv_size(aead)]; @@ -474,8 +480,8 @@ failure: { if (failed) { - DBG1(DBG_LIB,"disable %N[%s]: no key size supported", - encryption_algorithm_names, alg, plugin_name); + DBG1(DBG_LIB,"disable %N[%s]: %zd byte key size not supported", + encryption_algorithm_names, alg, plugin_name, key_size); return FALSE; } else @@ -490,9 +496,10 @@ failure: { if (speed) { - *speed = bench_aead(this, alg, create); - DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", - encryption_algorithm_names, alg, plugin_name, tested, *speed); + *speed = bench_aead(this, alg, create, key_size); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points " + "(%zd bit key)", encryption_algorithm_names, alg, + plugin_name, tested, *speed, key_size * 8); } else { @@ -1153,6 +1160,154 @@ failure: return !failed; } +/** + * Benchmark a DH backend + */ +static u_int bench_dh(private_crypto_tester_t *this, + diffie_hellman_group_t group, dh_constructor_t create) +{ + chunk_t pub = chunk_empty, shared = chunk_empty; + diffie_hellman_t *dh; + struct timespec start; + u_int runs; + + runs = 0; + start_timing(&start); + while (end_timing(&start) < this->bench_time) + { + dh = create(group); + if (!dh) + { + return 0; + } + if (dh->get_my_public_value(dh, &pub) && + dh->set_other_public_value(dh, pub) && + dh->get_shared_secret(dh, &shared)) + { + runs++; + } + chunk_free(&pub); + chunk_free(&shared); + dh->destroy(dh); + } + return runs; +} + +METHOD(crypto_tester_t, test_dh, bool, + private_crypto_tester_t *this, diffie_hellman_group_t group, + dh_constructor_t create, u_int *speed, const char *plugin_name) +{ + enumerator_t *enumerator; + dh_test_vector_t *v; + bool failed = FALSE; + u_int tested = 0; + + enumerator = this->dh->create_enumerator(this->dh); + while (enumerator->enumerate(enumerator, &v)) + { + diffie_hellman_t *a, *b; + chunk_t apub, bpub, asec, bsec; + + if (v->group != group) + { + continue; + } + + a = create(group); + b = create(group); + if (!a || !b) + { + DESTROY_IF(a); + DESTROY_IF(b); + failed = TRUE; + tested++; + DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed", + diffie_hellman_group_names, group, plugin_name); + break; + } + + if (!a->set_private_value || !b->set_private_value) + { /* does not support testing */ + a->destroy(a); + b->destroy(b); + continue; + } + failed = TRUE; + tested++; + + apub = bpub = asec = bsec = chunk_empty; + + if (!a->set_private_value(a, chunk_create(v->priv_a, v->priv_len)) || + !b->set_private_value(b, chunk_create(v->priv_b, v->priv_len))) + { + goto failure; + } + if (!a->get_my_public_value(a, &apub) || + !chunk_equals(apub, chunk_create(v->pub_a, v->pub_len))) + { + goto failure; + } + if (!b->get_my_public_value(b, &bpub) || + !chunk_equals(bpub, chunk_create(v->pub_b, v->pub_len))) + { + goto failure; + } + if (!a->set_other_public_value(a, bpub) || + !b->set_other_public_value(b, apub)) + { + goto failure; + } + if (!a->get_shared_secret(a, &asec) || + !chunk_equals(asec, chunk_create(v->shared, v->shared_len))) + { + goto failure; + } + if (!b->get_shared_secret(b, &bsec) || + !chunk_equals(bsec, chunk_create(v->shared, v->shared_len))) + { + goto failure; + } + + failed = FALSE; +failure: + a->destroy(a); + b->destroy(b); + chunk_free(&apub); + chunk_free(&bpub); + chunk_free(&asec); + chunk_free(&bsec); + if (failed) + { + DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed", + diffie_hellman_group_names, group, plugin_name, get_name(v)); + break; + } + } + enumerator->destroy(enumerator); + if (!tested) + { + DBG1(DBG_LIB, "%s %N[%s]: no test vectors found / untestable", + this->required ? "disabled" : "enabled ", + diffie_hellman_group_names, group, plugin_name); + return !this->required; + } + if (!failed) + { + if (speed) + { + *speed = bench_dh(this, group, create); + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors, %d points", + diffie_hellman_group_names, group, plugin_name, tested, *speed); + } + else + { + DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors", + diffie_hellman_group_names, group, plugin_name, tested); + } + } + return !failed; +} + METHOD(crypto_tester_t, add_crypter_vector, void, private_crypto_tester_t *this, crypter_test_vector_t *vector) { @@ -1189,6 +1344,12 @@ METHOD(crypto_tester_t, add_rng_vector, void, this->rng->insert_last(this->rng, vector); } +METHOD(crypto_tester_t, add_dh_vector, void, + private_crypto_tester_t *this, dh_test_vector_t *vector) +{ + this->dh->insert_last(this->dh, vector); +} + METHOD(crypto_tester_t, destroy, void, private_crypto_tester_t *this) { @@ -1198,6 +1359,7 @@ METHOD(crypto_tester_t, destroy, void, this->hasher->destroy(this->hasher); this->prf->destroy(this->prf); this->rng->destroy(this->rng); + this->dh->destroy(this->dh); free(this); } @@ -1216,12 +1378,14 @@ crypto_tester_t *crypto_tester_create() .test_hasher = _test_hasher, .test_prf = _test_prf, .test_rng = _test_rng, + .test_dh = _test_dh, .add_crypter_vector = _add_crypter_vector, .add_aead_vector = _add_aead_vector, .add_signer_vector = _add_signer_vector, .add_hasher_vector = _add_hasher_vector, .add_prf_vector = _add_prf_vector, .add_rng_vector = _add_rng_vector, + .add_dh_vector = _add_dh_vector, .destroy = _destroy, }, .crypter = linked_list_create(), @@ -1230,6 +1394,7 @@ crypto_tester_t *crypto_tester_create() .hasher = linked_list_create(), .prf = linked_list_create(), .rng = linked_list_create(), + .dh = linked_list_create(), .required = lib->settings->get_bool(lib->settings, "%s.crypto_test.required", FALSE, lib->ns), diff --git a/src/libstrongswan/crypto/crypto_tester.h b/src/libstrongswan/crypto/crypto_tester.h index add3b1cdf..6cc9b0d57 100644 --- a/src/libstrongswan/crypto/crypto_tester.h +++ b/src/libstrongswan/crypto/crypto_tester.h @@ -31,6 +31,7 @@ typedef struct signer_test_vector_t signer_test_vector_t; typedef struct hasher_test_vector_t hasher_test_vector_t; typedef struct prf_test_vector_t prf_test_vector_t; typedef struct rng_test_vector_t rng_test_vector_t; +typedef struct dh_test_vector_t dh_test_vector_t; struct crypter_test_vector_t { /** encryption algorithm this vector tests */ @@ -129,6 +130,27 @@ struct rng_test_vector_t { void *user; }; +struct dh_test_vector_t { + /** diffie hellman group to test */ + diffie_hellman_group_t group; + /** private value of alice */ + u_char *priv_a; + /** private value of bob */ + u_char *priv_b; + /** length of private values */ + size_t priv_len; + /** expected public value of alice */ + u_char *pub_a; + /** expected public value of bob */ + u_char *pub_b; + /** size of public values */ + size_t pub_len; + /** expected shared secret */ + u_char *shared; + /** size of shared secret */ + size_t shared_len; +}; + /** * Cryptographic primitive testing framework. */ @@ -206,6 +228,18 @@ struct crypto_tester_t { rng_constructor_t create, u_int *speed, const char *plugin_name); /** + * Test a Diffie-Hellman implementation. + * + * @param group group to test + * @param create constructor function for the DH backend + * @param speed speeed test result, NULL to omit + * @return TRUE if test passed + */ + bool (*test_dh)(crypto_tester_t *this, diffie_hellman_group_t group, + dh_constructor_t create, + u_int *speed, const char *plugin_name); + + /** * Add a test vector to test a crypter. * * @param vector pointer to test vector @@ -248,6 +282,13 @@ struct crypto_tester_t { void (*add_rng_vector)(crypto_tester_t *this, rng_test_vector_t *vector); /** + * Add a test vector to test a Diffie-Hellman backend. + * + * @param vector pointer to test vector + */ + void (*add_dh_vector)(crypto_tester_t *this, dh_test_vector_t *vector); + + /** * Destroy a crypto_tester_t. */ void (*destroy)(crypto_tester_t *this); diff --git a/src/libstrongswan/crypto/diffie_hellman.h b/src/libstrongswan/crypto/diffie_hellman.h index 4704cd0da..abebd66ad 100644 --- a/src/libstrongswan/crypto/diffie_hellman.h +++ b/src/libstrongswan/crypto/diffie_hellman.h @@ -117,6 +117,18 @@ struct diffie_hellman_t { __attribute__((warn_unused_result)); /** + * Set an explicit own private value to use. + * + * Calling this method is usually not required, as the DH backend generates + * an appropriate private value itself. It is optional to implement, and + * used mostly for testing purposes. + * + * @param value private value to set + */ + bool (*set_private_value)(diffie_hellman_t *this, chunk_t value) + __attribute__((warn_unused_result)); + + /** * Get the DH group used. * * @return DH group set in construction diff --git a/src/libstrongswan/crypto/iv/iv_gen.c b/src/libstrongswan/crypto/iv/iv_gen.c new file mode 100644 index 000000000..e18843210 --- /dev/null +++ b/src/libstrongswan/crypto/iv/iv_gen.c @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2015 Martin Willi + * Copyright (C) 2015 revosec AG + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "iv_gen.h" +#include "iv_gen_rand.h" +#include "iv_gen_seq.h" + +/** + * See header. + */ +iv_gen_t* iv_gen_create_for_alg(encryption_algorithm_t alg) +{ + switch (alg) + { + case ENCR_DES: + case ENCR_3DES: + case ENCR_RC5: + case ENCR_IDEA: + case ENCR_CAST: + case ENCR_BLOWFISH: + case ENCR_3IDEA: + case ENCR_AES_CBC: + case ENCR_CAMELLIA_CBC: + case ENCR_SERPENT_CBC: + case ENCR_TWOFISH_CBC: + case ENCR_RC2_CBC: + return iv_gen_rand_create(); + case ENCR_AES_CTR: + case ENCR_AES_CCM_ICV8: + case ENCR_AES_CCM_ICV12: + case ENCR_AES_CCM_ICV16: + case ENCR_AES_GCM_ICV8: + case ENCR_AES_GCM_ICV12: + case ENCR_AES_GCM_ICV16: + case ENCR_CAMELLIA_CTR: + case ENCR_CAMELLIA_CCM_ICV8: + case ENCR_CAMELLIA_CCM_ICV12: + case ENCR_CAMELLIA_CCM_ICV16: + case ENCR_NULL_AUTH_AES_GMAC: + return iv_gen_seq_create(); + case ENCR_NULL: + case ENCR_UNDEFINED: + case ENCR_DES_ECB: + case ENCR_DES_IV32: + case ENCR_DES_IV64: + break; + } + return NULL; +} diff --git a/src/libstrongswan/crypto/iv/iv_gen.h b/src/libstrongswan/crypto/iv/iv_gen.h index f6bc6471f..81b0701ce 100644 --- a/src/libstrongswan/crypto/iv/iv_gen.h +++ b/src/libstrongswan/crypto/iv/iv_gen.h @@ -58,4 +58,12 @@ struct iv_gen_t { void (*destroy)(iv_gen_t *this); }; +/** + * Select an IV generator for a given encryption algorithm. + * + * @param alg encryption algorithm + * @return IV generator + */ +iv_gen_t* iv_gen_create_for_alg(encryption_algorithm_t alg); + #endif /** IV_GEN_H_ @}*/ diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.c b/src/libstrongswan/crypto/iv/iv_gen_seq.c index 98d0c15a6..4de13744d 100644 --- a/src/libstrongswan/crypto/iv/iv_gen_seq.c +++ b/src/libstrongswan/crypto/iv/iv_gen_seq.c @@ -15,6 +15,11 @@ #include "iv_gen_seq.h" +/** + * Magic value for the initial IV state + */ +#define SEQ_IV_INIT_STATE (~(u_int64_t)0) + typedef struct private_iv_gen_t private_iv_gen_t; /** @@ -28,6 +33,11 @@ struct private_iv_gen_t { iv_gen_t public; /** + * Previously passed sequence number to enforce uniqueness + */ + u_int64_t prev; + + /** * Salt to mask counter */ u_int8_t *salt; @@ -43,6 +53,19 @@ METHOD(iv_gen_t, get_iv, bool, { return FALSE; } + if (size < sizeof(u_int64_t)) + { + return FALSE; + } + if (this->prev != SEQ_IV_INIT_STATE && seq <= this->prev) + { + return FALSE; + } + if (seq == SEQ_IV_INIT_STATE) + { + return FALSE; + } + this->prev = seq; if (len > sizeof(u_int64_t)) { len = sizeof(u_int64_t); @@ -84,6 +107,7 @@ iv_gen_t *iv_gen_seq_create() .allocate_iv = _allocate_iv, .destroy = _destroy, }, + .prev = SEQ_IV_INIT_STATE, ); rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); diff --git a/src/libstrongswan/crypto/iv/iv_gen_seq.h b/src/libstrongswan/crypto/iv/iv_gen_seq.h index 329dcca05..43ff4f65e 100644 --- a/src/libstrongswan/crypto/iv/iv_gen_seq.h +++ b/src/libstrongswan/crypto/iv/iv_gen_seq.h @@ -25,6 +25,9 @@ /** * Create an IV generator that generates sequential IVs (counter). * + * The passed external IV must be larger than the one passed to any previous + * call. + * * @return IV generator */ iv_gen_t *iv_gen_seq_create(); diff --git a/src/libstrongswan/crypto/signers/mac_signer.c b/src/libstrongswan/crypto/signers/mac_signer.c index 7c52aa305..1094c4473 100644 --- a/src/libstrongswan/crypto/signers/mac_signer.c +++ b/src/libstrongswan/crypto/signers/mac_signer.c @@ -85,7 +85,7 @@ METHOD(signer_t, verify_signature, bool, return FALSE; } return this->mac->get_mac(this->mac, data, mac) && - memeq(signature.ptr, mac, this->truncation); + memeq_const(signature.ptr, mac, this->truncation); } METHOD(signer_t, get_key_size, size_t, @@ -136,4 +136,3 @@ signer_t *mac_signer_create(mac_t *mac, size_t len) return &this->public; } - diff --git a/src/libstrongswan/crypto/transform.c b/src/libstrongswan/crypto/transform.c index 56252971a..7c6678b61 100644 --- a/src/libstrongswan/crypto/transform.c +++ b/src/libstrongswan/crypto/transform.c @@ -14,6 +14,8 @@ */ #include <crypto/transform.h> +#include <crypto/hashers/hasher.h> +#include <crypto/rngs/rng.h> ENUM_BEGIN(transform_type_names, UNDEFINED_TRANSFORM_TYPE, COMPRESSION_ALGORITHM, "UNDEFINED_TRANSFORM_TYPE", @@ -34,3 +36,33 @@ ENUM(extended_sequence_numbers_names, NO_EXT_SEQ_NUMBERS, EXT_SEQ_NUMBERS, "NO_EXT_SEQ", "EXT_SEQ", ); + + +/** + * See header + */ +enum_name_t* transform_get_enum_names(transform_type_t type) +{ + switch (type) + { + case HASH_ALGORITHM: + return hash_algorithm_names; + case RANDOM_NUMBER_GENERATOR: + return rng_quality_names; + case AEAD_ALGORITHM: + case ENCRYPTION_ALGORITHM: + return encryption_algorithm_names; + case PSEUDO_RANDOM_FUNCTION: + return pseudo_random_function_names; + case INTEGRITY_ALGORITHM: + return integrity_algorithm_names; + case DIFFIE_HELLMAN_GROUP: + return diffie_hellman_group_names; + case EXTENDED_SEQUENCE_NUMBERS: + return extended_sequence_numbers_names; + case UNDEFINED_TRANSFORM_TYPE: + case COMPRESSION_ALGORITHM: + break; + } + return NULL; +} diff --git a/src/libstrongswan/crypto/transform.h b/src/libstrongswan/crypto/transform.h index a585e9784..0cb84f0f5 100644 --- a/src/libstrongswan/crypto/transform.h +++ b/src/libstrongswan/crypto/transform.h @@ -47,6 +47,14 @@ enum transform_type_t { extern enum_name_t *transform_type_names; /** + * Get the enum names for a specific transform type. + * + * @param type type of transform to get enum names for + * @return enum names + */ +enum_name_t *transform_get_enum_names(transform_type_t type); + +/** * Extended sequence numbers, as in IKEv2 RFC 3.3.2. */ enum extended_sequence_numbers_t { |