SLH-DSA clean ups

- Make slh_dsa_sign() return the siglen when sig is NULL.
- Remove the ability in fromdata to generate the public key root
  given the private key and public key seed. This was messy and can
  be done by key generation instead.
- Add common EVP_PKEY gettablesto SLH_DSA keys
  (OSSL_PKEY_PARAM_BITS, OSSL_PKEY_PARAM_SECURITY_BITS, and
   OSSL_PKEY_PARAM_MAX_SIZE).
- Update tests based on the above changes.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Tim Hudson <tjh@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25882)
This commit is contained in:
slontis 2024-11-08 16:08:31 +11:00 committed by Tomas Mraz
parent ce3acbd07e
commit 5c2b404241
7 changed files with 89 additions and 102 deletions

View File

@ -64,12 +64,14 @@ static int slh_sign_internal(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *priv,
uint8_t *sig_ht = sig_fors + sig_fors_len;
const uint8_t *md, *pk_seed, *sk_seed;
if (sig_size < sig_len_expected)
return 0;
if (sig_len != NULL)
*sig_len = sig_len_expected;
if (sig == NULL)
return 1;
return (sig_len != NULL);
if (sig_size < sig_len_expected)
return 0;
/* Exit if private key is not set */
if (priv->has_priv == 0)
return 0;
@ -229,16 +231,16 @@ int ossl_slh_dsa_sign(SLH_DSA_CTX *slh_ctx, const SLH_DSA_KEY *priv,
const uint8_t *add_rand, int encode,
unsigned char *sig, size_t *siglen, size_t sigsize)
{
uint8_t *m;
size_t m_len;
uint8_t m_tmp[1024];
uint8_t m_tmp[1024], *m = m_tmp;
size_t m_len = 0;
int ret = 0;
m = msg_encode(msg, msg_len, ctx, ctx_len, encode, m_tmp, sizeof(m_tmp),
&m_len);
if (m == NULL)
return 0;
if (sig != NULL) {
m = msg_encode(msg, msg_len, ctx, ctx_len, encode, m_tmp, sizeof(m_tmp),
&m_len);
if (m == NULL)
return 0;
}
ret = slh_sign_internal(slh_ctx, priv, m, m_len, sig, siglen, sigsize, add_rand);
if (m != msg && m != m_tmp)
OPENSSL_free(m);

View File

@ -137,9 +137,8 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
int include_private)
{
size_t n, key_len, len = 0;
const OSSL_PARAM *param_priv = NULL, *param_pub, *param_pk_seed = NULL;
const OSSL_PARAM *param_priv = NULL, *param_pub = NULL;
void *p;
SLH_DSA_CTX *dsa_ctx = NULL;
if (key == NULL)
return 0;
@ -158,24 +157,20 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
/*
* There must always be a public key, since the private key cannot exist
* without the public key elements.
* If there is only the public seed then the private key MUST be present in
* order to compute the pk_root element.
*/
param_pub = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
if (param_pub == NULL) {
param_pk_seed = OSSL_PARAM_locate_const(params,
OSSL_PKEY_PARAM_SLH_DSA_PUB_SEED);
if (param_pk_seed == NULL || param_priv == NULL)
return 0;
}
if (param_pub == NULL)
return 0;
if (param_pub != NULL) {
p = key->pub;
if (!OSSL_PARAM_get_octet_string(param_pub, &p, key_len, &len))
return 0;
if (len != key_len)
return 0;
}
p = key->pub;
if (!OSSL_PARAM_get_octet_string(param_pub, &p, key_len, &len))
return 0;
/*
* This does not allow you to pass in just the PK SEED, this can be done
* via key generation
*/
if (len != key_len)
return 0;
if (param_priv != NULL) {
p = key->priv;
if (!OSSL_PARAM_get_octet_string(param_priv, &p, key_len, &len))
@ -185,29 +180,11 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
goto err;
key->has_priv = 1;
}
if (param_pk_seed != NULL) {
/*
* In this case we need to generate the pk_root
* which requires both the private key element(s) and the public key seed.
*/
p = SLH_DSA_PK_SEED(key);
if (!OSSL_PARAM_get_octet_string(param_pk_seed, &p, n, &len))
goto err;
if (len != n)
goto err;
/* Compute the pk_root element */
dsa_ctx = ossl_slh_dsa_ctx_new(key->params->alg, key->libctx, key->propq);
if (dsa_ctx == NULL
|| !slh_dsa_compute_pk_root(dsa_ctx, key))
goto err;
ossl_slh_dsa_ctx_free(dsa_ctx);
}
key->key_len = key_len; /* This indicates the public key is present */
return 1;
err:
key->key_len = 0;
key->has_priv = 0;
ossl_slh_dsa_ctx_free(dsa_ctx);
OPENSSL_cleanse(key->priv, key_len);
return 0;
}
@ -324,3 +301,8 @@ size_t ossl_slh_dsa_key_get_n(const SLH_DSA_KEY *key)
{
return key->params->n;
}
size_t ossl_slh_dsa_key_get_sig_len(const SLH_DSA_KEY *key)
{
return key->params->sig_len;
}

View File

@ -37,6 +37,7 @@ __owur const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key);
__owur const uint8_t *ossl_slh_dsa_key_get_priv(const SLH_DSA_KEY *key);
__owur size_t ossl_slh_dsa_key_get_len(const SLH_DSA_KEY *key);
__owur size_t ossl_slh_dsa_key_get_n(const SLH_DSA_KEY *key);
__owur size_t ossl_slh_dsa_key_get_sig_len(const SLH_DSA_KEY *key);
__owur int ossl_slh_dsa_key_type_matches(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key);
__owur SLH_DSA_CTX *ossl_slh_dsa_ctx_new(const char *alg,

View File

@ -93,12 +93,14 @@ static int slh_dsa_import(void *keydata, int selection, const OSSL_PARAM params[
return ossl_slh_dsa_key_fromdata(key, params, include_priv);
}
#define SLH_DSA_IMEXPORTABLE_PARAMETERS \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
static const OSSL_PARAM slh_dsa_key_types[] = {
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),
OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0),
SLH_DSA_IMEXPORTABLE_PARAMETERS,
OSSL_PARAM_END
};
static const OSSL_PARAM *slh_dsa_imexport_types(int selection)
{
if ((selection & SLH_DSA_POSSIBLE_SELECTIONS) == 0)
@ -106,9 +108,16 @@ static const OSSL_PARAM *slh_dsa_imexport_types(int selection)
return slh_dsa_key_types;
}
static const OSSL_PARAM slh_dsa_params[] = {
OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
SLH_DSA_IMEXPORTABLE_PARAMETERS,
OSSL_PARAM_END
};
static const OSSL_PARAM *slh_dsa_gettable_params(void *provctx)
{
return slh_dsa_key_types;
return slh_dsa_params;
}
static int key_to_params(SLH_DSA_KEY *key, OSSL_PARAM_BLD *tmpl,
@ -137,6 +146,17 @@ static int key_to_params(SLH_DSA_KEY *key, OSSL_PARAM_BLD *tmpl,
static int slh_dsa_get_params(void *keydata, OSSL_PARAM params[])
{
SLH_DSA_KEY *key = keydata;
OSSL_PARAM *p;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, 8 * ossl_slh_dsa_key_get_len(key)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
&& !OSSL_PARAM_set_int(p, 8 * ossl_slh_dsa_key_get_n(key)))
return 0;
if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
&& !OSSL_PARAM_set_int(p, ossl_slh_dsa_key_get_sig_len(key)))
return 0;
return key_to_params(key, NULL, params, 1);
}

