fipsinstall: Save the 'status indicator' if the FIPS provider is 3.0.X.

Fixes #23400

The 3.1 FIPS provider no longer writes out the 'status indicator' by
default due to changes related to FIPS 140-3 requirements. For Backwards
compatability if the fipsinstall detects it is loading a 3.0.X FIPS
provider then it will save the 'status indicator' by default.

Disclaimer: Using a fipsinstall command line utility that is not supplied
with the FIPS provider tarball source is not recommended.

This PR deliberately does not attempt to exclude any additional options
that were added after 3.0.X. These additional options will be ignored by older
providers.

Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Hugo Landau <hlandau@devever.net>
(Merged from https://github.com/openssl/openssl/pull/23689)
This commit is contained in:
slontis 2024-02-27 15:57:14 +11:00 committed by Tomas Mraz
parent 792b2c8da2
commit 01244adfc6
3 changed files with 63 additions and 20 deletions

View File

@ -284,7 +284,8 @@ err:
return ret;
}
static int load_fips_prov_and_run_self_test(const char *prov_name)
static int load_fips_prov_and_run_self_test(const char *prov_name,
int *is_fips_140_2_prov)
{
int ret = 0;
OSSL_PROVIDER *prov = NULL;
@ -314,7 +315,16 @@ static int load_fips_prov_and_run_self_test(const char *prov_name)
BIO_printf(bio_err, "\t%-10s\t%s\n", "version:", vers);
if (OSSL_PARAM_modified(params + 2))
BIO_printf(bio_err, "\t%-10s\t%s\n", "build:", build);
} else {
*p++ = OSSL_PARAM_construct_utf8_ptr(OSSL_PROV_PARAM_VERSION,
&vers, sizeof(vers));
*p = OSSL_PARAM_construct_end();
if (!OSSL_PROVIDER_get_params(prov, params)) {
BIO_printf(bio_err, "Failed to query FIPS module parameters\n");
goto end;
}
}
*is_fips_140_2_prov = (strncmp("3.0.", vers, 4) == 0);
ret = 1;
end:
OSSL_PROVIDER_unload(prov);
@ -436,7 +446,9 @@ static int write_config_fips_section(BIO *out, const char *section,
module_mac_len))
goto end;
if (install_mac != NULL && install_mac_len > 0) {
if (install_mac != NULL
&& install_mac_len > 0
&& opts->self_test_onload == 0) {
if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
install_mac_len)
|| BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS,
@ -559,6 +571,7 @@ end:
int fipsinstall_main(int argc, char **argv)
{
int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, pedantic = 0;
int is_fips_140_2_prov = 0, set_selftest_onload_option = 0;
const char *section_name = "fips_sect";
const char *mac_name = "HMAC";
const char *prov_name = "fips";
@ -734,11 +747,13 @@ int fipsinstall_main(int argc, char **argv)
verify = 1;
break;
case OPT_SELF_TEST_ONLOAD:
set_selftest_onload_option = 1;
fips_opts.self_test_onload = 1;
break;
case OPT_SELF_TEST_ONINSTALL:
if (!check_non_pedantic_fips(pedantic, "self_test_oninstall"))
goto end;
set_selftest_onload_option = 1;
fips_opts.self_test_onload = 0;
break;
}
@ -836,34 +851,43 @@ int fipsinstall_main(int argc, char **argv)
if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
goto end;
if (fips_opts.self_test_onload == 0) {
mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
strlen(INSTALL_STATUS_VAL));
if (mem_bio == NULL) {
BIO_printf(bio_err, "Unable to create memory BIO\n");
goto end;
}
if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
goto end;
} else {
install_mac_len = 0;
/* Calculate the MAC for the indicator status - it may not be used */
mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
strlen(INSTALL_STATUS_VAL));
if (mem_bio == NULL) {
BIO_printf(bio_err, "Unable to create memory BIO\n");
goto end;
}
if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
goto end;
if (verify) {
if (fips_opts.self_test_onload == 1)
install_mac_len = 0;
if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
install_mac, install_mac_len))
goto end;
if (!quiet)
BIO_printf(bio_err, "VERIFY PASSED\n");
} else {
conf = generate_config_and_load(prov_name, section_name, module_mac,
module_mac_len, &fips_opts);
if (conf == NULL)
goto end;
if (!load_fips_prov_and_run_self_test(prov_name))
if (!load_fips_prov_and_run_self_test(prov_name, &is_fips_140_2_prov))
goto end;
/*
* In OpenSSL 3.1 the code was changed so that the status indicator is
* not written out by default since this is a FIPS 140-3 requirement.
* For backwards compatibility - if the detected FIPS provider is 3.0.X
* (Which was a FIPS 140-2 validation), then the indicator status will
* be written to the config file unless 'self_test_onload' is set on the
* command line.
*/
if (set_selftest_onload_option == 0 && is_fips_140_2_prov)
fips_opts.self_test_onload = 0;
fout =
out_fname == NULL ? dup_bio_out(FORMAT_TEXT)
: bio_open_default(out_fname, 'w', FORMAT_TEXT);
@ -871,6 +895,7 @@ int fipsinstall_main(int argc, char **argv)
BIO_printf(bio_err, "Failed to open file\n");
goto end;
}
if (!write_config_fips_section(fout, section_name,
module_mac, module_mac_len, &fips_opts,
install_mac, install_mac_len))

