Commit c6c992b954 for openssl.org

commit c6c992b95406d4e597a57219f34db7d29afe6806
Author: Simo Sorce <simo@redhat.com>
Date:   Fri Feb 27 17:44:31 2026 -0500

    Generate FIPS parameter handling with Perl

    Replace the C preprocessor macros used for FIPS indicators and self-test
    parameters with a Perl-based code generation approach. This introduces
    `util/perl/OpenSSL/fipsparams.pm` and `providers/fips/fipsparams.inc.in`
    to generate the boilerplate code, simplifying `fipsprov.c` and reducing
    macro complexity.

    Co-authored-by: Gemini <gemini@google.com>
    Signed-off-by: Simo Sorce <simo@redhat.com>

    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
    Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
    (Merged from https://github.com/openssl/openssl/pull/30213)

diff --git a/.gitignore b/.gitignore
index 25ce225689..94610e62d6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -86,6 +86,7 @@ providers/common/include/prov/der_wrap.h
 providers/common/include/prov/der_sm2.h
 providers/common/include/prov/der_ml_dsa.h
 providers/common/include/prov/der_hkdf.h
+providers/fips/fipsparams.inc
 providers/implementations/asymciphers/rsa_enc.inc
 providers/implementations/asymciphers/sm2_enc.inc
 providers/implementations/exchange/dh_exch.inc
diff --git a/providers/fips/build.info b/providers/fips/build.info
index f6f38e9f41..895c5e9d99 100644
--- a/providers/fips/build.info
+++ b/providers/fips/build.info
@@ -4,3 +4,7 @@ SOURCE[../libfips.a]=fipsprov.c self_test.c self_test_data.c self_test_kats.c fi

 # It is necessary to have an explicit entry point
 SOURCE[../fips]=fips_entry.c
+
+DEPEND[]=fipsparams.inc
+DEPEND[fipsparams.inc]=../../util/perl|OpenSSL/fipsparams.pm
+GENERATE[fipsparams.inc]=fipsparams.inc.in
diff --git a/providers/fips/fipsparams.inc.in b/providers/fips/fipsparams.inc.in
new file mode 100644
index 0000000000..9127cd6f6c
--- /dev/null
+++ b/providers/fips/fipsparams.inc.in
@@ -0,0 +1,71 @@
+/*
+ * 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
+ */
+
+/*
+ * Handles the loading of FIPS algorithm conditional options from a config file
+ * passed from the core using OSSL_PARAM.
+ *
+ * The perl function generates code that:
+ *
+ * Creates fields in a structure for each item in the list using the first
+ * parameter as the base name.
+ *
+ * Creates a function to properly initialize each field based on the last
+ * parameter in each line.
+ *
+ * Creates a function to retrieve the values from the core.
+ *
+ * Creates a function to convert the retrieved string values to integer booleans.
+ *
+ * Creates getter functions for each parameter.
+ */
+{- use OpenSSL::fipsparams qw(produce_fips_indicators); -}
+{- produce_fips_indicators(
+        ['security_checks', 'OSSL_PROV_PARAM_SECURITY_CHECKS', '1'],
+        ['tls1_prf_ems_check', 'OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK', '0'],
+        ['no_short_mac', 'OSSL_PROV_PARAM_NO_SHORT_MAC', '1'],
+        ['hmac_key_check', 'OSSL_PROV_PARAM_HMAC_KEY_CHECK', '0'],
+        ['kmac_key_check', 'OSSL_PROV_PARAM_KMAC_KEY_CHECK', '0'],
+        ['restricted_drbg_digests', 'OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST', '0'],
+        ['signature_digest_check', 'OSSL_PROV_PARAM_SIGNATURE_DIGEST_CHECK', '0'],
+        ['hkdf_digest_check', 'OSSL_PROV_PARAM_HKDF_DIGEST_CHECK', '0'],
+        ['tls13_kdf_digest_check', 'OSSL_PROV_PARAM_TLS13_KDF_DIGEST_CHECK', '0'],
+        ['tls1_prf_digest_check', 'OSSL_PROV_PARAM_TLS1_PRF_DIGEST_CHECK', '0'],
+        ['sshkdf_digest_check', 'OSSL_PROV_PARAM_SSHKDF_DIGEST_CHECK', '0'],
+        ['sskdf_digest_check', 'OSSL_PROV_PARAM_SSKDF_DIGEST_CHECK', '0'],
+        ['x963kdf_digest_check', 'OSSL_PROV_PARAM_X963KDF_DIGEST_CHECK', '0'],
+        ['dsa_sign_disallowed', 'OSSL_PROV_PARAM_DSA_SIGN_DISABLED', '0'],
+        ['tdes_encrypt_disallowed', 'OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED', '0'],
+        ['rsa_pkcs15_padding_disabled', 'OSSL_PROV_PARAM_RSA_PKCS15_PAD_DISABLED', '0'],
+        ['rsa_pss_saltlen_check', 'OSSL_PROV_PARAM_RSA_PSS_SALTLEN_CHECK', '0'],
+        ['rsa_sign_x931_disallowed', 'OSSL_PROV_PARAM_RSA_SIGN_X931_PAD_DISABLED', '0'],
+        ['hkdf_key_check', 'OSSL_PROV_PARAM_HKDF_KEY_CHECK', '0'],
+        ['kbkdf_key_check', 'OSSL_PROV_PARAM_KBKDF_KEY_CHECK', '0'],
+        ['tls13_kdf_key_check', 'OSSL_PROV_PARAM_TLS13_KDF_KEY_CHECK', '0'],
+        ['tls1_prf_key_check', 'OSSL_PROV_PARAM_TLS1_PRF_KEY_CHECK', '0'],
+        ['sshkdf_key_check', 'OSSL_PROV_PARAM_SSHKDF_KEY_CHECK', '0'],
+        ['sskdf_key_check', 'OSSL_PROV_PARAM_SSKDF_KEY_CHECK', '0'],
+        ['x963kdf_key_check', 'OSSL_PROV_PARAM_X963KDF_KEY_CHECK', '0'],
+        ['x942kdf_key_check', 'OSSL_PROV_PARAM_X942KDF_KEY_CHECK', '0'],
+        ['pbkdf2_lower_bound_check', 'OSSL_PROV_PARAM_PBKDF2_LOWER_BOUND_CHECK', '1'],
+        ['ecdh_cofactor_check', 'OSSL_PROV_PARAM_ECDH_COFACTOR_CHECK', '0']) -}
+/*
+ * Handles the loading of FIPS self test parameters from the core using
+ * OSSL_PARAM.
+ *
+ * The perl function generates code that:
+ *
+ * Creates a function to retrieve the values from the core.
+ */
+{-use OpenSSL::fipsparams qw(produce_fips_selftest_params); -}
+{- produce_fips_selftest_params(
+        ['module_filename', 'OSSL_PROV_PARAM_CORE_MODULE_FILENAME'],
+        ['module_checksum_data', 'OSSL_PROV_FIPS_PARAM_MODULE_MAC'],
+        ['conditional_error_check', 'OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS'],
+        ['defer_tests', 'OSSL_PROV_FIPS_PARAM_DEFER_TESTS']) -}
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index 7ee38f837e..59509da631 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -94,24 +94,25 @@ typedef struct {
     unsigned char enabled;
 } FIPS_OPTION;

+typedef struct fips_global_st FIPS_GLOBAL;
+typedef struct fips_indicators_st FIPS_INDICATORS;
+static FIPS_INDICATORS *get_fips_indicators(FIPS_GLOBAL *fgbl);
+#include "fipsparams.inc"
+
 typedef struct fips_global_st {
     const OSSL_CORE_HANDLE *handle;
     SELF_TEST_POST_PARAMS selftest_params;

-#define OSSL_FIPS_PARAM(structname, paramname, initvalue) \
-    FIPS_OPTION fips_##structname;
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
+    FIPS_INDICATORS fips_indicators;

     /* Guards access to deferred self-test */
     CRYPTO_RWLOCK *deferred_lock;

 } FIPS_GLOBAL;

-static void init_fips_option(FIPS_OPTION *opt, int enabled)
+static inline FIPS_INDICATORS *get_fips_indicators(FIPS_GLOBAL *fgbl)
 {
-    opt->enabled = enabled;
-    opt->option = enabled ? "1" : "0";
+    return &fgbl->fips_indicators;
 }

 void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
@@ -121,10 +122,7 @@ void *ossl_fips_prov_ossl_ctx_new(OSSL_LIB_CTX *libctx)
     if (fgbl == NULL)
         return NULL;

-#define OSSL_FIPS_PARAM(structname, paramname, initvalue) \
-    init_fips_option(&fgbl->fips_##structname, initvalue);
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
+    init_fips_indicators(&fgbl->fips_indicators);

     return fgbl;
 }
@@ -159,23 +157,11 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
 {
     OSSL_PARAM core_params[33], *p = core_params;

-#define OSSL_FIPS_PARAM(structname, paramname)                 \
-    *p++ = OSSL_PARAM_construct_utf8_ptr(                      \
-        paramname, (char **)&fgbl->selftest_params.structname, \
-        sizeof(fgbl->selftest_params.structname));
-
-/* Parameters required for self testing */
-#include "fips_selftest_params.inc"
-#undef OSSL_FIPS_PARAM
+    /* Parameters required for self testing */
+    p = get_fips_selftest_params_from_core(p, &fgbl->selftest_params);

-/* FIPS indicator options can be enabled or disabled independently */
-#define OSSL_FIPS_PARAM(structname, paramname, initvalue) \
-    *p++ = OSSL_PARAM_construct_utf8_ptr(                 \
-        OSSL_PROV_PARAM_##paramname,                      \
-        (char **)&fgbl->fips_##structname.option,         \
-        sizeof(fgbl->fips_##structname.option));
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
+    /* FIPS indicator options can be enabled or disabled independently */
+    p = get_fips_indicator_params_from_core(p, &fgbl->fips_indicators);

     *p = OSSL_PARAM_construct_end();

@@ -184,7 +170,7 @@ static int fips_get_params_from_core(FIPS_GLOBAL *fgbl)
         return 0;
     }

-    return 1;
+    return set_fips_indicators_from_core(&fgbl->fips_indicators);
 }

 static const OSSL_PARAM *fips_gettable_params(void *provctx)
@@ -195,12 +181,7 @@ static const OSSL_PARAM *fips_gettable_params(void *provctx)
         OSSL_PARAM_DEFN(OSSL_PROV_PARAM_VERSION, OSSL_PARAM_UTF8_PTR, NULL, 0),
         OSSL_PARAM_DEFN(OSSL_PROV_PARAM_BUILDINFO, OSSL_PARAM_UTF8_PTR, NULL, 0),
         OSSL_PARAM_DEFN(OSSL_PROV_PARAM_STATUS, OSSL_PARAM_INTEGER, NULL, 0),
-
-#define OSSL_FIPS_PARAM(structname, paramname, initvalue) \
-    OSSL_PARAM_DEFN(OSSL_PROV_PARAM_##paramname, OSSL_PARAM_INTEGER, NULL, 0),
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
-
+        OSSL_FIPS_INDICATOR_PARAM_TYPES,
         OSSL_PARAM_END
     };
     return fips_param_types;
@@ -225,14 +206,7 @@ static int fips_get_params(void *provctx, OSSL_PARAM params[])
     if (p != NULL && !OSSL_PARAM_set_int(p, ossl_prov_is_running()))
         return 0;

-#define OSSL_FIPS_PARAM(structname, paramname, initvalue)                     \
-    p = OSSL_PARAM_locate(params, OSSL_PROV_PARAM_##paramname);               \
-    if (p != NULL && !OSSL_PARAM_set_int(p, fgbl->fips_##structname.enabled)) \
-        return 0;
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
-
-    return 1;
+    return get_fips_indicator_params(params, &fgbl->fips_indicators);
 }

 static void set_self_test_cb(FIPS_GLOBAL *fgbl)
@@ -1046,19 +1020,6 @@ int OSSL_provider_init_int(const OSSL_CORE_HANDLE *handle,
         && strcmp(fgbl->selftest_params.conditional_error_check, "0") == 0)
         SELF_TEST_disable_conditional_error_state();

-    /* Enable or disable FIPS provider options */
-#define OSSL_FIPS_PARAM(structname, paramname, unused)             \
-    if (fgbl->fips_##structname.option != NULL) {                  \
-        if (strcmp(fgbl->fips_##structname.option, "1") == 0)      \
-            fgbl->fips_##structname.enabled = 1;                   \
-        else if (strcmp(fgbl->fips_##structname.option, "0") == 0) \
-            fgbl->fips_##structname.enabled = 0;                   \
-        else                                                       \
-            goto err;                                              \
-    }
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
-
     ossl_prov_cache_exported_algorithms(fips_ciphers, exported_fips_ciphers);

     /* initialize deferred self-test infrastructure */
@@ -1264,16 +1225,6 @@ int BIO_snprintf(char *buf, size_t n, const char *format, ...)
     return ret;
 }

-#define OSSL_FIPS_PARAM(structname, paramname, unused)                                   \
-    int ossl_fips_config_##structname(OSSL_LIB_CTX *libctx)                              \
-    {                                                                                    \
-        FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX); \
-                                                                                         \
-        return fgbl->fips_##structname.enabled;                                          \
-    }
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
-
 void OSSL_SELF_TEST_get_callback(OSSL_LIB_CTX *libctx, OSSL_CALLBACK **cb,
     void **cbarg)
 {
diff --git a/providers/fips/include/fips_indicator_params.inc b/providers/fips/include/fips_indicator_params.inc
deleted file mode 100644
index 78f9fc0655..0000000000
--- a/providers/fips/include/fips_indicator_params.inc
+++ /dev/null
@@ -1,28 +0,0 @@
-OSSL_FIPS_PARAM(security_checks, SECURITY_CHECKS, 1)
-OSSL_FIPS_PARAM(tls1_prf_ems_check, TLS1_PRF_EMS_CHECK, 0)
-OSSL_FIPS_PARAM(no_short_mac, NO_SHORT_MAC, 1)
-OSSL_FIPS_PARAM(hmac_key_check, HMAC_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(kmac_key_check, KMAC_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(restricted_drbg_digests, DRBG_TRUNC_DIGEST, 0)
-OSSL_FIPS_PARAM(signature_digest_check, SIGNATURE_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(hkdf_digest_check, HKDF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(tls13_kdf_digest_check, TLS13_KDF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(tls1_prf_digest_check, TLS1_PRF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(sshkdf_digest_check, SSHKDF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(sskdf_digest_check, SSKDF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(x963kdf_digest_check, X963KDF_DIGEST_CHECK, 0)
-OSSL_FIPS_PARAM(dsa_sign_disallowed, DSA_SIGN_DISABLED, 0)
-OSSL_FIPS_PARAM(tdes_encrypt_disallowed, TDES_ENCRYPT_DISABLED, 0)
-OSSL_FIPS_PARAM(rsa_pkcs15_padding_disabled, RSA_PKCS15_PAD_DISABLED, 0)
-OSSL_FIPS_PARAM(rsa_pss_saltlen_check, RSA_PSS_SALTLEN_CHECK, 0)
-OSSL_FIPS_PARAM(rsa_sign_x931_disallowed, RSA_SIGN_X931_PAD_DISABLED, 0)
-OSSL_FIPS_PARAM(hkdf_key_check, HKDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(kbkdf_key_check, KBKDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(tls13_kdf_key_check, TLS13_KDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(tls1_prf_key_check, TLS1_PRF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(sshkdf_key_check, SSHKDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(sskdf_key_check, SSKDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(x963kdf_key_check, X963KDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(x942kdf_key_check, X942KDF_KEY_CHECK, 0)
-OSSL_FIPS_PARAM(pbkdf2_lower_bound_check, PBKDF2_LOWER_BOUND_CHECK, 1)
-OSSL_FIPS_PARAM(ecdh_cofactor_check, ECDH_COFACTOR_CHECK, 0)
diff --git a/providers/fips/include/fips_selftest_params.inc b/providers/fips/include/fips_selftest_params.inc
deleted file mode 100644
index 170ebc4c71..0000000000
--- a/providers/fips/include/fips_selftest_params.inc
+++ /dev/null
@@ -1,4 +0,0 @@
-OSSL_FIPS_PARAM(module_filename, OSSL_PROV_PARAM_CORE_MODULE_FILENAME)
-OSSL_FIPS_PARAM(module_checksum_data, OSSL_PROV_FIPS_PARAM_MODULE_MAC)
-OSSL_FIPS_PARAM(conditional_error_check, OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS)
-OSSL_FIPS_PARAM(defer_tests, OSSL_PROV_FIPS_PARAM_DEFER_TESTS)
diff --git a/providers/fips/include/fipscommon.h b/providers/fips/include/fipscommon.h
index c8df9a8ac4..ff73ea6d7d 100644
--- a/providers/fips/include/fipscommon.h
+++ b/providers/fips/include/fipscommon.h
@@ -10,9 +10,33 @@
 #ifdef FIPS_MODULE
 #include <openssl/types.h>

-#define OSSL_FIPS_PARAM(structname, paramname, unused) \
-    int ossl_fips_config_##structname(OSSL_LIB_CTX *libctx);
-#include "fips_indicator_params.inc"
-#undef OSSL_FIPS_PARAM
+int ossl_fips_config_security_checks(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tls1_prf_ems_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_no_short_mac(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_hmac_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_kmac_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_restricted_drbg_digests(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_signature_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_hkdf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tls13_kdf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tls1_prf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_sshkdf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_sskdf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_x963kdf_digest_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_dsa_sign_disallowed(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tdes_encrypt_disallowed(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_rsa_pkcs15_padding_disabled(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_rsa_pss_saltlen_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_rsa_sign_x931_disallowed(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_hkdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_kbkdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tls13_kdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_tls1_prf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_sshkdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_sskdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_x963kdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_x942kdf_key_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_pbkdf2_lower_bound_check(OSSL_LIB_CTX *libctx);
+int ossl_fips_config_ecdh_cofactor_check(OSSL_LIB_CTX *libctx);

 #endif
diff --git a/util/perl/OpenSSL/fipsparams.pm b/util/perl/OpenSSL/fipsparams.pm
new file mode 100644
index 0000000000..b6ea39707c
--- /dev/null
+++ b/util/perl/OpenSSL/fipsparams.pm
@@ -0,0 +1,135 @@
+#! /usr/bin/env perl
+# 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
+
+package OpenSSL::fipsparams;
+
+use strict;
+use warnings;
+use Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(produce_fips_indicators produce_fips_selftest_params);
+
+sub produce_fips_indicators {
+    my @params = @_;
+    my $s;
+    open(local *STDOUT, '>', \$s);
+
+    print "/* Machine generated by util/perl/OpenSSL/fipsparams.pm */\n";
+    print "\n";
+    print "typedef struct fips_indicators_st {\n";
+    foreach my $p (@params) {
+        printf "    const char *%s_string;\n", $p->[0];
+        printf "    unsigned char %s_enabled;\n", $p->[0];
+    }
+    print "} FIPS_INDICATORS;\n";
+
+    print "\n";
+    print "static void init_fips_indicators(FIPS_INDICATORS *indicators)\n";
+    print "{\n";
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        my $name = $p->[1];
+        my $enabled = $p->[2];
+        printf "    indicators->%s_string = \"%s\";\n", $field, $enabled;
+        printf "    indicators->%s_enabled = %s;\n", $field, $enabled;
+    }
+    print "}\n";
+
+    print "\n";
+    print "static OSSL_PARAM *get_fips_indicator_params_from_core(\n";
+    print "    OSSL_PARAM *op, FIPS_INDICATORS *fi)\n";
+    print "{\n";
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        my $name  = $p->[1];
+        print "    *op++ = OSSL_PARAM_construct_utf8_ptr(\n";
+        printf "        $name, (char **)&fi->%s_string,\n", $field;
+        printf "        sizeof(fi->%s_string));\n", $field;
+    }
+    print "    return op;\n";
+    print "}\n";
+
+    print "\n";
+    print "#define OSSL_FIPS_INDICATOR_PARAM_TYPES \\\n";
+    my $cnt = 0;
+    foreach my $p (@params) {
+        my $name  = $p->[1];
+        print "    OSSL_PARAM_DEFN($name, OSSL_PARAM_INTEGER, NULL, 0)";
+        print "," if ($cnt++ < $#params);
+        print "\\\n";
+    }
+    print "\n";
+
+    print "\n";
+    print "static int get_fips_indicator_params(OSSL_PARAM *params, FIPS_INDICATORS *fi)\n";
+    print "{\n";
+    print "    OSSL_PARAM *p;\n";
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        my $name  = $p->[1];
+        print "    p = OSSL_PARAM_locate(params, $name);\n";
+        printf "    if (p != NULL && !OSSL_PARAM_set_int(p, fi->%s_enabled))\n", $field;
+        print "        return 0;\n";
+    }
+    print "    return 1;\n";
+    print "}\n";
+
+    print "\n";
+    print "static int set_fips_indicators_from_core(FIPS_INDICATORS *fi)\n";
+    print "{\n";
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        printf "    if (fi->%s_string != NULL) {\n", $field;
+        printf "        if (strcmp(fi->%s_string, \"1\") == 0)\n", $field;
+        printf "            fi->%s_enabled = 1;\n", $field;
+        printf "        else if (strcmp(fi->%s_string, \"0\") == 0)\n", $field;
+        printf "            fi->%s_enabled = 0;\n", $field;
+        print "        else\n";
+        print "            return 0;\n";
+        print "    }\n";
+    }
+    print "    return 1;\n";
+    print "}\n";
+
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        print "\n";
+        printf "int ossl_fips_config_%s(OSSL_LIB_CTX *libctx)\n", $field;
+        print "{\n";
+        print "    FIPS_GLOBAL *fgbl = ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_FIPS_PROV_INDEX);\n";
+        print "    FIPS_INDICATORS *indicators = get_fips_indicators(fgbl);\n";
+        printf "    return indicators->%s_enabled;\n", $field;
+        print "}\n";
+    }
+
+    return $s;
+}
+
+sub produce_fips_selftest_params {
+    my @params = @_;
+    my $s;
+    open(local *STDOUT, '>', \$s);
+
+    print "/* Machine generated by util/perl/OpenSSL/fipsparams.pm */\n";
+
+    print "static OSSL_PARAM *get_fips_selftest_params_from_core(\n";
+    print "    OSSL_PARAM *op, SELF_TEST_POST_PARAMS *stpp)\n";
+    print "{\n";
+    foreach my $p (@params) {
+        my $field = $p->[0];
+        my $name  = $p->[1];
+        print "    *op++ = OSSL_PARAM_construct_utf8_ptr(\n";
+        print "        $name, (char **)&stpp->$field,\n";
+        print "        sizeof(stpp->$field));\n";
+    }
+    print "    return op;\n";
+    print "}\n";
+
+    return $s;
+}