From: slontis Date: Tue, 19 Nov 2024 04:40:13 +0000 (+1100) Subject: Add SLH-DSA encoder/decoder support. X-Git-Tag: openssl-3.5.0-alpha1~185 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a25bcde26a4553af5ffcd698c5d6f504806efc01;p=thirdparty%2Fopenssl.git Add SLH-DSA encoder/decoder support. This required adding additional EVP_PKEY_ASN1_METHOD methods. Reviewed-by: Paul Dale Reviewed-by: Viktor Dukhovni Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/25882) --- diff --git a/crypto/asn1/standard_methods.h b/crypto/asn1/standard_methods.h index ebb53e57db7..2c3bd392049 100644 --- a/crypto/asn1/standard_methods.h +++ b/crypto/asn1/standard_methods.h @@ -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 }; - diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c index 64ef8109831..22d27cf89a5 100644 --- a/crypto/evp/p_lib.c +++ b/crypto/evp/p_lib.c @@ -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) diff --git a/crypto/slh_dsa/build.info b/crypto/slh_dsa/build.info index 6f93bd41b00..bd6c78a44ad 100644 --- a/crypto/slh_dsa/build.info +++ b/crypto/slh_dsa/build.info @@ -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 diff --git a/crypto/slh_dsa/slh_dsa.c b/crypto/slh_dsa/slh_dsa.c index c271c21db04..03bc18dc13b 100644 --- a/crypto/slh_dsa/slh_dsa.c +++ b/crypto/slh_dsa/slh_dsa.c @@ -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 index 00000000000..870b78f3593 --- /dev/null +++ b/crypto/slh_dsa/slh_dsa_backend.c @@ -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 +#include +#include +#include +#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; +} diff --git a/crypto/slh_dsa/slh_dsa_key.c b/crypto/slh_dsa/slh_dsa_key.c index cf4f5c8787b..be531ca554a 100644 --- a/crypto/slh_dsa/slh_dsa_key.c +++ b/crypto/slh_dsa/slh_dsa_key.c @@ -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; +} diff --git a/crypto/slh_dsa/slh_dsa_key.h b/crypto/slh_dsa/slh_dsa_key.h index 520332965dc..bd9ef760e44 100644 --- a/crypto/slh_dsa/slh_dsa_key.h +++ b/crypto/slh_dsa/slh_dsa_key.h @@ -10,18 +10,29 @@ #include #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 index 00000000000..0e0aca49df1 --- /dev/null +++ b/crypto/slh_dsa/slh_dsa_meth.c @@ -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); diff --git a/crypto/slh_dsa/slh_params.c b/crypto/slh_dsa/slh_params.c index 39d9e5fb194..19ef56c2a12 100644 --- a/crypto/slh_dsa/slh_params.c +++ b/crypto/slh_dsa/slh_params.c @@ -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; diff --git a/crypto/slh_dsa/slh_params.h b/crypto/slh_dsa/slh_params.h index 80a0ad570f9..268e9f482f2 100644 --- a/crypto/slh_dsa/slh_params.h +++ b/crypto/slh_dsa/slh_params.h @@ -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; diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 53639b2bfab..8c6e994d0b7 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -20,6 +20,7 @@ #include #include "crypto/asn1.h" #include "crypto/evp.h" +#include "crypto/slh_dsa.h" #include "crypto/x509.h" #include #include @@ -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) { diff --git a/doc/man7/OSSL_PROVIDER-FIPS.pod b/doc/man7/OSSL_PROVIDER-FIPS.pod index 557296846ea..f60e8b7d4bd 100644 --- a/doc/man7/OSSL_PROVIDER-FIPS.pod +++ b/doc/man7/OSSL_PROVIDER-FIPS.pod @@ -242,6 +242,30 @@ This is an unapproved algorithm. =item ML-DSA-87, see L +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + =back =head2 Random Number Generation diff --git a/doc/man7/OSSL_PROVIDER-base.pod b/doc/man7/OSSL_PROVIDER-base.pod index f0bc498cb52..0156fd85571 100644 --- a/doc/man7/OSSL_PROVIDER-base.pod +++ b/doc/man7/OSSL_PROVIDER-base.pod @@ -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 diff --git a/doc/man7/OSSL_PROVIDER-default.pod b/doc/man7/OSSL_PROVIDER-default.pod index 2fd6d105f04..3f2ba5b90b8 100644 --- a/doc/man7/OSSL_PROVIDER-default.pod +++ b/doc/man7/OSSL_PROVIDER-default.pod @@ -195,8 +195,6 @@ The OpenSSL default provider supports these operations and algorithms: =item ECDSA, see L -=item SLH-DSA, see L - =item SM2 =item ML-DSA-44, see L @@ -213,6 +211,30 @@ The OpenSSL default provider supports these operations and algorithms: =item CMAC, see L +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + =back =head2 Asymmetric Cipher @@ -283,6 +305,30 @@ The OpenSSL default provider supports these operations and algorithms: =item MK-KEM-1024, see L +=item SLH-DSA-SHA2-128s, see L + +=item SLH-DSA-SHA2-128f, see L + +=item SLH-DSA-SHA2-192s, see L + +=item SLH-DSA-SHA2-192f, see L + +=item SLH-DSA-SHA2-256s, see L + +=item SLH-DSA-SHA2-256f, see L + +=item SLH-DSA-SHAKE-128s, see L + +=item SLH-DSA-SHAKE-128f, see L + +=item SLH-DSA-SHAKE-192s, see L + +=item SLH-DSA-SHAKE-192f, see L + +=item SLH-DSA-SHAKE-256s, see L + +=item SLH-DSA-SHAKE-256f, see L + =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 diff --git a/include/crypto/asn1.h b/include/crypto/asn1.h index 8461c1be8d2..ea833b9283e 100644 --- a/include/crypto/asn1.h +++ b/include/crypto/asn1.h @@ -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 diff --git a/include/crypto/evp.h b/include/crypto/evp.h index 861447f557b..a87f14a0129 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -15,6 +15,7 @@ # include # 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 }; diff --git a/include/crypto/slh_dsa.h b/include/crypto/slh_dsa.h index 86ad4f96f8a..353daf04c95 100644 --- a/include/crypto/slh_dsa.h +++ b/include/crypto/slh_dsa.h @@ -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); diff --git a/include/crypto/x509.h b/include/crypto/x509.h index e6ebae39145..3869cb4c36b 100644 --- a/include/crypto/x509.h +++ b/include/crypto/x509.h @@ -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); diff --git a/include/openssl/evp.h b/include/openssl/evp.h index c58377355fa..0cbb38aad89 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -86,6 +86,18 @@ # 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 diff --git a/providers/decoders.inc b/providers/decoders.inc index ae94042b828..ffae575c618 100644 --- a/providers/decoders.inc +++ b/providers/decoders.inc @@ -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), diff --git a/providers/encoders.inc b/providers/encoders.inc index 74931909440..41dc6ba9209 100644 --- a/providers/encoders.inc +++ b/providers/encoders.inc @@ -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), diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c index da4a7d8abeb..aca35cdaa40 100644 --- a/providers/implementations/encode_decode/decode_der2key.c +++ b/providers/implementations/encode_decode/decode_der2key.c @@ -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); diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c index bb7707a6dc7..4480746fd67 100644 --- a/providers/implementations/encode_decode/encode_key2any.c +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -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); diff --git a/providers/implementations/encode_decode/encode_key2text.c b/providers/implementations/encode_decode/encode_key2text.c index b3fd1c330db..56a5766432a 100644 --- a/providers/implementations/encode_decode/encode_key2text.c +++ b/providers/implementations/encode_decode/encode_key2text.c @@ -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 diff --git a/providers/implementations/include/prov/implementations.h b/providers/implementations/include/prov/implementations.h index b0281e5686b..a2396dccd68 100644 --- a/providers/implementations/include/prov/implementations.h +++ b/providers/implementations/include/prov/implementations.h @@ -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[]; diff --git a/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c index a5463edda1c..32ad8a09809 100644 --- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c @@ -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); diff --git a/test/endecode_test.c b/test/endecode_test.c index a75e412d99b..217fa027953 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -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); diff --git a/test/slh_dsa.inc b/test/slh_dsa.inc index 1d8294f3549..f475100d86a 100644 --- a/test/slh_dsa.inc +++ b/test/slh_dsa.inc @@ -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"; +*/