]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
Add SLH-DSA encoder/decoder support.
authorslontis <shane.lontis@oracle.com>
Tue, 19 Nov 2024 04:40:13 +0000 (15:40 +1100)
committerTomas Mraz <tomas@openssl.org>
Tue, 18 Feb 2025 09:17:29 +0000 (10:17 +0100)
This required adding additional EVP_PKEY_ASN1_METHOD methods.

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)

28 files changed:
crypto/asn1/standard_methods.h
crypto/evp/p_lib.c
crypto/slh_dsa/build.info
crypto/slh_dsa/slh_dsa.c
crypto/slh_dsa/slh_dsa_backend.c [new file with mode: 0644]
crypto/slh_dsa/slh_dsa_key.c
crypto/slh_dsa/slh_dsa_key.h
crypto/slh_dsa/slh_dsa_meth.c [new file with mode: 0644]
crypto/slh_dsa/slh_params.c
crypto/slh_dsa/slh_params.h
crypto/x509/x_pubkey.c
doc/man7/OSSL_PROVIDER-FIPS.pod
doc/man7/OSSL_PROVIDER-base.pod
doc/man7/OSSL_PROVIDER-default.pod
include/crypto/asn1.h
include/crypto/evp.h
include/crypto/slh_dsa.h
include/crypto/x509.h
include/openssl/evp.h
providers/decoders.inc
providers/encoders.inc
providers/implementations/encode_decode/decode_der2key.c
providers/implementations/encode_decode/encode_key2any.c
providers/implementations/encode_decode/encode_key2text.c
providers/implementations/include/prov/implementations.h
providers/implementations/keymgmt/slh_dsa_kmgmt.c
test/endecode_test.c
test/slh_dsa.inc

index ebb53e57db7ef81b16956b0b410004c971ba4daf..2c3bd392049a9cf8629a61c9989fb90ff4085540 100644 (file)
@@ -40,5 +40,18 @@ static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
 #ifndef OPENSSL_NO_SM2
     &ossl_sm2_asn1_meth,
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+    &ossl_slh_dsa_sha2_128s_asn1_meth,
+    &ossl_slh_dsa_sha2_128f_asn1_meth,
+    &ossl_slh_dsa_sha2_192s_asn1_meth,
+    &ossl_slh_dsa_sha2_192f_asn1_meth,
+    &ossl_slh_dsa_sha2_256s_asn1_meth,
+    &ossl_slh_dsa_sha2_256f_asn1_meth,
+    &ossl_slh_dsa_shake_128s_asn1_meth,
+    &ossl_slh_dsa_shake_128f_asn1_meth,
+    &ossl_slh_dsa_shake_192s_asn1_meth,
+    &ossl_slh_dsa_shake_192f_asn1_meth,
+    &ossl_slh_dsa_shake_256s_asn1_meth,
+    &ossl_slh_dsa_shake_256f_asn1_meth,
+#endif
 };
-
index 64ef8109831165f852533e98bc8b945faddb8a33..22d27cf89a53ed43357e79bbb1b9ccabbfa7917e 100644 (file)
@@ -43,6 +43,7 @@
 #include "crypto/ec.h"
 #include "crypto/ecx.h"
 #include "crypto/rsa.h"
+#include "crypto/slh_dsa.h"
 #ifndef FIPS_MODULE
 # include "crypto/asn1.h"
 # include "crypto/x509.h"
@@ -943,6 +944,17 @@ IMPLEMENT_ECX_VARIANT(ED448)
 
 # endif /* OPENSSL_NO_ECX */
 
+# ifndef OPENSSL_NO_SLH_DSA
+SLH_DSA_KEY *ossl_evp_pkey_get1_SLH_DSA_KEY(EVP_PKEY *pkey)
+{
+    SLH_DSA_KEY *ret = (SLH_DSA_KEY *)evp_pkey_get_legacy(pkey);
+
+    if (ret != NULL && !ossl_slh_dsa_key_up_ref(ret))
+        ret = NULL;
+    return ret;
+}
+# endif /* OPENSSL_NO_SLH_DSA */
+
 # if !defined(OPENSSL_NO_DH) && !defined(OPENSSL_NO_DEPRECATED_3_0)
 
 int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *dhkey)
index 6f93bd41b006584b4fba49c9bba9721962480a71..bd6c78a44ad5b92534b45cfee85e4fcc72ff754c 100644 (file)
@@ -4,6 +4,6 @@ $COMMON=slh_adrs.c slh_dsa.c slh_dsa_ctx.c slh_dsa_key.c slh_fors.c slh_hash.c \
         slh_hypertree.c slh_params.c slh_wots.c slh_xmss.c
 
 IF[{- !$disabled{'slh_dsa'} -}]
-  SOURCE[../../libcrypto]=$COMMON
+  SOURCE[../../libcrypto]=$COMMON slh_dsa_backend.c slh_dsa_meth.c
   SOURCE[../../providers/libfips.a]=$COMMON
 ENDIF
index c271c21db041de577b9b3300058a80a2aedb55e2..03bc18dc13b0b1904f6fd407f7797333706b5e8e 100644 (file)
@@ -158,7 +158,7 @@ static int slh_verify_internal(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *pub,
     uint32_t leaf_id;
 
     /* Exit if public key is not set */
-    if (pub->key_len == 0)
+    if (pub->pub == NULL)
         return 0;
 
     /* Exit if signature is invalid size */
diff --git a/crypto/slh_dsa/slh_dsa_backend.c b/crypto/slh_dsa/slh_dsa_backend.c
new file mode 100644 (file)
index 0000000..870b78f
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/core_dispatch.h>
+#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/x509.h>
+#include "slh_dsa_local.h"
+#include "slh_dsa_key.h"
+
+SLH_DSA_KEY *ossl_slh_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8_info,
+                                         OSSL_LIB_CTX *lib_ctx, const char *propq)
+{
+    SLH_DSA_KEY *key = NULL;
+    const X509_ALGOR *alg;
+    const uint8_t *p;
+    int nid, p_len, alg_param_type = 0;
+    ASN1_OCTET_STRING *oct = NULL;
+    const char *alg_name = NULL;
+
+    if (!PKCS8_pkey_get0(NULL, &p, &p_len, &alg, p8_info))
+        return 0;
+
+    X509_ALGOR_get0(NULL, &alg_param_type, NULL, alg);
+    if (alg_param_type != V_ASN1_UNDEF)
+         return 0;
+
+    oct = d2i_ASN1_OCTET_STRING(NULL, &p, p_len);
+    if (oct == NULL) {
+        p = NULL;
+        p_len = 0;
+    } else {
+        p = ASN1_STRING_get0_data(oct);
+        p_len = ASN1_STRING_length(oct);
+    }
+    if (p == NULL)
+        goto err;
+
+    nid = OBJ_obj2nid(alg->algorithm);
+    if (nid == NID_undef)
+        goto err;
+    alg_name = OBJ_nid2ln(nid);
+    if (alg_name == NULL)
+        goto err;
+
+    key = ossl_slh_dsa_key_new(lib_ctx, alg_name);
+    if (key == NULL
+            || !ossl_slh_dsa_set_priv(key, p, p_len))
+        goto err;
+    ASN1_OCTET_STRING_free(oct);
+    return key;
+err:
+    ossl_slh_dsa_key_free(key);
+    ASN1_OCTET_STRING_free(oct);
+    return NULL;
+}
index cf4f5c8787b3f06043d32a88c79738ea259a7e1c..be531ca554aeb0b79580a3f65a0f7606cb474c9c 100644 (file)
@@ -22,7 +22,7 @@ static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out);
  * @brief Create a new SLH_DSA_KEY object
  *
  * @param libctx A OSSL_LIB_CTX object used for fetching algorithms.
- * @param alg The algrithm name associated with the key type
+ * @param alg The algorithm name associated with the key type
  * @returns The new SLH_DSA_KEY object on success, or NULL on malloc failure
  */
 SLH_DSA_KEY *ossl_slh_dsa_key_new(OSSL_LIB_CTX *libctx, const char *alg)
@@ -61,7 +61,7 @@ void ossl_slh_dsa_key_free(SLH_DSA_KEY *key)
         return;
     REF_ASSERT_ISNT(i < 0);
 
-    OPENSSL_cleanse(&key->priv, sizeof(key->priv));
+    OPENSSL_cleanse(&key->priv, sizeof(key->priv) >> 1);
     OPENSSL_free(key->propq);
     CRYPTO_FREE_REF(&key->references);
     OPENSSL_free(key);
@@ -86,7 +86,7 @@ int ossl_slh_dsa_key_up_ref(SLH_DSA_KEY *key)
 /**
  * @brief Are 2 keys equal?
  *
- * To be equal the keys must have the same key data.
+ * To be equal the keys must have the same key data and algorithm name.
  *
  * @param key1 A SLH_DSA_KEY object
  * @param key2 A SLH_DSA_KEY object
@@ -99,14 +99,32 @@ int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2,
     int ok = 1;
 
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
-        if (key1->key_len != key2->key_len)
+        /* The parameter sets must match - i.e. The same algorithm name */
+        if (key1->params != key2->params)
             return 0;
-        ok = (memcmp(key1->pub, key2->pub, key1->key_len) == 0);
-    }
-    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
-        ok = ok && (key1->has_priv == key2->has_priv);
-        if (key1->has_priv)
-            ok = ok && (memcmp(key1->priv, key2->priv, key1->key_len) == 0);
+        /*
+         * If both keys dont have a public key return 1
+         * If only one of the keys has a public key return 0.
+         */
+        if (key1->pub == NULL)
+            return (key2->pub == NULL);
+        else if (key2->pub == NULL)
+            return 0;
+        /*
+         * Gets here if both keys have a public key
+         * Since the public key always exists with the private key, check either
+         * that the private key matches (which includes the public key) OR
+         * check that the public key matches depending on the selection.
+         */
+        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+            ok = ok && (key1->has_priv == key2->has_priv);
+            if (key1->has_priv)
+                ok = ok && (memcmp(key1->priv, key2->priv,
+                                   ossl_slh_dsa_key_get_priv_len(key1)) == 0);
+        } else {
+            ok = ok && (memcmp(key1->pub, key2->pub,
+                               ossl_slh_dsa_key_get_pub_len(key1)) == 0);
+        }
     }
     return ok;
 }
