Commit 5b70427d03 for openssl.org
commit 5b70427d031f71754097346c321bf6c7adebb58f
Author: Pauli <paul.dale@oracle.com>
Date: Wed Jul 8 13:57:34 2026 +1000
rsa: define generated parameter tries
Assisted-by: ChatGPT:gpt-5.6Sol
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Mounir Idrassi <mounir.idrassi@idrix.fr>
(Merged from https://github.com/openssl/openssl/pull/32502)
diff --git a/.gitignore b/.gitignore
index 9122acd77e..d9eb14a8bb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@
# Auto generated headers
/crypto/buildinf.h
/include/crypto/*_conf.h
+/include/crypto/rsa_params.h
/include/openssl/asn1.h
/include/openssl/asn1t.h
/include/openssl/bio.h
diff --git a/build.info b/build.info
index d7982a9553..cb30708f5f 100644
--- a/build.info
+++ b/build.info
@@ -45,6 +45,7 @@ DEPEND[]=include/openssl/asn1.h \
include/openssl/x509_acert.h \
include/openssl/x509_vfy.h \
include/crypto/dso_conf.h \
+ include/crypto/rsa_params.h \
providers/implementations/asymciphers/rsa_enc.inc \
providers/implementations/asymciphers/sm2_enc.inc \
providers/implementations/exchange/dh_exch.inc \
@@ -262,8 +263,11 @@ DEPEND[providers/implementations/asymciphers/rsa_enc.inc \
providers/implementations/rands/seed_src.inc \
providers/implementations/rands/seed_src_jitter.inc \
providers/implementations/rands/test_rng.inc \
+ include/crypto/rsa_params.h \
include/openssl/core_names.h]=util/perl|OpenSSL/paramnames.pm
+GENERATE[include/crypto/rsa_params.h]=\
+ include/crypto/rsa_params.h.in
GENERATE[providers/implementations/asymciphers/rsa_enc.inc]=\
providers/implementations/asymciphers/rsa_enc.inc.in
GENERATE[providers/implementations/asymciphers/sm2_enc.inc]=\
diff --git a/include/crypto/rsa.h b/include/crypto/rsa.h
index 0b853f9a80..a57702aa1d 100644
--- a/include/crypto/rsa.h
+++ b/include/crypto/rsa.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2019-2025 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2019-2026 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
@@ -17,6 +17,58 @@
#define RSA_MIN_MODULUS_BITS 512
+#ifdef FIPS_MODULE
+#define OSSL_RSA_PARAM_MAX_PRIMES 2
+#else
+#define OSSL_RSA_PARAM_MAX_PRIMES 10
+#endif
+
+typedef struct rsa_params_st {
+ OSSL_PARAM *n;
+ OSSL_PARAM *e;
+ OSSL_PARAM *d;
+ OSSL_PARAM *a;
+ OSSL_PARAM *b;
+ OSSL_PARAM *bits;
+ OSSL_PARAM *secbits;
+ OSSL_PARAM *maxsize;
+ OSSL_PARAM *seccat;
+ OSSL_PARAM *default_digest;
+ OSSL_PARAM *mandatory_digest;
+
+ /* PSS specific params */
+ OSSL_PARAM *digest;
+ OSSL_PARAM *digest_props;
+ OSSL_PARAM *maskgenfunc;
+ OSSL_PARAM *mgf1_digest;
+ OSSL_PARAM *pss_saltlen;
+
+ /* import specific params */
+ OSSL_PARAM *derive;
+
+#ifdef FIPS_MODULE
+ struct {
+ OSSL_PARAM *xp;
+ OSSL_PARAM *xp1;
+ OSSL_PARAM *xp2;
+ OSSL_PARAM *xq;
+ OSSL_PARAM *xq1;
+ OSSL_PARAM *xq2;
+ OSSL_PARAM *p1;
+ OSSL_PARAM *p2;
+ OSSL_PARAM *q1;
+ OSSL_PARAM *q2;
+ } fips;
+#endif
+
+ OSSL_PARAM *primes;
+ struct {
+ OSSL_PARAM *factors[OSSL_RSA_PARAM_MAX_PRIMES];
+ OSSL_PARAM *exps[OSSL_RSA_PARAM_MAX_PRIMES];
+ OSSL_PARAM *coeffs[OSSL_RSA_PARAM_MAX_PRIMES - 1];
+ } mp;
+} RSA_PARAMS;
+
typedef struct rsa_pss_params_30_st {
int hash_algorithm_nid;
struct {
@@ -73,13 +125,19 @@ RSA *ossl_rsa_dup(const RSA *rsa, int selection);
int ossl_rsa_todata(RSA *rsa, OSSL_PARAM_BLD *bld, OSSL_PARAM params[],
int include_private);
+int ossl_rsa_todata_parsed(RSA *rsa, OSSL_PARAM_BLD *bld,
+ const RSA_PARAMS *params, int include_private);
int ossl_rsa_fromdata(RSA *rsa, const OSSL_PARAM params[], int include_private);
+int ossl_rsa_fromdata_parsed(RSA *rsa, const RSA_PARAMS *params,
+ int include_private);
int ossl_rsa_pss_params_30_todata(const RSA_PSS_PARAMS_30 *pss,
OSSL_PARAM_BLD *bld, OSSL_PARAM params[]);
+int ossl_rsa_pss_params_30_todata_parsed(const RSA_PSS_PARAMS_30 *pss,
+ OSSL_PARAM_BLD *bld, const RSA_PARAMS *params);
int ossl_rsa_pss_params_30_fromdata(RSA_PSS_PARAMS_30 *pss_params,
- int *defaults_set,
- const OSSL_PARAM params[],
- OSSL_LIB_CTX *libctx);
+ int *defaults_set, const OSSL_PARAM params[], OSSL_LIB_CTX *libctx);
+int ossl_rsa_pss_params_30_fromdata_parsed(RSA_PSS_PARAMS_30 *pss_params,
+ int *defaults_set, const RSA_PARAMS *params, OSSL_LIB_CTX *libctx);
int ossl_rsa_set0_pss_params(RSA *r, RSA_PSS_PARAMS *pss);
int ossl_rsa_pss_get_param_unverified(const RSA_PSS_PARAMS *pss,
const EVP_MD **pmd, const EVP_MD **pmgf1md,
@@ -130,10 +188,13 @@ int ossl_rsa_generate_multi_prime_key(RSA *rsa, int bits, int primes,
#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS)
int ossl_rsa_acvp_test_gen_params_new(OSSL_PARAM **dst, const OSSL_PARAM src[]);
+int ossl_rsa_acvp_test_gen_params_new_parsed(OSSL_PARAM **dst,
+ const RSA_PARAMS *params);
void ossl_rsa_acvp_test_gen_params_free(OSSL_PARAM *dst);
int ossl_rsa_acvp_test_set_params(RSA *r, const OSSL_PARAM params[]);
int ossl_rsa_acvp_test_get_params(RSA *r, OSSL_PARAM params[]);
+int ossl_rsa_acvp_test_get_params_parsed(RSA *r, const RSA_PARAMS *params);
typedef struct rsa_acvp_test_st RSA_ACVP_TEST;
void ossl_rsa_acvp_test_free(RSA_ACVP_TEST *t);
#else
diff --git a/include/crypto/rsa_params.h.in b/include/crypto/rsa_params.h.in
new file mode 100644
index 0000000000..10188299df
--- /dev/null
+++ b/include/crypto/rsa_params.h.in
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2026 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
+ */
+
+{-
+use OpenSSL::paramnames qw(produce_param_decoder);
+-}
+
+#include "crypto/rsa.h"
+#include <openssl/err.h>
+#include <openssl/proverr.h>
+
+{-
+our @RSA_KEY_MP_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_FACTOR1', 'mp.factors[0]', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR2', 'mp.factors[1]', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR3', 'mp.factors[2]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR4', 'mp.factors[3]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR5', 'mp.factors[4]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR6', 'mp.factors[5]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR7', 'mp.factors[6]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR8', 'mp.factors[7]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR9', 'mp.factors[8]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_FACTOR10', 'mp.factors[9]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT1', 'mp.exps[0]', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT2', 'mp.exps[1]', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT3', 'mp.exps[2]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT4', 'mp.exps[3]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT5', 'mp.exps[4]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT6', 'mp.exps[5]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT7', 'mp.exps[6]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT8', 'mp.exps[7]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT9', 'mp.exps[8]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_EXPONENT10', 'mp.exps[9]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT1', 'mp.coeffs[0]', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT2', 'mp.coeffs[1]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT3', 'mp.coeffs[2]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT4', 'mp.coeffs[3]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT5', 'mp.coeffs[4]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT6', 'mp.coeffs[5]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT7', 'mp.coeffs[6]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT8', 'mp.coeffs[7]', 'BN', '!fips'],
+ ['OSSL_PKEY_PARAM_RSA_COEFFICIENT9', 'mp.coeffs[8]', 'BN', '!fips'],
+);
+
+our @RSA_KEY_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_N', 'n', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_E', 'e', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_D', 'd', 'BN'],
+ @RSA_KEY_MP_TYPES
+);
+
+our @RSA_PSS_IMPORT_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_DIGEST', 'digest', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_DIGEST_PROPS', 'digest_props', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_MASKGENFUNC', 'maskgenfunc', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_MGF1_DIGEST', 'mgf1_digest', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_PSS_SALTLEN', 'pss_saltlen', 'int'],
+);
+
+our @RSA_PSS_EXPORT_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_DIGEST', 'digest', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_MASKGENFUNC', 'maskgenfunc', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_MGF1_DIGEST', 'mgf1_digest', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_RSA_PSS_SALTLEN', 'pss_saltlen', 'int'],
+);
+
+our @RSA_GEN_BASIC_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_BITS', 'bits', 'size_t'],
+ ['OSSL_PKEY_PARAM_RSA_PRIMES', 'primes', 'size_t'],
+ ['OSSL_PKEY_PARAM_RSA_E', 'e', 'BN'],
+ ['OSSL_PKEY_PARAM_RSA_A', 'a', 'uint32'],
+ ['OSSL_PKEY_PARAM_RSA_B', 'b', 'uint32'],
+);
+
+our @RSA_ACVP_INPUT_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_TEST_XP', 'fips.xp', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_XP1', 'fips.xp1', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_XP2', 'fips.xp2', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_XQ', 'fips.xq', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_XQ1', 'fips.xq1', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_XQ2', 'fips.xq2', 'BN', 'fips'],
+);
+
+our @RSA_ACVP_OUTPUT_TYPES = (
+ ['OSSL_PKEY_PARAM_RSA_TEST_P1', 'fips.p1', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_P2', 'fips.p2', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_Q1', 'fips.q1', 'BN', 'fips'],
+ ['OSSL_PKEY_PARAM_RSA_TEST_Q2', 'fips.q2', 'BN', 'fips'],
+);
+
+return "";
+-}
+
+/* Key component parsing used by the public compatibility wrappers. */
+#define rsa_key_fromdata_st rsa_params_st
+{- produce_param_decoder('rsa_key_fromdata',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int']
+ )); -}
+
+#define rsa_key_todata_st rsa_params_st
+{- produce_param_decoder('rsa_key_todata',
+ (@RSA_KEY_TYPES, @RSA_ACVP_OUTPUT_TYPES)); -}
+
+#define rsa_pss_fromdata_st rsa_params_st
+{- produce_param_decoder('rsa_pss_fromdata', @RSA_PSS_IMPORT_TYPES); -}
+
+#define rsa_pss_todata_st rsa_params_st
+{- produce_param_decoder('rsa_pss_todata', @RSA_PSS_EXPORT_TYPES); -}
+
+/* The provider keymgmt import path parses its input only once. */
+#define rsa_import_st rsa_params_st
+{- produce_param_decoder('rsa_import',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int'],
+ @RSA_PSS_IMPORT_TYPES
+ )); -}
+
+/* Parameters processed by rsa_get_params(), including conditional ACVP data. */
+#define rsa_get_params_st rsa_params_st
+{- produce_param_decoder('rsa_get_params',
+ (['OSSL_PKEY_PARAM_BITS', 'bits', 'int'],
+ ['OSSL_PKEY_PARAM_SECURITY_BITS', 'secbits', 'int'],
+ ['OSSL_PKEY_PARAM_MAX_SIZE', 'maxsize', 'int'],
+ ['OSSL_PKEY_PARAM_SECURITY_CATEGORY', 'seccat', 'int'],
+ ['OSSL_PKEY_PARAM_DEFAULT_DIGEST', 'default_digest', 'utf8_string'],
+ ['OSSL_PKEY_PARAM_MANDATORY_DIGEST', 'mandatory_digest', 'utf8_string'],
+ @RSA_KEY_TYPES,
+ @RSA_PSS_EXPORT_TYPES,
+ @RSA_ACVP_OUTPUT_TYPES
+ )); -}
+
+/* Plain RSA generation parameters. */
+#define rsa_gen_set_params_st rsa_params_st
+{- produce_param_decoder('rsa_gen_set_params',
+ (@RSA_GEN_BASIC_TYPES,
+ @RSA_ACVP_INPUT_TYPES
+ )); -}
+
+#define rsapss_gen_set_params_st rsa_params_st
+{- produce_param_decoder('rsapss_gen_set_params',
+ (@RSA_GEN_BASIC_TYPES,
+ @RSA_PSS_IMPORT_TYPES,
+ @RSA_ACVP_INPUT_TYPES
+ )); -}
+
+/* Legacy EVP_PKEY import-from callbacks retain their existing signatures. */
+#define rsa_pkey_import_from_st rsa_params_st
+{- produce_param_decoder('rsa_pkey_import_from',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int'],
+ @RSA_PSS_IMPORT_TYPES
+ )); -}
+
+#define rsa_pss_pkey_import_from_st rsa_params_st
+{- produce_param_decoder('rsa_pss_pkey_import_from',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int'],
+ @RSA_PSS_IMPORT_TYPES
+ )); -}
+
+/* FIPS ACVP helpers also use the generated trie. */
+#define rsa_acvp_input_st rsa_params_st
+{- produce_param_decoder('rsa_acvp_input', @RSA_ACVP_INPUT_TYPES); -}
+
+#define rsa_acvp_output_st rsa_params_st
+{- produce_param_decoder('rsa_acvp_output', @RSA_ACVP_OUTPUT_TYPES); -}
+
+/* Selection-specific import and export declarations. */
+#define rsa_key_import_types_st
+#define rsa_key_import_types_decoder
+{- produce_param_decoder('rsa_key_import_types',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int']
+ )); -}
+
+#define rsa_key_export_types_st
+#define rsa_key_export_types_decoder
+{- produce_param_decoder('rsa_key_export_types', @RSA_KEY_TYPES); -}
+
+#define rsa_other_import_types_st
+#define rsa_other_import_types_decoder
+{- produce_param_decoder('rsa_other_import_types', @RSA_PSS_IMPORT_TYPES); -}
+
+#define rsa_other_export_types_st
+#define rsa_other_export_types_decoder
+{- produce_param_decoder('rsa_other_export_types', @RSA_PSS_EXPORT_TYPES); -}
+
+#define rsa_all_import_types_st
+#define rsa_all_import_types_decoder
+{- produce_param_decoder('rsa_all_import_types',
+ (@RSA_KEY_TYPES,
+ ['OSSL_PKEY_PARAM_RSA_DERIVE_FROM_PQ', 'derive', 'int'],
+ @RSA_PSS_IMPORT_TYPES
+ )); -}
+
+#define rsa_all_export_types_st
+#define rsa_all_export_types_decoder
+{- produce_param_decoder('rsa_all_export_types',
+ (@RSA_KEY_TYPES, @RSA_PSS_EXPORT_TYPES)); -}