From: Viktor Dukhovni Date: Mon, 24 Nov 2025 13:37:49 +0000 (+1100) Subject: Per-key encoding formats for ML-KEM and ML-DSA X-Git-Tag: 4.0-PRE-CLANG-FORMAT-WEBKIT~21 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3720c946f095d4f35f04f61cf6efa8b84e26fc7c;p=thirdparty%2Fopenssl.git Per-key encoding formats for ML-KEM and ML-DSA We support selection of ML-KEM and ML-DSA key formats on input and output at the provider level, these are essentially global defaults, in effect for the lifetime of the process. Unfortunately, the JAVA interface in openssl-jostle needs to be able to output a specific key in seed-only form. To that end, this PR introduces a new "output-formats" PKEY encoding parameter, that can be used with OSSL_ENCODER_CTX_set_params(3) when encoding a key to PKCS#8, after using OSSL_ENCODER_CTX_new_for_key(3), rather than i2d_PrivateKey(3), i2d_PKCS8PrivateKey(3) or PEM equivalents. Reviewed-by: Tomas Mraz Reviewed-by: Eugene Syromiatnikov Reviewed-by: Neil Horman Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/29206) --- diff --git a/crypto/ml_dsa/ml_dsa_key.c b/crypto/ml_dsa/ml_dsa_key.c index 94f906a9fc1..c5ef15c6035 100644 --- a/crypto/ml_dsa/ml_dsa_key.c +++ b/crypto/ml_dsa/ml_dsa_key.c @@ -454,10 +454,6 @@ static int keygen_internal(ML_DSA_KEY *out) && ossl_ml_dsa_sk_encode(out); err: - if (out->seed != NULL && (out->prov_flags & ML_DSA_KEY_RETAIN_SEED) == 0) { - OPENSSL_clear_free(out->seed, ML_DSA_SEED_BYTES); - out->seed = NULL; - } EVP_MD_CTX_free(md_ctx); OPENSSL_cleanse(augmented_seed, sizeof(augmented_seed)); OPENSSL_cleanse(expanded_seed, sizeof(expanded_seed)); diff --git a/crypto/ml_kem/ml_kem.c b/crypto/ml_kem/ml_kem.c index f316aaa8121..ec76147331b 100644 --- a/crypto/ml_kem/ml_kem.c +++ b/crypto/ml_kem/ml_kem.c @@ -1418,14 +1418,9 @@ int genkey(const uint8_t seed[ML_KEM_SEED_BYTES], /* Save |z| portion of seed for "implicit rejection" on failure. */ memcpy(key->z, seed + ML_KEM_RANDOM_BYTES, ML_KEM_RANDOM_BYTES); - /* Optionally save the |d| portion of the seed */ + /* Save the |d| portion of the seed */ key->d = key->z + ML_KEM_RANDOM_BYTES; - if (key->prov_flags & ML_KEM_KEY_RETAIN_SEED) { - memcpy(key->d, seed, ML_KEM_RANDOM_BYTES); - } else { - OPENSSL_cleanse(key->d, ML_KEM_RANDOM_BYTES); - key->d = NULL; - } + memcpy(key->d, seed, ML_KEM_RANDOM_BYTES); ret = 1; end: diff --git a/doc/man7/EVP_PKEY-ML-DSA.pod b/doc/man7/EVP_PKEY-ML-DSA.pod index e87053b0a18..11498c161f7 100644 --- a/doc/man7/EVP_PKEY-ML-DSA.pod +++ b/doc/man7/EVP_PKEY-ML-DSA.pod @@ -53,6 +53,25 @@ ML-DSA hashing operations. Use L after calling L. +=head2 Encoder Parameters + +=over 4 + +=item "output_formats" (B) + +This parameter can be used with L +and L to select the preferred B output +formats of a private key. +When this parameter is either not specified or empty, the behaviour is +determined by the provider configuration parameters described below. +Otherwise, it has the same syntax and behaviour as the provider configuration +B parameter, except that the B +parameter is then ignored, i.e. the C and C formats +remain available so long as the seed was initially known, regardless of any +setting of B. + +=back + =head2 Common ML-DSA parameters In addition to the common parameters that all keytypes should support (see @@ -91,10 +110,10 @@ configuration options programmatically. =item C (B) When set to a string representing a false boolean value (see -L), the seed will not be retained after key -generation or key import from a seed value. -If the resulting key is then written to a PKCS#8 object, it will contain -only the FIPS 204 C key. +L), the seed will not be included when +keys are encoded to B form, unless the C encoder +parameter is set to a nonempty value, as described above. +The output B object will contain only the FIPS 204 C key. =item C (B) @@ -285,6 +304,8 @@ L, L, L, L, +L, +L, L, L, L @@ -292,6 +313,7 @@ L =head1 HISTORY This functionality was added in OpenSSL 3.5. +The C B parameter was added in OpenSSL 4.0. =head1 COPYRIGHT diff --git a/doc/man7/EVP_PKEY-ML-KEM.pod b/doc/man7/EVP_PKEY-ML-KEM.pod index be12a50ccff..d8bc67022db 100644 --- a/doc/man7/EVP_PKEY-ML-KEM.pod +++ b/doc/man7/EVP_PKEY-ML-KEM.pod @@ -53,11 +53,30 @@ Use L after calling L. =back +=head2 Encoder Parameters + +=over 4 + +=item "output_formats" (B) + +This parameter can be used with L +and L to select the preferred B output +formats of a private key. +When this parameter is either not specified or empty, the behaviour is +determined by the provider configuration parameters described below. +Otherwise, it has the same syntax and behaviour as the provider configuration +B parameter, except that the B +parameter is then ignored, i.e. the C and C formats +remain available so long as the seed was initially known, regardless of any +setting of B. + +=back + =head2 Common parameters In addition to the common parameters that all keytypes should support (see L), B keys -keys support the parameters listed below. +support the parameters listed below. These are gettable using L or L. They can be initialised via L, and are returned by @@ -122,10 +141,10 @@ Specifying any other value of the parameter, e.g. C, skips the test. =item C (B) When set to a string representing a false boolean value (see -L), the seed will not be retained after key -generation or key import from a seed value. -If the resulting key is then written to a PKCS#8 object, it will contain -only the FIPS 203 C key. +L), the seed will not be included when +keys are encoded to B form, unless the C encoder +parameter is set to a nonempty value, as described above. +The output B object will contain only the FIPS 203 C key. =item C (B) @@ -193,14 +212,14 @@ recognised on input. =item C: This format represents B objects in which the private key contains -the 64-byte FIPS 204 seed B<(d, z)> without any ASN.1 encapsulation. +the 64-byte FIPS 203 seed B<(d, z)> without any ASN.1 encapsulation. If the C format is not included in the list, this format will not be recognised on input. =item C: This format represents B objects in which the private key contains -the FIPS 204 decapsulation key B without any ASN.1 encapsulation. +the FIPS 203 decapsulation key B without any ASN.1 encapsulation. If the C format is not included in the list, this format will not be recognised on input. @@ -305,6 +324,8 @@ L, L, L, L, +L, +L, L, L, L @@ -312,6 +333,7 @@ L =head1 HISTORY This functionality was added in OpenSSL 3.5. +The C B parameter was added in OpenSSL 4.0. =head1 COPYRIGHT diff --git a/include/openssl/core_names.h.in b/include/openssl/core_names.h.in index 66f796c03a2..77e0e3f59a4 100644 --- a/include/openssl/core_names.h.in +++ b/include/openssl/core_names.h.in @@ -116,9 +116,6 @@ extern "C" { #define OSSL_KEM_PARAM_OPERATION_RSASVE "RSASVE" #define OSSL_KEM_PARAM_OPERATION_DHKEM "DHKEM" -/* Provider configuration variables */ -#define OSSL_PKEY_RETAIN_SEED "pkey_retain_seed" - /* Parameter name definitions - generated by util/perl/OpenSSL/paramnames.pm */ {- generate_public_macros(); -} diff --git a/providers/implementations/encode_decode/encode_key2any.c b/providers/implementations/encode_decode/encode_key2any.c index c9945a54829..c9a718694d8 100644 --- a/providers/implementations/encode_decode/encode_key2any.c +++ b/providers/implementations/encode_decode/encode_key2any.c @@ -59,6 +59,9 @@ typedef struct key2any_ctx_st { EVP_CIPHER *cipher; struct ossl_passphrase_data_st pwdata; + + /* Just-in-time ML-KEM and ML-DSA output format override */ + char *output_formats; } KEY2ANY_CTX; typedef int check_key_type_fn(const void *key, int nid); @@ -864,7 +867,8 @@ static int ml_dsa_pki_priv_to_der(const void *vkey, unsigned char **pder, { KEY2ANY_CTX *ctx = vctx; - return ossl_ml_dsa_i2d_prvkey(vkey, pder, ctx->provctx); + return ossl_ml_dsa_i2d_prvkey(vkey, pder, + ctx->provctx, ctx->output_formats); } # define ml_dsa_epki_priv_to_der ml_dsa_pki_priv_to_der @@ -894,7 +898,8 @@ static int ml_kem_pki_priv_to_der(const void *vkey, unsigned char **pder, { KEY2ANY_CTX *ctx = vctx; - return ossl_ml_kem_i2d_prvkey(vkey, pder, ctx->provctx); + return ossl_ml_kem_i2d_prvkey(vkey, pder, + ctx->provctx, ctx->output_formats); } # define ml_kem_epki_priv_to_der ml_kem_pki_priv_to_der @@ -1130,6 +1135,7 @@ static void key2any_freectx(void *vctx) ossl_pw_clear_passphrase_data(&ctx->pwdata); EVP_CIPHER_free(ctx->cipher); + OPENSSL_free(ctx->output_formats); OPENSSL_free(ctx); } @@ -1169,6 +1175,15 @@ static int key2any_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (p.svprm != NULL && !OSSL_PARAM_get_int(p.svprm, &ctx->save_parameters)) return 0; + if (p.output_formats != NULL) { + char *val = NULL; + + if (!OSSL_PARAM_get_utf8_string(p.output_formats, &val, 0)) + return 0; + OPENSSL_free(ctx->output_formats); + ctx->output_formats = *val != '\0' ? val : NULL; + } + return 1; } diff --git a/providers/implementations/encode_decode/encode_key2any.inc.in b/providers/implementations/encode_decode/encode_key2any.inc.in index 6fe9688d4ed..fe59f3072ec 100644 --- a/providers/implementations/encode_decode/encode_key2any.inc.in +++ b/providers/implementations/encode_decode/encode_key2any.inc.in @@ -12,7 +12,8 @@ use OpenSSL::paramnames qw(produce_param_decoder); -} {- produce_param_decoder('key2any_set_ctx_params', - (['OSSL_ENCODER_PARAM_CIPHER', 'cipher', 'utf8_string'], - ['OSSL_ENCODER_PARAM_PROPERTIES', 'propq', 'utf8_string'], - ['OSSL_ENCODER_PARAM_SAVE_PARAMETERS', 'svprm', 'int'], + (['OSSL_ENCODER_PARAM_CIPHER', 'cipher', 'utf8_string'], + ['OSSL_ENCODER_PARAM_PROPERTIES', 'propq', 'utf8_string'], + ['OSSL_ENCODER_PARAM_SAVE_PARAMETERS', 'svprm', 'int'], + ['OSSL_PKEY_PARAM_OUTPUT_FORMATS', 'output_formats', 'utf8_string'], )); -} diff --git a/providers/implementations/encode_decode/ml_dsa_codecs.c b/providers/implementations/encode_decode/ml_dsa_codecs.c index 7850c94e3ba..14474528b25 100644 --- a/providers/implementations/encode_decode/ml_dsa_codecs.c +++ b/providers/implementations/encode_decode/ml_dsa_codecs.c @@ -283,14 +283,13 @@ int ossl_ml_dsa_i2d_pubkey(const ML_DSA_KEY *key, unsigned char **out) /* Allocate and encode PKCS#8 private key payload. */ int ossl_ml_dsa_i2d_prvkey(const ML_DSA_KEY *key, uint8_t **out, - PROV_CTX *provctx) + PROV_CTX *provctx, const char *formats) { const ML_DSA_PARAMS *params = ossl_ml_dsa_key_params(key); const ML_COMMON_CODEC *codec; ML_COMMON_PKCS8_FMT_PREF *fmt_slots, *slot; const ML_COMMON_PKCS8_FMT *p8fmt; uint8_t *buf = NULL, *pos; - const char *formats; int len = ML_DSA_SEED_BYTES; int ret = 0; const uint8_t *seed = ossl_ml_dsa_key_get_seed(key); @@ -307,8 +306,13 @@ int ossl_ml_dsa_i2d_prvkey(const ML_DSA_KEY *key, uint8_t **out, return 0; } - formats = ossl_prov_ctx_get_param( - provctx, OSSL_PKEY_PARAM_ML_DSA_OUTPUT_FORMATS, NULL); + if (formats == NULL) { + if ((ossl_ml_dsa_key_get_prov_flags(key) & ML_DSA_KEY_RETAIN_SEED) == 0) + seed = NULL; + formats = ossl_prov_ctx_get_param(provctx, + OSSL_PKEY_PARAM_ML_DSA_OUTPUT_FORMATS, + NULL); + } fmt_slots = ossl_ml_common_pkcs8_fmt_order(params->alg, codec->p8fmt, "output", formats); if (fmt_slots == NULL) diff --git a/providers/implementations/encode_decode/ml_kem_codecs.c b/providers/implementations/encode_decode/ml_kem_codecs.c index bbc52aa10ca..6e007b44cfb 100644 --- a/providers/implementations/encode_decode/ml_kem_codecs.c +++ b/providers/implementations/encode_decode/ml_kem_codecs.c @@ -302,15 +302,15 @@ int ossl_ml_kem_i2d_pubkey(const ML_KEM_KEY *key, unsigned char **out) /* Allocate and encode PKCS#8 private key payload. */ int ossl_ml_kem_i2d_prvkey(const ML_KEM_KEY *key, uint8_t **out, - PROV_CTX *provctx) + PROV_CTX *provctx, const char *formats) { const ML_KEM_VINFO *v = key->vinfo; const ML_COMMON_CODEC *codec; ML_COMMON_PKCS8_FMT_PREF *fmt_slots, *slot; const ML_COMMON_PKCS8_FMT *p8fmt; uint8_t *buf = NULL, *pos; - const char *formats; int len = ML_KEM_SEED_BYTES; + int have_seed = ossl_ml_kem_have_seed(key); int ret = 0; /* Not ours to handle */ @@ -324,8 +324,13 @@ int ossl_ml_kem_i2d_prvkey(const ML_KEM_KEY *key, uint8_t **out, return 0; } - formats = ossl_prov_ctx_get_param( - provctx, OSSL_PKEY_PARAM_ML_KEM_OUTPUT_FORMATS, NULL); + if (formats == NULL) { + if ((key->prov_flags & ML_KEM_KEY_RETAIN_SEED) == 0) + have_seed = 0; + formats = ossl_prov_ctx_get_param(provctx, + OSSL_PKEY_PARAM_ML_KEM_OUTPUT_FORMATS, + NULL); + } fmt_slots = ossl_ml_common_pkcs8_fmt_order(v->algorithm_name, codec->p8fmt, "output", formats); if (fmt_slots == NULL) @@ -333,7 +338,7 @@ int ossl_ml_kem_i2d_prvkey(const ML_KEM_KEY *key, uint8_t **out, /* If we don't have a seed, skip seedful entries */ for (slot = fmt_slots; (p8fmt = slot->fmt) != NULL; ++slot) - if (ossl_ml_kem_have_seed(key) || p8fmt->seed_length == 0) + if (have_seed || p8fmt->seed_length == 0) break; /* No matching table entries, give up */ if (p8fmt == NULL diff --git a/providers/implementations/include/prov/ml_dsa_codecs.h b/providers/implementations/include/prov/ml_dsa_codecs.h index 722434baaee..34bde63fe94 100644 --- a/providers/implementations/include/prov/ml_dsa_codecs.h +++ b/providers/implementations/include/prov/ml_dsa_codecs.h @@ -33,7 +33,7 @@ int ossl_ml_dsa_i2d_pubkey(const ML_DSA_KEY *key, unsigned char **out); __owur __owur int ossl_ml_dsa_i2d_prvkey(const ML_DSA_KEY *key, unsigned char **out, - PROV_CTX *provctx); + PROV_CTX *provctx, const char *formats); # endif /* OPENSSL_NO_ML_DSA */ #endif /* PROV_ML_DSA_CODECS_H */ diff --git a/providers/implementations/include/prov/ml_kem_codecs.h b/providers/implementations/include/prov/ml_kem_codecs.h index 1a48c25ce39..406a46601b3 100644 --- a/providers/implementations/include/prov/ml_kem_codecs.h +++ b/providers/implementations/include/prov/ml_kem_codecs.h @@ -33,7 +33,7 @@ int ossl_ml_kem_i2d_pubkey(const ML_KEM_KEY *key, unsigned char **out); __owur __owur int ossl_ml_kem_i2d_prvkey(const ML_KEM_KEY *key, unsigned char **out, - PROV_CTX *provctx); + PROV_CTX *provctx, const char *formats); # endif /* OPENSSL_NO_ML_KEM */ #endif /* PROV_ML_KEM_CODECS_H */ diff --git a/test/evp_extra_test.c b/test/evp_extra_test.c index ec8179d7730..9ec90fc308f 100644 --- a/test/evp_extra_test.c +++ b/test/evp_extra_test.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -737,6 +738,39 @@ static const unsigned char kExampleDHKeyDER[] = { # endif #endif +#ifndef OPENSSL_NO_ML_KEM +/* + * openssl genpkey -provparam ml-kem.output_formats=seed-only \ + * -algorithm ml-kem-512 -outform DER | + * xxd -i + */ +static const unsigned char kMLKEMSeedOnlyDER[] = { + 0x30, 0x54, 0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x04, 0x01, 0x04, 0x42, 0x80, 0x40, 0x21, 0xe4, + 0x30, 0x56, 0x08, 0x64, 0xd3, 0xd4, 0x37, 0x33, 0x1c, 0xe5, 0xc9, 0xd8, + 0x26, 0x10, 0x9b, 0x4d, 0x58, 0xb4, 0xe2, 0x57, 0x70, 0x0f, 0x28, 0xe2, + 0xd2, 0xa8, 0x6b, 0xb6, 0x2b, 0x85, 0x1b, 0x25, 0x39, 0x29, 0xca, 0x6d, + 0x9a, 0xf0, 0x11, 0x5d, 0xca, 0xf4, 0xf7, 0x9a, 0x50, 0x39, 0xa7, 0x52, + 0x39, 0x5d, 0x84, 0xa9, 0xb9, 0x84, 0x4c, 0xa2, 0xe5, 0x49, 0xd7, 0x81, + 0xd1, 0x6d +}; +#endif + +#ifndef OPENSSL_NO_ML_DSA +/* + * openssl genpkey -provparam ml-dsa.output_formats=seed-only \ + * -algorithm ml-dsa-44 -outform DER | + * xxd -i + */ +static const unsigned char kMLDSASeedOnlyDER[] = { + 0x30, 0x34, 0x02, 0x01, 0x00, 0x30, 0x0b, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x03, 0x11, 0x04, 0x22, 0x80, 0x20, 0xc5, 0xbb, + 0x12, 0x9c, 0x76, 0xac, 0x6f, 0x03, 0x6c, 0x56, 0x32, 0xf4, 0x66, 0xb8, + 0x8c, 0x77, 0x4b, 0xe0, 0xaa, 0x4a, 0xd6, 0xa0, 0x96, 0x12, 0xc3, 0x8c, + 0xe7, 0x71, 0xbe, 0xf8, 0xba, 0xbe +}; +#endif + static const unsigned char kCFBDefaultKey[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C @@ -926,6 +960,140 @@ static EVP_PKEY *load_example_ec_key(void) } #endif +#if !defined(OPENSSL_NO_ML_KEM) || !defined(OPENSSL_NO_ML_DSA) +static EVP_PKEY *load_ml_key(const char *keytype, const char *input_type, + const unsigned char *data, size_t data_len) +{ + const unsigned char **pdata = &data; + EVP_PKEY *pkey = NULL; + OSSL_DECODER_CTX *dctx = + OSSL_DECODER_CTX_new_for_pkey(&pkey, input_type, "PrivateKeyInfo", + keytype, 0, testctx, testpropq); + + if (!TEST_ptr(dctx)) + return NULL; + /* |pkey| will be NULL on error */ + (void)OSSL_DECODER_from_data(dctx, pdata, &data_len); + OSSL_DECODER_CTX_free(dctx); + return pkey; +} + +static int +store_ml_key(EVP_PKEY *pkey, const char *input_type, const char *fmts, + const unsigned char *expect, size_t expectlen) +{ + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + OSSL_ENCODER_CTX *ectx = NULL; + unsigned char *buf = NULL, *der = NULL; + size_t len = 0; + long derlen; + int ret = 0; + + /* Just-in-time encoding format selection */ + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_OUTPUT_FORMATS, + (char *)fmts, 0); + + ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, EVP_PKEY_KEYPAIR, input_type, + "PrivateKeyInfo", testpropq); + if (!TEST_ptr(ectx)) + return 0; + if (!TEST_true(OSSL_ENCODER_CTX_set_params(ectx, params)) + || !TEST_true(OSSL_ENCODER_to_data(ectx, &buf, &len))) + goto end; + + if (strcmp(input_type, "PEM") == 0) { + BIO *pembio = BIO_new_mem_buf(buf, len); + char *name = NULL, *header = NULL; + + if (!TEST_ptr(pembio)) + goto end; + ret = PEM_read_bio(pembio, &name, &header, &der, &derlen); + BIO_free(pembio); + if (TEST_true(ret)) { + if (!TEST_int_eq(strcmp(name, PEM_STRING_PKCS8INF), 0) + || !TEST_true(header == NULL || *header == '\0')) + ret = 0; + OPENSSL_free(name); + OPENSSL_free(header); + if (!ret) + goto end; + } + } else { + der = buf; + derlen = len; + } + ret = expect != NULL ? + TEST_mem_eq(der, (size_t) derlen, expect, expectlen) : + TEST_size_t_eq((size_t) derlen, expectlen); + + end: + OSSL_ENCODER_CTX_free(ectx); + if (der != buf) + OPENSSL_free(der); + OPENSSL_free(buf); + return ret; +} + +static int test_ml_seed_only(int idx) +{ + const char *alg; + const unsigned char *seedonly; + EVP_PKEY *pkey = NULL; + size_t seedonlysz, privonlysz; + const char *outform = (idx & 1) ? "DER" : "PEM"; + int ret = 0; + + if (idx & 2) { +# ifndef OPENSSL_NO_ML_DSA + alg = "ML-DSA-44"; + seedonly = kMLDSASeedOnlyDER; + seedonlysz = sizeof(kMLDSASeedOnlyDER); + privonlysz = 2588; +# else + return 0; +# endif + } else { +# ifndef OPENSSL_NO_ML_KEM + alg = "ML-KEM-512"; + seedonly = kMLKEMSeedOnlyDER; + seedonlysz = sizeof(kMLKEMSeedOnlyDER); + privonlysz = 1660; +# else + return 0; +# endif + } + + pkey = load_ml_key(alg, "DER", seedonly, seedonlysz); + if (!TEST_ptr(pkey)) + return 0; + + /* + * Check that the "output_formats" parameter is behaving as expected. + * With "seed-only" check full payload, otherwise just the DER length. + */ + if (store_ml_key(pkey, outform, "seed-only", seedonly, seedonlysz) + && store_ml_key(pkey, outform, "bare-seed", NULL, seedonlysz - 2) + && store_ml_key(pkey, outform, "priv-only", NULL, privonlysz)) + ret = 1; + + EVP_PKEY_free(pkey); + return ret; +} +#endif + +#ifndef OPENSSL_NO_ML_KEM +static int test_ml_kem_seed_only(int idx) +{ + return test_ml_seed_only(idx); +} +#endif +#ifndef OPENSSL_NO_ML_DSA +static int test_ml_dsa_seed_only(int idx) +{ + return test_ml_seed_only(idx + 2); +} +#endif + #ifndef OPENSSL_NO_DEPRECATED_3_0 # ifndef OPENSSL_NO_DH static EVP_PKEY *load_example_dh_key(void) @@ -6910,6 +7078,13 @@ int setup_tests(void) ADD_TEST(test_evp_cipher_pipeline); +#ifndef OPENSSL_NO_ML_KEM + ADD_ALL_TESTS(test_ml_kem_seed_only, 2); +#endif +#ifndef OPENSSL_NO_ML_DSA + ADD_ALL_TESTS(test_ml_dsa_seed_only, 2); +#endif + return 1; } diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index b73863b9855..744edb10e36 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -307,6 +307,7 @@ my %params = ( 'OSSL_PKEY_PARAM_DIST_ID' => "distid", 'OSSL_PKEY_PARAM_PUB_KEY' => "pub", 'OSSL_PKEY_PARAM_PRIV_KEY' => "priv", + 'OSSL_PKEY_PARAM_OUTPUT_FORMATS' => "output_formats", # PKEY_PARAM_IMPLICIT_REJECTION isn't actually used, or meaningful. We keep # it for API stability, but please use ASYM_CIPHER_PARAM_IMPLICIT_REJECTION # instead.