@@ -114,11 +132,11 @@ int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2,
 int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection)
 {
     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
-        if (key->key_len == 0)
-            return 0;
+        if (key->pub == NULL)
+            return 0; /* No public key */
         if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
                 && key->has_priv == 0)
-            return 0;
+            return 0; /* No private key */
         return 1;
     }
     return 0;
@@ -136,56 +154,55 @@ int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection)
 int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[],
                               int include_private)
 {
-    size_t n, key_len, len = 0;
+    size_t priv_len, key_len, data_len = 0;
     const OSSL_PARAM *param_priv = NULL, *param_pub = NULL;
     void *p;
 
     if (key == NULL)
         return 0;
-    n = key->params->n;
-    assert(n != 0);
-    /* Both the public and private key are composed of 2 elements of size n */
-    key_len = 2 * n;
+
+    /* The private key consists of 4 elements SK_SEED, SK_PRF, PK_SEED and PK_ROOT */
+    priv_len = ossl_slh_dsa_key_get_priv_len(key);
+    /* The size of either SK_SEED + SK_PRF OR PK_SEED + PK_ROOT */
+    key_len = priv_len >> 1;
 
     /* Private key is optional */
     if (include_private) {
         param_priv = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
-        if (param_priv == NULL)
-            return 0;
+        if (param_priv != NULL) {
+            p = key->priv;
+            if (!OSSL_PARAM_get_octet_string(param_priv, &p, priv_len, &data_len))
+                return 0;
+            /* If the data read includes all 4 elements then we are finished */
+            if (data_len == priv_len) {
+                key->has_priv = 1;
+                key->pub = SLH_DSA_PUB(key);
+                return 1;
+            }
+            /* Otherwise it must be just SK_SEED + SK_PRF */
+            if (data_len != key_len)
+                goto err;
+            key->has_priv = 1;
+        }
     }
-
     /*
-     * There must always be a public key, since the private key cannot exist
-     * without the public key elements.
+     * In the case where the passed in private key does not contain the public key
+     * there MUST be a separate public key, since the private key cannot exist
+     * without the public key elements. NOTE that this does not accept half of
+     * the public key, (Keygen must be used for this case currently).
      */
+    p = SLH_DSA_PUB(key);
     param_pub = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
-    if (param_pub == NULL)
-        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))
-            return 0;
-        /* This is assuming that the private component contains no public elements */
-        if (len != key_len)
-            goto err;
-        key->has_priv = 1;
-    }
-    key->key_len = key_len; /* This indicates the public key is present */
+    if (param_pub == NULL
+            || !OSSL_PARAM_get_octet_string(param_pub, &p, key_len, &data_len)
+            || data_len != key_len)
+        goto err;
+    key->pub = p;
     return 1;
  err:
-    key->key_len = 0;
+    key->pub = NULL;
     key->has_priv = 0;
-    OPENSSL_cleanse(key->priv, key_len);
+    OPENSSL_cleanse(key->priv, priv_len);
     return 0;
 }
 
@@ -231,29 +248,32 @@ int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *lib_ctx,
                               SLH_DSA_KEY *out)
 {
     size_t n = ctx->params->n;
-    size_t key_len = 2 * n;
+    size_t secret_key_len = 2 * n; /* The length of SK_SEED + SK_PRF */
+    size_t pk_seed_len = n;        /* The length of PK_SEED */
+    size_t entropy_len_expected = secret_key_len + pk_seed_len;
+    uint8_t *priv = SLH_DSA_PRIV(out);
+    uint8_t *pub = SLH_DSA_PUB(out);
 
     assert(ctx->params == out->params);
 
     if (entropy != NULL && entropy_len != 0) {
-        if (entropy_len < (key_len + n))
+        if (entropy_len < entropy_len_expected)
             goto err;
-        memcpy(out->priv, entropy, key_len);
-        memcpy(out->pub, entropy + key_len, n);
+        memcpy(priv, entropy, entropy_len_expected);
     } else {
-        if (RAND_priv_bytes_ex(lib_ctx, out->priv, key_len, 0) <= 0
-                || RAND_bytes_ex(lib_ctx, out->pub, n, 0) <= 0)
+        if (RAND_priv_bytes_ex(lib_ctx, priv, secret_key_len, 0) <= 0
+                || RAND_bytes_ex(lib_ctx, pub, pk_seed_len, 0) <= 0)
             goto err;
     }
     if (!slh_dsa_compute_pk_root(ctx, out))
         goto err;
-    out->key_len = key_len;
+    out->pub = pub;
     out->has_priv = 1;
     return 1;
 err:
+    out->pub = NULL;
     out->has_priv = 0;
-    out->key_len = 0;
-    OPENSSL_cleanse(&out->priv, sizeof(out->priv));
+    OPENSSL_cleanse(priv, secret_key_len);
     return 0;
 }
 
@@ -272,28 +292,32 @@ int ossl_slh_dsa_key_type_matches(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key)
     return (key->params == ctx->params);
 }
 
-/*
- * @returns 1 if the SLH_DSA key contains a private component, or 0 if the
- *          key is just a public key.
- */
-int ossl_slh_dsa_key_is_private(const SLH_DSA_KEY *key)
+/* Returns the public key data or NULL if there is no public key */
+const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key)
 {
-    return key->has_priv;
+    return key->pub;
 }
 
-const uint8_t *ossl_slh_dsa_key_get_pub(const SLH_DSA_KEY *key)
+/* Returns the constant 2 * |n| which is the size of PK_SEED + PK_ROOT */
+size_t ossl_slh_dsa_key_get_pub_len(const SLH_DSA_KEY *key)
 {
-    return key->pub;
+    return 2 * key->params->n;
 }
 
+/* Returns the private key data or NULL if there is no private key */
 const uint8_t *ossl_slh_dsa_key_get_priv(const SLH_DSA_KEY *key)
 {
-    return key->priv;
+    return key->has_priv ? key->priv : NULL;
 }
 
-size_t ossl_slh_dsa_key_get_len(const SLH_DSA_KEY *key)
+/*
+ * Returns the constant 4 * |n| which is the size of both
+ * the private and public key components.
+ * SK_SEED + SK_ROOT + PK_SEED + PK_ROOT
+ */
+size_t ossl_slh_dsa_key_get_priv_len(const SLH_DSA_KEY *key)
 {
-    return key->key_len;
+    return 4 * key->params->n;
 }
 
 size_t ossl_slh_dsa_key_get_n(const SLH_DSA_KEY *key)
@@ -305,3 +329,32 @@ size_t ossl_slh_dsa_key_get_sig_len(const SLH_DSA_KEY *key)
 {
     return key->params->sig_len;
 }
+void ossl_slh_dsa_key_set0_libctx(SLH_DSA_KEY *key, OSSL_LIB_CTX *lib_ctx)
+{
+    key->libctx = lib_ctx;
+}
+
+const char *ossl_slh_dsa_key_get_name(const SLH_DSA_KEY *key)
+{
+    return key->params->alg;
+}
+
+int ossl_slh_dsa_set_priv(SLH_DSA_KEY *key, const uint8_t *priv, size_t priv_len)
+{
+    if (ossl_slh_dsa_key_get_priv_len(key) != priv_len)
+        return 0;
+    memcpy(key->priv, priv, priv_len);
+    key->has_priv = 1;
+    key->pub = SLH_DSA_PUB(key);
+    return 1;
+}
+
+int ossl_slh_dsa_set_pub(SLH_DSA_KEY *key, const uint8_t *pub, size_t pub_len)
+{
+    if (ossl_slh_dsa_key_get_pub_len(key) != pub_len)
+        return 0;
+    key->pub = SLH_DSA_PUB(key);
+    memcpy(key->pub, pub, pub_len);
+    key->has_priv = 0;
+    return 1;
+}
index 520332965dc7ee0ced4d7661589c8596cb1cad40..bd9ef760e444a524dad5ca0f5199aed6f797474a 100644 (file)
 #include <openssl/e_os2.h>
 #include "internal/refcount.h"
 
