crypto-tester: Support testing DH groups using DH test vectors
This commit is contained in:
@@ -377,6 +377,12 @@ METHOD(crypto_factory_t, create_dh, diffie_hellman_t*,
|
|||||||
{
|
{
|
||||||
if (entry->algo == group)
|
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);
|
diffie_hellman = entry->create_dh(group, g, p);
|
||||||
if (diffie_hellman)
|
if (diffie_hellman)
|
||||||
{
|
{
|
||||||
@@ -692,8 +698,17 @@ METHOD(crypto_factory_t, add_dh, bool,
|
|||||||
private_crypto_factory_t *this, diffie_hellman_group_t group,
|
private_crypto_factory_t *this, diffie_hellman_group_t group,
|
||||||
const char *plugin_name, dh_constructor_t create)
|
const char *plugin_name, dh_constructor_t create)
|
||||||
{
|
{
|
||||||
add_entry(this, this->dhs, group, plugin_name, 0, create);
|
u_int speed = 0;
|
||||||
return TRUE;
|
|
||||||
|
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,
|
METHOD(crypto_factory_t, remove_dh, void,
|
||||||
@@ -892,6 +907,8 @@ METHOD(crypto_factory_t, add_test_vector, void,
|
|||||||
return this->tester->add_prf_vector(this->tester, vector);
|
return this->tester->add_prf_vector(this->tester, vector);
|
||||||
case RANDOM_NUMBER_GENERATOR:
|
case RANDOM_NUMBER_GENERATOR:
|
||||||
return this->tester->add_rng_vector(this->tester, vector);
|
return this->tester->add_rng_vector(this->tester, vector);
|
||||||
|
case DIFFIE_HELLMAN_GROUP:
|
||||||
|
return this->tester->add_dh_vector(this->tester, vector);
|
||||||
default:
|
default:
|
||||||
DBG1(DBG_LIB, "%N test vectors not supported, ignored",
|
DBG1(DBG_LIB, "%N test vectors not supported, ignored",
|
||||||
transform_type_names, type);
|
transform_type_names, type);
|
||||||
@@ -1016,6 +1033,7 @@ static u_int verify_registered_algorithms(crypto_factory_t *factory)
|
|||||||
TEST_ALGORITHMS(hasher);
|
TEST_ALGORITHMS(hasher);
|
||||||
TEST_ALGORITHMS(prf);
|
TEST_ALGORITHMS(prf);
|
||||||
TEST_ALGORITHMS(rng);
|
TEST_ALGORITHMS(rng);
|
||||||
|
TEST_ALGORITHMS(dh);
|
||||||
this->lock->unlock(this->lock);
|
this->lock->unlock(this->lock);
|
||||||
return failures;
|
return failures;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -67,6 +67,11 @@ struct private_crypto_tester_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *rng;
|
linked_list_t *rng;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of Diffie-Hellman test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *dh;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is a test vector required to pass a test?
|
* Is a test vector required to pass a test?
|
||||||
*/
|
*/
|
||||||
@@ -1155,6 +1160,154 @@ failure:
|
|||||||
return !failed;
|
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,
|
METHOD(crypto_tester_t, add_crypter_vector, void,
|
||||||
private_crypto_tester_t *this, crypter_test_vector_t *vector)
|
private_crypto_tester_t *this, crypter_test_vector_t *vector)
|
||||||
{
|
{
|
||||||
@@ -1191,6 +1344,12 @@ METHOD(crypto_tester_t, add_rng_vector, void,
|
|||||||
this->rng->insert_last(this->rng, vector);
|
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,
|
METHOD(crypto_tester_t, destroy, void,
|
||||||
private_crypto_tester_t *this)
|
private_crypto_tester_t *this)
|
||||||
{
|
{
|
||||||
@@ -1200,6 +1359,7 @@ METHOD(crypto_tester_t, destroy, void,
|
|||||||
this->hasher->destroy(this->hasher);
|
this->hasher->destroy(this->hasher);
|
||||||
this->prf->destroy(this->prf);
|
this->prf->destroy(this->prf);
|
||||||
this->rng->destroy(this->rng);
|
this->rng->destroy(this->rng);
|
||||||
|
this->dh->destroy(this->dh);
|
||||||
free(this);
|
free(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1218,12 +1378,14 @@ crypto_tester_t *crypto_tester_create()
|
|||||||
.test_hasher = _test_hasher,
|
.test_hasher = _test_hasher,
|
||||||
.test_prf = _test_prf,
|
.test_prf = _test_prf,
|
||||||
.test_rng = _test_rng,
|
.test_rng = _test_rng,
|
||||||
|
.test_dh = _test_dh,
|
||||||
.add_crypter_vector = _add_crypter_vector,
|
.add_crypter_vector = _add_crypter_vector,
|
||||||
.add_aead_vector = _add_aead_vector,
|
.add_aead_vector = _add_aead_vector,
|
||||||
.add_signer_vector = _add_signer_vector,
|
.add_signer_vector = _add_signer_vector,
|
||||||
.add_hasher_vector = _add_hasher_vector,
|
.add_hasher_vector = _add_hasher_vector,
|
||||||
.add_prf_vector = _add_prf_vector,
|
.add_prf_vector = _add_prf_vector,
|
||||||
.add_rng_vector = _add_rng_vector,
|
.add_rng_vector = _add_rng_vector,
|
||||||
|
.add_dh_vector = _add_dh_vector,
|
||||||
.destroy = _destroy,
|
.destroy = _destroy,
|
||||||
},
|
},
|
||||||
.crypter = linked_list_create(),
|
.crypter = linked_list_create(),
|
||||||
@@ -1232,6 +1394,7 @@ crypto_tester_t *crypto_tester_create()
|
|||||||
.hasher = linked_list_create(),
|
.hasher = linked_list_create(),
|
||||||
.prf = linked_list_create(),
|
.prf = linked_list_create(),
|
||||||
.rng = linked_list_create(),
|
.rng = linked_list_create(),
|
||||||
|
.dh = linked_list_create(),
|
||||||
|
|
||||||
.required = lib->settings->get_bool(lib->settings,
|
.required = lib->settings->get_bool(lib->settings,
|
||||||
"%s.crypto_test.required", FALSE, lib->ns),
|
"%s.crypto_test.required", FALSE, lib->ns),
|
||||||
|
|||||||
@@ -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 hasher_test_vector_t hasher_test_vector_t;
|
||||||
typedef struct prf_test_vector_t prf_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 rng_test_vector_t rng_test_vector_t;
|
||||||
|
typedef struct dh_test_vector_t dh_test_vector_t;
|
||||||
|
|
||||||
struct crypter_test_vector_t {
|
struct crypter_test_vector_t {
|
||||||
/** encryption algorithm this vector tests */
|
/** encryption algorithm this vector tests */
|
||||||
@@ -129,6 +130,27 @@ struct rng_test_vector_t {
|
|||||||
void *user;
|
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.
|
* Cryptographic primitive testing framework.
|
||||||
*/
|
*/
|
||||||
@@ -205,6 +227,18 @@ struct crypto_tester_t {
|
|||||||
bool (*test_rng)(crypto_tester_t *this, rng_quality_t quality,
|
bool (*test_rng)(crypto_tester_t *this, rng_quality_t quality,
|
||||||
rng_constructor_t create,
|
rng_constructor_t create,
|
||||||
u_int *speed, const char *plugin_name);
|
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.
|
* Add a test vector to test a crypter.
|
||||||
*
|
*
|
||||||
@@ -247,6 +281,13 @@ struct crypto_tester_t {
|
|||||||
*/
|
*/
|
||||||
void (*add_rng_vector)(crypto_tester_t *this, rng_test_vector_t *vector);
|
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.
|
* Destroy a crypto_tester_t.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user