Add configure option to disable testing key exchange methods

If this is used, the functionality to set a private key/value/seed for
key exchange methods is removed (including from the interface to avoid
accidentally forgetting to wrap implementations and uses of set_seed()).

The set_seed() method is assigned outside the INIT() macro to avoid
potentially undefined behavior (preprocessing directives in macro
arguments).

The test done by the crypto tester is a simple functionality test.
This commit is contained in:
Tobias Brunner
2025-04-10 08:31:09 +02:00
parent a7c285bc50
commit 6cbd93838b
19 changed files with 250 additions and 50 deletions
+5
View File
@@ -70,6 +70,7 @@ ARG_WITH_SET([mpz_powm_sec], [yes], [use the more side-channel resistant
ARG_WITH_SET([dev-headers], [no], [install strongSwan development headers to directory.]) ARG_WITH_SET([dev-headers], [no], [install strongSwan development headers to directory.])
ARG_WITH_SET([printf-hooks], [auto], [force the use of a specific printf hook implementation (auto, builtin, glibc, vstr).]) ARG_WITH_SET([printf-hooks], [auto], [force the use of a specific printf hook implementation (auto, builtin, glibc, vstr).])
ARG_WITH_SET([rubygemdir], ["gem environment gemdir"], [path to install ruby gems to]) ARG_WITH_SET([rubygemdir], ["gem environment gemdir"], [path to install ruby gems to])
ARG_WITH_SET([testable-ke], [yes], [make key exchange implementations testable by providing a set_seed() method])
if test -n "$PKG_CONFIG"; then if test -n "$PKG_CONFIG"; then
systemdsystemunitdir_default=$($PKG_CONFIG --variable=systemdsystemunitdir systemd) systemdsystemunitdir_default=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)
@@ -1351,6 +1352,10 @@ if test x$unwind_backtraces = xtrue; then
AC_SUBST(UNWINDLIB) AC_SUBST(UNWINDLIB)
fi fi
if test "x$testable_ke" = xyes; then
AC_DEFINE([TESTABLE_KE], [1], [Define to 1 if key exchange methods should be testable.])
fi
AM_CONDITIONAL(USE_DEV_HEADERS, [test "x$dev_headers" != xno]) AM_CONDITIONAL(USE_DEV_HEADERS, [test "x$dev_headers" != xno])
if test x$dev_headers = xyes; then if test x$dev_headers = xyes; then
dev_headers="$includedir/strongswan" dev_headers="$includedir/strongswan"
+76 -1
View File
@@ -1690,6 +1690,8 @@ static u_int bench_ke(private_crypto_tester_t *this,
return runs; return runs;
} }
#ifdef TESTABLE_KE
static bool test_single_ke(key_exchange_method_t method, ke_test_vector_t *v, static bool test_single_ke(key_exchange_method_t method, ke_test_vector_t *v,
ke_constructor_t create) ke_constructor_t create)
{ {
@@ -1769,14 +1771,54 @@ failure:
chunk_free(&a_sec); chunk_free(&a_sec);
chunk_free(&b_sec); chunk_free(&b_sec);
DESTROY_IF(drbg); DESTROY_IF(drbg);
return success; return success;
} }
#else /* TESTABLE_KE */
static bool test_single_ke(key_exchange_method_t method, ke_constructor_t create)
{
key_exchange_t *a = NULL, *b = NULL;
chunk_t a_pub, b_pub, a_sec, b_sec;
bool success = FALSE;
a_pub = b_pub = a_sec = b_sec = chunk_empty;
a = create(method);
b = create(method);
if (!a || !b)
{
goto failure;
}
if (!a->get_public_key(a, &a_pub) ||
!b->set_public_key(b, a_pub) ||
!b->get_shared_secret(b, &b_sec) ||
!b->get_public_key(b, &b_pub) ||
chunk_equals(a_pub, b_pub) ||
!a->set_public_key(a, b_pub) ||
!a->get_shared_secret(a, &a_sec) ||
!chunk_equals(a_sec, b_sec))
{
goto failure;
}
success = TRUE;
failure:
DESTROY_IF(a);
DESTROY_IF(b);
chunk_free(&a_pub);
chunk_free(&b_pub);
chunk_free(&a_sec);
chunk_free(&b_sec);
return success;
}
#endif /* TESTABLE_KE */
METHOD(crypto_tester_t, test_ke, bool, METHOD(crypto_tester_t, test_ke, bool,
private_crypto_tester_t *this, key_exchange_method_t method, private_crypto_tester_t *this, key_exchange_method_t method,
ke_constructor_t create, u_int *speed, const char *plugin_name) ke_constructor_t create, u_int *speed, const char *plugin_name)
{ {
#ifdef TESTABLE_KE
enumerator_t *enumerator; enumerator_t *enumerator;
ke_test_vector_t *v; ke_test_vector_t *v;
bool success = TRUE; bool success = TRUE;
@@ -1808,6 +1850,7 @@ METHOD(crypto_tester_t, test_ke, bool,
key_exchange_method_names, method, plugin_name); key_exchange_method_names, method, plugin_name);
return !this->required; return !this->required;
} }
if (success) if (success)
{ {
if (speed) if (speed)
@@ -1823,6 +1866,38 @@ METHOD(crypto_tester_t, test_ke, bool,
} }
} }
return success; return success;
#else /* TESTABLE_KE */
if (method == MODP_CUSTOM)
{
DBG1(DBG_LIB, "enabled %N[%s]: untestable",
key_exchange_method_names, method, plugin_name);
return TRUE;
}
if (!test_single_ke(method, create))
{
DBG1(DBG_LIB, "disabled %N[%s]: failed basic test",
key_exchange_method_names, method, plugin_name);
return FALSE;
}
if (speed)
{
*speed = bench_ke(this, method, create);
DBG1(DBG_LIB, "enabled %N[%s]: passed basic test (vector tests "
"disabled), %d points", key_exchange_method_names, method,
plugin_name, *speed);
}
else
{
DBG1(DBG_LIB, "enabled %N[%s]: passed basic test (vector tests "
"disabled)", key_exchange_method_names, method, plugin_name);
}
return TRUE;
#endif /* TESTABLE_KE */
} }
METHOD(crypto_tester_t, add_crypter_vector, void, METHOD(crypto_tester_t, add_crypter_vector, void,
+4
View File
@@ -153,6 +153,8 @@ struct key_exchange_t {
bool (*get_public_key)(key_exchange_t *this, chunk_t *value) bool (*get_public_key)(key_exchange_t *this, chunk_t *value)
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
#ifdef TESTABLE_KE
/** /**
* Set a seed used for the derivation of private key material. * Set a seed used for the derivation of private key material.
* *
@@ -167,6 +169,8 @@ struct key_exchange_t {
bool (*set_seed)(key_exchange_t *this, chunk_t value, drbg_t *drbg) bool (*set_seed)(key_exchange_t *this, chunk_t value, drbg_t *drbg)
__attribute__((warn_unused_result)); __attribute__((warn_unused_result));
#endif /* TESTABLE_KE */
/** /**
* Get the key exchange method used. * Get the key exchange method used.
* *
@@ -134,6 +134,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_botan_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_botan_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -141,6 +143,8 @@ METHOD(key_exchange_t, set_seed, bool,
return load_private_key(this, value); return load_private_key(this, value);
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_botan_diffie_hellman_t *this, chunk_t *secret) private_botan_diffie_hellman_t *this, chunk_t *secret)
{ {
@@ -186,7 +190,6 @@ static botan_diffie_hellman_t *create_generic(key_exchange_method_t group,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -194,6 +197,10 @@ static botan_diffie_hellman_t *create_generic(key_exchange_method_t group,
.group = group, .group = group,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
if (!chunk_to_botan_mp(p, &this->p)) if (!chunk_to_botan_mp(p, &this->p))
{ {
destroy(this); destroy(this);
@@ -107,6 +107,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_botan_ec_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_botan_ec_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -135,6 +137,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_botan_ec_diffie_hellman_t *this, chunk_t *secret) private_botan_ec_diffie_hellman_t *this, chunk_t *secret)
{ {
@@ -177,7 +181,6 @@ botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -185,6 +188,10 @@ botan_ec_diffie_hellman_t *botan_ec_diffie_hellman_create(
.group = group, .group = group,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
switch (group) switch (group)
{ {
case ECP_256_BIT: case ECP_256_BIT:
+9 -1
View File
@@ -291,6 +291,8 @@ METHOD(key_exchange_t, get_method, key_exchange_method_t,
return this->method; return this->method;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_key_exchange_t *this, chunk_t value, drbg_t *drbg) private_key_exchange_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -303,6 +305,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, METHOD(key_exchange_t, destroy, void,
private_key_exchange_t *this) private_key_exchange_t *this)
{ {
@@ -343,12 +347,16 @@ key_exchange_t *botan_kem_create(key_exchange_method_t method)
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_seed = _set_seed,
.destroy = _destroy, .destroy = _destroy,
}, },
.method = method, .method = method,
.name = strdup(name), .name = strdup(name),
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
return &this->public; return &this->public;
} }
@@ -93,6 +93,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -115,6 +117,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_diffie_hellman_t *this, chunk_t *secret) private_diffie_hellman_t *this, chunk_t *secret)
{ {
@@ -155,12 +159,15 @@ key_exchange_t *botan_x25519_create(key_exchange_method_t ke)
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
if (!botan_get_rng(&rng, RNG_STRONG)) if (!botan_get_rng(&rng, RNG_STRONG))
{ {
free(this); free(this);
@@ -103,6 +103,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return FALSE; return FALSE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_curve25519_dh_t *this, chunk_t value, drbg_t *drbg) private_curve25519_dh_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -113,6 +115,8 @@ METHOD(key_exchange_t, set_seed, bool,
return this->drv->set_key(this->drv, value.ptr); return this->drv->set_key(this->drv, value.ptr);
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_curve25519_dh_t *this, chunk_t *secret) private_curve25519_dh_t *this, chunk_t *secret)
{ {
@@ -157,7 +161,6 @@ curve25519_dh_t *curve25519_dh_create(key_exchange_method_t group)
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -165,6 +168,10 @@ curve25519_dh_t *curve25519_dh_create(key_exchange_method_t group)
.drv = curve25519_drv_probe(), .drv = curve25519_drv_probe(),
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
if (!this->drv) if (!this->drv)
{ {
free(this); free(this);
+9 -1
View File
@@ -143,6 +143,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_gcrypt_dh_t *this, chunk_t value, drbg_t *drbg) private_gcrypt_dh_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -161,6 +163,8 @@ METHOD(key_exchange_t, set_seed, bool,
return !err; return !err;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_gcrypt_dh_t *this, chunk_t *secret) private_gcrypt_dh_t *this, chunk_t *secret)
{ {
@@ -208,7 +212,6 @@ static gcrypt_dh_t *create_generic(key_exchange_method_t group, size_t exp_len,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -216,6 +219,11 @@ static gcrypt_dh_t *create_generic(key_exchange_method_t group, size_t exp_len,
.group = group, .group = group,
.p_len = p.len, .p_len = p.len,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
err = gcry_mpi_scan(&this->p, GCRYMPI_FMT_USG, p.ptr, p.len, NULL); err = gcry_mpi_scan(&this->p, GCRYMPI_FMT_USG, p.ptr, p.len, NULL);
if (err) if (err)
{ {
@@ -135,6 +135,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_gmp_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_gmp_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -144,6 +146,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_gmp_diffie_hellman_t *this, chunk_t *secret) private_gmp_diffie_hellman_t *this, chunk_t *secret)
{ {
@@ -228,7 +232,6 @@ static gmp_diffie_hellman_t *create_generic(key_exchange_method_t group,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -237,6 +240,10 @@ static gmp_diffie_hellman_t *create_generic(key_exchange_method_t group,
.p_len = p.len, .p_len = p.len,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
mpz_init(this->p); mpz_init(this->p);
mpz_init(this->yb); mpz_init(this->yb);
mpz_init(this->ya); mpz_init(this->ya);
+8 -1
View File
@@ -941,6 +941,8 @@ METHOD(key_exchange_t, get_shared_secret, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_key_exchange_t *this, chunk_t value, drbg_t *drbg) private_key_exchange_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -949,6 +951,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, METHOD(key_exchange_t, destroy, void,
private_key_exchange_t *this) private_key_exchange_t *this)
{ {
@@ -985,7 +989,6 @@ key_exchange_t *ml_kem_create(key_exchange_method_t method)
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_seed = _set_seed,
.destroy = _destroy, .destroy = _destroy,
}, },
.method = method, .method = method,
@@ -996,6 +999,10 @@ key_exchange_t *ml_kem_create(key_exchange_method_t method)
.H = lib->crypto->create_hasher(lib->crypto, HASH_SHA3_256), .H = lib->crypto->create_hasher(lib->crypto, HASH_SHA3_256),
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
if (!this->shake128 || !this->shake256 || !this->G || !this->H) if (!this->shake128 || !this->shake256 || !this->G || !this->H)
{ {
destroy(this); destroy(this);
@@ -180,6 +180,7 @@ METHOD(key_exchange_t, set_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
#if OPENSSL_VERSION_NUMBER >= 0x30000000L #if OPENSSL_VERSION_NUMBER >= 0x30000000L
/** /**
@@ -273,6 +274,7 @@ METHOD(key_exchange_t, set_seed, bool,
} }
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, METHOD(key_exchange_t, destroy, void,
private_openssl_diffie_hellman_t *this) private_openssl_diffie_hellman_t *this)
@@ -304,7 +306,6 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -312,6 +313,10 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create(
.group = group, .group = group,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
if (group == MODP_CUSTOM) if (group == MODP_CUSTOM)
{ {
chunk_t g_chunk, p_chunk; chunk_t g_chunk, p_chunk;
@@ -305,6 +305,8 @@ int openssl_ecdh_group_to_nid(key_exchange_method_t group)
} }
} }
#ifdef TESTABLE_KE
/** /**
* Parse the given private key as BIGNUM and calculate the corresponding public * Parse the given private key as BIGNUM and calculate the corresponding public
* key as EC_POINT. * key as EC_POINT.
@@ -429,6 +431,7 @@ error:
} }
#endif /* OPENSSL_VERSION_NUMBER */ #endif /* OPENSSL_VERSION_NUMBER */
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, METHOD(key_exchange_t, destroy, void,
private_openssl_ec_diffie_hellman_t *this) private_openssl_ec_diffie_hellman_t *this)
@@ -460,7 +463,6 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(key_exchange_metho
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -468,6 +470,10 @@ openssl_ec_diffie_hellman_t *openssl_ec_diffie_hellman_create(key_exchange_metho
.group = group, .group = group,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
#if OPENSSL_VERSION_NUMBER >= 0x30000000L #if OPENSSL_VERSION_NUMBER >= 0x30000000L
this->ec_group = EC_GROUP_new_by_curve_name(curve); this->ec_group = EC_GROUP_new_by_curve_name(curve);
this->key = EVP_EC_gen(OSSL_EC_curve_nid2name(curve)); this->key = EVP_EC_gen(OSSL_EC_curve_nid2name(curve));
@@ -324,6 +324,8 @@ METHOD(key_exchange_t, set_public_key, bool, private_key_exchange_t *this,
return openssl_kem_encapsulate(this, value); return openssl_kem_encapsulate(this, value);
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, private_key_exchange_t *this, METHOD(key_exchange_t, set_seed, bool, private_key_exchange_t *this,
chunk_t ignore, drbg_t *seed) chunk_t ignore, drbg_t *seed)
{ {
@@ -336,6 +338,8 @@ METHOD(key_exchange_t, set_seed, bool, private_key_exchange_t *this,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, private_key_exchange_t *this) METHOD(key_exchange_t, destroy, void, private_key_exchange_t *this)
{ {
EVP_PKEY_free(this->pkey); EVP_PKEY_free(this->pkey);
@@ -357,12 +361,16 @@ key_exchange_t *openssl_kem_create(key_exchange_method_t method)
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
.group = method .group = method
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
return &this->public; return &this->public;
} }
#endif /* OPENSSL_IS_AWSLC */ #endif /* OPENSSL_IS_AWSLC */
@@ -114,6 +114,8 @@ METHOD(key_exchange_t, get_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_key_exchange_t *this, chunk_t value, drbg_t *drbg) private_key_exchange_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -127,6 +129,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_shared_secret, bool, METHOD(key_exchange_t, get_shared_secret, bool,
private_key_exchange_t *this, chunk_t *secret) private_key_exchange_t *this, chunk_t *secret)
{ {
@@ -193,13 +197,17 @@ key_exchange_t *openssl_x_diffie_hellman_create(key_exchange_method_t ke)
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
.ke = ke, .ke = ke,
.key = key, .key = key,
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
return &this->public; return &this->public;
} }
@@ -124,6 +124,8 @@ METHOD(key_exchange_t, set_public_key, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_wolfssl_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_wolfssl_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -150,6 +152,8 @@ METHOD(key_exchange_t, set_seed, bool,
return success; return success;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, get_method, key_exchange_method_t, METHOD(key_exchange_t, get_method, key_exchange_method_t,
private_wolfssl_diffie_hellman_t *this) private_wolfssl_diffie_hellman_t *this)
{ {
@@ -223,7 +227,6 @@ static wolfssl_diffie_hellman_t *create_generic(key_exchange_method_t group,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -232,6 +235,10 @@ static wolfssl_diffie_hellman_t *create_generic(key_exchange_method_t group,
.len = p.len, .len = p.len,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
if (wc_InitDhKey(&this->dh) != 0) if (wc_InitDhKey(&this->dh) != 0)
{ {
free(this); free(this);
@@ -100,6 +100,41 @@ static bool ecp2chunk(int keysize, ecc_point *point, chunk_t *chunk,
return wolfssl_mp_cat(keysize, point->x, y, chunk); return wolfssl_mp_cat(keysize, point->x, y, chunk);
} }
METHOD(key_exchange_t, set_public_key, bool,
private_wolfssl_ec_diffie_hellman_t *this, chunk_t value)
{
chunk_t uncomp;
if (!key_exchange_verify_pubkey(this->group, value))
{
return FALSE;
}
/* prepend 0x04 to indicate uncompressed point format */
uncomp = chunk_cata("cc", chunk_from_chars(0x04), value);
if (wc_ecc_import_x963_ex(uncomp.ptr, uncomp.len, &this->pubkey,
this->curve_id) != 0)
{
DBG1(DBG_LIB, "ECDH public value is malformed");
return FALSE;
}
if (wc_ecc_check_key(&this->pubkey) != 0)
{
DBG1(DBG_LIB, "ECDH public value is invalid");
return FALSE;
}
return TRUE;
}
METHOD(key_exchange_t, get_public_key, bool,
private_wolfssl_ec_diffie_hellman_t *this,chunk_t *value)
{
return ecp2chunk(this->keysize, &this->key.pubkey, value, FALSE);
}
#ifdef TESTABLE_KE
/** /**
* Perform the elliptic curve scalar multiplication. * Perform the elliptic curve scalar multiplication.
*/ */
@@ -136,39 +171,6 @@ static bool wolfssl_ecc_multiply(const ecc_set_type *ecc_set, mp_int *scalar,
return ret == 0; return ret == 0;
} }
METHOD(key_exchange_t, set_public_key, bool,
private_wolfssl_ec_diffie_hellman_t *this, chunk_t value)
{
chunk_t uncomp;
if (!key_exchange_verify_pubkey(this->group, value))
{
return FALSE;
}
/* prepend 0x04 to indicate uncompressed point format */
uncomp = chunk_cata("cc", chunk_from_chars(0x04), value);
if (wc_ecc_import_x963_ex(uncomp.ptr, uncomp.len, &this->pubkey,
this->curve_id) != 0)
{
DBG1(DBG_LIB, "ECDH public value is malformed");
return FALSE;
}
if (wc_ecc_check_key(&this->pubkey) != 0)
{
DBG1(DBG_LIB, "ECDH public value is invalid");
return FALSE;
}
return TRUE;
}
METHOD(key_exchange_t, get_public_key, bool,
private_wolfssl_ec_diffie_hellman_t *this,chunk_t *value)
{
return ecp2chunk(this->keysize, &this->key.pubkey, value, FALSE);
}
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_wolfssl_ec_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_wolfssl_ec_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -209,6 +211,8 @@ METHOD(key_exchange_t, set_seed, bool,
return success; return success;
} }
#endif /* TESTABLE_KE */
/** /**
* Derive the shared secret * Derive the shared secret
*/ */
@@ -291,7 +295,6 @@ wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(key_exchange_metho
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_seed = _set_seed,
.get_method = _get_method, .get_method = _get_method,
.destroy = _destroy, .destroy = _destroy,
}, },
@@ -299,6 +302,10 @@ wolfssl_ec_diffie_hellman_t *wolfssl_ec_diffie_hellman_create(key_exchange_metho
.group = group, .group = group,
); );
#ifdef TESTABLE_KE
this->public.ke.set_seed = _set_seed;
#endif
if (wc_ecc_init(&this->key) != 0 || wc_ecc_init(&this->pubkey) != 0) if (wc_ecc_init(&this->key) != 0 || wc_ecc_init(&this->pubkey) != 0)
{ {
DBG1(DBG_LIB, "key init failed, ecdh create failed"); DBG1(DBG_LIB, "key init failed, ecdh create failed");
@@ -254,6 +254,8 @@ METHOD(key_exchange_t, get_method, key_exchange_method_t,
return this->method; return this->method;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed, bool, METHOD(key_exchange_t, set_seed, bool,
private_key_exchange_t *this, chunk_t value, drbg_t *drbg) private_key_exchange_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -266,6 +268,8 @@ METHOD(key_exchange_t, set_seed, bool,
return TRUE; return TRUE;
} }
#endif /* TESTABLE_KE */
METHOD(key_exchange_t, destroy, void, METHOD(key_exchange_t, destroy, void,
private_key_exchange_t *this) private_key_exchange_t *this)
{ {
@@ -312,12 +316,16 @@ key_exchange_t *wolfssl_kem_create(key_exchange_method_t method)
.get_public_key = _get_public_key, .get_public_key = _get_public_key,
.set_public_key = _set_public_key, .set_public_key = _set_public_key,
.get_shared_secret = _get_shared_secret, .get_shared_secret = _get_shared_secret,
.set_seed = _set_seed,
.destroy = _destroy, .destroy = _destroy,
}, },
.method = method, .method = method,
.type = type, .type = type,
); );
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed;
#endif
return &this->public; return &this->public;
} }
@@ -142,6 +142,8 @@ METHOD(key_exchange_t, get_public_key_25519, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed_25519, bool, METHOD(key_exchange_t, set_seed_25519, bool,
private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -170,7 +172,7 @@ METHOD(key_exchange_t, set_seed_25519, bool,
} }
return ret == 0; return ret == 0;
} }
#endif /* TESTABLE_KE */
#endif /* HAVE_CURVE25519 */ #endif /* HAVE_CURVE25519 */
#ifdef HAVE_CURVE448 #ifdef HAVE_CURVE448
@@ -229,6 +231,8 @@ METHOD(key_exchange_t, get_public_key_448, bool,
return TRUE; return TRUE;
} }
#ifdef TESTABLE_KE
METHOD(key_exchange_t, set_seed_448, bool, METHOD(key_exchange_t, set_seed_448, bool,
private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg) private_diffie_hellman_t *this, chunk_t value, drbg_t *drbg)
{ {
@@ -258,6 +262,7 @@ METHOD(key_exchange_t, set_seed_448, bool,
return ret == 0; return ret == 0;
} }
#endif /* TESTABLE_KE */
#endif /* HAVE_CURVE448 */ #endif /* HAVE_CURVE448 */
METHOD(key_exchange_t, get_method, key_exchange_method_t, METHOD(key_exchange_t, get_method, key_exchange_method_t,
@@ -317,7 +322,9 @@ key_exchange_t *wolfssl_x_diffie_hellman_create(key_exchange_method_t group)
this->public.get_shared_secret = _get_shared_secret_25519; this->public.get_shared_secret = _get_shared_secret_25519;
this->public.set_public_key = _set_public_key_25519; this->public.set_public_key = _set_public_key_25519;
this->public.get_public_key = _get_public_key_25519; this->public.get_public_key = _get_public_key_25519;
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed_25519; this->public.set_seed = _set_seed_25519;
#endif
if (wc_curve25519_init(&this->key.key25519) != 0 || if (wc_curve25519_init(&this->key.key25519) != 0 ||
wc_curve25519_init(&this->pub.key25519) != 0) wc_curve25519_init(&this->pub.key25519) != 0)
@@ -336,7 +343,9 @@ key_exchange_t *wolfssl_x_diffie_hellman_create(key_exchange_method_t group)
this->public.get_shared_secret = _get_shared_secret_448; this->public.get_shared_secret = _get_shared_secret_448;
this->public.set_public_key = _set_public_key_448; this->public.set_public_key = _set_public_key_448;
this->public.get_public_key = _get_public_key_448; this->public.get_public_key = _get_public_key_448;
#ifdef TESTABLE_KE
this->public.set_seed = _set_seed_448; this->public.set_seed = _set_seed_448;
#endif
if (wc_curve448_init(&this->key.key448) != 0 || if (wc_curve448_init(&this->key.key448) != 0 ||
wc_curve448_init(&this->pub.key448) != 0) wc_curve448_init(&this->pub.key448) != 0)