-#define SLH_DSA_MAX_KEYLEN 32 * 2 /* 2 * n */
-#define SLH_DSA_SK_SEED(key) (key->priv)
-#define SLH_DSA_SK_PRF(key)  (key->priv + key->params->n)
-#define SLH_DSA_PK_SEED(key) (key->pub)
-#define SLH_DSA_PK_ROOT(key) (key->pub + key->params->n)
+#define SLH_DSA_MAX_N 32
+#define SLH_DSA_SK_SEED(key) ((key)->priv)
+#define SLH_DSA_SK_PRF(key)  ((key)->priv + (key)->params->n)
+#define SLH_DSA_PK_SEED(key) ((key)->priv + (key)->params->n * 2)
+#define SLH_DSA_PK_ROOT(key) ((key)->priv + (key)->params->n * 3)
+#define SLH_DSA_PUB(key) SLH_DSA_PK_SEED(key)
+#define SLH_DSA_PRIV(key) SLH_DSA_SK_SEED(key)
 
 struct slh_dsa_key_st {
-    /* The public key consists of a SEED and ROOT values each of size |n| */
-    uint8_t pub[SLH_DSA_MAX_KEYLEN];
-    /* The private key consists of a SEED and PRF values of size |n| */
-    uint8_t priv[SLH_DSA_MAX_KEYLEN];
-    size_t key_len; /* This value is set to 2 * n if there is a public key */
+    /*
+     * A private key consists of
+     *  Private SEED and PRF values of size |n|
+     *  Public SEED and ROOT values of size |n|
+     *  (Unlike X25519 the public key is not (fully) constructed from the
+     *  private key so when encoded the private key must contain the public key)
+     */
+    uint8_t priv[4 * SLH_DSA_MAX_N];
+    /*
+     * pub will be NULL initially.
+     * When either a private or public key is loaded it will then point
+     * to &priv[n * 2]
+     */
+    uint8_t *pub;
     CRYPTO_REF_COUNT references;
     OSSL_LIB_CTX *libctx;
     char *propq;
diff --git a/crypto/slh_dsa/slh_dsa_meth.c b/crypto/slh_dsa/slh_dsa_meth.c
new file mode 100644 (file)
index 0000000..0e0aca4
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include "internal/deprecated.h" /* EVP_PKEY_assign() */
+
+#include "internal/cryptlib.h"
+#include "crypto/asn1.h"
+#include "crypto/evp.h"
+#include "crypto/x509.h"
+#include "crypto/slh_dsa.h"
+
+static SLH_DSA_KEY *ossl_slh_dsa_key_create(const X509_ALGOR *palg,
+                                            const unsigned char *p, int p_len,
+                                            int id, int public,
+                                            OSSL_LIB_CTX *libctx,
+                                            const char *propq)
+{
+    int ret = 0;
+    SLH_DSA_KEY *key = NULL;
+
+    if (p == NULL)
+        return 0;
+    if (palg != NULL) {
+        int ptype;
+
+        /* Algorithm parameters must be absent */
+        X509_ALGOR_get0(NULL, &ptype, NULL, palg);
+        if (ptype != V_ASN1_UNDEF)
+            return 0;
+        if (id == EVP_PKEY_NONE)
+            id = OBJ_obj2nid(palg->algorithm);
+        else if (id != OBJ_obj2nid(palg->algorithm))
+            return 0;
+    }
+    if (id == EVP_PKEY_NONE)
+        return 0;
+
+    key = ossl_slh_dsa_key_new(libctx, OBJ_nid2ln(id));
+    if (key == NULL)
+        return 0;
+    if (public)
+        ret = ossl_slh_dsa_set_pub(key, p, p_len);
+    else
+        ret = ossl_slh_dsa_set_priv(key, p, p_len);
+
+    if (ret == 0) {
+        ossl_slh_dsa_key_free(key);
+        key = NULL;
+    }
+    return key;
+}
+
+static int slh_dsa_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
+{
+    const unsigned char *p;
+    int pklen;
+    X509_ALGOR *palg;
+    SLH_DSA_KEY *key;
+    OSSL_LIB_CTX *libctx;
+    const char *propq;
+    int ret = 0;
+
+    if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
+        return 0;
+    ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey);
+    key = ossl_slh_dsa_key_create(palg, p, pklen, pkey->ameth->pkey_id, 1,
+                                  libctx, propq);
+    if (key != NULL) {
+        ret = 1;
+        EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, key);
+    }
+    return ret;
+}
+
+static void slh_dsa_free(EVP_PKEY *pkey)
+{
+    ossl_slh_dsa_key_free(pkey->pkey.slh_dsa);
+}
+
+/* Minimal ASN1 method table to support PUB_KEY decoding */
+#define IMPLEMENT_PKEY_ASN1_METHOD(alg, name, PKEY_NAME)                       \
+const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_##name##_asn1_meth = {                 \
+    EVP_PKEY_SLH_DSA_##PKEY_NAME, EVP_PKEY_SLH_DSA_##PKEY_NAME,                \
+    0,                                                                         \
+    alg,                                                                       \
+    "OpenSSL " alg " algorithm",                                               \
+    slh_dsa_pub_decode, NULL, NULL, NULL,                                      \
+    NULL, NULL, NULL,                                                          \
+    NULL, NULL, NULL,                                                          \
+    NULL, NULL, NULL, NULL, NULL, NULL,                                        \
+    NULL,                                                                      \
+    slh_dsa_free,                                                              \
+}
+
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128s", sha2_128s, SHA2_128S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128f", sha2_128f, SHA2_128F);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-192s", sha2_192s, SHA2_192S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-192f", sha2_192f, SHA2_192F);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-256s", sha2_256s, SHA2_256S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-256f", sha2_256f, SHA2_256F);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128s", shake_128s, SHAKE_128S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-128f", shake_128f, SHAKE_128F);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-192s", shake_192s, SHAKE_192S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-192f", shake_192f, SHAKE_192F);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-256s", shake_256s, SHAKE_256S);
+IMPLEMENT_PKEY_ASN1_METHOD("SLH-DSA-SHA2-256f", shake_256f, SHAKE_256F);
index 39d9e5fb194a2c367bb29380cb9dc914c4e72095..19ef56c2a12feeac2a425df7b673030a83242557 100644 (file)
@@ -44,6 +44,8 @@ const SLH_DSA_PARAMS *ossl_slh_dsa_params_get(const char *alg)
 {
     const SLH_DSA_PARAMS *p;
 
+    if (alg == NULL)
+        return NULL;
     for (p = slh_dsa_params; p->alg != NULL; ++p) {
         if (strcmp(p->alg, alg) == 0)
             return p;
index 80a0ad570f99595555c60035041d1c86f326162b..268e9f482f2a1d70365179a8e28e0c4a6c26d7ac 100644 (file)
@@ -11,7 +11,7 @@
 
 /*
  * Refer to FIPS 205 Section 11 parameter sets.
- * lgw has been omitted since it is 4 for all algorithms i.e log(16)
+ * lgw has been omitted since it is 4 for all algorithms i.e. log(16)
  */
 typedef struct slh_dsa_params_st {
     const char *alg;
index 53639b2bfabac9764ba5a16a5a81d00919e4fca4..8c6e994d0b776218e988475cb3125788f7ddbed1 100644 (file)
@@ -20,6 +20,7 @@
 #include <openssl/engine.h>
 #include "crypto/asn1.h"
 #include "crypto/evp.h"
+#include "crypto/slh_dsa.h"
 #include "crypto/x509.h"
 #include <openssl/rsa.h>
 #include <openssl/dsa.h>
@@ -1007,6 +1008,79 @@ int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp)
 # endif /* OPENSSL_NO_ECX */
 #endif
 
+#ifndef OPENSSL_NO_SLH_DSA
+
+static SLH_DSA_KEY *d2i_SLH_DSA_PUBKEY(SLH_DSA_KEY **a,
+                                       const unsigned char **pp,
+                                       long length, int key_type)
+{
+    EVP_PKEY *pkey;
+    SLH_DSA_KEY *key = NULL;
+    const unsigned char *q;
+
+    q = *pp;
+    pkey = ossl_d2i_PUBKEY_legacy(NULL, &q, length);
+    if (pkey == NULL)
+        return NULL;
+    if (EVP_PKEY_get_id(pkey) == key_type)
+        key = ossl_evp_pkey_get1_SLH_DSA_KEY(pkey);
+    EVP_PKEY_free(pkey);
+    if (key == NULL)
+        return NULL;
+    *pp = q;
+    if (a != NULL) {
+        ossl_slh_dsa_key_free(*a);
+        *a = key;
+    }
+    return key;
+}
+
+static int i2d_SLH_DSA_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp,
+                              int key_type)
+{
+    EVP_PKEY *pktmp;
+    int ret;
+
+    if (a == NULL)
+        return 0;
+    if ((pktmp = EVP_PKEY_new()) == NULL) {
+        ERR_raise(ERR_LIB_ASN1, ERR_R_EVP_LIB);
+        return -1;
+    }
+    (void)EVP_PKEY_assign(pktmp, key_type, (SLH_DSA_KEY *)a);
+    ret = i2d_PUBKEY(pktmp, pp);
+    pktmp->pkey.ptr = NULL;
+    EVP_PKEY_free(pktmp);
+    return ret;
+}
+
+#define IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(alg)                                  \
+int ossl_i2d_SLH_DSA_##alg##_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp)  \
+{                                                                              \
+    return i2d_SLH_DSA_PUBKEY(a, pp, EVP_PKEY_SLH_DSA_##alg);                  \
+}                                                                              \
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_##alg##_PUBKEY(SLH_DSA_KEY **a,                  \
+                                             const unsigned char **pp,         \
+                                             long length)                      \
+{                                                                              \
+    return d2i_SLH_DSA_PUBKEY(a, pp, length, EVP_PKEY_SLH_DSA_##alg);          \
+}
+
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_128S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_128F)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_192S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_192F)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_256S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHA2_256F)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_128S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_128F)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_192S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_192F)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_256S)
+IMPLEMENT_SLH_DSA_PUBKEY_D2I_I2D(SHAKE_256F)
+
+#endif /* OPENSSL_NO_SLH_DSA */
+
 void X509_PUBKEY_set0_public_key(X509_PUBKEY *pub,
                                  unsigned char *penc, int penclen)
 {
index 557296846ea18d046fca2fe237c4cd68cb55f098..f60e8b7d4bd5c3b106bd950d864a6a6e1222073c 100644 (file)
@@ -242,6 +242,30 @@ This is an unapproved algorithm.
 
 =item ML-DSA-87, see L<EVP_KEYMGMT-ML-DSA(7)>
 
+=item SLH-DSA-SHA2-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
 =back
 
 =head2 Random Number Generation
index f0bc498cb5283dca5611a652ecf36052857833c8..0156fd8557199627a854fe4118f00ad4be26d8fe 100644 (file)
@@ -108,6 +108,30 @@ are also available in the default provider.
 
 =item ML-KEM-1024
 
+=item SLH-DSA-SHA2-128s
+
+=item SLH-DSA-SHA2-128f
+
+=item SLH-DSA-SHA2-192s
+
+=item SLH-DSA-SHA2-192f
+
+=item SLH-DSA-SHA2-256s
+
+=item SLH-DSA-SHA2-256f
+
+=item SLH-DSA-SHAKE-128s
+
+=item SLH-DSA-SHAKE-128f
+
+=item SLH-DSA-SHAKE-192s
+
+=item SLH-DSA-SHAKE-192f
+
+=item SLH-DSA-SHAKE-256s
+
+=item SLH-DSA-SHAKE-256f
+
 =back
 
 In addition to this provider, all of these encoding algorithms are also
@@ -154,6 +178,30 @@ combination with the FIPS provider.
 
 =item ML-KEM-1024
 
+=item SLH-DSA-SHA2-128s
+
+=item SLH-DSA-SHA2-128f
+
+=item SLH-DSA-SHA2-192s
+
+=item SLH-DSA-SHA2-192f
+
+=item SLH-DSA-SHA2-256s
+
+=item SLH-DSA-SHA2-256f
+
+=item SLH-DSA-SHAKE-128s
+
+=item SLH-DSA-SHAKE-128f
+
+=item SLH-DSA-SHAKE-192s
+
+=item SLH-DSA-SHAKE-192f
+
+=item SLH-DSA-SHAKE-256s
+
+=item SLH-DSA-SHAKE-256f
+
 =back
 
 In addition to this provider, all of these decoding algorithms are also
index 2fd6d105f04a5765763db2b153e3f2627706dc91..3f2ba5b90b8449a01f2ea11bc5a2483651563626 100644 (file)
@@ -195,8 +195,6 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item ECDSA, see L<EVP_SIGNATURE-ECDSA(7)>
 
-=item SLH-DSA, see L<EVP_SIGNATURE-SLH-DSA(7)>
-
 =item SM2
 
 =item ML-DSA-44, see L<EVP_SIGNATURE-ML-DSA(7)>
@@ -213,6 +211,30 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item CMAC, see L<EVP_SIGNATURE-CMAC(7)>
 
+=item SLH-DSA-SHA2-128s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-128f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256s, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256f, see L<EVP_SIGNATURE-SLH-DSA(7)>
+
 =back
 
 =head2 Asymmetric Cipher
@@ -283,6 +305,30 @@ The OpenSSL default provider supports these operations and algorithms:
 
 =item MK-KEM-1024, see L<EVP_KEYMGMT-ML-KEM-1024(7)>
 
+=item SLH-DSA-SHA2-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-192f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHA2-256f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-128f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-192f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256s, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
+=item SLH-DSA-SHAKE-256f, see L<EVP_KEYMGMT-SLH-DSA(7)>
+
 =item TLS1-PRF
 
 =item HKDF
@@ -358,6 +404,30 @@ are also available in the base provider.
 
 =item ML-KEM-1024
 
+=item SLH-DSA-SHA2-128s
+
+=item SLH-DSA-SHA2-128f
+
+=item SLH-DSA-SHA2-192s
+
+=item SLH-DSA-SHA2-192f
+
+=item SLH-DSA-SHA2-256s
+
+=item SLH-DSA-SHA2-256f
+
+=item SLH-DSA-SHAKE-128s
+
+=item SLH-DSA-SHAKE-128f
+
+=item SLH-DSA-SHAKE-192s
+
+=item SLH-DSA-SHAKE-192f
+
+=item SLH-DSA-SHAKE-256s
+
+=item SLH-DSA-SHAKE-256f
+
 =back
 
 In addition to this provider, all of these encoding algorithms are also
@@ -402,6 +472,30 @@ combination with the FIPS provider.
 
 =item ML-KEM-1024
 
+=item SLH-DSA-SHA2-128s
+
+=item SLH-DSA-SHA2-128f
+
+=item SLH-DSA-SHA2-192s
+
+=item SLH-DSA-SHA2-192f
+
+=item SLH-DSA-SHA2-256s
+
+=item SLH-DSA-SHA2-256f
+
+=item SLH-DSA-SHAKE-128s
+
+=item SLH-DSA-SHAKE-128f
+
+=item SLH-DSA-SHAKE-192s
+
+=item SLH-DSA-SHAKE-192f
+
+=item SLH-DSA-SHAKE-256s
+
+=item SLH-DSA-SHAKE-256f
+
 =back
 
 In addition to this provider, all of these decoding algorithms are also
index 8461c1be8d2100295ba91475891210ba308cdc54..ea833b9283e343d466f819f82707b3a2fcad00db 100644 (file)
@@ -103,6 +103,19 @@ extern const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth;
 extern const EVP_PKEY_ASN1_METHOD ossl_rsa_asn1_meths[2];
 extern const EVP_PKEY_ASN1_METHOD ossl_rsa_pss_asn1_meth;
 
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_128s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_128f_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_192s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_192f_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_256s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_sha2_256f_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_128s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_128f_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_192s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_192f_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_256s_asn1_meth;
+extern const EVP_PKEY_ASN1_METHOD ossl_slh_dsa_shake_256f_asn1_meth;
+
 /*
  * These are used internally in the ASN1_OBJECT to keep track of whether the
  * names and data need to be free()ed
index 861447f557bc1672ede5ded506909859e3588ec1..a87f14a01296b8b74ecd8a1d1ca1851f4a783606 100644 (file)
@@ -15,6 +15,7 @@
 # include <openssl/core_dispatch.h>
 # include "internal/refcount.h"
 # include "crypto/ecx.h"
+# include "crypto/slh_dsa.h"
 
 /*
  * Default PKCS5 PBE KDF salt lengths
@@ -662,6 +663,9 @@ union legacy_pkey_st {
 #   ifndef OPENSSL_NO_ECX
     ECX_KEY *ecx;           /* X25519, X448, Ed25519, Ed448 */
 #   endif
+#   ifndef OPENSSL_NO_SLH_DSA
+    SLH_DSA_KEY *slh_dsa;  /* SLH_DSA_* */
+#   endif
 #  endif
 };
 
