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; 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; int ret = 0;
OSSL_PROVIDER *prov = NULL; 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); BIO_printf(bio_err, "\t%-10s\t%s\n", "version:", vers);
if (OSSL_PARAM_modified(params + 2)) if (OSSL_PARAM_modified(params + 2))
BIO_printf(bio_err, "\t%-10s\t%s\n", "build:", build); 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; ret = 1;
end: end:
OSSL_PROVIDER_unload(prov); OSSL_PROVIDER_unload(prov);
@ -436,7 +446,9 @@ static int write_config_fips_section(BIO *out, const char *section,
module_mac_len)) module_mac_len))
goto end; 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, if (!print_mac(out, OSSL_PROV_FIPS_PARAM_INSTALL_MAC, install_mac,
install_mac_len) install_mac_len)
|| BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_STATUS, || 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 fipsinstall_main(int argc, char **argv)
{ {
int ret = 1, verify = 0, gotkey = 0, gotdigest = 0, pedantic = 0; 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 *section_name = "fips_sect";
const char *mac_name = "HMAC"; const char *mac_name = "HMAC";
const char *prov_name = "fips"; const char *prov_name = "fips";
@ -734,11 +747,13 @@ int fipsinstall_main(int argc, char **argv)
verify = 1; verify = 1;
break; break;
case OPT_SELF_TEST_ONLOAD: case OPT_SELF_TEST_ONLOAD:
set_selftest_onload_option = 1;
fips_opts.self_test_onload = 1; fips_opts.self_test_onload = 1;
break; break;
case OPT_SELF_TEST_ONINSTALL: case OPT_SELF_TEST_ONINSTALL:
if (!check_non_pedantic_fips(pedantic, "self_test_oninstall")) if (!check_non_pedantic_fips(pedantic, "self_test_oninstall"))
goto end; goto end;
set_selftest_onload_option = 1;
fips_opts.self_test_onload = 0; fips_opts.self_test_onload = 0;
break; 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)) if (!do_mac(ctx, read_buffer, module_bio, module_mac, &module_mac_len))
goto end; goto end;
if (fips_opts.self_test_onload == 0) { /* Calculate the MAC for the indicator status - it may not be used */
mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL, mem_bio = BIO_new_mem_buf((const void *)INSTALL_STATUS_VAL,
strlen(INSTALL_STATUS_VAL)); strlen(INSTALL_STATUS_VAL));
if (mem_bio == NULL) { if (mem_bio == NULL) {
BIO_printf(bio_err, "Unable to create memory BIO\n"); BIO_printf(bio_err, "Unable to create memory BIO\n");
goto end; goto end;
}
if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
goto end;
} else {
install_mac_len = 0;
} }
if (!do_mac(ctx2, read_buffer, mem_bio, install_mac, &install_mac_len))
goto end;
if (verify) { 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, if (!verify_config(in_fname, section_name, module_mac, module_mac_len,
install_mac, install_mac_len)) install_mac, install_mac_len))
goto end; goto end;
if (!quiet) if (!quiet)
BIO_printf(bio_err, "VERIFY PASSED\n"); BIO_printf(bio_err, "VERIFY PASSED\n");
} else { } else {
conf = generate_config_and_load(prov_name, section_name, module_mac, conf = generate_config_and_load(prov_name, section_name, module_mac,
module_mac_len, &fips_opts); module_mac_len, &fips_opts);
if (conf == NULL) if (conf == NULL)
goto end; 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; 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 = fout =
out_fname == NULL ? dup_bio_out(FORMAT_TEXT) out_fname == NULL ? dup_bio_out(FORMAT_TEXT)
: bio_open_default(out_fname, 'w', 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"); BIO_printf(bio_err, "Failed to open file\n");
goto end; goto end;
} }
if (!write_config_fips_section(fout, section_name, if (!write_config_fips_section(fout, section_name,
module_mac, module_mac_len, &fips_opts, module_mac, module_mac_len, &fips_opts,
install_mac, install_mac_len)) 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 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 could possibly then add the 2 fields into the configuration using some other
mechanism. mechanism.
This option defaults to 0 for any OpenSSL FIPS 140-2 provider (OpenSSL 3.0.X).
This is the default. and is not relevant for an OpenSSL FIPS 140-3 provider, since this is no
longer allowed.
=item B<-self_test_oninstall> =item B<-self_test_oninstall>
The converse of B<-self_test_oninstall>. The two fields related to the The converse of B<-self_test_oninstall>. The two fields related to the
"test status indicator" and "MAC status indicator" are written to the "test status indicator" and "MAC status indicator" are written to the
output configuration file. output configuration file.
This field is not relevant for an OpenSSL FIPS 140-3 provider, since this is no
longer allowed.
=item B<-quiet> =item B<-quiet>

View file

@ -63,7 +63,7 @@ my @commandline =
( 'x942kdf_key_check', 'x942kdf-key-check' ) ( '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); + 4 * (scalar @commandline);
my $infile = bldtop_file('providers', platform->dso('fips')); 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'])), '-section_name', 'fips_sect', '-verify'])),
"fipsinstall verify fail"); "fipsinstall verify fail");
# output a fips.cnf file containing mac data # output a fips.cnf file containing mac data
ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile, ok(run(app(['openssl', 'fipsinstall', '-out', 'fips.cnf', '-module', $infile,
'-provider_name', 'fips', '-mac_name', 'HMAC', '-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'])), '-section_name', 'fips_sect', '-verify'])),
"fipsinstall 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 Tests if POST is disabled
SKIP: { SKIP: {
skip "Skipping POST checks", 13 skip "Skipping POST checks", 13
@ -466,4 +482,3 @@ foreach my $cp (@commandline) {
ok(find_line_file("${l} = 1", "fips-${o}.cnf") == 1, ok(find_line_file("${l} = 1", "fips-${o}.cnf") == 1,
"fipsinstall enables ${l} with -${o} option"); "fipsinstall enables ${l} with -${o} option");
} }