View File

@ -127,13 +127,16 @@ static int slh_sign(void *vctx, unsigned char *sig, size_t *siglen,
if (!ossl_prov_is_running())
return 0;
if (ctx->add_random_len != 0) {
opt_rand = ctx->add_random;
} else if (ctx->deterministic == 0) {
n = ossl_slh_dsa_key_get_n(ctx->key);
if (RAND_priv_bytes_ex(ctx->libctx, add_rand, n, 0) <= 0)
return 0;
opt_rand = add_rand;
if (sig != NULL) {
if (ctx->add_random_len != 0) {
opt_rand = ctx->add_random;
} else if (ctx->deterministic == 0) {
n = ossl_slh_dsa_key_get_n(ctx->key);
if (RAND_priv_bytes_ex(ctx->libctx, add_rand, n, 0) <= 0)
return 0;
opt_rand = add_rand;
}
}
ret = ossl_slh_dsa_sign(ctx->ctx, ctx->key, msg, msg_len,
ctx->context_string, ctx->context_string_len,

View File

@ -59,9 +59,6 @@ static int slh_dsa_create_keypair(EVP_PKEY **pkey, const char *name,
OSSL_PARAM *params = NULL;
const char *pub_name = OSSL_PKEY_PARAM_PUB_KEY;
if (pub_len != priv_len)
pub_name = OSSL_PKEY_PARAM_SLH_DSA_PUB_SEED;
if (!TEST_ptr(bld = OSSL_PARAM_BLD_new())
|| !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld,
OSSL_PKEY_PARAM_PRIV_KEY,
@ -210,8 +207,8 @@ static int slh_dsa_sign_verify_test(int tst_id)
EVP_PKEY *pkey = NULL;
EVP_SIGNATURE *sig_alg = NULL;
OSSL_PARAM params[4], *p = params;
uint8_t sig[64 * 1024];
size_t sig_len = sizeof(sig);
uint8_t *psig = NULL;
size_t psig_len = 0, sig_len2 = 0;
uint8_t digest[32];
size_t digest_len = sizeof(digest);
int encode = 0, deterministic = 1;
@ -237,22 +234,29 @@ static int slh_dsa_sign_verify_test(int tst_id)
if (!TEST_ptr(sig_alg = EVP_SIGNATURE_fetch(lib_ctx, td->alg, NULL)))
goto err;
if (!TEST_int_eq(EVP_PKEY_sign_init_ex2(sctx, sig_alg, params), 1)
|| !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len,
|| !TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &psig_len,
td->msg, td->msg_len), 1)
|| !TEST_true(EVP_PKEY_get_size_t_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE,
&sig_len2))
|| !TEST_int_eq(sig_len2, psig_len)
|| !TEST_ptr(psig = OPENSSL_zalloc(psig_len))
|| !TEST_int_eq(EVP_PKEY_sign(sctx, psig, &psig_len,
td->msg, td->msg_len), 1))
goto err;
if (!TEST_int_eq(EVP_Q_digest(lib_ctx, "SHA256", NULL, sig, sig_len,
if (!TEST_int_eq(EVP_Q_digest(lib_ctx, "SHA256", NULL, psig, psig_len,
digest, &digest_len), 1))
goto err;
if (!TEST_mem_eq(digest, digest_len, td->sig_digest, td->sig_digest_len))
goto err;
if (!do_slh_dsa_verify(td, sig, sig_len))
if (!do_slh_dsa_verify(td, psig, psig_len))
goto err;
ret = 1;
err:
EVP_SIGNATURE_free(sig_alg);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(sctx);
OPENSSL_free(psig);
return ret;
}
@ -287,6 +291,7 @@ static int slh_dsa_keygen_test(int tst_id)
size_t priv_len, pub_len;
size_t key_len = tst->priv_len / 2;
size_t n = key_len / 2;
int bits = 0, sec_bits = 0, sig_len = 0;
if (!TEST_ptr(pkey = do_gen_key(tst->name, tst->priv, key_len + n)))
goto err;
@ -297,6 +302,17 @@ static int slh_dsa_keygen_test(int tst_id)
if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
pub, sizeof(pub), &pub_len)))
goto err;
if (!TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_BITS, &bits))
|| !TEST_int_eq(bits, 8 * key_len)
|| !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_SECURITY_BITS,
&sec_bits))
|| !TEST_int_eq(sec_bits, 8 * n)
|| !TEST_true(EVP_PKEY_get_int_param(pkey, OSSL_PKEY_PARAM_MAX_SIZE,
&sig_len))
|| !TEST_int_ge(sig_len, 7856)
|| !TEST_int_le(sig_len, 49856))
goto err;
if (!TEST_size_t_eq(priv_len, key_len)
|| !TEST_size_t_eq(pub_len, key_len))
goto err;
@ -308,39 +324,6 @@ err:
return ret;
}
/*
* Given raw values for the private key + public key seed
* generate the public root using from data.
*/
static int slh_dsa_pub_root_from_data_test(void)
{
int ret = 0;
uint8_t priv[64], pub[64];
size_t priv_len = 0, pub_len = 0;
EVP_PKEY *pkey = NULL;
const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
size_t key_len = tst->priv_len / 2;
size_t n = key_len / 2;
if (!slh_dsa_create_keypair(&pkey, tst->name, tst->priv, key_len,
tst->priv + key_len, n))
goto err;
if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
priv, sizeof(priv), &priv_len)))
goto err;
if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
pub, sizeof(pub), &pub_len)))
goto err;
if (!TEST_mem_eq(pub, pub_len, tst->priv + key_len, key_len))
goto err;
ret = 1;
err:
OPENSSL_cleanse(priv, priv_len);
EVP_PKEY_free(pkey);
return ret;
}
const OPTIONS *test_get_options(void)
{
static const OPTIONS options[] = {
@ -377,7 +360,6 @@ int setup_tests(void)
ADD_TEST(slh_dsa_key_eq_test);
ADD_ALL_TESTS(slh_dsa_sign_verify_test, OSSL_NELEM(slh_dsa_sig_testdata));
ADD_ALL_TESTS(slh_dsa_keygen_test, OSSL_NELEM(slh_dsa_keygen_testdata));
ADD_TEST(slh_dsa_pub_root_from_data_test);
return 1;
}

View File

@ -447,9 +447,6 @@ my %params = (
# SLH_DSA Key generation parameters
'PKEY_PARAM_SLH_DSA_ENTROPY' => "entropy",
# SLH_DSA parameters
'PKEY_PARAM_SLH_DSA_PUB_SEED' => "pk-seed",
# Key Exchange parameters
'EXCHANGE_PARAM_PAD' => "pad",# uint