index 86ad4f96f8a10cbb54a86c44f38c3f571f2ea838..353daf04c9579e5aa347113548fde32beebbbd00 100644 (file)
@@ -32,13 +32,23 @@ __owur int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM *params,
 __owur int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *libctx,
                                      const uint8_t *entropy, size_t entropy_len,
                                      SLH_DSA_KEY *out);
-__owur int ossl_slh_dsa_key_is_private(const SLH_DSA_KEY *key);
 __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_pub_len(const SLH_DSA_KEY *key);
+__owur int ossl_slh_dsa_set_priv(SLH_DSA_KEY *key, const uint8_t *priv,
+                                 size_t priv_len);
+__owur int ossl_slh_dsa_set_pub(SLH_DSA_KEY *key, const uint8_t *pub,
+                                size_t pub_len);
+__owur size_t ossl_slh_dsa_key_get_priv_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 const char *ossl_slh_dsa_key_get_name(const SLH_DSA_KEY *key);
 __owur int ossl_slh_dsa_key_type_matches(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *key);
+__owur int ossl_slh_dsa_key_to_text(BIO *out, const SLH_DSA_KEY *key, int selection);
+void ossl_slh_dsa_key_set0_libctx(SLH_DSA_KEY *key, OSSL_LIB_CTX *lib_ctx);
+SLH_DSA_KEY *ossl_slh_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
+                                         OSSL_LIB_CTX *libctx, const char *propq);
+SLH_DSA_KEY *ossl_evp_pkey_get1_SLH_DSA_KEY(EVP_PKEY *pkey);
 
 __owur SLH_DSA_CTX *ossl_slh_dsa_ctx_new(const char *alg,
                                          OSSL_LIB_CTX *lib_ctx, const char *propq);
index e6ebae39145ac72a5aa46fdc47e210105f0c86fc..3869cb4c36b865c2d7a3768f913d70ec139a5729 100644 (file)
@@ -363,6 +363,46 @@ ECX_KEY *ossl_d2i_X448_PUBKEY(ECX_KEY **a,
                               const unsigned char **pp, long length);
 int ossl_i2d_X448_PUBKEY(const ECX_KEY *a, unsigned char **pp);
 # endif /* OPENSSL_NO_EC */
