From: Pauli Date: Wed, 18 Jun 2025 00:19:51 +0000 (+1000) Subject: ml-kem: update to use improved parameter handling X-Git-Tag: openssl-3.6.0-alpha1~583 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4fc06921b7f3a5e2fe4caf74dfae5df37fb7824f;p=thirdparty%2Fopenssl.git ml-kem: update to use improved parameter handling Reviewed-by: Shane Lontis Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/27847) --- diff --git a/providers/implementations/keymgmt/ml_kem_kmgmt.c.in b/providers/implementations/keymgmt/ml_kem_kmgmt.c.in index 21cc69acd15..19cd4639e92 100644 --- a/providers/implementations/keymgmt/ml_kem_kmgmt.c.in +++ b/providers/implementations/keymgmt/ml_kem_kmgmt.c.in @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ {- -use OpenSSL::paramnames qw(produce_param_list); +use OpenSSL::paramnames qw(produce_param_decoder); -} #include @@ -22,7 +22,6 @@ use OpenSSL::paramnames qw(produce_param_list); #include "crypto/ml_kem.h" #include "internal/fips.h" #include "internal/param_build_set.h" -#include "internal/param_names.h" #include "prov/implementations.h" #include "prov/providercommon.h" #include "prov/provider_ctx.h" @@ -329,19 +328,16 @@ err: return ret; } -/* Machine generated by util/perl/OpenSSL/paramnames.pm */ -{- produce_param_list('static', 'ml_kem_key_types', - 'static', 'ml_kem_key_types_find_pidx', - (['PKEY_PARAM_ML_KEM_SEED', 'octet_string'], - ['PKEY_PARAM_PRIV_KEY', 'octet_string'], - ['PKEY_PARAM_PUB_KEY', 'octet_string'], - )); -} -/* End of machine generated */ +{- produce_param_decoder('ml_kem_key_type_params', + (['PKEY_PARAM_ML_KEM_SEED', 'seed', 'octet_string'], + ['PKEY_PARAM_PRIV_KEY', 'privkey', 'octet_string'], + ['PKEY_PARAM_PUB_KEY', 'pubkey', 'octet_string'], + )); -} static const OSSL_PARAM *ml_kem_imexport_types(int selection) { if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) - return ml_kem_key_types; + return ml_kem_key_type_params_ettable; return NULL; } @@ -384,62 +380,53 @@ static int ml_kem_key_fromdata(ML_KEM_KEY *key, const OSSL_PARAM params[], int include_private) { - const OSSL_PARAM *p = NULL; const void *pubenc = NULL, *prvenc = NULL, *seedenc = NULL; size_t publen = 0, prvlen = 0, seedlen = 0, puboff; const ML_KEM_VINFO *v; + struct ml_kem_key_type_params_st p; /* Invalid attempt to mutate a key, what is the right error to report? */ if (key == NULL || ossl_ml_kem_have_pubkey(key)) return 0; v = ossl_ml_kem_key_vinfo(key); + p = ml_kem_key_type_params_decoder(params); /* * When a private key is provided, without a seed, any public key also * provided will be ignored (apart from length), just as with the seed. */ - for (p = params; p->key != NULL; p++) - switch (ml_kem_key_types_find_pidx(p->key)) { - default: - break; - - case PIDX_PKEY_PARAM_ML_KEM_SEED: - if (include_private) { - /* - * When a seed is provided, the private and public keys may be ignored, - * after validating just their lengths. Comparing encodings or hashes - * when applicable is possible, but not currently implemented. - */ - if (OSSL_PARAM_get_octet_string_ptr(p, &seedenc, &seedlen) != 1) - return 0; - if (seedlen != 0 && seedlen != ML_KEM_SEED_BYTES) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); - return 0; - } - } - break; - - case PIDX_PKEY_PARAM_PRIV_KEY: - if (include_private) { - if (OSSL_PARAM_get_octet_string_ptr(p, &prvenc, &prvlen) != 1) - return 0; - if (prvlen != 0 && prvlen != v->prvkey_bytes) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - } - break; - - /* Used only when no seed or private key is provided. */ - case PIDX_PKEY_PARAM_PUB_KEY: - if (OSSL_PARAM_get_octet_string_ptr(p, &pubenc, &publen) != 1) - return 0; - if (publen != 0 && publen != v->pubkey_bytes) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } - break; + if (p.seed != NULL && include_private) { + /* + * When a seed is provided, the private and public keys may be ignored, + * after validating just their lengths. Comparing encodings or hashes + * when applicable is possible, but not currently implemented. + */ + if (OSSL_PARAM_get_octet_string_ptr(p.seed, &seedenc, &seedlen) != 1) + return 0; + if (seedlen != 0 && seedlen != ML_KEM_SEED_BYTES) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_SEED_LENGTH); + return 0; } + } + + if (p.privkey != NULL && include_private) { + if (OSSL_PARAM_get_octet_string_ptr(p.privkey, &prvenc, &prvlen) != 1) + return 0; + if (prvlen != 0 && prvlen != v->prvkey_bytes) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + + /* Used only when no seed or private key is provided. */ + if (p.pubkey != NULL) { + if (OSSL_PARAM_get_octet_string_ptr(p.pubkey, &pubenc, &publen) != 1) + return 0; + if (publen != 0 && publen != v->pubkey_bytes) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } /* The caller MUST specify at least one of seed, private or public keys. */ if (seedlen == 0 && publen == 0 && prvlen == 0) { @@ -498,23 +485,20 @@ static int ml_kem_import(void *vkey, int selection, const OSSL_PARAM params[]) return res; } -/* Machine generated by util/perl/OpenSSL/paramnames.pm */ -{- produce_param_list('static', 'ml_kem_known_gettable_params', - 'static', 'ml_kem_get_params_find_pidx', - (['PKEY_PARAM_BITS', 'int'], - ['PKEY_PARAM_SECURITY_BITS', 'int'], - ['PKEY_PARAM_MAX_SIZE', 'int'], - ['PKEY_PARAM_SECURITY_CATEGORY', 'int'], - ['PKEY_PARAM_ML_KEM_SEED', 'octet_string'], - ['PKEY_PARAM_PRIV_KEY', 'octet_string'], - ['PKEY_PARAM_PUB_KEY', 'octet_string'], - ['PKEY_PARAM_ENCODED_PUBLIC_KEY', 'octet_string'], - )); -} -/* End of machine generated */ +{- produce_param_decoder('ml_kem_get_params', + (['PKEY_PARAM_BITS', 'bits', 'int'], + ['PKEY_PARAM_SECURITY_BITS', 'secbits', 'int'], + ['PKEY_PARAM_MAX_SIZE', 'maxsize', 'int'], + ['PKEY_PARAM_SECURITY_CATEGORY', 'seccat', 'int'], + ['PKEY_PARAM_ML_KEM_SEED', 'seed', 'octet_string'], + ['PKEY_PARAM_PRIV_KEY', 'privkey', 'octet_string'], + ['PKEY_PARAM_PUB_KEY', 'pubkey', 'octet_string'], + ['PKEY_PARAM_ENCODED_PUBLIC_KEY', 'encpubkey', 'octet_string'], + )); -} static const OSSL_PARAM *ml_kem_gettable_params(void *provctx) { - return ml_kem_known_gettable_params; + return ml_kem_get_params_ettable; } #ifndef FIPS_MODULE @@ -564,6 +548,21 @@ void *ml_kem_load(const void *reference, size_t reference_sz) } #endif +static int ml_kem_get_key_param(const ML_KEM_KEY *key, OSSL_PARAM *p, + size_t bytes, + int (*get_f)(uint8_t *out, size_t len, + const ML_KEM_KEY *key)) +{ + if (p->data_type != OSSL_PARAM_OCTET_STRING) + return 0; + p->return_size = bytes; + if (p->data != NULL) + if (p->data_size < p->return_size + || !(*get_f)(p->data, p->return_size, key)) + return 0; + return 1; +} + /* * It is assumed the key is guaranteed non-NULL here, and is from this provider */ @@ -571,113 +570,74 @@ static int ml_kem_get_params(void *vkey, OSSL_PARAM params[]) { ML_KEM_KEY *key = vkey; const ML_KEM_VINFO *v = ossl_ml_kem_key_vinfo(key); - OSSL_PARAM *p; - uint8_t *pubenc = NULL; - - for (p = params; p->key != NULL; p++) - switch (ml_kem_get_params_find_pidx(p->key)) { - default: - break; - - case PIDX_PKEY_PARAM_BITS: - if (!OSSL_PARAM_set_int(p, v->bits)) - return 0; - break; - - case PIDX_PKEY_PARAM_SECURITY_BITS: - if (!OSSL_PARAM_set_int(p, v->secbits)) - return 0; - break; - - case PIDX_PKEY_PARAM_MAX_SIZE: - if (!OSSL_PARAM_set_int(p, v->ctext_bytes)) - return 0; - break; - - case PIDX_PKEY_PARAM_SECURITY_CATEGORY: - if (!OSSL_PARAM_set_int(p, v->security_category)) - return 0; - break; + struct ml_kem_get_params_st p = ml_kem_get_params_decoder(params); + + if (p.bits != NULL && !OSSL_PARAM_set_int(p.bits, v->bits)) + return 0; + + if (p.secbits != NULL && !OSSL_PARAM_set_int(p.secbits, v->secbits)) + return 0; + + if (p.maxsize != NULL && !OSSL_PARAM_set_int(p.maxsize, v->ctext_bytes)) + return 0; + + if (p.seccat != NULL && !OSSL_PARAM_set_int(p.seccat, v->security_category)) + return 0; + if (p.pubkey != NULL && ossl_ml_kem_have_pubkey(key)) { /* Exported to EVP_PKEY_get_raw_public_key() */ - case PIDX_PKEY_PARAM_PUB_KEY: + if (!ml_kem_get_key_param(key, p.pubkey, v->pubkey_bytes, + &ossl_ml_kem_encode_public_key)) + return 0; + } + + if (p.encpubkey != NULL && ossl_ml_kem_have_pubkey(key)) { /* Needed by EVP_PKEY_get1_encoded_public_key() */ - case PIDX_PKEY_PARAM_ENCODED_PUBLIC_KEY: - if (ossl_ml_kem_have_pubkey(key)) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - p->return_size = v->pubkey_bytes; - if (p->data == NULL) - break; - if (p->data_size < p->return_size) - return 0; - if (pubenc != NULL) { - memcpy(p->data, pubenc, p->return_size); - break; - } - if (!ossl_ml_kem_encode_public_key(p->data, p->return_size, key)) - return 0; - pubenc = p->data; - } - break; + if (!ml_kem_get_key_param(key, p.encpubkey, v->pubkey_bytes, + &ossl_ml_kem_encode_public_key)) + return 0; + } + if (p.privkey != NULL && ossl_ml_kem_have_prvkey(key)) { /* Exported to EVP_PKEY_get_raw_private_key() */ - case PIDX_PKEY_PARAM_PRIV_KEY: - if (ossl_ml_kem_have_prvkey(key)) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - p->return_size = v->prvkey_bytes; - if (p->data != NULL) { - if (p->data_size < p->return_size) - return 0; - if (!ossl_ml_kem_encode_private_key(p->data, p->return_size, key)) - return 0; - } - } - break; + if (!ml_kem_get_key_param(key, p.privkey, v->prvkey_bytes, + &ossl_ml_kem_encode_private_key)) + return 0; + } + if (p.seed != NULL && ossl_ml_kem_have_seed(key)) { /* Exported for import */ - case PIDX_PKEY_PARAM_ML_KEM_SEED: - if (ossl_ml_kem_have_seed(key)) { - if (p->data_type != OSSL_PARAM_OCTET_STRING) - return 0; - p->return_size = ML_KEM_SEED_BYTES; - if (p->data != NULL) { - if (p->data_size < p->return_size) - return 0; - if (!ossl_ml_kem_encode_seed(p->data, p->return_size, key)) - return 0; - } - } - break; - } + if (!ml_kem_get_key_param(key, p.seed, ML_KEM_SEED_BYTES, + &ossl_ml_kem_encode_seed)) + return 0; + } return 1; } +{- produce_param_decoder('ml_kem_set_params', + (['PKEY_PARAM_ENCODED_PUBLIC_KEY', 'pub', 'octet_string'], + )); -} + static const OSSL_PARAM *ml_kem_settable_params(void *provctx) { - static const OSSL_PARAM arr[] = { - /* Used in TLS via EVP_PKEY_set1_encoded_public_key(). */ - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), - OSSL_PARAM_END - }; - - return arr; + return ml_kem_set_params_ettable; } static int ml_kem_set_params(void *vkey, const OSSL_PARAM params[]) { ML_KEM_KEY *key = vkey; - const OSSL_PARAM *p; const void *pubenc = NULL; size_t publen = 0; + struct ml_kem_set_params_st p; if (ossl_param_is_empty(params)) return 1; - p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); - if (p != NULL - && (OSSL_PARAM_get_octet_string_ptr(p, &pubenc, &publen) != 1 + p = ml_kem_set_params_decoder(params); + + /* Used in TLS via EVP_PKEY_set1_encoded_public_key(). */ + if (p.pub != NULL + && (OSSL_PARAM_get_octet_string_ptr(p.pub, &pubenc, &publen) != 1 || publen != key->vinfo->pubkey_bytes)) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY); return 0; @@ -697,31 +657,36 @@ static int ml_kem_set_params(void *vkey, const OSSL_PARAM params[]) return ossl_ml_kem_parse_public_key(pubenc, publen, key); } +{- produce_param_decoder('ml_kem_gen_set_params', + (['PKEY_PARAM_ML_DSA_SEED', 'seed', 'octet_string'], + ['PKEY_PARAM_PROPERTIES', 'propq', 'utf8_string'], + )); -} + static int ml_kem_gen_set_params(void *vgctx, const OSSL_PARAM params[]) { PROV_ML_KEM_GEN_CTX *gctx = vgctx; - const OSSL_PARAM *p; + struct ml_kem_gen_set_params_st p; if (gctx == NULL) return 0; if (ossl_param_is_empty(params)) return 1; - p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES); - if (p != NULL) { - if (p->data_type != OSSL_PARAM_UTF8_STRING) + p = ml_kem_gen_set_params_decoder(params); + + if (p.propq != NULL) { + if (p.propq->data_type != OSSL_PARAM_UTF8_STRING) return 0; OPENSSL_free(gctx->propq); - if ((gctx->propq = OPENSSL_strdup(p->data)) == NULL) + if ((gctx->propq = OPENSSL_strdup(p.propq->data)) == NULL) return 0; } - p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ML_KEM_SEED); - if (p != NULL) { + if (p.seed != NULL) { size_t len = ML_KEM_SEED_BYTES; gctx->seed = gctx->seedbuf; - if (OSSL_PARAM_get_octet_string(p, (void **)&gctx->seed, len, &len) + if (OSSL_PARAM_get_octet_string(p.seed, (void **)&gctx->seed, len, &len) && len == ML_KEM_SEED_BYTES) return 1; @@ -761,11 +726,7 @@ static void *ml_kem_gen_init(void *provctx, int selection, static const OSSL_PARAM *ml_kem_gen_settable_params(ossl_unused void *vgctx, ossl_unused void *provctx) { - static OSSL_PARAM settable[] = { - OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ML_KEM_SEED, NULL, 0), - OSSL_PARAM_END - }; - return settable; + return ml_kem_gen_set_params_ettable; } static void *ml_kem_gen(void *vgctx, OSSL_CALLBACK *osslcb, void *cbarg)