crypto-tester: Add facility to test KDFs
This commit is contained in:
@@ -368,6 +368,20 @@ METHOD(crypto_factory_t, create_kdf, kdf_t*,
|
|||||||
{
|
{
|
||||||
if (entry->algo == algo)
|
if (entry->algo == algo)
|
||||||
{
|
{
|
||||||
|
if (this->test_on_create)
|
||||||
|
{
|
||||||
|
kdf_test_args_t test_args = {};
|
||||||
|
|
||||||
|
va_start(test_args.args, algo);
|
||||||
|
if (!this->tester->test_kdf(this->tester, algo,
|
||||||
|
entry->create_kdf, &test_args, NULL,
|
||||||
|
default_plugin_name))
|
||||||
|
{
|
||||||
|
va_end(test_args.args);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
va_end(test_args.args);
|
||||||
|
}
|
||||||
va_start(args, algo);
|
va_start(args, algo);
|
||||||
kdf = entry->create_kdf(algo, args);
|
kdf = entry->create_kdf(algo, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
@@ -787,8 +801,17 @@ METHOD(crypto_factory_t, add_kdf, bool,
|
|||||||
private_crypto_factory_t *this, key_derivation_function_t algo,
|
private_crypto_factory_t *this, key_derivation_function_t algo,
|
||||||
const char *plugin_name, kdf_constructor_t create)
|
const char *plugin_name, kdf_constructor_t create)
|
||||||
{
|
{
|
||||||
add_entry(this, this->kdfs, algo, plugin_name, 0, create);
|
u_int speed = 0;
|
||||||
return TRUE;
|
|
||||||
|
if (!this->test_on_add ||
|
||||||
|
this->tester->test_kdf(this->tester, algo, create, NULL,
|
||||||
|
this->bench ? &speed : NULL, plugin_name))
|
||||||
|
{
|
||||||
|
add_entry(this, this->kdfs, algo, plugin_name, 0, create);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
this->test_failures++;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(crypto_factory_t, remove_kdf, void,
|
METHOD(crypto_factory_t, remove_kdf, void,
|
||||||
@@ -1255,6 +1278,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 EXTENDED_OUTPUT_FUNCTION:
|
case EXTENDED_OUTPUT_FUNCTION:
|
||||||
return this->tester->add_xof_vector(this->tester, vector);
|
return this->tester->add_xof_vector(this->tester, vector);
|
||||||
|
case KEY_DERIVATION_FUNCTION:
|
||||||
|
return this->tester->add_kdf_vector(this->tester, vector);
|
||||||
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
||||||
return this->tester->add_drbg_vector(this->tester, vector);
|
return this->tester->add_drbg_vector(this->tester, vector);
|
||||||
case RANDOM_NUMBER_GENERATOR:
|
case RANDOM_NUMBER_GENERATOR:
|
||||||
@@ -1318,6 +1343,10 @@ METHOD(enumerator_t, verify_enumerate, bool,
|
|||||||
*valid = this->tester->test_xof(this->tester, entry->algo,
|
*valid = this->tester->test_xof(this->tester, entry->algo,
|
||||||
entry->create_xof, NULL, entry->plugin_name);
|
entry->create_xof, NULL, entry->plugin_name);
|
||||||
break;
|
break;
|
||||||
|
case KEY_DERIVATION_FUNCTION:
|
||||||
|
*valid = this->tester->test_kdf(this->tester, entry->algo,
|
||||||
|
entry->create_kdf, NULL, NULL, entry->plugin_name);
|
||||||
|
break;
|
||||||
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
||||||
*valid = this->tester->test_drbg(this->tester, entry->algo,
|
*valid = this->tester->test_drbg(this->tester, entry->algo,
|
||||||
entry->create_drbg, NULL, entry->plugin_name);
|
entry->create_drbg, NULL, entry->plugin_name);
|
||||||
@@ -1373,6 +1402,9 @@ METHOD(crypto_factory_t, create_verify_enumerator, enumerator_t*,
|
|||||||
case EXTENDED_OUTPUT_FUNCTION:
|
case EXTENDED_OUTPUT_FUNCTION:
|
||||||
inner = this->xofs->create_enumerator(this->xofs);
|
inner = this->xofs->create_enumerator(this->xofs);
|
||||||
break;
|
break;
|
||||||
|
case KEY_DERIVATION_FUNCTION:
|
||||||
|
inner = this->kdfs->create_enumerator(this->kdfs);
|
||||||
|
break;
|
||||||
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
case DETERMINISTIC_RANDOM_BIT_GENERATOR:
|
||||||
inner = this->drbgs->create_enumerator(this->drbgs);
|
inner = this->drbgs->create_enumerator(this->drbgs);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -69,6 +69,11 @@ struct private_crypto_tester_t {
|
|||||||
*/
|
*/
|
||||||
linked_list_t *xof;
|
linked_list_t *xof;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of KDF test vectors
|
||||||
|
*/
|
||||||
|
linked_list_t *kdf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of DRBG test vectors
|
* List of DRBG test vectors
|
||||||
*/
|
*/
|
||||||
@@ -1186,6 +1191,185 @@ failure:
|
|||||||
return !failed;
|
return !failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a KDF using the given arguments
|
||||||
|
*/
|
||||||
|
static kdf_t *create_kdf_args(kdf_constructor_t create,
|
||||||
|
key_derivation_function_t alg, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
kdf_t *kdf;
|
||||||
|
|
||||||
|
va_start(args, alg);
|
||||||
|
kdf = create(alg, args);
|
||||||
|
va_end(args);
|
||||||
|
return kdf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a KDF using arguments from the given test vector
|
||||||
|
*/
|
||||||
|
static kdf_t *create_kdf_vector(kdf_constructor_t create,
|
||||||
|
key_derivation_function_t alg,
|
||||||
|
kdf_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
switch (alg)
|
||||||
|
{
|
||||||
|
case KDF_PRF_PLUS:
|
||||||
|
return create_kdf_args(create, alg, vector->arg.prf);
|
||||||
|
case KDF_UNDEFINED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the given test vector applies to the passed arguments
|
||||||
|
*/
|
||||||
|
static bool kdf_vector_applies(key_derivation_function_t alg,
|
||||||
|
kdf_test_args_t *args, kdf_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
bool applies = FALSE;
|
||||||
|
|
||||||
|
switch (alg)
|
||||||
|
{
|
||||||
|
case KDF_PRF_PLUS:
|
||||||
|
{
|
||||||
|
pseudo_random_function_t prf;
|
||||||
|
VA_ARGS_VGET(args->args, prf);
|
||||||
|
applies = (prf == vector->arg.prf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case KDF_UNDEFINED:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return applies;
|
||||||
|
}
|
||||||
|
|
||||||
|
METHOD(crypto_tester_t, test_kdf, bool,
|
||||||
|
private_crypto_tester_t *this, key_derivation_function_t alg,
|
||||||
|
kdf_constructor_t create, kdf_test_args_t *args, u_int *speed,
|
||||||
|
const char *plugin_name)
|
||||||
|
{
|
||||||
|
enumerator_t *enumerator;
|
||||||
|
kdf_test_vector_t *vector;
|
||||||
|
va_list copy;
|
||||||
|
bool failed = FALSE;
|
||||||
|
u_int tested = 0, construction_failed = 0;
|
||||||
|
|
||||||
|
enumerator = this->kdf->create_enumerator(this->kdf);
|
||||||
|
while (enumerator->enumerate(enumerator, &vector))
|
||||||
|
{
|
||||||
|
kdf_t *kdf;
|
||||||
|
chunk_t out = chunk_empty;
|
||||||
|
|
||||||
|
if (vector->alg != alg ||
|
||||||
|
(args && !kdf_vector_applies(alg, args, vector)))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
tested++;
|
||||||
|
failed = TRUE;
|
||||||
|
if (args)
|
||||||
|
{
|
||||||
|
va_copy(copy, args->args);
|
||||||
|
kdf = create(alg, copy);
|
||||||
|
va_end(copy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
kdf = create_kdf_vector(create, alg, vector);
|
||||||
|
}
|
||||||
|
if (!kdf)
|
||||||
|
{
|
||||||
|
if (args)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "disabled %N[%s]: creating instance failed",
|
||||||
|
key_derivation_function_names, alg, plugin_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* while there could be a problem, the constructor might just not
|
||||||
|
* be able to create an instance for this test vector, we check
|
||||||
|
* for that at the end */
|
||||||
|
construction_failed++;
|
||||||
|
failed = FALSE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vector->key.len &&
|
||||||
|
!kdf->set_param(kdf, KDF_PARAM_KEY, vector->key))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
if (vector->salt.len &&
|
||||||
|
!kdf->set_param(kdf, KDF_PARAM_SALT, vector->salt))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
/* allocated bytes */
|
||||||
|
if (!kdf->allocate_bytes(kdf, vector->out.len, &out))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
if (!chunk_equals(out, vector->out))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
/* bytes to existing buffer */
|
||||||
|
memset(out.ptr, 0, out.len);
|
||||||
|
if (!kdf->get_bytes(kdf, out.len, out.ptr))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
if (!chunk_equals(out, vector->out))
|
||||||
|
{
|
||||||
|
goto failure;
|
||||||
|
}
|
||||||
|
|
||||||
|
failed = FALSE;
|
||||||
|
failure:
|
||||||
|
kdf->destroy(kdf);
|
||||||
|
chunk_free(&out);
|
||||||
|
if (failed)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "disabled %N[%s]: %s test vector failed",
|
||||||
|
key_derivation_function_names, alg, plugin_name,
|
||||||
|
get_name(vector));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
enumerator->destroy(enumerator);
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "%s %N[%s]: no test vectors found",
|
||||||
|
this->required ? "disabled" : "enabled ",
|
||||||
|
key_derivation_function_names, alg, plugin_name);
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
tested -= construction_failed;
|
||||||
|
if (!tested)
|
||||||
|
{
|
||||||
|
DBG1(DBG_LIB, "%s %N[%s]: unable to apply any available test vectors",
|
||||||
|
this->required ? "disabled" : "enabled ",
|
||||||
|
key_derivation_function_names, alg, plugin_name);
|
||||||
|
return !this->required;
|
||||||
|
}
|
||||||
|
if (!failed)
|
||||||
|
{
|
||||||
|
if (speed)
|
||||||
|
{
|
||||||
|
DBG2(DBG_LIB, "benchmarking for %N is currently not supported",
|
||||||
|
key_derivation_function_names, alg);
|
||||||
|
}
|
||||||
|
DBG1(DBG_LIB, "enabled %N[%s]: passed %u test vectors",
|
||||||
|
key_derivation_function_names, alg, plugin_name, tested);
|
||||||
|
}
|
||||||
|
return !failed;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Benchmark a DRBG
|
* Benchmark a DRBG
|
||||||
*/
|
*/
|
||||||
@@ -1622,6 +1806,12 @@ METHOD(crypto_tester_t, add_xof_vector, void,
|
|||||||
this->xof->insert_last(this->xof, vector);
|
this->xof->insert_last(this->xof, vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
METHOD(crypto_tester_t, add_kdf_vector, void,
|
||||||
|
private_crypto_tester_t *this, kdf_test_vector_t *vector)
|
||||||
|
{
|
||||||
|
this->kdf->insert_last(this->kdf, vector);
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(crypto_tester_t, add_drbg_vector, void,
|
METHOD(crypto_tester_t, add_drbg_vector, void,
|
||||||
private_crypto_tester_t *this, drbg_test_vector_t *vector)
|
private_crypto_tester_t *this, drbg_test_vector_t *vector)
|
||||||
{
|
{
|
||||||
@@ -1649,6 +1839,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->xof->destroy(this->xof);
|
this->xof->destroy(this->xof);
|
||||||
|
this->kdf->destroy(this->kdf);
|
||||||
this->drbg->destroy(this->drbg);
|
this->drbg->destroy(this->drbg);
|
||||||
this->rng->destroy(this->rng);
|
this->rng->destroy(this->rng);
|
||||||
this->dh->destroy(this->dh);
|
this->dh->destroy(this->dh);
|
||||||
@@ -1670,6 +1861,7 @@ crypto_tester_t *crypto_tester_create()
|
|||||||
.test_hasher = _test_hasher,
|
.test_hasher = _test_hasher,
|
||||||
.test_prf = _test_prf,
|
.test_prf = _test_prf,
|
||||||
.test_xof = _test_xof,
|
.test_xof = _test_xof,
|
||||||
|
.test_kdf = _test_kdf,
|
||||||
.test_drbg = _test_drbg,
|
.test_drbg = _test_drbg,
|
||||||
.test_rng = _test_rng,
|
.test_rng = _test_rng,
|
||||||
.test_dh = _test_dh,
|
.test_dh = _test_dh,
|
||||||
@@ -1679,6 +1871,7 @@ crypto_tester_t *crypto_tester_create()
|
|||||||
.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_xof_vector = _add_xof_vector,
|
.add_xof_vector = _add_xof_vector,
|
||||||
|
.add_kdf_vector = _add_kdf_vector,
|
||||||
.add_drbg_vector = _add_drbg_vector,
|
.add_drbg_vector = _add_drbg_vector,
|
||||||
.add_rng_vector = _add_rng_vector,
|
.add_rng_vector = _add_rng_vector,
|
||||||
.add_dh_vector = _add_dh_vector,
|
.add_dh_vector = _add_dh_vector,
|
||||||
@@ -1690,6 +1883,7 @@ crypto_tester_t *crypto_tester_create()
|
|||||||
.hasher = linked_list_create(),
|
.hasher = linked_list_create(),
|
||||||
.prf = linked_list_create(),
|
.prf = linked_list_create(),
|
||||||
.xof = linked_list_create(),
|
.xof = linked_list_create(),
|
||||||
|
.kdf = linked_list_create(),
|
||||||
.drbg = linked_list_create(),
|
.drbg = linked_list_create(),
|
||||||
.rng = linked_list_create(),
|
.rng = linked_list_create(),
|
||||||
.dh = linked_list_create(),
|
.dh = linked_list_create(),
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ 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 xof_test_vector_t xof_test_vector_t;
|
typedef struct xof_test_vector_t xof_test_vector_t;
|
||||||
|
typedef struct kdf_test_vector_t kdf_test_vector_t;
|
||||||
|
typedef struct kdf_test_args_t kdf_test_args_t;
|
||||||
typedef struct drbg_test_vector_t drbg_test_vector_t;
|
typedef struct drbg_test_vector_t drbg_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;
|
typedef struct dh_test_vector_t dh_test_vector_t;
|
||||||
@@ -130,6 +132,26 @@ struct xof_test_vector_t {
|
|||||||
u_char *out;
|
u_char *out;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct kdf_test_vector_t {
|
||||||
|
/** kdf algorithm this test vector tests */
|
||||||
|
key_derivation_function_t alg;
|
||||||
|
/** argument passed to constructor, type depends on alg */
|
||||||
|
union {
|
||||||
|
pseudo_random_function_t prf;
|
||||||
|
} arg;
|
||||||
|
/** optional key */
|
||||||
|
chunk_t key;
|
||||||
|
/** optional salt */
|
||||||
|
chunk_t salt;
|
||||||
|
/** expected output */
|
||||||
|
chunk_t out;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct kdf_test_args_t {
|
||||||
|
/** the arguments used to construct the KDF */
|
||||||
|
va_list args;
|
||||||
|
};
|
||||||
|
|
||||||
struct drbg_test_vector_t {
|
struct drbg_test_vector_t {
|
||||||
/** drbg type this test vector tests */
|
/** drbg type this test vector tests */
|
||||||
drbg_type_t type;
|
drbg_type_t type;
|
||||||
@@ -256,6 +278,22 @@ struct crypto_tester_t {
|
|||||||
bool (*test_xof)(crypto_tester_t *this, ext_out_function_t alg,
|
bool (*test_xof)(crypto_tester_t *this, ext_out_function_t alg,
|
||||||
xof_constructor_t create,
|
xof_constructor_t create,
|
||||||
u_int *speed, const char *plugin_name);
|
u_int *speed, const char *plugin_name);
|
||||||
|
/**
|
||||||
|
* Test a KDF algorithm.
|
||||||
|
*
|
||||||
|
* If constructor arguments are passed, only matching test vectors are
|
||||||
|
* tried. Otherwise, all are tried and implementations are allowed to fail
|
||||||
|
* construction with unsupported arguments.
|
||||||
|
*
|
||||||
|
* @param alg algorithm to test
|
||||||
|
* @param create constructor function for the XOF
|
||||||
|
* @param args optional arguments to pass to constructor
|
||||||
|
* @param speed speed test result, NULL to omit
|
||||||
|
* @return TRUE if test passed
|
||||||
|
*/
|
||||||
|
bool (*test_kdf)(crypto_tester_t *this, key_derivation_function_t alg,
|
||||||
|
kdf_constructor_t create, kdf_test_args_t *args,
|
||||||
|
u_int *speed, const char *plugin_name);
|
||||||
/**
|
/**
|
||||||
* Test a DRBG type.
|
* Test a DRBG type.
|
||||||
*
|
*
|
||||||
@@ -332,6 +370,13 @@ struct crypto_tester_t {
|
|||||||
*/
|
*/
|
||||||
void (*add_xof_vector)(crypto_tester_t *this, xof_test_vector_t *vector);
|
void (*add_xof_vector)(crypto_tester_t *this, xof_test_vector_t *vector);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a test vector to test a KDF.
|
||||||
|
*
|
||||||
|
* @param vector pointer to test vector
|
||||||
|
*/
|
||||||
|
void (*add_kdf_vector)(crypto_tester_t *this, kdf_test_vector_t *vector);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a test vector to test a DRBG.
|
* Add a test vector to test a DRBG.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ static transform_type_t tfs[] = {
|
|||||||
HASH_ALGORITHM,
|
HASH_ALGORITHM,
|
||||||
PSEUDO_RANDOM_FUNCTION,
|
PSEUDO_RANDOM_FUNCTION,
|
||||||
EXTENDED_OUTPUT_FUNCTION,
|
EXTENDED_OUTPUT_FUNCTION,
|
||||||
|
KEY_DERIVATION_FUNCTION,
|
||||||
DETERMINISTIC_RANDOM_BIT_GENERATOR,
|
DETERMINISTIC_RANDOM_BIT_GENERATOR,
|
||||||
RANDOM_NUMBER_GENERATOR,
|
RANDOM_NUMBER_GENERATOR,
|
||||||
DIFFIE_HELLMAN_GROUP,
|
DIFFIE_HELLMAN_GROUP,
|
||||||
|
|||||||
Reference in New Issue
Block a user