]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
SLH-DSA: Add EVP_PKEY_CTX_dup() support.
authorslontis <shane.lontis@oracle.com>
Tue, 11 Feb 2025 04:30:59 +0000 (15:30 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Feb 2025 09:17:29 +0000 (10:17 +0100)
Reviewed-by: Tim Hudson <tjh@openssl.org>
Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
(Merged from https://github.com/openssl/openssl/pull/26701)

crypto/slh_dsa/slh_dsa_hash_ctx.c
crypto/slh_dsa/slh_dsa_key.h
crypto/slh_dsa/slh_dsa_local.h
include/crypto/slh_dsa.h
providers/implementations/keymgmt/slh_dsa_kmgmt.c
providers/implementations/signature/slh_dsa_sig.c
test/slh_dsa_test.c

index f640801be56998c4c91feefcac76b9734928cb31..89ec68467b7ea63062a6e53f5c3d07d70ad34079 100644 (file)
@@ -60,6 +60,42 @@ SLH_DSA_HASH_CTX *ossl_slh_dsa_hash_ctx_new(const SLH_DSA_KEY *key)
     return NULL;
 }
 
+/**
+ * @brief Duplicate a SLH_DSA_HASH_CTX
+ *
+ * @param ctx The SLH_DSA_HASH_CTX object to duplicate.
+ */
+SLH_DSA_HASH_CTX *ossl_slh_dsa_hash_ctx_dup(const SLH_DSA_HASH_CTX *src)
+{
+    SLH_DSA_HASH_CTX *ret = OPENSSL_zalloc(sizeof(*ret));
+
+    if (ret == NULL)
+        return NULL;
+
+    ret->hmac_digest_used = src->hmac_digest_used;
+    /* Note that the key is not ref counted, since it does not own the key */
+    ret->key = src->key;
+
+    if (src->md_ctx != NULL
+            && (ret->md_ctx = EVP_MD_CTX_dup(src->md_ctx)) == NULL)
+        goto err;
+    if (src->md_big_ctx != NULL) {
+        if (src->md_big_ctx != src->md_ctx) {
+            if ((ret->md_big_ctx = EVP_MD_CTX_dup(src->md_big_ctx)) == NULL)
+                goto err;
+        } else {
+            ret->md_big_ctx = ret->md_ctx;
+        }
+    }
+    if (src->hmac_ctx != NULL
+            && (ret->hmac_ctx = EVP_MAC_CTX_dup(src->hmac_ctx)) == NULL)
+        goto err;
+    return ret;
+ err:
+    ossl_slh_dsa_hash_ctx_free(ret);
+    return NULL;
+}
+
 /**
  * @brief Destroy a SLH_DSA_HASH_CTX
  *
index 3c81b55d56c86ebd938160de228eb69f0c8eb8f4..851821c8dd02dfe088e3b88a254cb74dc4f71cfb 100644 (file)
@@ -17,6 +17,9 @@
 #define SLH_DSA_PUB(key) SLH_DSA_PK_SEED(key)
 #define SLH_DSA_PRIV(key) SLH_DSA_SK_SEED(key)
 
+/*
+ * NOTE: Any changes to this structure may require updating ossl_slh_dsa_key_dup().
+ */
 struct slh_dsa_key_st {
     /*
      * A private key consists of
index 40d26f67202ea1ef9214e8802444fdf745795659..1c66382c72b7d27c3b6cc2ddf41fa5092fc0cddf 100644 (file)
@@ -41,6 +41,9 @@
  * SLH_DSA_HASH_CTX is a container to hold all of these objects. This object is
  * resolved early and is then passed to most SLH_DSA related functions, since
  * there are many nested layers of calls that require these values.
+ *
+ * NOTE: Any changes to this structure will need updating in
+ * ossl_slh_dsa_hash_ctx_dup().
  */
 struct slh_dsa_hash_ctx_st {
     const SLH_DSA_KEY *key; /* This key is not owned by this object */
index 72390783bbeb6447758ca175f27caea6b248b1b1..002427e1ab0a9363e0520c0a63aac12fab022a0b 100644 (file)
@@ -51,6 +51,7 @@ __owur int ossl_slh_dsa_key_get_type(const SLH_DSA_KEY *key);
 __owur int ossl_slh_dsa_key_type_matches(const SLH_DSA_KEY *key, const char *alg);
 __owur SLH_DSA_HASH_CTX *ossl_slh_dsa_hash_ctx_new(const SLH_DSA_KEY *key);
 void ossl_slh_dsa_hash_ctx_free(SLH_DSA_HASH_CTX *ctx);
+__owur SLH_DSA_HASH_CTX *ossl_slh_dsa_hash_ctx_dup(const SLH_DSA_HASH_CTX *src);
 
 __owur int ossl_slh_dsa_sign(SLH_DSA_HASH_CTX *slh_ctx,
                              const uint8_t *msg, size_t msg_len,
index 4b33f891877cce5be97ee8d61df78f37d8b77550..e7ef60871b570468ce842372d74d1e6d9e3fa4af 100644 (file)
@@ -32,6 +32,7 @@ static OSSL_FUNC_keymgmt_gen_init_fn slh_dsa_gen_init;
 static OSSL_FUNC_keymgmt_gen_cleanup_fn slh_dsa_gen_cleanup;
 static OSSL_FUNC_keymgmt_gen_set_params_fn slh_dsa_gen_set_params;
 static OSSL_FUNC_keymgmt_gen_settable_params_fn slh_dsa_gen_settable_params;
+static OSSL_FUNC_keymgmt_dup_fn slh_dsa_dup_key;
 
 #define SLH_DSA_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
 
@@ -56,6 +57,13 @@ static void slh_dsa_free_key(void *keydata)
     ossl_slh_dsa_key_free((SLH_DSA_KEY *)keydata);
 }
 
+static void *slh_dsa_dup_key(const void *keydata_from, int selection)
+{
+    if (ossl_prov_is_running())
+        return ossl_slh_dsa_key_dup(keydata_from, selection);
+    return NULL;
+}
+
 static int slh_dsa_has(const void *keydata, int selection)
 {
     const SLH_DSA_KEY *key = keydata;
@@ -412,6 +420,7 @@ static void slh_dsa_gen_cleanup(void *genctx)
     const OSSL_DISPATCH ossl_slh_dsa_##fn##_keymgmt_functions[] = {            \
         { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))slh_dsa_##fn##_new_key },     \
         { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))slh_dsa_free_key },          \
+        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))slh_dsa_dup_key },            \
         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))slh_dsa_has },                \
         { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))slh_dsa_match },            \
         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))slh_dsa_import },          \