+
+# ifndef OPENSSL_NO_SLH_DSA
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_128S_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_128F_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_192S_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_192F_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_256S_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHA2_256F_PUBKEY(SLH_DSA_KEY **a,
+                                               const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_128S_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_128F_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_192S_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_192F_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_256S_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+SLH_DSA_KEY *ossl_d2i_SLH_DSA_SHAKE_256F_PUBKEY(SLH_DSA_KEY **a,
+                                                const uint8_t **pp, long length);
+int ossl_i2d_SLH_DSA_SHA2_128S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHA2_128F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHA2_192S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHA2_192F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHA2_256S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHA2_256F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_128S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_128F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_192S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_192F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_256S_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+int ossl_i2d_SLH_DSA_SHAKE_256F_PUBKEY(const SLH_DSA_KEY *a, uint8_t **pp);
+# endif /* OPENSSL_NO_SLH_DSA */
+
 EVP_PKEY *ossl_d2i_PUBKEY_legacy(EVP_PKEY **a, const unsigned char **pp,
                                  long length);
 int ossl_x509_check_private_key(const EVP_PKEY *k, const EVP_PKEY *pkey);
index c58377355fa219943b3a534ca5ed110f57d59350..0cbb38aad89c8cf078b31b6e5474775b59dd0f22 100644 (file)
 # define EVP_PKEY_ML_DSA_44 NID_ML_DSA_44
 # define EVP_PKEY_ML_DSA_65 NID_ML_DSA_65
 # define EVP_PKEY_ML_DSA_87 NID_ML_DSA_87
+# define EVP_PKEY_SLH_DSA_SHA2_128S NID_SLH_DSA_SHA2_128s
+# define EVP_PKEY_SLH_DSA_SHA2_128F NID_SLH_DSA_SHA2_128f
+# define EVP_PKEY_SLH_DSA_SHA2_192S NID_SLH_DSA_SHA2_192s
+# define EVP_PKEY_SLH_DSA_SHA2_192F NID_SLH_DSA_SHA2_192f
+# define EVP_PKEY_SLH_DSA_SHA2_256S NID_SLH_DSA_SHA2_256s
+# define EVP_PKEY_SLH_DSA_SHA2_256F NID_SLH_DSA_SHA2_256f
+# define EVP_PKEY_SLH_DSA_SHAKE_128S NID_SLH_DSA_SHAKE_128s
+# define EVP_PKEY_SLH_DSA_SHAKE_128F NID_SLH_DSA_SHAKE_128f
+# define EVP_PKEY_SLH_DSA_SHAKE_192S NID_SLH_DSA_SHAKE_192s
+# define EVP_PKEY_SLH_DSA_SHAKE_192F NID_SLH_DSA_SHAKE_192f
+# define EVP_PKEY_SLH_DSA_SHAKE_256S NID_SLH_DSA_SHAKE_256s
+# define EVP_PKEY_SLH_DSA_SHAKE_256F NID_SLH_DSA_SHAKE_256f
 
 /* Special indicator that the object is uniquely provider side */
 # define EVP_PKEY_KEYMGMT -1
index ae94042b828821a04a22bca3f99dabcdb235fa02..ffae575c61873787c26adfd739c9a0ae0e9ccb39 100644 (file)
@@ -82,6 +82,32 @@ DECODER_w_structure("ML-KEM-768", der, SubjectPublicKeyInfo, ml_kem_768, yes),
 DECODER_w_structure("ML-KEM-1024", der, PrivateKeyInfo, ml_kem_1024, yes),
 DECODER_w_structure("ML-KEM-1024", der, SubjectPublicKeyInfo, ml_kem_1024, yes),
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+DECODER_w_structure( "SLH-DSA-SHA2-128s", der, PrivateKeyInfo, slh_dsa_sha2_128s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-128f", der, PrivateKeyInfo, slh_dsa_sha2_128f, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-192s", der, PrivateKeyInfo, slh_dsa_sha2_192s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-192f", der, PrivateKeyInfo, slh_dsa_sha2_192f, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-256s", der, PrivateKeyInfo, slh_dsa_sha2_256s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-256f", der, PrivateKeyInfo, slh_dsa_sha2_256f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-128s", der, PrivateKeyInfo, slh_dsa_shake_128s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-128f", der, PrivateKeyInfo, slh_dsa_shake_128f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-192s", der, PrivateKeyInfo, slh_dsa_shake_192s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-192f", der, PrivateKeyInfo, slh_dsa_shake_192f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-256s", der, PrivateKeyInfo, slh_dsa_shake_256s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-256f", der, PrivateKeyInfo, slh_dsa_shake_256f, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-128s", der, SubjectPublicKeyInfo, slh_dsa_sha2_128s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-128f", der, SubjectPublicKeyInfo, slh_dsa_sha2_128f, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-192s", der, SubjectPublicKeyInfo, slh_dsa_sha2_192s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-192f", der, SubjectPublicKeyInfo, slh_dsa_sha2_192f, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-256s", der, SubjectPublicKeyInfo, slh_dsa_sha2_256s, yes),
+DECODER_w_structure( "SLH-DSA-SHA2-256f", der, SubjectPublicKeyInfo, slh_dsa_sha2_256f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-128s", der, SubjectPublicKeyInfo, slh_dsa_shake_128s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-128f", der, SubjectPublicKeyInfo, slh_dsa_shake_128f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-192s", der, SubjectPublicKeyInfo, slh_dsa_shake_192s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-192f", der, SubjectPublicKeyInfo, slh_dsa_shake_192f, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-256s", der, SubjectPublicKeyInfo, slh_dsa_shake_256s, yes),
+DECODER_w_structure("SLH-DSA-SHAKE-256f", der, SubjectPublicKeyInfo, slh_dsa_shake_256f, yes),
+#endif /* OPENSSL_NO_SLH_DSA */
 DECODER_w_structure("RSA", der, PrivateKeyInfo, rsa, yes),
 DECODER_w_structure("RSA", der, SubjectPublicKeyInfo, rsa, yes),
 DECODER_w_structure("RSA", der, type_specific_keypair, rsa, yes),
index 74931909440fd943868a09554bff88c03becdc2f..41dc6ba9209d43de85a8e92d1899f7b63f0f77a2 100644 (file)
@@ -72,12 +72,25 @@ ENCODER_TEXT("ML-KEM-512", ml_kem_512, yes),
 ENCODER_TEXT("ML-KEM-768", ml_kem_768, yes),
 ENCODER_TEXT("ML-KEM-1024", ml_kem_1024, yes),
 #endif
-
-# ifndef OPENSSL_NO_ML_DSA
+#ifndef OPENSSL_NO_ML_DSA
 ENCODER_TEXT("ML-DSA-44", ml_dsa_44, yes),
 ENCODER_TEXT("ML-DSA-65", ml_dsa_65, yes),
 ENCODER_TEXT("ML-DSA-87", ml_dsa_87, yes),
-# endif
+#endif
+#ifndef OPENSSL_NO_SLH_DSA
+ENCODER_TEXT("SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes),
+ENCODER_TEXT("SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes),
+ENCODER_TEXT("SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes),
+ENCODER_TEXT("SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes),
+ENCODER_TEXT("SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes),
+ENCODER_TEXT("SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes),
+ENCODER_TEXT("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes),
+#endif
 
 /*
  * Entries for key type specific output formats.  The structure name on these
@@ -233,6 +246,85 @@ ENCODER_w_structure("ED448", ed448, yes, pem, PrivateKeyInfo),
 ENCODER_w_structure("ED448", ed448, yes, der, SubjectPublicKeyInfo),
 ENCODER_w_structure("ED448", ed448, yes, pem, SubjectPublicKeyInfo),
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, der, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, der, EncryptedPrivateKeyInfo),
+
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, pem, EncryptedPrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, pem, EncryptedPrivateKeyInfo),
+
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, der, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, der, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, der, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, der, PrivateKeyInfo),
+
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, pem, PrivateKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, pem, PrivateKeyInfo),
+
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, der, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, der, SubjectPublicKeyInfo),
+
+ENCODER_w_structure( "SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure( "SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, yes, pem, SubjectPublicKeyInfo),
+ENCODER_w_structure("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, yes, pem, SubjectPublicKeyInfo),
+#endif
 
 #ifndef OPENSSL_NO_ML_KEM
 ENCODER_w_structure("ML-KEM-512", ml_kem_512, yes, der, EncryptedPrivateKeyInfo),
index da4a7d8abeb2fd86e48496814413480d30c7702b..aca35cdaa408e8fb073c7176fa20a583ae3285e4 100644 (file)
@@ -33,6 +33,7 @@
 #include "crypto/ecx.h"
 #include "crypto/rsa.h"
 #include "crypto/ml_dsa.h"
+#include "crypto/slh_dsa.h"
 #include "crypto/x509.h"
 #include "crypto/ml_kem.h"
 #include "openssl/obj_mac.h"
@@ -620,6 +621,146 @@ ml_kem_d2i_PUBKEY(const uint8_t **der, long der_len,
 
 #endif
 
+
+# ifndef OPENSSL_NO_SLH_DSA
+
+/* SLH_DSA only implements PKCS#8 and SubjectPublicKeyInfo */
+
+static void *slh_dsa_d2i_PKCS8(void **key, const unsigned char **der, long der_len,
+                               struct der2key_ctx_st *ctx)
+{
+    return der2key_decode_p8(der, der_len, ctx,
+                             (key_from_pkcs8_t *)ossl_slh_dsa_key_from_pkcs8);
+}
+
+static void slh_dsa_key_adjust(void *key, struct der2key_ctx_st *ctx)
+{
+    ossl_slh_dsa_key_set0_libctx(key, PROV_LIBCTX_OF(ctx->provctx));
+}
+
+#  define slh_dsa_sha2_128s_evp_type        EVP_PKEY_SLH_DSA_SHA2_128S
+#  define slh_dsa_sha2_128s_d2i_private_key NULL
+#  define slh_dsa_sha2_128s_d2i_public_key  NULL
+#  define slh_dsa_sha2_128s_d2i_key_params  NULL
+#  define slh_dsa_sha2_128s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_128s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_128S_PUBKEY
+#  define slh_dsa_sha2_128s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_128s_check           NULL
+#  define slh_dsa_sha2_128s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_sha2_128f_evp_type        EVP_PKEY_SLH_DSA_SHA2_128F
+#  define slh_dsa_sha2_128f_d2i_private_key NULL
+#  define slh_dsa_sha2_128f_d2i_public_key  NULL
+#  define slh_dsa_sha2_128f_d2i_key_params  NULL
+#  define slh_dsa_sha2_128f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_128f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_128F_PUBKEY
+#  define slh_dsa_sha2_128f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_128f_check           NULL
+#  define slh_dsa_sha2_128f_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_sha2_192s_evp_type        EVP_PKEY_SLH_DSA_SHA2_192S
+#  define slh_dsa_sha2_192s_d2i_private_key NULL
+#  define slh_dsa_sha2_192s_d2i_public_key  NULL
+#  define slh_dsa_sha2_192s_d2i_key_params  NULL
+#  define slh_dsa_sha2_192s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_192s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_192S_PUBKEY
+#  define slh_dsa_sha2_192s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_192s_check           NULL
+#  define slh_dsa_sha2_192s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_sha2_192f_evp_type        EVP_PKEY_SLH_DSA_SHA2_192F
+#  define slh_dsa_sha2_192f_d2i_private_key NULL
+#  define slh_dsa_sha2_192f_d2i_public_key  NULL
+#  define slh_dsa_sha2_192f_d2i_key_params  NULL
+#  define slh_dsa_sha2_192f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_192f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_192F_PUBKEY
+#  define slh_dsa_sha2_192f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_192f_check           NULL
+#  define slh_dsa_sha2_192f_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_sha2_256s_evp_type        EVP_PKEY_SLH_DSA_SHA2_256S
+#  define slh_dsa_sha2_256s_d2i_private_key NULL
+#  define slh_dsa_sha2_256s_d2i_public_key  NULL
+#  define slh_dsa_sha2_256s_d2i_key_params  NULL
+#  define slh_dsa_sha2_256s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_256s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_256S_PUBKEY
+#  define slh_dsa_sha2_256s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_256s_check           NULL
+#  define slh_dsa_sha2_256s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_sha2_256f_evp_type        EVP_PKEY_SLH_DSA_SHA2_256F
+#  define slh_dsa_sha2_256f_d2i_private_key NULL
+#  define slh_dsa_sha2_256f_d2i_public_key  NULL
+#  define slh_dsa_sha2_256f_d2i_key_params  NULL
+#  define slh_dsa_sha2_256f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_sha2_256f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHA2_256F_PUBKEY
+#  define slh_dsa_sha2_256f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_sha2_256f_check           NULL
+#  define slh_dsa_sha2_256f_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_128s_evp_type        EVP_PKEY_SLH_DSA_SHAKE_128S
+#  define slh_dsa_shake_128s_d2i_private_key NULL
+#  define slh_dsa_shake_128s_d2i_public_key  NULL
+#  define slh_dsa_shake_128s_d2i_key_params  NULL
+#  define slh_dsa_shake_128s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_128s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_128S_PUBKEY
+#  define slh_dsa_shake_128s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_128s_check           NULL
+#  define slh_dsa_shake_128s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_128f_evp_type        EVP_PKEY_SLH_DSA_SHAKE_128F
+#  define slh_dsa_shake_128f_d2i_private_key NULL
+#  define slh_dsa_shake_128f_d2i_public_key  NULL
+#  define slh_dsa_shake_128f_d2i_key_params  NULL
+#  define slh_dsa_shake_128f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_128f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_128F_PUBKEY
+#  define slh_dsa_shake_128f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_128f_check           NULL
+#  define slh_dsa_shake_128f_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_192s_evp_type        EVP_PKEY_SLH_DSA_SHAKE_192S
+#  define slh_dsa_shake_192s_d2i_private_key NULL
+#  define slh_dsa_shake_192s_d2i_public_key  NULL
+#  define slh_dsa_shake_192s_d2i_key_params  NULL
+#  define slh_dsa_shake_192s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_192s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_192S_PUBKEY
+#  define slh_dsa_shake_192s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_192s_check           NULL
+#  define slh_dsa_shake_192s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_192f_evp_type        EVP_PKEY_SLH_DSA_SHAKE_192F
+#  define slh_dsa_shake_192f_d2i_private_key NULL
+#  define slh_dsa_shake_192f_d2i_public_key  NULL
+#  define slh_dsa_shake_192f_d2i_key_params  NULL
+#  define slh_dsa_shake_192f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_192f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_192F_PUBKEY
+#  define slh_dsa_shake_192f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_192f_check           NULL
+#  define slh_dsa_shake_192f_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_256s_evp_type        EVP_PKEY_SLH_DSA_SHAKE_256S
+#  define slh_dsa_shake_256s_d2i_private_key NULL
+#  define slh_dsa_shake_256s_d2i_public_key  NULL
+#  define slh_dsa_shake_256s_d2i_key_params  NULL
+#  define slh_dsa_shake_256s_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_256s_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_256S_PUBKEY
+#  define slh_dsa_shake_256s_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_256s_check           NULL
+#  define slh_dsa_shake_256s_adjust          slh_dsa_key_adjust
+
+#  define slh_dsa_shake_256f_evp_type        EVP_PKEY_SLH_DSA_SHAKE_256F
+#  define slh_dsa_shake_256f_d2i_private_key NULL
+#  define slh_dsa_shake_256f_d2i_public_key  NULL
+#  define slh_dsa_shake_256f_d2i_key_params  NULL
+#  define slh_dsa_shake_256f_d2i_PKCS8       slh_dsa_d2i_PKCS8
+#  define slh_dsa_shake_256f_d2i_PUBKEY      (d2i_of_void *)ossl_d2i_SLH_DSA_SHAKE_256F_PUBKEY
+#  define slh_dsa_shake_256f_free            (free_key_fn *)ossl_slh_dsa_key_free
+#  define slh_dsa_shake_256f_check           NULL
+#  define slh_dsa_shake_256f_adjust          slh_dsa_key_adjust
+
+
+# endif /* OPENSSL_NO_SLH_DSA */
+
 /* ---------------------------------------------------------------------- */
 
 #define rsa_evp_type                    EVP_PKEY_RSA
@@ -999,6 +1140,33 @@ MAKE_DECODER("ML-KEM-768", ml_kem_768, ml_kem_768, SubjectPublicKeyInfo);
 MAKE_DECODER("ML-KEM-1024", ml_kem_1024, ml_kem_1024, PrivateKeyInfo);
 MAKE_DECODER("ML-KEM-1024", ml_kem_1024, ml_kem_1024, SubjectPublicKeyInfo);
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+MAKE_DECODER("SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, slh_dsa, PrivateKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, slh_dsa, PrivateKeyInfo);
+
+MAKE_DECODER("SLH-DSA-SHA2-128s", slh_dsa_sha2_128s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-128f", slh_dsa_sha2_128f, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-192s", slh_dsa_sha2_192s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-192f", slh_dsa_sha2_192f, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-256s", slh_dsa_sha2_256s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHA2-256f", slh_dsa_sha2_256f, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-128s", slh_dsa_shake_128s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-128f", slh_dsa_shake_128f, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-192s", slh_dsa_shake_192s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-192f", slh_dsa_shake_192f, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-256s", slh_dsa_shake_256s, slh_dsa, SubjectPublicKeyInfo);
+MAKE_DECODER("SLH-DSA-SHAKE-256f", slh_dsa_shake_256f, slh_dsa, SubjectPublicKeyInfo);
+#endif /* OPENSSL_NO_SLH_DSA */
 MAKE_DECODER("RSA", rsa, rsa, PrivateKeyInfo);
 MAKE_DECODER("RSA", rsa, rsa, SubjectPublicKeyInfo);
 MAKE_DECODER("RSA", rsa, rsa, type_specific_keypair);
index bb7707a6dc71bf22b58a1c4fb604894ece538177..4480746fd67122ae4b7e2cc9b49195533adf09e8 100644 (file)
@@ -33,6 +33,7 @@
 #include "crypto/ml_kem.h"
 #include "crypto/rsa.h"
 #include "crypto/ml_dsa.h"
+#include "crypto/slh_dsa.h"
 #include "prov/implementations.h"
 #include "prov/bio.h"
 #include "prov/provider_ctx.h"
@@ -1022,6 +1023,98 @@ static int rsa_check_key_type(const void *rsa, int expected_type)
 
 /* ---------------------------------------------------------------------- */
 
+#ifndef OPENSSL_NO_SLH_DSA
+# define prepare_slh_dsa_params NULL
+
+static int slh_dsa_spki_pub_to_der(const void *vkey, unsigned char **pder)
+{
+    const SLH_DSA_KEY *key = vkey;
+    uint8_t *key_blob;
+    size_t key_len;
+
+    if (key == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    key_len = ossl_slh_dsa_key_get_pub_len(key);
+    key_blob = OPENSSL_memdup(ossl_slh_dsa_key_get_pub(key), key_len);
+    if (key_blob == NULL)
+        return 0;
+
+    *pder = key_blob;
+    return key_len;
+}
+
+static int slh_dsa_pki_priv_to_der(const void *vkey, unsigned char **pder)
+{
+    const SLH_DSA_KEY *key = vkey;
+    const uint8_t *priv;
+    ASN1_OCTET_STRING oct;
+    size_t key_blob_len;
+
+    if (key == NULL
+            || (priv = ossl_slh_dsa_key_get_priv(key))== NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+
+    oct.data = (uint8_t *)priv;
+    oct.length = ossl_slh_dsa_key_get_priv_len(key);
+    oct.flags = 0;
+
+    key_blob_len = i2d_ASN1_OCTET_STRING(&oct, pder);
+    if (key_blob_len < 0) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_ASN1_LIB);
+        return 0;
+    }
+
+    return key_blob_len;
+}
+# define slh_dsa_epki_priv_to_der slh_dsa_pki_priv_to_der
+
+/* SLH_DSA only has PKCS#8 / SubjectPublicKeyInfo representations. */
+
+# define slh_dsa_check_key_type NULL
+# define slh_dsa_sha2_128s_evp_type EVP_PKEY_SLH_DSA_SHA2_128S
+# define slh_dsa_sha2_128f_evp_type EVP_PKEY_SLH_DSA_SHA2_128F
+# define slh_dsa_sha2_192s_evp_type EVP_PKEY_SLH_DSA_SHA2_192S
+# define slh_dsa_sha2_192f_evp_type EVP_PKEY_SLH_DSA_SHA2_192F
+# define slh_dsa_sha2_256s_evp_type EVP_PKEY_SLH_DSA_SHA2_256S
+# define slh_dsa_sha2_256f_evp_type EVP_PKEY_SLH_DSA_SHA2_256F
+# define slh_dsa_shake_128s_evp_type EVP_PKEY_SLH_DSA_SHAKE_128S
+# define slh_dsa_shake_128f_evp_type EVP_PKEY_SLH_DSA_SHAKE_128F
+# define slh_dsa_shake_192s_evp_type EVP_PKEY_SLH_DSA_SHAKE_192S
+# define slh_dsa_shake_192f_evp_type EVP_PKEY_SLH_DSA_SHAKE_192F
+# define slh_dsa_shake_256s_evp_type EVP_PKEY_SLH_DSA_SHAKE_256S
+# define slh_dsa_shake_256f_evp_type EVP_PKEY_SLH_DSA_SHAKE_256F
+# define slh_dsa_sha2_128s_input_type "SLH-DSA-SHA2-128s"
+# define slh_dsa_sha2_128f_input_type "SLH-DSA-SHA2-128f"
+# define slh_dsa_sha2_192s_input_type "SLH-DSA-SHA2-192s"
+# define slh_dsa_sha2_192f_input_type "SLH-DSA-SHA2-192f"
+# define slh_dsa_sha2_256s_input_type "SLH-DSA-SHA2-256s"
+# define slh_dsa_sha2_256f_input_type "SLH-DSA-SHA2-256f"
+# define slh_dsa_shake_128s_input_type "SLH-DSA-SHAKE-128s"
+# define slh_dsa_shake_128f_input_type "SLH-DSA-SHAKE-128f"
+# define slh_dsa_shake_192s_input_type "SLH-DSA-SHAKE-192s"
+# define slh_dsa_shake_192f_input_type "SLH-DSA-SHAKE-192f"
+# define slh_dsa_shake_256s_input_type "SLH-DSA-SHAKE-256s"
+# define slh_dsa_shake_256f_input_type "SLH-DSA-SHAKE-256f"
+# define slh_dsa_sha2_128s_pem_type "SLH-DSA-SHA2-128s"
+# define slh_dsa_sha2_128f_pem_type "SLH-DSA-SHA2-128f"
+# define slh_dsa_sha2_192s_pem_type "SLH-DSA-SHA2-192s"
+# define slh_dsa_sha2_192f_pem_type "SLH-DSA-SHA2-192f"
+# define slh_dsa_sha2_256s_pem_type "SLH-DSA-SHA2-256s"
+# define slh_dsa_sha2_256f_pem_type "SLH-DSA-SHA2-256f"
+# define slh_dsa_shake_128s_pem_type "SLH-DSA-SHAKE-128s"
+# define slh_dsa_shake_128f_pem_type "SLH-DSA-SHAKE-128f"
+# define slh_dsa_shake_192s_pem_type "SLH-DSA-SHAKE-192s"
+# define slh_dsa_shake_192f_pem_type "SLH-DSA-SHAKE-192f"
+# define slh_dsa_shake_256s_pem_type "SLH-DSA-SHAKE-256s"
+# define slh_dsa_shake_256f_pem_type "SLH-DSA-SHAKE-256f"
+#endif
+
+/* ---------------------------------------------------------------------- */
+
 static OSSL_FUNC_decoder_newctx_fn key2any_newctx;
 static OSSL_FUNC_decoder_freectx_fn key2any_freectx;
 
@@ -1510,6 +1603,83 @@ MAKE_ENCODER(x448, ecx, SubjectPublicKeyInfo, der);
 MAKE_ENCODER(x448, ecx, SubjectPublicKeyInfo, pem);
 # endif
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, EncryptedPrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, EncryptedPrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, EncryptedPrivateKeyInfo, pem);
+
+
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, PrivateKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, PrivateKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, PrivateKeyInfo, pem);
+
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_sha2_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_128F, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_192F, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_sha2_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHA2_256F, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, SubjectPublicKeyInfo, der);
+MAKE_ENCODER(slh_dsa_shake_128s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_128f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_128F, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_192f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192F, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256S, SubjectPublicKeyInfo, pem);
+MAKE_ENCODER(slh_dsa_shake_256f, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_256F, SubjectPublicKeyInfo, pem);
+#endif /* OPENSSL_NO_SLH_DSA */
 
 #ifndef OPENSSL_NO_ML_KEM
 MAKE_ENCODER(ml_kem_512, ml_kem, EncryptedPrivateKeyInfo, der);
index b3fd1c330dbc825966bb24f5ed0a1a7f1d80bb52..56a5766432a5a7c121fbaf8ea5c9bb01880671db 100644 (file)
@@ -26,6 +26,7 @@
 #include "crypto/ml_kem.h"       /* ML_KEM_KEY, etc... */
 #include "crypto/rsa.h"          /* RSA_PSS_PARAMS_30, etc... */
 #include "crypto/ml_dsa.h"
+#include "crypto/slh_dsa.h"
 #include "prov/bio.h"
 #include "prov/implementations.h"
 #include "internal/encoder.h"
@@ -445,6 +446,46 @@ static int ml_kem_to_text(BIO *out, const void *vkey, int selection)
 
 /* ---------------------------------------------------------------------- */
 
+#ifndef OPENSSL_NO_SLH_DSA
+static int slh_dsa_to_text(BIO *out, const void *key, int selection)
+{
+    const char *name;
+
+    if (out == NULL || key == NULL) {
+        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
+        return 0;
+    }
+    if (ossl_slh_dsa_key_get_pub(key) == NULL) {
+        /* Regardless of the |selection|, there must be a public key */
+        ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
+        return 0;
+    }
+
+    name = ossl_slh_dsa_key_get_name(key);
+    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
+        if (ossl_slh_dsa_key_get_priv(key) == NULL) {
+            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
+            return 0;
+        }
+        if (BIO_printf(out, "%s Private-Key:\n", name) <= 0)
+            return 0;
+        if (!print_labeled_buf(out, "priv:", ossl_slh_dsa_key_get_priv(key),
+                               ossl_slh_dsa_key_get_priv_len(key)))
+            return 0;
+    } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
+        if (BIO_printf(out, "%s Public-Key:\n", name) <= 0)
+            return 0;
+    }
+
+    if (!print_labeled_buf(out, "pub:", ossl_slh_dsa_key_get_pub(key),
+                           ossl_slh_dsa_key_get_pub_len(key)))
+        return 0;
+
+    return 1;
+}
+
+#endif /* OPENSSL_NO_SLH_DSA */
+
 static int rsa_to_text(BIO *out, const void *key, int selection)
 {
     const RSA *rsa = key;
@@ -712,3 +753,18 @@ MAKE_TEXT_ENCODER(ml_dsa_44, ml_dsa);
 MAKE_TEXT_ENCODER(ml_dsa_65, ml_dsa);
 MAKE_TEXT_ENCODER(ml_dsa_87, ml_dsa);
 #endif
+
+#ifndef OPENSSL_NO_SLH_DSA
+MAKE_TEXT_ENCODER(slh_dsa_sha2_128s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_sha2_128f, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_sha2_192s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_sha2_192f, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_sha2_256s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_sha2_256f, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_128s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_128f, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_192s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_192f, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_256s, slh_dsa);
+MAKE_TEXT_ENCODER(slh_dsa_shake_256f, slh_dsa);
+#endif
index b0281e5686b6950db13643af2fcc0ba2731f342f..a2396dccd684b81c68a26879795d9d66ac267e41 100644 (file)
@@ -620,6 +620,107 @@ extern const OSSL_DISPATCH ossl_ml_dsa_87_to_SubjectPublicKeyInfo_pem_encoder_fu
 extern const OSSL_DISPATCH ossl_ml_dsa_87_to_OSSL_current_der_encoder_functions[];
 extern const OSSL_DISPATCH ossl_ml_dsa_87_to_text_encoder_functions[];
 
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_EncryptedPrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_EncryptedPrivateKeyInfo_pem_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_PrivateKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_PrivateKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_PrivateKeyInfo_pem_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_SubjectPublicKeyInfo_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_SubjectPublicKeyInfo_pem_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_OSSL_current_der_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_OSSL_current_der_encoder_functions[];
+
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_128f_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_192f_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_sha2_256f_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_128f_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_192f_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256s_to_text_encoder_functions[];
+extern const OSSL_DISPATCH ossl_slh_dsa_shake_256f_to_text_encoder_functions[];
+
 /* Decoders */
 extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_dh_decoder_functions[];
 extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_dh_decoder_functions[];
@@ -693,6 +794,31 @@ extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_sm2_decoder_function
 extern const OSSL_DISPATCH ossl_type_specific_no_pub_der_to_sm2_decoder_functions[];
 #endif
 
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_128s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_128f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_192s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_192f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_256s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_sha2_256f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_128s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_128f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_192s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_192f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_256s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_slh_dsa_shake_256f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_128s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_128f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_192s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_192f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_256s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_sha2_256f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_128s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_128f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_192s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_192f_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_256s_decoder_functions[];
+extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_slh_dsa_shake_256f_decoder_functions[];
+
 extern const OSSL_DISPATCH ossl_PrivateKeyInfo_der_to_rsa_decoder_functions[];
 extern const OSSL_DISPATCH ossl_SubjectPublicKeyInfo_der_to_rsa_decoder_functions[];
 extern const OSSL_DISPATCH ossl_type_specific_keypair_der_to_rsa_decoder_functions[];
index a5463edda1c989479fd04dfa7051d48f2af2d263..32ad8a098097039abec53e1d30ff5f8055d564ad 100644 (file)
@@ -121,35 +121,35 @@ static const OSSL_PARAM *slh_dsa_gettable_params(void *provctx)
 }
 
 static int key_to_params(SLH_DSA_KEY *key, OSSL_PARAM_BLD *tmpl,
-                         OSSL_PARAM params[], int include_private)
+                         int include_private)
 {
-    if (key == NULL)
-        return 0;
-
-    if (!ossl_param_build_set_octet_string(tmpl, params,
-                                           OSSL_PKEY_PARAM_PUB_KEY,
-                                           ossl_slh_dsa_key_get_pub(key),
-                                           ossl_slh_dsa_key_get_len(key)))
-        return 0;
-
-    if (include_private
-        && ossl_slh_dsa_key_is_private(key)
-        && !ossl_param_build_set_octet_string(tmpl, params,
-                                              OSSL_PKEY_PARAM_PRIV_KEY,
-                                              ossl_slh_dsa_key_get_priv(key),
-                                              ossl_slh_dsa_key_get_len(key)))
+    /* Error if there is no key or public key */
+    if (key == NULL || ossl_slh_dsa_key_get_pub(key) == NULL)
         return 0;
-
-    return 1;
+    /*
+     * Note that the private key always contains the public key elements so we
+     * just save the one blob and return.
+     */
+    if (include_private && ossl_slh_dsa_key_get_priv(key) != NULL)
+        return ossl_param_build_set_octet_string(tmpl, NULL,
+                                                 OSSL_PKEY_PARAM_PRIV_KEY,
+                                                 ossl_slh_dsa_key_get_priv(key),
+                                                 ossl_slh_dsa_key_get_priv_len(key));
+    /* Otherwise write out the public key element */
+    return ossl_param_build_set_octet_string(tmpl, NULL,
+                                             OSSL_PKEY_PARAM_PUB_KEY,
+                                             ossl_slh_dsa_key_get_pub(key),
+                                             ossl_slh_dsa_key_get_pub_len(key));
 }
 
 static int slh_dsa_get_params(void *keydata, OSSL_PARAM params[])
 {
     SLH_DSA_KEY *key = keydata;
     OSSL_PARAM *p;
+    const uint8_t *pub, *priv;
 
     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
-            && !OSSL_PARAM_set_int(p, 8 * ossl_slh_dsa_key_get_len(key)))
+            && !OSSL_PARAM_set_int(p, 8 * ossl_slh_dsa_key_get_pub_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)))
@@ -158,7 +158,25 @@ static int slh_dsa_get_params(void *keydata, OSSL_PARAM params[])
             && !OSSL_PARAM_set_int(p, ossl_slh_dsa_key_get_sig_len(key)))
         return 0;
 
-    return key_to_params(key, NULL, params, 1);
+    pub = ossl_slh_dsa_key_get_pub(key);
+    priv = ossl_slh_dsa_key_get_priv(key);
+
+    /* This just gets the private elements */
+    p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PRIV_KEY);
+    if (p != NULL) {
+        if (priv == NULL
+                || !OSSL_PARAM_set_octet_string(p, priv,
+                                                ossl_slh_dsa_key_get_priv_len(key) / 2))
+            return 0;
+    }
+    p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_PUB_KEY);
+    if (p != NULL) {
+        if (pub == NULL
+                || !OSSL_PARAM_set_octet_string(p, pub,
+                                                ossl_slh_dsa_key_get_pub_len(key)))
+        return 0;
+    }
+    return 1;
 }
 
 static int slh_dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
