]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
SLH-DSA clean ups
authorslontis <shane.lontis@oracle.com>
Fri, 8 Nov 2024 05:08:31 +0000 (16:08 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Feb 2025 09:13:53 +0000 (10:13 +0100)
- 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)

crypto/slh_dsa/slh_dsa.c
crypto/slh_dsa/slh_dsa_key.c
include/crypto/slh_dsa.h
providers/implementations/keymgmt/slh_dsa_kmgmt.c
providers/implementations/signature/slh_dsa_sig.c
test/slh_dsa_test.c
util/perl/OpenSSL/paramnames.pm

index 8f6736b91b871e81868667c6142cdcf0f3d71ac0..10b0b1f66b011928ab43764c078e4fc0a95274fd 100644 (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);
index 922d1650846d2f765bb9e7d0a3911d1950e00b3a..e189c8e55e4fa6e8a0b1a5531e4d8bbf7db1ea0f 100644 (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;
+}
index 14139508b4cf81e38864b3048b0f2dfbd2a1cbfd..86ad4f96f8a10cbb54a86c44f38c3f571f2ea838 100644 (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,
index f833f588ea60a5b7b767ca26731a7b0ce3c39aee..7deb42b345068bf87b1d60cb6405c1c191951605 100644 (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);
 }
index ddee41ca759e9a0c59ca641a097608324854c1d8..d279f1fbf7d847b8a3c367af5153f995c43722b6 100644 (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,
index 15cdf8bea0bb3c956cc83223426d645ccd52ef6f..7e66e3a100a4418faceb7b7453516c3e7d25b346 100644 (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,46 +302,24 @@ 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_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;
 }
@@ -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;
 }
 
index fa34e137e90831b40ef2702199aa7133dcc23c58..be5b8c027ac9175ebad787ba18a0db477259c05c 100644 (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