index b30ebcf5328f23ab52d892a6e847474782904bed..f8c07f4236cbb71a17d4a0b84bd6822613d8d287 100644 (file)
@@ -34,9 +34,13 @@ static OSSL_FUNC_signature_digest_sign_init_fn slh_dsa_digest_signverify_init;
 static OSSL_FUNC_signature_digest_sign_fn slh_dsa_digest_sign;
 static OSSL_FUNC_signature_digest_verify_fn slh_dsa_digest_verify;
 static OSSL_FUNC_signature_freectx_fn slh_dsa_freectx;
+static OSSL_FUNC_signature_dupctx_fn slh_dsa_dupctx;
 static OSSL_FUNC_signature_set_ctx_params_fn slh_dsa_set_ctx_params;
 static OSSL_FUNC_signature_settable_ctx_params_fn slh_dsa_settable_ctx_params;
 
+/*
+ * NOTE: Any changes to this structure may require updating slh_dsa_dupctx().
+ */
 typedef struct {
     SLH_DSA_KEY *key; /* Note that the key is not owned by this object */
     SLH_DSA_HASH_CTX *hash_ctx;
@@ -86,6 +90,35 @@ static void *slh_dsa_newctx(void *provctx, const char *alg, const char *propq)
     return NULL;
 }
 
+static void *slh_dsa_dupctx(void *vctx)
+{
+    PROV_SLH_DSA_CTX *src = (PROV_SLH_DSA_CTX *)vctx;
+    PROV_SLH_DSA_CTX *ret;
+
+    if (!ossl_prov_is_running())
+        return NULL;
+
+    /*
+     * Note that the SLH_DSA_KEY is ref counted via EVP_PKEY so we can just copy
+     * the key here.
+     */
+    ret = OPENSSL_memdup(src, sizeof(*src));
+    if (ret == NULL)
+        return NULL;
+    ret->propq = NULL;
+    ret->hash_ctx = NULL;
+    if (src->propq != NULL && (ret->propq = OPENSSL_strdup(src->propq)) == NULL)
+        goto err;
+    ret->hash_ctx = ossl_slh_dsa_hash_ctx_dup(src->hash_ctx);
+    if (ret->hash_ctx == NULL)
+        goto err;
+
+    return ret;
+ err:
+    slh_dsa_freectx(ret);
+    return NULL;
+}
+
 static int slh_dsa_set_alg_id_buffer(PROV_SLH_DSA_CTX *ctx)
 {
     int ret;
@@ -334,6 +367,7 @@ static int slh_dsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
         { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY,                                   \
           (void (*)(void))slh_dsa_digest_verify },                             \
         { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))slh_dsa_freectx },      \
+        { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))slh_dsa_dupctx },        \
         { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))slh_dsa_set_ctx_params },\
         { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                             \
           (void (*)(void))slh_dsa_settable_ctx_params },                       \
