Path: blob/main/crypto/openssl/apps/fipsinstall.c
103369 views
/*1* Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include <openssl/evp.h>10#include <openssl/err.h>11#include <openssl/provider.h>12#include <openssl/params.h>13#include <openssl/fips_names.h>14#include <openssl/core_names.h>15#include <openssl/self_test.h>16#include <openssl/fipskey.h>17#include "apps.h"18#include "progs.h"1920#define BUFSIZE 40962122/* Configuration file values */23#define VERSION_KEY "version"24#define VERSION_VAL "1"25#define INSTALL_STATUS_VAL "INSTALL_SELF_TEST_KATS_RUN"2627static OSSL_CALLBACK self_test_events;28static char *self_test_corrupt_desc = NULL;29static char *self_test_corrupt_type = NULL;30static int self_test_log = 1;31static int quiet = 0;3233typedef enum OPTION_choice {34OPT_COMMON,35OPT_IN,36OPT_OUT,37OPT_MODULE,38OPT_PEDANTIC,39OPT_PROV_NAME,40OPT_SECTION_NAME,41OPT_MAC_NAME,42OPT_MACOPT,43OPT_VERIFY,44OPT_NO_LOG,45OPT_CORRUPT_DESC,46OPT_CORRUPT_TYPE,47OPT_QUIET,48OPT_CONFIG,49OPT_NO_CONDITIONAL_ERRORS,50OPT_NO_SECURITY_CHECKS,51OPT_TLS_PRF_EMS_CHECK,52OPT_NO_SHORT_MAC,53OPT_DISALLOW_PKCS15_PADDING,54OPT_RSA_PSS_SALTLEN_CHECK,55OPT_DISALLOW_SIGNATURE_X931_PADDING,56OPT_HMAC_KEY_CHECK,57OPT_KMAC_KEY_CHECK,58OPT_DISALLOW_DRGB_TRUNC_DIGEST,59OPT_SIGNATURE_DIGEST_CHECK,60OPT_HKDF_DIGEST_CHECK,61OPT_TLS13_KDF_DIGEST_CHECK,62OPT_TLS1_PRF_DIGEST_CHECK,63OPT_SSHKDF_DIGEST_CHECK,64OPT_SSKDF_DIGEST_CHECK,65OPT_X963KDF_DIGEST_CHECK,66OPT_DISALLOW_DSA_SIGN,67OPT_DISALLOW_TDES_ENCRYPT,68OPT_HKDF_KEY_CHECK,69OPT_KBKDF_KEY_CHECK,70OPT_TLS13_KDF_KEY_CHECK,71OPT_TLS1_PRF_KEY_CHECK,72OPT_SSHKDF_KEY_CHECK,73OPT_SSKDF_KEY_CHECK,74OPT_X963KDF_KEY_CHECK,75OPT_X942KDF_KEY_CHECK,76OPT_NO_PBKDF2_LOWER_BOUND_CHECK,77OPT_ECDH_COFACTOR_CHECK,78OPT_SELF_TEST_ONLOAD,79OPT_SELF_TEST_ONINSTALL80} OPTION_CHOICE;8182const OPTIONS fipsinstall_options[] = {83OPT_SECTION("General"),84{ "help", OPT_HELP, '-', "Display this summary" },85{ "pedantic", OPT_PEDANTIC, '-', "Set options for strict FIPS compliance" },86{ "verify", OPT_VERIFY, '-',87"Verify a config file instead of generating one" },88{ "module", OPT_MODULE, '<', "File name of the provider module" },89{ "provider_name", OPT_PROV_NAME, 's', "FIPS provider name" },90{ "section_name", OPT_SECTION_NAME, 's',91"FIPS Provider config section name (optional)" },92{ "no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-',93"Disable the ability of the fips module to enter an error state if"94" any conditional self tests fail" },95{ "no_security_checks", OPT_NO_SECURITY_CHECKS, '-',96"Disable the run-time FIPS security checks in the module" },97{ "self_test_onload", OPT_SELF_TEST_ONLOAD, '-',98"Forces self tests to always run on module load" },99{ "self_test_oninstall", OPT_SELF_TEST_ONINSTALL, '-',100"Forces self tests to run once on module installation" },101{ "ems_check", OPT_TLS_PRF_EMS_CHECK, '-',102"Enable the run-time FIPS check for EMS during TLS1_PRF" },103{ "no_short_mac", OPT_NO_SHORT_MAC, '-', "Disallow short MAC output" },104{ "no_drbg_truncated_digests", OPT_DISALLOW_DRGB_TRUNC_DIGEST, '-',105"Disallow truncated digests with Hash and HMAC DRBGs" },106{ "signature_digest_check", OPT_SIGNATURE_DIGEST_CHECK, '-',107"Enable checking for approved digests for signatures" },108{ "hmac_key_check", OPT_HMAC_KEY_CHECK, '-', "Enable key check for HMAC" },109{ "kmac_key_check", OPT_KMAC_KEY_CHECK, '-', "Enable key check for KMAC" },110{ "hkdf_digest_check", OPT_HKDF_DIGEST_CHECK, '-',111"Enable digest check for HKDF" },112{ "tls13_kdf_digest_check", OPT_TLS13_KDF_DIGEST_CHECK, '-',113"Enable digest check for TLS13-KDF" },114{ "tls1_prf_digest_check", OPT_TLS1_PRF_DIGEST_CHECK, '-',115"Enable digest check for TLS1-PRF" },116{ "sshkdf_digest_check", OPT_SSHKDF_DIGEST_CHECK, '-',117"Enable digest check for SSHKDF" },118{ "sskdf_digest_check", OPT_SSKDF_DIGEST_CHECK, '-',119"Enable digest check for SSKDF" },120{ "x963kdf_digest_check", OPT_X963KDF_DIGEST_CHECK, '-',121"Enable digest check for X963KDF" },122{ "dsa_sign_disabled", OPT_DISALLOW_DSA_SIGN, '-',123"Disallow DSA signing" },124{ "tdes_encrypt_disabled", OPT_DISALLOW_TDES_ENCRYPT, '-',125"Disallow Triple-DES encryption" },126{ "rsa_pkcs15_padding_disabled", OPT_DISALLOW_PKCS15_PADDING, '-',127"Disallow PKCS#1 version 1.5 padding for RSA encryption" },128{ "rsa_pss_saltlen_check", OPT_RSA_PSS_SALTLEN_CHECK, '-',129"Enable salt length check for RSA-PSS signature operations" },130{ "rsa_sign_x931_disabled", OPT_DISALLOW_SIGNATURE_X931_PADDING, '-',131"Disallow X931 Padding for RSA signing" },132{ "hkdf_key_check", OPT_HKDF_KEY_CHECK, '-',133"Enable key check for HKDF" },134{ "kbkdf_key_check", OPT_KBKDF_KEY_CHECK, '-',135"Enable key check for KBKDF" },136{ "tls13_kdf_key_check", OPT_TLS13_KDF_KEY_CHECK, '-',137"Enable key check for TLS13-KDF" },138{ "tls1_prf_key_check", OPT_TLS1_PRF_KEY_CHECK, '-',139"Enable key check for TLS1-PRF" },140{ "sshkdf_key_check", OPT_SSHKDF_KEY_CHECK, '-',141"Enable key check for SSHKDF" },142{ "sskdf_key_check", OPT_SSKDF_KEY_CHECK, '-',143"Enable key check for SSKDF" },144{ "x963kdf_key_check", OPT_X963KDF_KEY_CHECK, '-',145"Enable key check for X963KDF" },146{ "x942kdf_key_check", OPT_X942KDF_KEY_CHECK, '-',147"Enable key check for X942KDF" },148{ "no_pbkdf2_lower_bound_check", OPT_NO_PBKDF2_LOWER_BOUND_CHECK, '-',149"Disable lower bound check for PBKDF2" },150{ "ecdh_cofactor_check", OPT_ECDH_COFACTOR_CHECK, '-',151"Enable Cofactor check for ECDH" },152OPT_SECTION("Input"),153{ "in", OPT_IN, '<', "Input config file, used when verifying" },154155OPT_SECTION("Output"),156{ "out", OPT_OUT, '>', "Output config file, used when generating" },157{ "mac_name", OPT_MAC_NAME, 's', "MAC name" },158{ "macopt", OPT_MACOPT, 's', "MAC algorithm parameters in n:v form." },159{ OPT_MORE_STR, 0, 0, "See 'PARAMETER NAMES' in the EVP_MAC_ docs" },160{ "noout", OPT_NO_LOG, '-', "Disable logging of self test events" },161{ "corrupt_desc", OPT_CORRUPT_DESC, 's', "Corrupt a self test by description" },162{ "corrupt_type", OPT_CORRUPT_TYPE, 's', "Corrupt a self test by type" },163{ "config", OPT_CONFIG, '<', "The parent config to verify" },164{ "quiet", OPT_QUIET, '-', "No messages, just exit status" },165{ NULL }166};167168typedef struct {169unsigned int self_test_onload : 1;170unsigned int conditional_errors : 1;171unsigned int security_checks : 1;172unsigned int hmac_key_check : 1;173unsigned int kmac_key_check : 1;174unsigned int tls_prf_ems_check : 1;175unsigned int no_short_mac : 1;176unsigned int drgb_no_trunc_dgst : 1;177unsigned int signature_digest_check : 1;178unsigned int hkdf_digest_check : 1;179unsigned int tls13_kdf_digest_check : 1;180unsigned int tls1_prf_digest_check : 1;181unsigned int sshkdf_digest_check : 1;182unsigned int sskdf_digest_check : 1;183unsigned int x963kdf_digest_check : 1;184unsigned int dsa_sign_disabled : 1;185unsigned int tdes_encrypt_disabled : 1;186unsigned int rsa_pkcs15_padding_disabled : 1;187unsigned int rsa_pss_saltlen_check : 1;188unsigned int sign_x931_padding_disabled : 1;189unsigned int hkdf_key_check : 1;190unsigned int kbkdf_key_check : 1;191unsigned int tls13_kdf_key_check : 1;192unsigned int tls1_prf_key_check : 1;193unsigned int sshkdf_key_check : 1;194unsigned int sskdf_key_check : 1;195unsigned int x963kdf_key_check : 1;196unsigned int x942kdf_key_check : 1;197unsigned int pbkdf2_lower_bound_check : 1;198unsigned int ecdh_cofactor_check : 1;199} FIPS_OPTS;200201/* Pedantic FIPS compliance */202static const FIPS_OPTS pedantic_opts = {2031, /* self_test_onload */2041, /* conditional_errors */2051, /* security_checks */2061, /* hmac_key_check */2071, /* kmac_key_check */2081, /* tls_prf_ems_check */2091, /* no_short_mac */2101, /* drgb_no_trunc_dgst */2111, /* signature_digest_check */2121, /* hkdf_digest_check */2131, /* tls13_kdf_digest_check */2141, /* tls1_prf_digest_check */2151, /* sshkdf_digest_check */2161, /* sskdf_digest_check */2171, /* x963kdf_digest_check */2181, /* dsa_sign_disabled */2191, /* tdes_encrypt_disabled */2201, /* rsa_pkcs15_padding_disabled */2211, /* rsa_pss_saltlen_check */2221, /* sign_x931_padding_disabled */2231, /* hkdf_key_check */2241, /* kbkdf_key_check */2251, /* tls13_kdf_key_check */2261, /* tls1_prf_key_check */2271, /* sshkdf_key_check */2281, /* sskdf_key_check */2291, /* x963kdf_key_check */2301, /* x942kdf_key_check */2311, /* pbkdf2_lower_bound_check */2321, /* ecdh_cofactor_check */233};234235/* Default FIPS settings for backward compatibility */236static FIPS_OPTS fips_opts = {2371, /* self_test_onload */2381, /* conditional_errors */2391, /* security_checks */2400, /* hmac_key_check */2410, /* kmac_key_check */2420, /* tls_prf_ems_check */2430, /* no_short_mac */2440, /* drgb_no_trunc_dgst */2450, /* signature_digest_check */2460, /* hkdf_digest_check */2470, /* tls13_kdf_digest_check */2480, /* tls1_prf_digest_check */2490, /* sshkdf_digest_check */2500, /* sskdf_digest_check */2510, /* x963kdf_digest_check */2520, /* dsa_sign_disabled */2530, /* tdes_encrypt_disabled */2540, /* rsa_pkcs15_padding_disabled */2550, /* rsa_pss_saltlen_check */2560, /* sign_x931_padding_disabled */2570, /* hkdf_key_check */2580, /* kbkdf_key_check */2590, /* tls13_kdf_key_check */2600, /* tls1_prf_key_check */2610, /* sshkdf_key_check */2620, /* sskdf_key_check */2630, /* x963kdf_key_check */2640, /* x942kdf_key_check */2651, /* pbkdf2_lower_bound_check */2660, /* ecdh_cofactor_check */267};268269static int check_non_pedantic_fips(int pedantic, const char *name)270{271if (pedantic) {272BIO_printf(bio_err, "Cannot specify -%s after -pedantic\n", name);273return 0;274}275return 1;276}277278static int do_mac(EVP_MAC_CTX *ctx, unsigned char *tmp, BIO *in,279unsigned char *out, size_t *out_len)280{281int ret = 0;282int i;283size_t outsz = *out_len;284285if (!EVP_MAC_init(ctx, NULL, 0, NULL))286goto err;287if (EVP_MAC_CTX_get_mac_size(ctx) > outsz)288goto end;289while ((i = BIO_read(in, (char *)tmp, BUFSIZE)) != 0) {290if (i < 0 || !EVP_MAC_update(ctx, tmp, i))291goto err;292}293end:294if (!EVP_MAC_final(ctx, out, out_len, outsz))295goto err;296ret = 1;297err:298return ret;299}300301static int load_fips_prov_and_run_self_test(const char *prov_name,302int *is_fips_140_2_prov)303{304int ret = 0;305OSSL_PROVIDER *prov = NULL;306OSSL_PARAM params[4], *p = params;307char *name = "", *vers = "", *build = "";308309prov = OSSL_PROVIDER_load(NULL, prov_name);310if (prov == NULL) {311BIO_printf(bio_err, "Failed to load FIPS module\n");312goto end;313}314if (!quiet) {315*p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_NAME,316&name, sizeof(name));317*p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,318&vers, sizeof(vers));319*p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_BUILDINFO,320&build, sizeof(build));321*p = OSSL_PARAM_construct_end();322if (!OSSL_PROVIDER_get_params(prov, params)) {323BIO_printf(bio_err, "Failed to query FIPS module parameters\n");324goto end;325}326if (OSSL_PARAM_modified(params))327BIO_printf(bio_err, "\t%-10s\t%s\n", "name:", name);328if (OSSL_PARAM_modified(params + 1))329BIO_printf(bio_err, "\t%-10s\t%s\n", "version:", vers);330if (OSSL_PARAM_modified(params + 2))331BIO_printf(bio_err, "\t%-10s\t%s\n", "build:", build);332} else {333*p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,334&vers, sizeof(vers));335*p = OSSL_PARAM_construct_end();336if (!OSSL_PROVIDER_get_params(prov, params)) {337BIO_printf(bio_err, "Failed to query FIPS module parameters\n");338goto end;339}340}341*is_fips_140_2_prov = (strncmp("3.0.", vers, 4) == 0);342ret = 1;343end:344OSSL_PROVIDER_unload(prov);345return ret;346}347348static int print_mac(BIO *bio, const char *label, const unsigned char *mac,349size_t len)350{351int ret;352char *hexstr = NULL;353354hexstr = OPENSSL_buf2hexstr(mac, (long)len);355if (hexstr == NULL)356return 0;357ret = BIO_printf(bio, "%s = %s\n", label, hexstr);358OPENSSL_free(hexstr);359return ret;360}361362static int write_config_header(BIO *out, const char *prov_name,363const char *section)364{365return BIO_printf(out, "openssl_conf = openssl_init\n\n")366&& BIO_printf(out, "[openssl_init]\n")367&& BIO_printf(out, "providers = provider_section\n\n")368&& BIO_printf(out, "[provider_section]\n")369&& BIO_printf(out, "%s = %s\n\n", prov_name, section);370}371372/*373* Outputs a fips related config file that contains entries for the fips374* module checksum, installation indicator checksum and the options375* conditional_errors and security_checks.376*377* Returns 1 if the config file is written otherwise it returns 0 on error.378*/379static int write_config_fips_section(BIO *out, const char *section,380unsigned char *module_mac,381size_t module_mac_len,382const FIPS_OPTS *opts,383unsigned char *install_mac,384size_t install_mac_len)385{386int ret = 0;387388if (BIO_printf(out, "[%s]\n", section) <= 0389|| BIO_printf(out, "activate = 1\n") <= 0390|| BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION,391VERSION_VAL)392<= 0393|| BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS,394opts->conditional_errors ? "1" : "0")395<= 0396|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SECURITY_CHECKS,397opts->security_checks ? "1" : "0")398<= 0399|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HMAC_KEY_CHECK,400opts->hmac_key_check ? "1" : "0")401<= 0402|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_KMAC_KEY_CHECK,403opts->kmac_key_check ? "1" : "0")404<= 0405|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TLS1_PRF_EMS_CHECK,406opts->tls_prf_ems_check ? "1" : "0")407<= 0408|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_NO_SHORT_MAC,409opts->no_short_mac ? "1" : "0")410<= 0411|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_DRBG_TRUNC_DIGEST,412opts->drgb_no_trunc_dgst ? "1" : "0")413<= 0414|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SIGNATURE_DIGEST_CHECK,415opts->signature_digest_check ? "1" : "0")416<= 0417|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HKDF_DIGEST_CHECK,418opts->hkdf_digest_check ? "1" : "0")419<= 0420|| BIO_printf(out, "%s = %s\n",421OSSL_PROV_PARAM_TLS13_KDF_DIGEST_CHECK,422opts->tls13_kdf_digest_check ? "1" : "0")423<= 0424|| BIO_printf(out, "%s = %s\n",425OSSL_PROV_PARAM_TLS1_PRF_DIGEST_CHECK,426opts->tls1_prf_digest_check ? "1" : "0")427<= 0428|| BIO_printf(out, "%s = %s\n",429OSSL_PROV_PARAM_SSHKDF_DIGEST_CHECK,430opts->sshkdf_digest_check ? "1" : "0")431<= 0432|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSKDF_DIGEST_CHECK,433opts->sskdf_digest_check ? "1" : "0")434<= 0435|| BIO_printf(out, "%s = %s\n",436OSSL_PROV_PARAM_X963KDF_DIGEST_CHECK,437opts->x963kdf_digest_check ? "1" : "0")438<= 0439|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_DSA_SIGN_DISABLED,440opts->dsa_sign_disabled ? "1" : "0")441<= 0442|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TDES_ENCRYPT_DISABLED,443opts->tdes_encrypt_disabled ? "1" : "0")444<= 0445|| BIO_printf(out, "%s = %s\n",446OSSL_PROV_PARAM_RSA_PKCS15_PAD_DISABLED,447opts->rsa_pkcs15_padding_disabled ? "1" : "0")448<= 0449|| BIO_printf(out, "%s = %s\n",450OSSL_PROV_PARAM_RSA_PSS_SALTLEN_CHECK,451opts->rsa_pss_saltlen_check ? "1" : "0")452<= 0453|| BIO_printf(out, "%s = %s\n",454OSSL_PROV_PARAM_RSA_SIGN_X931_PAD_DISABLED,455opts->sign_x931_padding_disabled ? "1" : "0")456<= 0457|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_HKDF_KEY_CHECK,458opts->hkdf_key_check ? "1" : "0")459<= 0460|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_KBKDF_KEY_CHECK,461opts->kbkdf_key_check ? "1" : "0")462<= 0463|| BIO_printf(out, "%s = %s\n",464OSSL_PROV_PARAM_TLS13_KDF_KEY_CHECK,465opts->tls13_kdf_key_check ? "1" : "0")466<= 0467|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_TLS1_PRF_KEY_CHECK,468opts->tls1_prf_key_check ? "1" : "0")469<= 0470|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSHKDF_KEY_CHECK,471opts->sshkdf_key_check ? "1" : "0")472<= 0473|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_SSKDF_KEY_CHECK,474opts->sskdf_key_check ? "1" : "0")475<= 0476|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X963KDF_KEY_CHECK,477opts->x963kdf_key_check ? "1" : "0")478<= 0479|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_X942KDF_KEY_CHECK,480opts->x942kdf_key_check ? "1" : "0")481<= 0482|| BIO_printf(out, "%s = %s\n",483OSSL_PROV_PARAM_PBKDF2_LOWER_BOUND_CHECK,484opts->pbkdf2_lower_bound_check ? "1" : "0")485<= 0486|| BIO_printf(out, "%s = %s\n", OSSL_PROV_PARAM_ECDH_COFACTOR_CHECK,487opts->ecdh_cofactor_check ? "1" : "0")488<= 0489|| !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac,490module_mac_len))491goto end;492493if (install_mac != NULL494&& install_mac_len > 0495&& opts->self_test_onload == 0) {496if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,497install_mac_len)498|| BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,499INSTALL_STATUS_VAL)500<= 0)501goto end;502}503ret = 1;504end:505return ret;506}507508static CONF *generate_config_and_load(const char *prov_name,509const char *section,510unsigned char *module_mac,511size_t module_mac_len,512const FIPS_OPTS *opts)513{514BIO *mem_bio = NULL;515CONF *conf = NULL;516517mem_bio = BIO_new(BIO_s_mem());518if (mem_bio == NULL)519return 0;520if (!write_config_header(mem_bio, prov_name, section)521|| !write_config_fips_section(mem_bio, section,522module_mac, module_mac_len,523opts, NULL, 0))524goto end;525526conf = app_load_config_bio(mem_bio, NULL);527if (conf == NULL)528goto end;529530if (CONF_modules_load(conf, NULL, 0) <= 0)531goto end;532BIO_free(mem_bio);533return conf;534end:535NCONF_free(conf);536BIO_free(mem_bio);537return NULL;538}539540static void free_config_and_unload(CONF *conf)541{542if (conf != NULL) {543NCONF_free(conf);544CONF_modules_unload(1);545}546}547548static int verify_module_load(const char *parent_config_file)549{550return OSSL_LIB_CTX_load_config(NULL, parent_config_file);551}552553/*554* Returns 1 if the config file entries match the passed in module_mac and555* install_mac values, otherwise it returns 0.556*/557static int verify_config(const char *infile, const char *section,558unsigned char *module_mac, size_t module_mac_len,559unsigned char *install_mac, size_t install_mac_len)560{561int ret = 0;562char *s = NULL;563unsigned char *buf1 = NULL, *buf2 = NULL;564long len;565CONF *conf = NULL;566567/* read in the existing values and check they match the saved values */568conf = app_load_config(infile);569if (conf == NULL)570goto end;571572s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_VERSION);573if (s == NULL || strcmp(s, VERSION_VAL) != 0) {574BIO_printf(bio_err, "version not found\n");575goto end;576}577s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_MODULE_MAC);578if (s == NULL) {579BIO_printf(bio_err, "Module integrity MAC not found\n");580goto end;581}582buf1 = OPENSSL_hexstr2buf(s, &len);583if (buf1 == NULL584|| (size_t)len != module_mac_len585|| memcmp(module_mac, buf1, module_mac_len) != 0) {586BIO_printf(bio_err, "Module integrity mismatch\n");587goto end;588}589if (install_mac != NULL && install_mac_len > 0) {590s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_STATUS);591if (s == NULL || strcmp(s, INSTALL_STATUS_VAL) != 0) {592BIO_printf(bio_err, "install status not found\n");593goto end;594}595s = NCONF_get_string(conf, section, OSSL_PROV_FIPS_PARAM_INSTALL_MAC);596if (s == NULL) {597BIO_printf(bio_err, "Install indicator MAC not found\n");598goto end;599}600buf2 = OPENSSL_hexstr2buf(s, &len);601if (buf2 == NULL602|| (size_t)len != install_mac_len603|| memcmp(install_mac, buf2, install_mac_len) != 0) {604BIO_printf(bio_err, "Install indicator status mismatch\n");605goto end;606}607}608ret = 1;609end:610OPENSSL_free(buf1);611OPENSSL_free(buf2);612NCONF_free(conf);613return ret;614}615616int fipsinstall_main(int argc, char **argv)617{618int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, pedantic = 0;619int is_fips_140_2_prov = 0, set_selftest_onload_option = 0;620const char *section_name = "fips_sect";621const char *mac_name = "HMAC";622const char *prov_name = "fips";623BIO *module_bio = NULL, *mem_bio = NULL, *fout = NULL;624char *in_fname = NULL, *out_fname = NULL, *prog;625char *module_fname = NULL, *parent_config = NULL, *module_path = NULL;626const char *tail;627EVP_MAC_CTX *ctx = NULL, *ctx2 = NULL;628STACK_OF(OPENSSL_STRING) *opts = NULL;629OPTION_CHOICE o;630unsigned char *read_buffer = NULL;631unsigned char module_mac[EVP_MAX_MD_SIZE];632size_t module_mac_len = EVP_MAX_MD_SIZE;633unsigned char install_mac[EVP_MAX_MD_SIZE];634size_t install_mac_len = EVP_MAX_MD_SIZE;635EVP_MAC *mac = NULL;636CONF *conf = NULL;637638if ((opts = sk_OPENSSL_STRING_new_null()) == NULL)639goto end;640641prog = opt_init(argc, argv, fipsinstall_options);642while ((o = opt_next()) != OPT_EOF) {643switch (o) {644case OPT_EOF:645case OPT_ERR:646opthelp:647BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);648goto cleanup;649case OPT_HELP:650opt_help(fipsinstall_options);651ret = 0;652goto end;653case OPT_IN:654in_fname = opt_arg();655break;656case OPT_OUT:657out_fname = opt_arg();658break;659case OPT_PEDANTIC:660fips_opts = pedantic_opts;661pedantic = 1;662break;663case OPT_NO_CONDITIONAL_ERRORS:664if (!check_non_pedantic_fips(pedantic, "no_conditional_errors"))665goto end;666fips_opts.conditional_errors = 0;667break;668case OPT_NO_SECURITY_CHECKS:669if (!check_non_pedantic_fips(pedantic, "no_security_checks"))670goto end;671fips_opts.security_checks = 0;672break;673case OPT_HMAC_KEY_CHECK:674fips_opts.hmac_key_check = 1;675break;676case OPT_KMAC_KEY_CHECK:677fips_opts.kmac_key_check = 1;678break;679case OPT_TLS_PRF_EMS_CHECK:680fips_opts.tls_prf_ems_check = 1;681break;682case OPT_NO_SHORT_MAC:683fips_opts.no_short_mac = 1;684break;685case OPT_DISALLOW_DRGB_TRUNC_DIGEST:686fips_opts.drgb_no_trunc_dgst = 1;687break;688case OPT_SIGNATURE_DIGEST_CHECK:689fips_opts.signature_digest_check = 1;690break;691case OPT_HKDF_DIGEST_CHECK:692fips_opts.hkdf_digest_check = 1;693break;694case OPT_TLS13_KDF_DIGEST_CHECK:695fips_opts.tls13_kdf_digest_check = 1;696break;697case OPT_TLS1_PRF_DIGEST_CHECK:698fips_opts.tls1_prf_digest_check = 1;699break;700case OPT_SSHKDF_DIGEST_CHECK:701fips_opts.sshkdf_digest_check = 1;702break;703case OPT_SSKDF_DIGEST_CHECK:704fips_opts.sskdf_digest_check = 1;705break;706case OPT_X963KDF_DIGEST_CHECK:707fips_opts.x963kdf_digest_check = 1;708break;709case OPT_DISALLOW_DSA_SIGN:710fips_opts.dsa_sign_disabled = 1;711break;712case OPT_DISALLOW_TDES_ENCRYPT:713fips_opts.tdes_encrypt_disabled = 1;714break;715case OPT_RSA_PSS_SALTLEN_CHECK:716fips_opts.rsa_pss_saltlen_check = 1;717break;718case OPT_DISALLOW_SIGNATURE_X931_PADDING:719fips_opts.sign_x931_padding_disabled = 1;720break;721case OPT_DISALLOW_PKCS15_PADDING:722fips_opts.rsa_pkcs15_padding_disabled = 1;723break;724case OPT_HKDF_KEY_CHECK:725fips_opts.hkdf_key_check = 1;726break;727case OPT_KBKDF_KEY_CHECK:728fips_opts.kbkdf_key_check = 1;729break;730case OPT_TLS13_KDF_KEY_CHECK:731fips_opts.tls13_kdf_key_check = 1;732break;733case OPT_TLS1_PRF_KEY_CHECK:734fips_opts.tls1_prf_key_check = 1;735break;736case OPT_SSHKDF_KEY_CHECK:737fips_opts.sshkdf_key_check = 1;738break;739case OPT_SSKDF_KEY_CHECK:740fips_opts.sskdf_key_check = 1;741break;742case OPT_X963KDF_KEY_CHECK:743fips_opts.x963kdf_key_check = 1;744break;745case OPT_X942KDF_KEY_CHECK:746fips_opts.x942kdf_key_check = 1;747break;748case OPT_NO_PBKDF2_LOWER_BOUND_CHECK:749if (!check_non_pedantic_fips(pedantic, "no_pbkdf2_lower_bound_check"))750goto end;751fips_opts.pbkdf2_lower_bound_check = 0;752break;753case OPT_ECDH_COFACTOR_CHECK:754fips_opts.ecdh_cofactor_check = 1;755break;756case OPT_QUIET:757quiet = 1;758/* FALLTHROUGH */759case OPT_NO_LOG:760self_test_log = 0;761break;762case OPT_CORRUPT_DESC:763self_test_corrupt_desc = opt_arg();764break;765case OPT_CORRUPT_TYPE:766self_test_corrupt_type = opt_arg();767break;768case OPT_PROV_NAME:769prov_name = opt_arg();770break;771case OPT_MODULE:772module_fname = opt_arg();773break;774case OPT_SECTION_NAME:775section_name = opt_arg();776break;777case OPT_MAC_NAME:778mac_name = opt_arg();779break;780case OPT_CONFIG:781parent_config = opt_arg();782break;783case OPT_MACOPT:784if (!sk_OPENSSL_STRING_push(opts, opt_arg()))785goto opthelp;786if (HAS_PREFIX(opt_arg(), "hexkey:"))787gotkey = 1;788else if (HAS_PREFIX(opt_arg(), "digest:"))789gotdigest = 1;790break;791case OPT_VERIFY:792verify = 1;793break;794case OPT_SELF_TEST_ONLOAD:795set_selftest_onload_option = 1;796fips_opts.self_test_onload = 1;797break;798case OPT_SELF_TEST_ONINSTALL:799if (!check_non_pedantic_fips(pedantic, "self_test_oninstall"))800goto end;801set_selftest_onload_option = 1;802fips_opts.self_test_onload = 0;803break;804}805}806807/* No extra arguments. */808if (!opt_check_rest_arg(NULL))809goto opthelp;810if (verify && in_fname == NULL) {811BIO_printf(bio_err, "Missing -in option for -verify\n");812goto opthelp;813}814815if (parent_config != NULL) {816/* Test that a parent config can load the module */817if (verify_module_load(parent_config)) {818ret = OSSL_PROVIDER_available(NULL, prov_name) ? 0 : 1;819if (!quiet) {820BIO_printf(bio_err, "FIPS provider is %s\n",821ret == 0 ? "available" : "not available");822}823}824goto end;825}826if (module_fname == NULL)827goto opthelp;828829tail = opt_path_end(module_fname);830if (tail != NULL) {831module_path = OPENSSL_strdup(module_fname);832if (module_path == NULL)833goto end;834module_path[tail - module_fname] = '\0';835if (!OSSL_PROVIDER_set_default_search_path(NULL, module_path))836goto end;837}838839if (self_test_log840|| self_test_corrupt_desc != NULL841|| self_test_corrupt_type != NULL)842OSSL_SELF_TEST_set_callback(NULL, self_test_events, NULL);843844/* Use the default FIPS HMAC digest and key if not specified. */845if (!gotdigest && !sk_OPENSSL_STRING_push(opts, "digest:SHA256"))846goto end;847if (!gotkey && !sk_OPENSSL_STRING_push(opts, "hexkey:" FIPS_KEY_STRING))848goto end;849850module_bio = bio_open_default(module_fname, 'r', FORMAT_BINARY);851if (module_bio == NULL) {852BIO_printf(bio_err, "Failed to open module file\n");853goto end;854}855856read_buffer = app_malloc(BUFSIZE, "I/O buffer");857if (read_buffer == NULL)858goto end;859860mac = EVP_MAC_fetch(app_get0_libctx(), mac_name, app_get0_propq());861if (mac == NULL) {862BIO_printf(bio_err, "Unable to get MAC of type %s\n", mac_name);863goto end;864}865866ctx = EVP_MAC_CTX_new(mac);867if (ctx == NULL) {868BIO_printf(bio_err, "Unable to create MAC CTX for module check\n");869goto end;870}871872if (opts != NULL) {873int ok = 1;874OSSL_PARAM *params = app_params_new_from_opts(opts, EVP_MAC_settable_ctx_params(mac));875876if (params == NULL)877goto end;878879if (!EVP_MAC_CTX_set_params(ctx, params)) {880BIO_printf(bio_err, "MAC parameter error\n");881ERR_print_errors(bio_err);882ok = 0;883}884app_params_free(params);885if (!ok)886goto end;887}888889ctx2 = EVP_MAC_CTX_dup(ctx);890if (ctx2 == NULL) {891BIO_printf(bio_err, "Unable to create MAC CTX for install indicator\n");892goto end;893}894895if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))896goto end;897898/* Calculate the MAC for the indicator status - it may not be used */899mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,900strlen(INSTALL_STATUS_VAL));901if (mem_bio == NULL) {902BIO_printf(bio_err, "Unable to create memory BIO\n");903goto end;904}905if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))906goto end;907908if (verify) {909if (fips_opts.self_test_onload == 1)910install_mac_len = 0;911if (!verify_config(in_fname, section_name, module_mac, module_mac_len,912install_mac, install_mac_len))913goto end;914if (!quiet)915BIO_printf(bio_err, "VERIFY PASSED\n");916} else {917conf = generate_config_and_load(prov_name, section_name, module_mac,918module_mac_len, &fips_opts);919if (conf == NULL)920goto end;921if (!load_fips_prov_and_run_self_test(prov_name, &is_fips_140_2_prov))922goto end;923924/*925* In OpenSSL 3.1 the code was changed so that the status indicator is926* not written out by default since this is a FIPS 140-3 requirement.927* For backwards compatibility - if the detected FIPS provider is 3.0.X928* (Which was a FIPS 140-2 validation), then the indicator status will929* be written to the config file unless 'self_test_onload' is set on the930* command line.931*/932if (set_selftest_onload_option == 0 && is_fips_140_2_prov)933fips_opts.self_test_onload = 0;934935fout = out_fname == NULL ? dup_bio_out(FORMAT_TEXT)936: bio_open_default(out_fname, 'w', FORMAT_TEXT);937if (fout == NULL) {938BIO_printf(bio_err, "Failed to open file\n");939goto end;940}941942if (!write_config_fips_section(fout, section_name,943module_mac, module_mac_len, &fips_opts,944install_mac, install_mac_len))945goto end;946if (!quiet)947BIO_printf(bio_err, "INSTALL PASSED\n");948}949950ret = 0;951end:952if (ret == 1) {953if (!quiet)954BIO_printf(bio_err, "%s FAILED\n", verify ? "VERIFY" : "INSTALL");955ERR_print_errors(bio_err);956}957958cleanup:959OPENSSL_free(module_path);960BIO_free(fout);961BIO_free(mem_bio);962BIO_free(module_bio);963sk_OPENSSL_STRING_free(opts);964EVP_MAC_free(mac);965EVP_MAC_CTX_free(ctx2);966EVP_MAC_CTX_free(ctx);967OPENSSL_free(read_buffer);968free_config_and_unload(conf);969return ret;970}971972static int self_test_events(const OSSL_PARAM params[], void *arg)973{974const OSSL_PARAM *p = NULL;975const char *phase = NULL, *type = NULL, *desc = NULL;976int ret = 0;977978p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_PHASE);979if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)980goto err;981phase = (const char *)p->data;982983p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_DESC);984if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)985goto err;986desc = (const char *)p->data;987988p = OSSL_PARAM_locate_const(params, OSSL_PROV_PARAM_SELF_TEST_TYPE);989if (p == NULL || p->data_type != OSSL_PARAM_UTF8_STRING)990goto err;991type = (const char *)p->data;992993if (self_test_log) {994if (strcmp(phase, OSSL_SELF_TEST_PHASE_START) == 0)995BIO_printf(bio_err, "%s : (%s) : ", desc, type);996else if (strcmp(phase, OSSL_SELF_TEST_PHASE_PASS) == 0997|| strcmp(phase, OSSL_SELF_TEST_PHASE_FAIL) == 0)998BIO_printf(bio_err, "%s\n", phase);999}1000/*1001* The self test code will internally corrupt the KAT test result if an1002* error is returned during the corrupt phase.1003*/1004if (strcmp(phase, OSSL_SELF_TEST_PHASE_CORRUPT) == 01005&& (self_test_corrupt_desc != NULL1006|| self_test_corrupt_type != NULL)) {1007if (self_test_corrupt_desc != NULL1008&& strcmp(self_test_corrupt_desc, desc) != 0)1009goto end;1010if (self_test_corrupt_type != NULL1011&& strcmp(self_test_corrupt_type, type) != 0)1012goto end;1013BIO_printf(bio_err, "%s ", phase);1014goto err;1015}1016end:1017ret = 1;1018err:1019return ret;1020}102110221023