summaryrefslogtreecommitdiff
path: root/src/libstrongswan/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/crypto')
-rw-r--r--src/libstrongswan/crypto/aead.c4
-rw-r--r--src/libstrongswan/crypto/aead.h3
-rw-r--r--src/libstrongswan/crypto/crypto_factory.c182
-rw-r--r--src/libstrongswan/crypto/crypto_factory.h21
-rw-r--r--src/libstrongswan/crypto/crypto_tester.c193
-rw-r--r--src/libstrongswan/crypto/crypto_tester.h41
-rw-r--r--src/libstrongswan/crypto/diffie_hellman.h12
-rw-r--r--src/libstrongswan/crypto/iv/iv_gen.c61
-rw-r--r--src/libstrongswan/crypto/iv/iv_gen.h8
-rw-r--r--src/libstrongswan/crypto/iv/iv_gen_seq.c24
-rw-r--r--src/libstrongswan/crypto/iv/iv_gen_seq.h3
-rw-r--r--src/libstrongswan/crypto/signers/mac_signer.c3
-rw-r--r--src/libstrongswan/crypto/transform.c32
-rw-r--r--src/libstrongswan/crypto/transform.h8
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 {