@@ -183,7 +201,7 @@ static int slh_dsa_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
         return 0;
 
     include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
-    if (!key_to_params(key, tmpl, NULL, include_private))
+    if (!key_to_params(key, tmpl, include_private))
         goto err;
 
     params = OSSL_PARAM_BLD_to_param(tmpl);
index a75e412d99b8ed25954c9ab31d71406ea244e2ec..217fa0279537c9179224d09cedb06602cdf2b843 100644 (file)
@@ -1068,6 +1068,32 @@ IMPLEMENT_TEST_SUITE(ML_KEM_768, "ML-KEM-768", 1)
 KEYS(ML_KEM_1024);
 IMPLEMENT_TEST_SUITE(ML_KEM_1024, "ML-KEM-1024", 1)
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+KEYS(SLH_DSA_SHA2_128s);
+KEYS(SLH_DSA_SHA2_128f);
+KEYS(SLH_DSA_SHA2_192s);
+KEYS(SLH_DSA_SHA2_192f);
+KEYS(SLH_DSA_SHA2_256s);
+KEYS(SLH_DSA_SHA2_256f);
+KEYS(SLH_DSA_SHAKE_128s);
+KEYS(SLH_DSA_SHAKE_128f);
+KEYS(SLH_DSA_SHAKE_192s);
+KEYS(SLH_DSA_SHAKE_192f);
+KEYS(SLH_DSA_SHAKE_256s);
+KEYS(SLH_DSA_SHAKE_256f);
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_128s, "SLH-DSA-SHA2-128s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_128f, "SLH-DSA-SHA2-128f", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_192s, "SLH-DSA-SHA2-192s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_192f, "SLH-DSA-SHA2-192f", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_256s, "SLH-DSA-SHA2-256s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHA2_256f, "SLH-DSA-SHA2-256f", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_128s, "SLH-DSA-SHAKE-128s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_128f, "SLH-DSA-SHAKE-128f", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_192s, "SLH-DSA-SHAKE-192s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_192f, "SLH-DSA-SHAKE-192f", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_256s, "SLH-DSA-SHAKE-256s", 1)
+IMPLEMENT_TEST_SUITE(SLH_DSA_SHAKE_256f, "SLH-DSA-SHAKE-256f", 1)
+#endif /* OPENSSL_NO_SLH_DSA */
 KEYS(RSA);
 IMPLEMENT_TEST_SUITE(RSA, "RSA", 1)
 IMPLEMENT_TEST_SUITE_LEGACY(RSA, "RSA")
