]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
ml-kem: update to use improved parameter handling
authorPauli <ppzgs1@gmail.com>
Wed, 18 Jun 2025 00:19:51 +0000 (10:19 +1000)
committerPauli <ppzgs1@gmail.com>
Thu, 19 Jun 2025 22:39:29 +0000 (08:39 +1000)
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/27847)

providers/implementations/keymgmt/ml_kem_kmgmt.c.in

index 21cc69acd153d429ff29e16fe41ea3fe78e30236..19cd4639e92ad01515fefdce52e89f3412482086 100644 (file)
@@ -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 <openssl/core_dispatch.h>
@@ -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)