- 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)
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;
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);
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;
/*
* 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))
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;
}
{
return key->params->n;
}
+
+size_t ossl_slh_dsa_key_get_sig_len(const SLH_DSA_KEY *key)
+{
+ return key->params->sig_len;
+}
__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,
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)
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,
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);
}
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,
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,
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;
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;
}
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;
if (!TEST_true(EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
pub, sizeof(pub), &pub_len)))
goto err;
- if (!TEST_size_t_eq(priv_len, key_len)
- || !TEST_size_t_eq(pub_len, key_len))
+ 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_mem_eq(pub, pub_len, tst->priv + key_len, key_len))
- goto err;
- ret = 1;
-err:
- EVP_PKEY_free(pkey);
- 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)))
+ if (!TEST_size_t_eq(priv_len, key_len)
+ || !TEST_size_t_eq(pub_len, key_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;
}
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;
}
# 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