@@ -1453,6 +1479,20 @@ int setup_tests(void)
         MAKE_KEYS(ML_KEM_1024, "ML-KEM-1024", NULL);
     }
 #endif
+#ifndef OPENSSL_NO_SLH_DSA
+    MAKE_KEYS(SLH_DSA_SHA2_128s, "SLH-DSA-SHA2-128s", NULL);
+    MAKE_KEYS(SLH_DSA_SHA2_128f, "SLH-DSA-SHA2-128f", NULL);
+    MAKE_KEYS(SLH_DSA_SHA2_192s, "SLH-DSA-SHA2-192s", NULL);
+    MAKE_KEYS(SLH_DSA_SHA2_192f, "SLH-DSA-SHA2-192f", NULL);
+    MAKE_KEYS(SLH_DSA_SHA2_256s, "SLH-DSA-SHA2-256s", NULL);
+    MAKE_KEYS(SLH_DSA_SHA2_256f, "SLH-DSA-SHA2-256f", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_128s, "SLH-DSA-SHAKE-128s", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_128f, "SLH-DSA-SHAKE-128f", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_192s, "SLH-DSA-SHAKE-192s", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_192f, "SLH-DSA-SHAKE-192f", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_256s, "SLH-DSA-SHAKE-256s", NULL);
+    MAKE_KEYS(SLH_DSA_SHAKE_256f, "SLH-DSA-SHAKE-256f", NULL);
+#endif /* OPENSSL_NO_SLH_DSA */
 
     TEST_info("Loading RSA key...");
     ok = ok && TEST_ptr(key_RSA = load_pkey_pem(rsa_file, keyctx));