index d39b1146ee3b4b32852d2652190f92a6b8e1c2f5..7f5a4e54d31eb3f9254f75e6c1ab76338c38ba23 100644 (file)
@@ -116,7 +116,8 @@ end:
 static int slh_dsa_key_eq_test(void)
 {
     int ret = 0;
-    EVP_PKEY *key[3] = { NULL, NULL, NULL };
+    size_t i;
+    EVP_PKEY *key[4] = { NULL, NULL, NULL, NULL };
     SLH_DSA_SIG_TEST_DATA *td1 = &slh_dsa_sig_testdata[0];
     SLH_DSA_SIG_TEST_DATA *td2 = &slh_dsa_sig_testdata[1];
 #ifndef OPENSSL_NO_EC
@@ -125,11 +126,13 @@ static int slh_dsa_key_eq_test(void)
 
     if (!TEST_ptr(key[0] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
             || !TEST_ptr(key[1] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1))
-            || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1)))
+            || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1))
+            || !TEST_ptr(key[3] = EVP_PKEY_dup(key[0])))
         goto end;
 
     if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1)
-            || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1))
+            || !TEST_int_ne(EVP_PKEY_eq(key[0], key[2]), 1)
+            || !TEST_int_eq(EVP_PKEY_eq(key[0], key[3]), 1))
         goto end;
 
 #ifndef OPENSSL_NO_EC
@@ -140,10 +143,9 @@ static int slh_dsa_key_eq_test(void)
 #else
     ret = 1;
 #endif
-end:
-    EVP_PKEY_free(key[2]);
-    EVP_PKEY_free(key[1]);
-    EVP_PKEY_free(key[0]);
+ end:
+    for (i = 0; i < OSSL_NELEM(key); ++i)
+        EVP_PKEY_free(key[i]);
     return ret;
 }
 
@@ -433,11 +435,11 @@ static int slh_dsa_deterministic_usage_test(void)
     EVP_CIPHER *cipher = NULL; /* Used to encrypt the private key */
     char *pass = "Password";
     BIO *pub_bio = NULL, *priv_bio = NULL;
-    EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL;
+    EVP_PKEY_CTX *gctx = NULL, *sctx = NULL, *vctx = NULL, *dupctx = NULL;
     EVP_PKEY *gkey = NULL, *pub = NULL, *priv = NULL;
     EVP_SIGNATURE *sig_alg = NULL;
     uint8_t *sig  = NULL;
-    size_t sig_len = 0;
+    size_t sig_len = 0, len = 0;
     uint8_t msg[] = { 0x01, 0x02, 0x03, 0x04 };
     size_t msg_len = sizeof(msg);
     const SLH_DSA_KEYGEN_TEST_DATA *tst = &slh_dsa_keygen_testdata[0];
@@ -471,18 +473,32 @@ static int slh_dsa_deterministic_usage_test(void)
             || !TEST_int_eq(EVP_PKEY_sign_message_init(sctx, sig_alg, params), 1))
         goto err;
 
+    if (!TEST_ptr(dupctx = EVP_PKEY_CTX_dup(sctx)))
+        goto err;
+
     /* Determine the size of the signature & allocate space */
-    if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1)
-            || !TEST_ptr(sig = OPENSSL_malloc(sig_len))
-            || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1))
+    if (!TEST_int_eq(EVP_PKEY_sign(sctx, NULL, &sig_len, msg, msg_len), 1))
+        goto err;
+    len = sig_len;
+    if (!TEST_ptr(sig = OPENSSL_zalloc(sig_len * 2))
+            || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &len, msg, msg_len), 1)
+            || !TEST_size_t_eq(sig_len, len)
+            || !TEST_int_eq(EVP_PKEY_sign(dupctx, sig + sig_len, &len,
+                                          msg, msg_len), 1)
+            || !TEST_size_t_eq(sig_len, len))
         goto err;
     /* Read the public key and add to a verify ctx */
     if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL))
             || !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL)))
         goto err;
+    EVP_PKEY_CTX_free(dupctx);
+
     /* verify the signature */
     if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1)
-            || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1))
+            || !TEST_ptr(dupctx = EVP_PKEY_CTX_dup(vctx))
+            || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1)
+            || !TEST_int_eq(EVP_PKEY_verify(dupctx, sig + sig_len, sig_len,
+                                            msg, msg_len), 1))
         goto err;
     ret = 1;
 err:
@@ -494,6 +510,7 @@ err:
     EVP_PKEY_CTX_free(gctx);
     EVP_PKEY_CTX_free(sctx);
     EVP_PKEY_CTX_free(vctx);
+    EVP_PKEY_CTX_free(dupctx);
     BIO_free(pub_bio);
     BIO_free(priv_bio);
     OPENSSL_free(sig);