From eba0e11c39dcacb14da1eda699d528eae829b0a2 Mon Sep 17 00:00:00 2001 From: slontis Date: Thu, 21 Nov 2024 16:09:18 +1100 Subject: [PATCH] Add SLH_DSA key validation. The pairwise test requires that the computed PK_ROOT key matches the keys PK_ROOT value. The public and private key tests just require the key elements to exist. Reviewed-by: Paul Dale Reviewed-by: Viktor Dukhovni Reviewed-by: Tim Hudson (Merged from https://github.com/openssl/openssl/pull/25882) --- crypto/slh_dsa/slh_dsa_backend.c | 2 +- crypto/slh_dsa/slh_dsa_key.c | 75 +++++- crypto/slh_dsa/slh_dsa_local.h | 4 +- crypto/slh_dsa/slh_dsa_meth.c | 31 +-- crypto/x509/x_pubkey.c | 22 +- doc/designs/slh-dsa.md | 2 +- include/crypto/evp.h | 4 +- include/crypto/slh_dsa.h | 2 + .../encode_decode/decode_der2key.c | 244 +++++++++--------- .../encode_decode/encode_key2any.c | 3 - .../encode_decode/encode_key2text.c | 35 +-- .../implementations/keymgmt/slh_dsa_kmgmt.c | 18 +- test/endecode_test.c | 83 +++--- test/slh_dsa_test.c | 69 +++-- 14 files changed, 341 insertions(+), 253 deletions(-) diff --git a/crypto/slh_dsa/slh_dsa_backend.c b/crypto/slh_dsa/slh_dsa_backend.c index 870b78f3593..8cf089de16e 100644 --- a/crypto/slh_dsa/slh_dsa_backend.c +++ b/crypto/slh_dsa/slh_dsa_backend.c @@ -29,7 +29,7 @@ SLH_DSA_KEY *ossl_slh_dsa_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8_info, X509_ALGOR_get0(NULL, &alg_param_type, NULL, alg); if (alg_param_type != V_ASN1_UNDEF) - return 0; + return 0; oct = d2i_ASN1_OCTET_STRING(NULL, &p, p_len); if (oct == NULL) { diff --git a/crypto/slh_dsa/slh_dsa_key.c b/crypto/slh_dsa/slh_dsa_key.c index be531ca554a..a454fb27a70 100644 --- a/crypto/slh_dsa/slh_dsa_key.c +++ b/crypto/slh_dsa/slh_dsa_key.c @@ -15,8 +15,10 @@ #include #include "slh_dsa_local.h" #include "slh_dsa_key.h" +#include "internal/encoder.h" -static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out); +static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out, + int verify); /** * @brief Create a new SLH_DSA_KEY object @@ -142,6 +144,22 @@ int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection) return 0; } +int ossl_slh_dsa_key_pairwise_check(const SLH_DSA_KEY *key) +{ + int ret; + SLH_DSA_CTX *ctx = NULL; + + if (key->pub == NULL || key->has_priv == 0) + return 0; + + ctx = ossl_slh_dsa_ctx_new(key->params->alg, key->libctx, key->propq); + if (ctx == NULL) + return 0; + ret = slh_dsa_compute_pk_root(ctx, (SLH_DSA_KEY *)key, 1); + ossl_slh_dsa_ctx_free(ctx); + return ret; +} + /** * @brief Load a SLH_DSA key from raw data. * @@ -213,20 +231,28 @@ int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM params[], * @param ctx Contains SLH_DSA algorithm functions and constants. * @param out A SLH_DSA key containing the private key (seed and prf) and public key seed. * The public root key is written to this key. - * @returns 1 if the root key is generated, or 0 on error. + * @param validate If set to 1 the computed public key is not written to the key, + * but will be compared to the existing value. + * @returns 1 if the root key is generated or compared successfully, or 0 on error. */ -static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out) +static int slh_dsa_compute_pk_root(SLH_DSA_CTX *ctx, SLH_DSA_KEY *out, + int validate) { SLH_ADRS_FUNC_DECLARE(ctx, adrsf); SLH_ADRS_DECLARE(adrs); const SLH_DSA_PARAMS *params = out->params; + size_t n = params->n; + uint8_t pk_root[SLH_DSA_MAX_N], *dst; adrsf->zero(adrs); adrsf->set_layer_address(adrs, params->d - 1); + + dst = validate ? pk_root : SLH_DSA_PK_ROOT(out); + /* Generate the ROOT public key */ return ossl_slh_xmss_node(ctx, SLH_DSA_SK_SEED(out), 0, params->hm, - SLH_DSA_PK_SEED(out), adrs, - SLH_DSA_PK_ROOT(out), params->n); + SLH_DSA_PK_SEED(out), adrs, dst, n) + && (validate == 0 || memcmp(dst, SLH_DSA_PK_ROOT(out), n) == 0); } /** @@ -265,7 +291,7 @@ int ossl_slh_dsa_generate_key(SLH_DSA_CTX *ctx, OSSL_LIB_CTX *lib_ctx, || RAND_bytes_ex(lib_ctx, pub, pk_seed_len, 0) <= 0) goto err; } - if (!slh_dsa_compute_pk_root(ctx, out)) + if (!slh_dsa_compute_pk_root(ctx, out, 0)) goto err; out->pub = pub; out->has_priv = 1; @@ -358,3 +384,40 @@ int ossl_slh_dsa_set_pub(SLH_DSA_KEY *key, const uint8_t *pub, size_t pub_len) key->has_priv = 0; return 1; } + +int ossl_slh_dsa_key_to_text(BIO *out, const SLH_DSA_KEY *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 (!ossl_bio_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 (!ossl_bio_print_labeled_buf(out, "pub:", ossl_slh_dsa_key_get_pub(key), + ossl_slh_dsa_key_get_pub_len(key))) + return 0; + + return 1; +} diff --git a/crypto/slh_dsa/slh_dsa_local.h b/crypto/slh_dsa/slh_dsa_local.h index d48952e55bb..288de32f377 100644 --- a/crypto/slh_dsa/slh_dsa_local.h +++ b/crypto/slh_dsa/slh_dsa_local.h @@ -17,13 +17,13 @@ * It is the size used by WOTS+ public and private key elements as well as * signature elements. */ -#define SLH_MAX_N 32 +#define SLH_MAX_N 32 /* * For the given standard w=16 for all parameter sets. * A n byte message is converted into 2 * n base 16 Integers followed * by 3 Integers for the checksum of these values. */ -#define SLH_WOTS_LEN(n) (2 * (n) + 3) +#define SLH_WOTS_LEN(n) (2 * (n) + 3) /* * FIPS 205 SLH_DSA algorithms have many different parameters which includes: diff --git a/crypto/slh_dsa/slh_dsa_meth.c b/crypto/slh_dsa/slh_dsa_meth.c index 0e0aca49df1..0bad7cca2c7 100644 --- a/crypto/slh_dsa/slh_dsa_meth.c +++ b/crypto/slh_dsa/slh_dsa_meth.c @@ -15,6 +15,22 @@ #include "crypto/x509.h" #include "crypto/slh_dsa.h" +/* 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, \ + } + static SLH_DSA_KEY *ossl_slh_dsa_key_create(const X509_ALGOR *palg, const unsigned char *p, int p_len, int id, int public, @@ -83,21 +99,6 @@ 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); diff --git a/crypto/x509/x_pubkey.c b/crypto/x509/x_pubkey.c index 8c6e994d0b7..4f0c785a783 100644 --- a/crypto/x509/x_pubkey.c +++ b/crypto/x509/x_pubkey.c @@ -1054,17 +1054,17 @@ static int i2d_SLH_DSA_PUBKEY(const SLH_DSA_KEY *a, unsigned char **pp, 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); \ -} +# 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) diff --git a/doc/designs/slh-dsa.md b/doc/designs/slh-dsa.md index 4cca1f2b572..7926cd56056 100644 --- a/doc/designs/slh-dsa.md +++ b/doc/designs/slh-dsa.md @@ -60,7 +60,7 @@ The fields 'key_len' and 'has_priv' are used to determine if a key has loaded the public and private key elements. The 'params' field is the parameter set which is resolved via the algorithm name. -The FIPS 205 the SLH_DSA private key contains the public key. +In FIPS 205 the SLH_DSA private key contains the public key. In OpenSSL these components are stored separately, so there must always be a public key in order for the key to be valid. diff --git a/include/crypto/evp.h b/include/crypto/evp.h index a87f14a0129..5e2f8a148ec 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -663,9 +663,9 @@ union legacy_pkey_st { # ifndef OPENSSL_NO_ECX ECX_KEY *ecx; /* X25519, X448, Ed25519, Ed448 */ # endif -# ifndef OPENSSL_NO_SLH_DSA +# 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 353daf04c95..dc04df8061e 100644 --- a/include/crypto/slh_dsa.h +++ b/include/crypto/slh_dsa.h @@ -27,11 +27,13 @@ __owur int ossl_slh_dsa_key_up_ref(SLH_DSA_KEY *key); __owur int ossl_slh_dsa_key_equal(const SLH_DSA_KEY *key1, const SLH_DSA_KEY *key2, int selection); __owur int ossl_slh_dsa_key_has(const SLH_DSA_KEY *key, int selection); +__owur int ossl_slh_dsa_key_pairwise_check(const SLH_DSA_KEY *key); __owur int ossl_slh_dsa_key_fromdata(SLH_DSA_KEY *key, const OSSL_PARAM *params, int include_private); __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_to_text(BIO *out, const SLH_DSA_KEY *key, int selection); __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_pub_len(const SLH_DSA_KEY *key); diff --git a/providers/implementations/encode_decode/decode_der2key.c b/providers/implementations/encode_decode/decode_der2key.c index aca35cdaa40..85f6bfc5dc4 100644 --- a/providers/implementations/encode_decode/decode_der2key.c +++ b/providers/implementations/encode_decode/decode_der2key.c @@ -622,7 +622,7 @@ ml_kem_d2i_PUBKEY(const uint8_t **der, long der_len, #endif -# ifndef OPENSSL_NO_SLH_DSA +#ifndef OPENSSL_NO_SLH_DSA /* SLH_DSA only implements PKCS#8 and SubjectPublicKeyInfo */ @@ -638,128 +638,126 @@ 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 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 */ /* ---------------------------------------------------------------------- */ diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c index 4480746fd67..9c0f2176f4e 100644 --- a/providers/implementations/encode_decode/encode_key2any.c +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -1628,8 +1628,6 @@ MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, Encrypted 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); @@ -1654,7 +1652,6 @@ MAKE_ENCODER(slh_dsa_shake_192s, slh_dsa, EVP_PKEY_SLH_DSA_SHAKE_192S, PrivateKe 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); diff --git a/providers/implementations/encode_decode/encode_key2text.c b/providers/implementations/encode_decode/encode_key2text.c index 56a5766432a..a2fb47ef3c8 100644 --- a/providers/implementations/encode_decode/encode_key2text.c +++ b/providers/implementations/encode_decode/encode_key2text.c @@ -449,41 +449,8 @@ 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; + return ossl_slh_dsa_key_to_text(out, (SLH_DSA_KEY *)key, selection); } - #endif /* OPENSSL_NO_SLH_DSA */ static int rsa_to_text(BIO *out, const void *key, int selection) diff --git a/providers/implementations/keymgmt/slh_dsa_kmgmt.c b/providers/implementations/keymgmt/slh_dsa_kmgmt.c index 288f49390d3..52b6858ebb1 100644 --- a/providers/implementations/keymgmt/slh_dsa_kmgmt.c +++ b/providers/implementations/keymgmt/slh_dsa_kmgmt.c @@ -27,6 +27,7 @@ static OSSL_FUNC_keymgmt_export_types_fn slh_dsa_imexport_types; static OSSL_FUNC_keymgmt_load_fn slh_dsa_load; static OSSL_FUNC_keymgmt_get_params_fn slh_dsa_get_params; static OSSL_FUNC_keymgmt_gettable_params_fn slh_dsa_gettable_params; +static OSSL_FUNC_keymgmt_validate_fn slh_dsa_validate; static OSSL_FUNC_keymgmt_gen_init_fn slh_dsa_gen_init; static OSSL_FUNC_keymgmt_gen_cleanup_fn slh_dsa_gen_cleanup; static OSSL_FUNC_keymgmt_gen_set_params_fn slh_dsa_gen_set_params; @@ -79,6 +80,18 @@ static int slh_dsa_match(const void *keydata1, const void *keydata2, int selecti return ossl_slh_dsa_key_equal(key1, key2, selection); } +static int slh_dsa_validate(const void *key_data, int selection, int check_type) +{ + const SLH_DSA_KEY *key = key_data; + + if (!slh_dsa_has(key, selection)) + return 0; + + if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR) + return ossl_slh_dsa_key_pairwise_check(key); + return 1; +} + static int slh_dsa_import(void *keydata, int selection, const OSSL_PARAM params[]) { SLH_DSA_KEY *key = keydata; @@ -175,7 +188,7 @@ static int slh_dsa_get_params(void *keydata, OSSL_PARAM params[]) if (pub == NULL || !OSSL_PARAM_set_octet_string(p, pub, ossl_slh_dsa_key_get_pub_len(key))) - return 0; + return 0; } return 1; } @@ -279,7 +292,7 @@ static int slh_dsa_fips140_pairwise_test(SLH_DSA_CTX *ctx, const SLH_DSA_KEY *ke if (sig == NULL) goto err; - if (ossl_slh_dsa_sign(ctx, key, msg, msg_len, NULL, 0, NULL, 0, + if (ossl_slh_dsa_sign(ctx, key, msg, msg_len, NULL, 0, NULL, 0, sig, &sig_len, sig_len) != 1) goto err; @@ -400,6 +413,7 @@ static void slh_dsa_gen_cleanup(void *genctx) { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))slh_dsa_load }, \ { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))slh_dsa_get_params }, \ { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))slh_dsa_gettable_params },\ + { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))slh_dsa_validate }, \ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))slh_dsa_gen_init }, \ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))slh_dsa_##fn##_gen }, \ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))slh_dsa_gen_cleanup },\ diff --git a/test/endecode_test.c b/test/endecode_test.c index 217fa027953..17752e7d17a 100644 --- a/test/endecode_test.c +++ b/test/endecode_test.c @@ -110,7 +110,8 @@ static EVP_PKEY *make_template(const char *type, OSSL_PARAM *genparams) !defined(OPENSSL_NO_DSA) || \ !defined(OPENSSL_NO_EC) || \ !defined(OPENSSL_NO_ML_DSA) || \ - !defined(OPENSSL_NO_ML_KEM) + !defined(OPENSSL_NO_ML_KEM) || \ + !defined(OPENSSL_NO_SLH_DSA) static EVP_PKEY *make_key(const char *type, EVP_PKEY *template, OSSL_PARAM *genparams) { @@ -1396,7 +1397,7 @@ int setup_tests(void) /* FIPS(3.0.0): provider imports explicit params but they won't work #17998 */ is_fips_3_0_0 = is_fips && fips_provider_version_eq(testctx, 3, 0, 0); - /* FIPS(3.5.0) is the first to support ML-KEM and ML-DSA */ + /* FIPS(3.5.0) is the first to support ML-DSA, ML-KEM and SLH-DSA */ is_fips_lt_3_5 = is_fips && fips_provider_version_lt(testctx, 3, 5, 0); #ifdef STATIC_LEGACY @@ -1480,18 +1481,20 @@ int setup_tests(void) } #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); + if (!is_fips_lt_3_5) { + 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..."); @@ -1581,18 +1584,20 @@ int setup_tests(void) #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); + if (!is_fips_lt_3_5) { + 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 */ } @@ -1659,18 +1664,20 @@ 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); + if (!is_fips_lt_3_5) { + 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); diff --git a/test/slh_dsa_test.c b/test/slh_dsa_test.c index 7dc8d549aea..c378eb8d1e9 100644 --- a/test/slh_dsa_test.c +++ b/test/slh_dsa_test.c @@ -28,20 +28,22 @@ static OSSL_LIB_CTX *lib_ctx = NULL; static OSSL_PROVIDER *null_prov = NULL; static OSSL_PROVIDER *lib_prov = NULL; -static EVP_PKEY *slh_dsa_pubkey_from_data(const char *alg, - const unsigned char *data, size_t datalen) +static EVP_PKEY *slh_dsa_key_from_data(const char *alg, + const unsigned char *data, size_t datalen, + int public) { int ret; EVP_PKEY_CTX *ctx = NULL; EVP_PKEY *key = NULL; OSSL_PARAM params[2]; + const char *keytype = public ? OSSL_PKEY_PARAM_PUB_KEY : OSSL_PKEY_PARAM_PRIV_KEY; + int selection = public ? EVP_PKEY_PUBLIC_KEY : EVP_PKEY_KEYPAIR; - params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, - (unsigned char *)data, datalen); + params[0] = OSSL_PARAM_construct_octet_string(keytype, (uint8_t *)data, datalen); params[1] = OSSL_PARAM_construct_end(); ret = TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(lib_ctx, alg, NULL)) && TEST_int_eq(EVP_PKEY_fromdata_init(ctx), 1) - && (EVP_PKEY_fromdata(ctx, &key, EVP_PKEY_PUBLIC_KEY, params) == 1); + && (EVP_PKEY_fromdata(ctx, &key, selection, params) == 1); if (ret == 0) { EVP_PKEY_free(key); key = NULL; @@ -96,10 +98,10 @@ static int slh_dsa_bad_pub_len_test(void) OPENSSL_cleanse(pubdata, sizeof(pubdata)); memcpy(pubdata, td->pub, td->pub_len); - if (!TEST_ptr_null(pkey = slh_dsa_pubkey_from_data(td->alg, pubdata, - td->pub_len - 1)) - || !TEST_ptr_null(pkey = slh_dsa_pubkey_from_data(td->alg, pubdata, - td->pub_len + 1))) + if (!TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata, + td->pub_len - 1, 1)) + || !TEST_ptr_null(pkey = slh_dsa_key_from_data(td->alg, pubdata, + td->pub_len + 1, 1))) goto end; ret = 1; @@ -121,9 +123,9 @@ static int slh_dsa_key_eq_test(void) EVP_PKEY *eckey = NULL; #endif - if (!TEST_ptr(key[0] = slh_dsa_pubkey_from_data(td1->alg, td1->pub, td1->pub_len)) - || !TEST_ptr(key[1] = slh_dsa_pubkey_from_data(td1->alg, td1->pub, td1->pub_len)) - || !TEST_ptr(key[2] = slh_dsa_pubkey_from_data(td2->alg, td2->pub, td2->pub_len))) + if (!TEST_ptr(key[0] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1)) + || !TEST_ptr(key[1] = slh_dsa_key_from_data(td1->alg, td1->pub, td1->pub_len, 1)) + || !TEST_ptr(key[2] = slh_dsa_key_from_data(td2->alg, td2->pub, td2->pub_len, 1))) goto end; if (!TEST_int_eq(EVP_PKEY_eq(key[0], key[1]), 1) @@ -152,13 +154,44 @@ static int slh_dsa_key_validate_test(void) EVP_PKEY_CTX *vctx = NULL; EVP_PKEY *key = NULL; - if (!TEST_ptr(key = slh_dsa_pubkey_from_data(td->alg, td->pub, td->pub_len))) + if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1))) return 0; if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) goto end; - ret = TEST_int_eq(EVP_PKEY_check(vctx), 1); + if (!TEST_int_eq(EVP_PKEY_public_check(vctx), 1)) + goto end; + if (!TEST_int_eq(EVP_PKEY_private_check(vctx), 0)) + goto end; + if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0)) + goto end; + ret = 1; +end: EVP_PKEY_CTX_free(vctx); + EVP_PKEY_free(key); + return ret; +} + +static int slh_dsa_key_validate_failure_test(void) +{ + int ret = 0; + EVP_PKEY_CTX *vctx = NULL; + EVP_PKEY *key = NULL; + + /* + * Loading 128s private key data into a 128f algorithm will have an incorrect + * public key. + */ + if (!TEST_ptr(key = slh_dsa_key_from_data("SLH-DSA-SHA2-128f", + slh_dsa_sha2_128s_0_keygen_priv, + sizeof(slh_dsa_sha2_128s_0_keygen_priv), 0))) + return 0; + if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) + goto end; + if (!TEST_int_eq(EVP_PKEY_pairwise_check(vctx), 0)) + goto end; + ret = 1; end: + EVP_PKEY_CTX_free(vctx); EVP_PKEY_free(key); return ret; } @@ -182,7 +215,7 @@ static int do_slh_dsa_verify(const SLH_DSA_SIG_TEST_DATA *td, *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING, &encode); *p = OSSL_PARAM_construct_end(); - if (!TEST_ptr(key = slh_dsa_pubkey_from_data(td->alg, td->pub, td->pub_len))) + if (!TEST_ptr(key = slh_dsa_key_from_data(td->alg, td->pub, td->pub_len, 1))) return 0; if (!TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, key, NULL))) goto err; @@ -365,6 +398,10 @@ static int slh_dsa_usage_test(void) || !TEST_ptr(sig = OPENSSL_malloc(sig_len)) || !TEST_int_eq(EVP_PKEY_sign(sctx, sig, &sig_len, msg, msg_len), 1)) goto err; + if (!TEST_true(EVP_PKEY_pairwise_check(sctx)) + || !TEST_true(EVP_PKEY_public_check(sctx)) + || !TEST_true(EVP_PKEY_private_check(sctx))) + goto err; /* Read the public key and add to a verify ctx */ if (!TEST_ptr(PEM_read_bio_PUBKEY_ex(pub_bio, &pub, NULL, NULL, lib_ctx, NULL)) || !TEST_ptr(vctx = EVP_PKEY_CTX_new_from_pkey(lib_ctx, pub, NULL))) @@ -373,6 +410,7 @@ static int slh_dsa_usage_test(void) if (!TEST_int_eq(EVP_PKEY_verify_message_init(vctx, sig_alg, NULL), 1) || !TEST_int_eq(EVP_PKEY_verify(vctx, sig, sig_len, msg, msg_len), 1)) goto err; + ret = 1; err: EVP_CIPHER_free(cipher); @@ -495,6 +533,7 @@ int setup_tests(void) ADD_TEST(slh_dsa_bad_pub_len_test); ADD_TEST(slh_dsa_key_validate_test); + ADD_TEST(slh_dsa_key_validate_failure_test); ADD_TEST(slh_dsa_key_eq_test); ADD_TEST(slh_dsa_usage_test); ADD_TEST(slh_dsa_deterministic_usage_test); -- 2.47.2