View File

@ -367,14 +367,17 @@ used for cross compiling, since the self tests need to run at least once on each
target machine. Once the self tests have run on the target machine the user
could possibly then add the 2 fields into the configuration using some other
mechanism.
This is the default.
This option defaults to 0 for any OpenSSL FIPS 140-2 provider (OpenSSL 3.0.X).
and is not relevant for an OpenSSL FIPS 140-3 provider, since this is no
longer allowed.
=item B<-self_test_oninstall>
The converse of B<-self_test_oninstall>. The two fields related to the
"test status indicator" and "MAC status indicator" are written to the
output configuration file.
This field is not relevant for an OpenSSL FIPS 140-3 provider, since this is no
longer allowed.
=item B<-quiet>

View File

@ -63,7 +63,7 @@ my @commandline =
( 'x942kdf_key_check', 'x942kdf-key-check' )
);
plan tests => 35 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
plan tests => 37 + (scalar @pedantic_okay) + (scalar @pedantic_fail)
+ 4 * (scalar @commandline);
my $infile = bldtop_file('providers', platform->dso('fips'));
@ -150,7 +150,6 @@ ok(!run(app(['openssl', 'fipsinstall', '-in', 'dummy.tmp', '-module', $infile,
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail");
# output a fips.cnf file containing mac data
ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC',
@ -165,6 +164,23 @@ ok(run(app(['openssl', 'fipsinstall', '-in', 'fips.cnf', '-module', $infile,
'-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify");
# Test that default options for fipsinstall output the 'install-status' for
# FIPS 140-2 providers.
SKIP: {
run(test(["fips_version_test", "-config", $provconf, "<3.1.0"]),
capture => 1, statusvar => \my $exit);
skip "Skipping FIPS 140-3 provider", 2
if !$exit;
ok(find_line_file('install-mac = ', 'fips.cnf') == 1,
'FIPS 140-2 should output install-mac');
ok(find_line_file('install-status = INSTALL_SELF_TEST_KATS_RUN',
'fips.cnf') == 1,
'FIPS 140-2 should output install-status');
}
# Skip Tests if POST is disabled
SKIP: {
skip "Skipping POST checks", 13
@ -466,4 +482,3 @@ foreach my $cp (@commandline) {
ok(find_line_file("${l} = 1", "fips-${o}.cnf") == 1,
"fipsinstall enables ${l} with -${o} option");
}