The branch master has been updated via bfa6aaab45c30ced2da851ee92f8ac5942f08078 (commit) via e6c54619d151eeec32055bbd713cda11a9182246 (commit) from ebe3f24b3d53e503bd37a2a08a8b1f896014c30d (commit)
- Log ----------------------------------------------------------------- commit bfa6aaab45c30ced2da851ee92f8ac5942f08078 Author: Matt Caswell <m...@openssl.org> Date: Wed Aug 5 14:46:48 2020 +0100 Test that EVP_default_properties_is_fips_enabled() works early We check that EVP_default_properties_is_fips_enabled() is working even before other function calls have auto-loaded the config file. Reviewed-by: Paul Dale <paul.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12567) commit e6c54619d151eeec32055bbd713cda11a9182246 Author: Matt Caswell <m...@openssl.org> Date: Fri Jul 31 17:29:21 2020 +0100 Load the default config file before working with default properties A config file can change the global default properties. Therefore we must ensure that the config file is loaded before reading or amending them. Fixes #12565 Reviewed-by: Paul Dale <paul.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/12567) ----------------------------------------------------------------------- Summary of changes: crypto/evp/evp_cnf.c | 3 +- crypto/evp/evp_fetch.c | 22 +++++++---- crypto/property/property.c | 9 ++++- include/crypto/evp.h | 2 + include/internal/property.h | 2 +- test/build.info | 6 ++- test/defltfips_test.c | 81 ++++++++++++++++++++++++++++++++++++++++ test/evp_test.c | 3 +- test/fips.cnf | 7 ++++ test/recipes/30-test_defltfips.t | 43 +++++++++++++++++++++ test/tls-provider.c | 12 +++++- 11 files changed, 174 insertions(+), 16 deletions(-) create mode 100644 test/defltfips_test.c create mode 100644 test/recipes/30-test_defltfips.t diff --git a/crypto/evp/evp_cnf.c b/crypto/evp/evp_cnf.c index 27815553bd..455b258a9a 100644 --- a/crypto/evp/evp_cnf.c +++ b/crypto/evp/evp_cnf.c @@ -14,6 +14,7 @@ #include <openssl/x509.h> #include <openssl/x509v3.h> #include <openssl/trace.h> +#include "crypto/evp.h" DEFINE_STACK_OF(CONF_VALUE) @@ -52,7 +53,7 @@ static int alg_module_init(CONF_IMODULE *md, const CONF *cnf) return 0; } } else if (strcmp(oval->name, "default_properties") == 0) { - if (!EVP_set_default_properties(cnf->libctx, oval->value)) { + if (!evp_set_default_properties_int(cnf->libctx, oval->value, 0)) { EVPerr(EVP_F_ALG_MODULE_INIT, EVP_R_SET_DEFAULT_PROPERTY_FAILURE); return 0; } diff --git a/crypto/evp/evp_fetch.c b/crypto/evp/evp_fetch.c index 4c3992ab40..7b0cea7f0b 100644 --- a/crypto/evp/evp_fetch.c +++ b/crypto/evp/evp_fetch.c @@ -377,11 +377,12 @@ void evp_method_store_flush(OPENSSL_CTX *libctx) ossl_method_store_flush_cache(store, 1); } -static int evp_set_default_properties(OPENSSL_CTX *libctx, - OSSL_PROPERTY_LIST *def_prop) +static int evp_set_parsed_default_properties(OPENSSL_CTX *libctx, + OSSL_PROPERTY_LIST *def_prop, + int loadconfig) { OSSL_METHOD_STORE *store = get_evp_method_store(libctx); - OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx); + OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, loadconfig); if (plp != NULL) { ossl_property_free(*plp); @@ -394,7 +395,8 @@ static int evp_set_default_properties(OPENSSL_CTX *libctx, return 0; } -int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq) +int evp_set_default_properties_int(OPENSSL_CTX *libctx, const char *propq, + int loadconfig) { OSSL_PROPERTY_LIST *pl = NULL; @@ -402,13 +404,17 @@ int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq) EVPerr(0, EVP_R_DEFAULT_QUERY_PARSE_ERROR); return 0; } - return evp_set_default_properties(libctx, pl); + return evp_set_parsed_default_properties(libctx, pl, loadconfig); } +int EVP_set_default_properties(OPENSSL_CTX *libctx, const char *propq) +{ + return evp_set_default_properties_int(libctx, propq, 1); +} static int evp_default_properties_merge(OPENSSL_CTX *libctx, const char *propq) { - OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx); + OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1); OSSL_PROPERTY_LIST *pl1, *pl2; if (propq == NULL) @@ -425,13 +431,13 @@ static int evp_default_properties_merge(OPENSSL_CTX *libctx, const char *propq) EVPerr(0, ERR_R_MALLOC_FAILURE); return 0; } - return evp_set_default_properties(libctx, pl2); + return evp_set_parsed_default_properties(libctx, pl2, 0); } static int evp_default_property_is_enabled(OPENSSL_CTX *libctx, const char *prop_name) { - OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx); + OSSL_PROPERTY_LIST **plp = ossl_ctx_global_properties(libctx, 1); return plp != NULL && ossl_property_is_enabled(libctx, prop_name, *plp); } diff --git a/crypto/property/property.c b/crypto/property/property.c index cb82f8956b..608a909d49 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -96,8 +96,13 @@ static const OPENSSL_CTX_METHOD ossl_ctx_global_properties_method = { ossl_ctx_global_properties_free, }; -OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OPENSSL_CTX *libctx) +OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OPENSSL_CTX *libctx, + int loadconfig) { +#ifndef FIPS_MODULE + if (loadconfig && !OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL)) + return NULL; +#endif return openssl_ctx_get_data(libctx, OPENSSL_CTX_GLOBAL_PROPERTIES, &ossl_ctx_global_properties_method); } @@ -352,7 +357,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, if (prop_query != NULL) p2 = pq = ossl_parse_query(store->ctx, prop_query); - plp = ossl_ctx_global_properties(store->ctx); + plp = ossl_ctx_global_properties(store->ctx, 1); if (plp != NULL && *plp != NULL) { if (pq == NULL) { pq = *plp; diff --git a/include/crypto/evp.h b/include/crypto/evp.h index f170e59324..d2b2584357 100644 --- a/include/crypto/evp.h +++ b/include/crypto/evp.h @@ -771,3 +771,5 @@ EVP_PKEY *evp_pkcs82pkey_int(const PKCS8_PRIV_KEY_INFO *p8, OPENSSL_CTX *libctx, const char *propq); #endif /* !defined(FIPS_MODULE) */ void evp_method_store_flush(OPENSSL_CTX *libctx); +int evp_set_default_properties_int(OPENSSL_CTX *libctx, const char *propq, + int loadconfig); diff --git a/include/internal/property.h b/include/internal/property.h index ca1d1e055c..cd3982549d 100644 --- a/include/internal/property.h +++ b/include/internal/property.h @@ -45,7 +45,7 @@ int ossl_method_store_fetch(OSSL_METHOD_STORE *store, int nid, const char *prop_query, void **method); /* Get the global properties associate with the specified library context */ -OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OPENSSL_CTX *ctx); +OSSL_PROPERTY_LIST **ossl_ctx_global_properties(OPENSSL_CTX *ctx, int loadconfig); /* property query cache functions */ int ossl_method_store_cache_get(OSSL_METHOD_STORE *store, int nid, diff --git a/test/build.info b/test/build.info index 1dd3db7c79..11fce8e279 100644 --- a/test/build.info +++ b/test/build.info @@ -57,7 +57,7 @@ IF[{- !$disabled{tests} -}] http_test servername_test ocspapitest fatalerrtest tls13ccstest \ sysdefaulttest errtest ssl_ctx_test gosttest \ context_internal_test aesgcmtest params_test evp_pkey_dparams_test \ - keymgmt_internal_test hexstr_test provider_status_test + keymgmt_internal_test hexstr_test provider_status_test defltfips_test IF[{- !$disabled{'deprecated-3.0'} -}] PROGRAMS{noinst}=enginetest @@ -324,6 +324,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[sslapitest]=../include ../apps/include .. DEPEND[sslapitest]=../libcrypto ../libssl libtestutil.a + SOURCE[defltfips_test]=defltfips_test.c + INCLUDE[defltfips_test]=../include ../apps/include + DEPEND[defltfips_test]=../libcrypto libtestutil.a + SOURCE[ocspapitest]=ocspapitest.c INCLUDE[ocspapitest]=../include ../apps/include DEPEND[ocspapitest]=../libcrypto libtestutil.a diff --git a/test/defltfips_test.c b/test/defltfips_test.c new file mode 100644 index 0000000000..a8349211b6 --- /dev/null +++ b/test/defltfips_test.c @@ -0,0 +1,81 @@ +#include <string.h> +#include <openssl/evp.h> +#include <openssl/provider.h> +#include "testutil.h" + +static int is_fips; + +static int test_is_fips_enabled(void) +{ + int is_fips_enabled, is_fips_loaded; + EVP_MD *sha256 = NULL; + + /* + * Check we're in FIPS mode when we're supposed to be. We do this early to + * confirm that EVP_default_properties_is_fips_enabled() works even before + * other function calls have auto-loaded the config file. + */ + is_fips_enabled = EVP_default_properties_is_fips_enabled(NULL); + is_fips_loaded = OSSL_PROVIDER_available(NULL, "fips"); + + /* + * Check we're in an expected state. EVP_default_properties_is_fips_enabled + * can return true even if the FIPS provider isn't loaded - it is only based + * on the default properties. However we only set those properties if also + * loading the FIPS provider. + */ + if (!TEST_int_eq(is_fips, is_fips_enabled) + || !TEST_int_eq(is_fips, is_fips_loaded)) + return 0; + + /* + * Fetching an algorithm shouldn't change the state and should come from + * expected provider. + */ + sha256 = EVP_MD_fetch(NULL, "SHA2-256", NULL); + if (!TEST_ptr(sha256)) + return 0; + if (is_fips + && !TEST_str_eq(OSSL_PROVIDER_name(EVP_MD_provider(sha256)), "fips")) { + EVP_MD_free(sha256); + return 0; + } + EVP_MD_free(sha256); + + /* State should still be consistent */ + is_fips_enabled = EVP_default_properties_is_fips_enabled(NULL); + if (!TEST_int_eq(is_fips, is_fips_enabled)) + return 0; + + return 1; +} + +int setup_tests(void) +{ + size_t argc; + + if (!test_skip_common_options()) { + TEST_error("Error parsing test options\n"); + return 0; + } + + argc = test_get_argument_count(); + switch(argc) { + case 0: + is_fips = 0; + break; + case 1: + if (strcmp(test_get_argument(0), "fips") == 0) { + is_fips = 1; + break; + } + /* fall through */ + default: + TEST_error("Invalid argument\n"); + return 0; + } + + /* Must be the first test before any other libcrypto calls are made */ + ADD_TEST(test_is_fips_enabled); + return 1; +} diff --git a/test/evp_test.c b/test/evp_test.c index b980abc944..cd6077e10d 100644 --- a/test/evp_test.c +++ b/test/evp_test.c @@ -2095,7 +2095,8 @@ static int rand_test_init(EVP_TEST *t, const char *name) if (!TEST_ptr(rdata = OPENSSL_zalloc(sizeof(*rdata)))) return 0; - rand = EVP_RAND_fetch(libctx, "TEST-RAND", NULL); + /* TEST-RAND is available in the FIPS provider but not with "fips=yes" */ + rand = EVP_RAND_fetch(libctx, "TEST-RAND", "-fips"); if (rand == NULL) goto err; rdata->parent = EVP_RAND_CTX_new(rand, NULL); diff --git a/test/fips.cnf b/test/fips.cnf index d6c3c6be14..fa131a8bf6 100644 --- a/test/fips.cnf +++ b/test/fips.cnf @@ -4,6 +4,13 @@ openssl_conf = openssl_init [openssl_init] providers = provider_sect +alg_section = evp_properties + +[evp_properties] +# Ensure FIPS non-approved algorithms in the FIPS module are suppressed (e.g. +# TEST-RAND). This also means that EVP_default_properties_is_fips_enabled() +# returns the expected value +default_properties = "fips=yes" [provider_sect] fips = fips_sect diff --git a/test/recipes/30-test_defltfips.t b/test/recipes/30-test_defltfips.t new file mode 100644 index 0000000000..c98591eb86 --- /dev/null +++ b/test/recipes/30-test_defltfips.t @@ -0,0 +1,43 @@ +#! /usr/bin/env perl +# Copyright 2015-2020 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 strict; +use warnings; + +use OpenSSL::Test qw/:DEFAULT srctop_file srctop_dir bldtop_file bldtop_dir/; +use OpenSSL::Test::Utils; +use Cwd qw(abs_path); + +BEGIN { + setup("test_evp"); +} + +use lib srctop_dir('Configurations'); +use lib bldtop_dir('.'); +use platform; + +my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0); + +plan tests => + ($no_fips ? 1 : 3); + +unless ($no_fips) { + my $infile = bldtop_file('providers', platform->dso('fips')); + + ok(run(app(['openssl', 'fipsinstall', + '-out', bldtop_file('providers', 'fipsmodule.cnf'), + '-module', $infile])), + "fipsinstall"); + + $ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "fips.cnf")); + ok(run(test(["defltfips_test", "fips"])), "running defltfips_test fips"); +} + +$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default.cnf")); +ok(run(test(["defltfips_test"])), "running defltfips_test"); diff --git a/test/tls-provider.c b/test/tls-provider.c index 496ba7ead9..924ede501b 100644 --- a/test/tls-provider.c +++ b/test/tls-provider.c @@ -180,7 +180,11 @@ static const OSSL_DISPATCH xor_keyexch_functions[] = { }; static const OSSL_ALGORITHM tls_prov_keyexch[] = { - { "XOR", "provider=tls-provider", xor_keyexch_functions }, + /* + * Obviously this is not FIPS approved, but in order to test in conjuction + * with the FIPS provider we pretend that it is. + */ + { "XOR", "provider=tls-provider,fips=yes", xor_keyexch_functions }, { NULL, NULL, NULL } }; @@ -414,7 +418,11 @@ static const OSSL_DISPATCH xor_keymgmt_functions[] = { }; static const OSSL_ALGORITHM tls_prov_keymgmt[] = { - { "XOR", "provider=tls-provider", xor_keymgmt_functions }, + /* + * Obviously this is not FIPS approved, but in order to test in conjuction + * with the FIPS provider we pretend that it is. + */ + { "XOR", "provider=tls-provider,fips=yes", xor_keymgmt_functions }, { NULL, NULL, NULL } };