@@ -1507,6 +1547,10 @@ int setup_tests(void)
         ADD_TEST_SUITE(ED448);
         ADD_TEST_SUITE(X25519);
         ADD_TEST_SUITE(X448);
+        /*
+         * ED25519, ED448, X25519 and X448 have no support for
+         * PEM_write_bio_PrivateKey_traditional(), so no legacy tests.
+         */
 #endif
 #ifndef OPENSSL_NO_ML_KEM
         if (!is_fips_lt_3_5) {
@@ -1515,10 +1559,6 @@ int setup_tests(void)
             ADD_TEST_SUITE(ML_KEM_1024);
         }
 #endif
-        /*
-         * ED25519, ED448, X25519 and X448 have no support for
-         * PEM_write_bio_PrivateKey_traditional(), so no legacy tests.
-         */
         ADD_TEST_SUITE(RSA);
         ADD_TEST_SUITE_LEGACY(RSA);
         ADD_TEST_SUITE(RSA_PSS);
@@ -1539,6 +1579,21 @@ int setup_tests(void)
             ADD_TEST_SUITE(ML_DSA_87);
         }
 #endif /* OPENSSL_NO_ML_DSA */
+
+#ifndef OPENSSL_NO_SLH_DSA
+        ADD_TEST_SUITE(SLH_DSA_SHA2_128s);
+        ADD_TEST_SUITE(SLH_DSA_SHA2_128f);
+        ADD_TEST_SUITE(SLH_DSA_SHA2_192s);
+        ADD_TEST_SUITE(SLH_DSA_SHA2_192f);
+        ADD_TEST_SUITE(SLH_DSA_SHA2_256s);
+        ADD_TEST_SUITE(SLH_DSA_SHA2_256f);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_128s);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_128f);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_192s);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_192f);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_256s);
+        ADD_TEST_SUITE(SLH_DSA_SHAKE_256f);
+#endif /* OPENSSL_NO_SLH_DSA */
     }
 
     return 1;
@@ -1603,6 +1658,21 @@ void cleanup_tests(void)
     }
 #endif /* OPENSSL_NO_ML_DSA */
 
+#ifndef OPENSSL_NO_SLH_DSA
+    FREE_KEYS(SLH_DSA_SHA2_128s);
+    FREE_KEYS(SLH_DSA_SHA2_128f);
+    FREE_KEYS(SLH_DSA_SHA2_192s);
+    FREE_KEYS(SLH_DSA_SHA2_192f);
+    FREE_KEYS(SLH_DSA_SHA2_256s);
+    FREE_KEYS(SLH_DSA_SHA2_256f);
+    FREE_KEYS(SLH_DSA_SHAKE_128s);
+    FREE_KEYS(SLH_DSA_SHAKE_128f);
+    FREE_KEYS(SLH_DSA_SHAKE_192s);
+    FREE_KEYS(SLH_DSA_SHAKE_192f);
+    FREE_KEYS(SLH_DSA_SHAKE_256s);
+    FREE_KEYS(SLH_DSA_SHAKE_256f);
+#endif /* OPENSSL_NO_SLH_DSA */
+
     OSSL_PROVIDER_unload(nullprov);
     OSSL_PROVIDER_unload(deflprov);
     OSSL_PROVIDER_unload(keyprov);
index 1d8294f3549bd8575ba118912dd51c70f3dc4a6f..f475100d86af0d461f6b40c7bbb5f201dfea35b3 100644 (file)
@@ -295,3 +295,187 @@ static const SLH_DSA_KEYGEN_TEST_DATA slh_dsa_keygen_testdata[] = {
     SLH_DSA_KEYGEN_TEST_ITEM(slh_dsa_shake_256s_0, "SLH-DSA-SHAKE-256s"),
     SLH_DSA_KEYGEN_TEST_ITEM(slh_dsa_shake_256f_0, "SLH-DSA-SHAKE-256f"),
 };
+/*
+static const char pem_priv[] =
+"-----BEGIN PRIVATE KEY-----\n"
+"MFICAQAwCwYJYIZIAWUDBAMUBECg/HdWVy8wCPVEOZwlyeCHwoKHq1StsWAfys+F\n"
+"wplaVEBPaQzZoUVRL2Hy5N6SktpxNx51SzwqefJHHhRgii40\n"
+"-----END PRIVATE KEY-----\n";
+
+static const char pem_cert[]=
+"-----BEGIN CERTIFICATE-----\n"
+"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\n"
+"1rpNKWJK7upkPEgtkj67Ubs=\n"
+"-----END CERTIFICATE-----\n";
+*/