diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-09-10 14:01:30 +1000 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2020-09-12 16:46:51 +1000 |
commit | 35e6ea3bdc2741c1818337e75756b45d6a2a6122 (patch) | |
tree | 5e3220d285fb8cbc899c7e7565475c832c00943e | |
parent | 801ed9edbad11b3f0646b396c672dbae33353de2 (diff) |
keygen: add FIPS error state management to conditional self tests
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12801)
-rw-r--r-- | apps/fipsinstall.c | 48 | ||||
-rw-r--r-- | crypto/dsa/dsa_key.c | 2 | ||||
-rw-r--r-- | crypto/ec/ec_key.c | 2 | ||||
-rw-r--r-- | crypto/err/openssl.txt | 3 | ||||
-rw-r--r-- | crypto/rsa/rsa_gen.c | 2 | ||||
-rw-r--r-- | doc/man1/openssl-fipsinstall.pod.in | 18 | ||||
-rw-r--r-- | include/openssl/fips_names.h | 7 | ||||
-rw-r--r-- | include/openssl/self_test.h | 1 | ||||
-rw-r--r-- | providers/common/include/prov/providercommon.h | 2 | ||||
-rw-r--r-- | providers/common/include/prov/providercommonerr.h | 3 | ||||
-rw-r--r-- | providers/common/provider_err.c | 2 | ||||
-rw-r--r-- | providers/fips/fipsprov.c | 7 | ||||
-rw-r--r-- | providers/fips/self_test.c | 20 | ||||
-rw-r--r-- | providers/fips/self_test.h | 5 | ||||
-rw-r--r-- | providers/implementations/rands/crngt.c | 3 | ||||
-rw-r--r-- | providers/prov_running.c | 4 |
16 files changed, 103 insertions, 26 deletions
diff --git a/apps/fipsinstall.c b/apps/fipsinstall.c index 104806c1b7..2df7d0f024 100644 --- a/apps/fipsinstall.c +++ b/apps/fipsinstall.c @@ -38,7 +38,8 @@ typedef enum OPTION_choice { OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, OPT_IN, OPT_OUT, OPT_MODULE, OPT_PROV_NAME, OPT_SECTION_NAME, OPT_MAC_NAME, OPT_MACOPT, OPT_VERIFY, - OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG + OPT_NO_LOG, OPT_CORRUPT_DESC, OPT_CORRUPT_TYPE, OPT_QUIET, OPT_CONFIG, + OPT_NO_CONDITIONAL_ERRORS } OPTION_CHOICE; const OPTIONS fipsinstall_options[] = { @@ -50,7 +51,9 @@ const OPTIONS fipsinstall_options[] = { {"provider_name", OPT_PROV_NAME, 's', "FIPS provider name"}, {"section_name", OPT_SECTION_NAME, 's', "FIPS Provider config section name (optional)"}, - + {"no_conditional_errors", OPT_NO_CONDITIONAL_ERRORS, '-', + "Disable the ability of the fips module to enter an error state if" + " any conditional self tests fail"}, OPT_SECTION("Input"), {"in", OPT_IN, '<', "Input config file, used when verifying"}, @@ -132,24 +135,28 @@ static int write_config_header(BIO *out, const char *prov_name, /* * Outputs a fips related config file that contains entries for the fips - * module checksum and the installation indicator checksum. + * module checksum, installation indicator checksum and the option + * conditional_errors. * * Returns 1 if the config file is written otherwise it returns 0 on error. */ static int write_config_fips_section(BIO *out, const char *section, unsigned char *module_mac, size_t module_mac_len, + int conditional_errors, unsigned char *install_mac, size_t install_mac_len) { int ret = 0; - if (!(BIO_printf(out, "[%s]\n", section) > 0 - && BIO_printf(out, "activate = 1\n") > 0 - && BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, - VERSION_VAL) > 0 - && print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, - module_mac_len))) + if (BIO_printf(out, "[%s]\n", section) <= 0 + || BIO_printf(out, "activate = 1\n") <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, + VERSION_VAL) <= 0 + || BIO_printf(out, "%s = %s\n", OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS, + conditional_errors ? "1" : "0") <= 0 + || !print_mac(out, OSSL_PROV_FIPS_PARAM_MODULE_MAC, module_mac, + module_mac_len)) goto end; if (install_mac != NULL) { @@ -168,7 +175,8 @@ end: static CONF *generate_config_and_load(const char *prov_name, const char *section, unsigned char *module_mac, - size_t module_mac_len) + size_t module_mac_len, + int conditional_errors) { BIO *mem_bio = NULL; CONF *conf = NULL; @@ -177,8 +185,10 @@ static CONF *generate_config_and_load(const char *prov_name, if (mem_bio == NULL) return 0; if (!write_config_header(mem_bio, prov_name, section) - || !write_config_fips_section(mem_bio, section, module_mac, - module_mac_len, NULL, 0)) + || !write_config_fips_section(mem_bio, section, + module_mac, module_mac_len, + conditional_errors, + NULL, 0)) goto end; conf = app_load_config_bio(mem_bio, NULL); @@ -272,6 +282,7 @@ end: int fipsinstall_main(int argc, char **argv) { int ret = 1, verify = 0, gotkey = 0, gotdigest = 0; + int enable_conditional_errors = 1; const char *section_name = "fips_sect"; const char *mac_name = "HMAC"; const char *prov_name = "fips"; @@ -311,6 +322,9 @@ opthelp: case OPT_OUT: out_fname = opt_arg(); break; + case OPT_NO_CONDITIONAL_ERRORS: + enable_conditional_errors = 0; + break; case OPT_QUIET: quiet = 1; /* FALLTHROUGH */ @@ -457,7 +471,8 @@ opthelp: } else { conf = generate_config_and_load(prov_name, section_name, module_mac, - module_mac_len); + module_mac_len, + enable_conditional_errors); if (conf == NULL) goto end; if (!load_fips_prov_and_run_self_test(prov_name)) @@ -468,9 +483,10 @@ opthelp: BIO_printf(bio_err, "Failed to open file\n"); goto end; } - if (!write_config_fips_section(fout, section_name, module_mac, - module_mac_len, install_mac, - install_mac_len)) + if (!write_config_fips_section(fout, section_name, + module_mac, module_mac_len, + enable_conditional_errors, + install_mac, install_mac_len)) goto end; if (!quiet) BIO_printf(bio_out, "INSTALL PASSED\n"); diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index b537ec0b3c..bf9d8a269c 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -18,6 +18,7 @@ #include "internal/cryptlib.h" #include <openssl/bn.h> #include <openssl/self_test.h> +#include "prov/providercommon.h" #include "crypto/dsa.h" #include "dsa_local.h" @@ -113,6 +114,7 @@ static int dsa_keygen(DSA *dsa, int pairwise_test) OSSL_SELF_TEST_get_callback(dsa->libctx, &cb, &cbarg); ok = dsa_keygen_pairwise_test(dsa, cb, cbarg); if (!ok) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); BN_free(dsa->pub_key); BN_clear_free(dsa->priv_key); dsa->pub_key = NULL; diff --git a/crypto/ec/ec_key.c b/crypto/ec/ec_key.c index 84ce095693..84e1b96c48 100644 --- a/crypto/ec/ec_key.c +++ b/crypto/ec/ec_key.c @@ -21,6 +21,7 @@ #include <openssl/err.h> #include <openssl/engine.h> #include <openssl/self_test.h> +#include "prov/providercommon.h" #include "crypto/bn.h" static int ecdsa_keygen_pairwise_test(EC_KEY *eckey, OSSL_CALLBACK *cb, @@ -330,6 +331,7 @@ int ec_generate_key(OPENSSL_CTX *libctx, EC_KEY *eckey, int pairwise_test) err: /* Step (9): If there is an error return an invalid keypair. */ if (!ok) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); BN_clear(eckey->priv_key); if (eckey->pub_key != NULL) EC_POINT_set_to_infinity(group, eckey->pub_key); diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index 6c2e81efb9..35c1dd6bdc 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2877,6 +2877,7 @@ PROV_R_FAILED_TO_GENERATE_KEY:121:failed to generate key PROV_R_FAILED_TO_GET_PARAMETER:103:failed to get parameter PROV_R_FAILED_TO_SET_PARAMETER:104:failed to set parameter PROV_R_FAILED_TO_SIGN:175:failed to sign +PROV_R_FIPS_MODULE_CONDITIONAL_ERROR:227:fips module conditional error PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE:224:fips module entering error state PROV_R_FIPS_MODULE_IN_ERROR_STATE:225:fips module in error state PROV_R_GENERATE_ERROR:191:generate error @@ -2936,7 +2937,7 @@ PROV_R_MODULE_INTEGRITY_FAILURE:214:module integrity failure PROV_R_NOT_A_PRIVATE_KEY:221:not a private key PROV_R_NOT_A_PUBLIC_KEY:220:not a public key PROV_R_NOT_INSTANTIATED:193:not instantiated -PROV_R_NOT_PARAMETERS:224:not parameters +PROV_R_NOT_PARAMETERS:226:not parameters PROV_R_NOT_SUPPORTED:136:not supported PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length PROV_R_NO_KEY_SET:114:no key set diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c index b7a37b77a2..dc4ec0a8d3 100644 --- a/crypto/rsa/rsa_gen.c +++ b/crypto/rsa/rsa_gen.c @@ -24,6 +24,7 @@ #include "internal/cryptlib.h" #include <openssl/bn.h> #include <openssl/self_test.h> +#include "prov/providercommon.h" #include "rsa_local.h" static int rsa_keygen_pairwise_test(RSA *rsa, OSSL_CALLBACK *cb, void *cbarg); @@ -444,6 +445,7 @@ static int rsa_keygen(OPENSSL_CTX *libctx, RSA *rsa, int bits, int primes, OSSL_SELF_TEST_get_callback(libctx, &stcb, &stcbarg); ok = rsa_keygen_pairwise_test(rsa, stcb, stcbarg); if (!ok) { + ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT); /* Clear intermediate results */ BN_clear_free(rsa->d); BN_clear_free(rsa->p); diff --git a/doc/man1/openssl-fipsinstall.pod.in b/doc/man1/openssl-fipsinstall.pod.in index 451e8a775d..7fb6ad5636 100644 --- a/doc/man1/openssl-fipsinstall.pod.in +++ b/doc/man1/openssl-fipsinstall.pod.in @@ -19,6 +19,7 @@ B<openssl fipsinstall> [B<-macopt> I<nm>:I<v>] [B<-noout>] [B<-quiet>] +[B<-no_conditional_errors>] [B<-corrupt_desc> I<selftest_description>] [B<-corrupt_type> I<selftest_type>] [B<-config> I<parent_config>] @@ -43,6 +44,17 @@ This indicates if the Known Answer Self Tests (KAT's) have successfully run. =item - A MAC of the status indicator. +=item - A control for conditional self tests errors. + +By default if a continuous test (e.g a key pair test) fails then the FIPS module +will enter an error state, and no services or cryptographic algorithms will be +able to be accessed after this point. +The default value of '1' will cause the fips module error state to be entered. +If the value is '0' then the module error state will not be entered. +Regardless of whether the error state is entered or not, the current operation +(e.g. key generation) will return an error. The user is responsible for retrying +the operation if the module error state is not entered. + =back This file is described in L<fips_config(5)>. @@ -133,6 +145,12 @@ The default digest is SHA-256. Disable logging of the self tests. +=item B<-no_conditional_errors> + +Configure the module to not enter an error state if a conditional self test +fails as described above. + + =item B<-quiet> Do not output pass/fail messages. Implies B<-noout>. diff --git a/include/openssl/fips_names.h b/include/openssl/fips_names.h index 493ddb046d..7dec75fcea 100644 --- a/include/openssl/fips_names.h +++ b/include/openssl/fips_names.h @@ -39,6 +39,13 @@ extern "C" { */ # define OSSL_PROV_FIPS_PARAM_INSTALL_STATUS "install-status" +/* + * A boolean that determines if the FIPS conditional test errors result in + * the module entering an error state. + * Type: OSSL_PARAM_UTF8_STRING + */ +# define OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS "conditional-errors" + # ifdef __cplusplus } # endif diff --git a/include/openssl/self_test.h b/include/openssl/self_test.h index ff6e1b8e08..aa153581fa 100644 --- a/include/openssl/self_test.h +++ b/include/openssl/self_test.h @@ -27,6 +27,7 @@ extern "C" { # define OSSL_SELF_TEST_TYPE_NONE "None" # define OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY "Module_Integrity" # define OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY "Install_Integrity" +# define OSSL_SELF_TEST_TYPE_CRNG "Continuous_RNG_Test" # define OSSL_SELF_TEST_TYPE_PCT "Pairwise_Consistency_Test" # define OSSL_SELF_TEST_TYPE_KAT_CIPHER "KAT_Cipher" # define OSSL_SELF_TEST_TYPE_KAT_DIGEST "KAT_Digest" diff --git a/providers/common/include/prov/providercommon.h b/providers/common/include/prov/providercommon.h index 280d2d2072..44e9c812aa 100644 --- a/providers/common/include/prov/providercommon.h +++ b/providers/common/include/prov/providercommon.h @@ -20,7 +20,7 @@ int cipher_capable_aes_cbc_hmac_sha256(void); OSSL_FUNC_provider_get_capabilities_fn provider_get_capabilities; /* Set the error state if this is a FIPS module */ -void ossl_set_error_state(void); +void ossl_set_error_state(const char *type); /* Return true if the module is in a usable condition */ int ossl_prov_is_running(void); diff --git a/providers/common/include/prov/providercommonerr.h b/providers/common/include/prov/providercommonerr.h index d4d3c7e8e8..d972a819e2 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -75,6 +75,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_FAILED_TO_GET_PARAMETER 103 # define PROV_R_FAILED_TO_SET_PARAMETER 104 # define PROV_R_FAILED_TO_SIGN 175 +# define PROV_R_FIPS_MODULE_CONDITIONAL_ERROR 227 # define PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE 224 # define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225 # define PROV_R_GENERATE_ERROR 191 @@ -133,7 +134,7 @@ int ERR_load_PROV_strings(void); # define PROV_R_NOT_A_PRIVATE_KEY 221 # define PROV_R_NOT_A_PUBLIC_KEY 220 # define PROV_R_NOT_INSTANTIATED 193 -# define PROV_R_NOT_PARAMETERS 224 +# define PROV_R_NOT_PARAMETERS 226 # define PROV_R_NOT_SUPPORTED 136 # define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113 # define PROV_R_NO_KEY_SET 114 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 329bb279eb..606d78cc57 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -58,6 +58,8 @@ static const ERR_STRING_DATA PROV_str_reasons[] = { {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SET_PARAMETER), "failed to set parameter"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FAILED_TO_SIGN), "failed to sign"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR), + "fips module conditional error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE), "fips module entering error state"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_IN_ERROR_STATE), diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 0f1c979efe..4290a87e6e 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -126,6 +126,9 @@ static OSSL_PARAM core_params[] = OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_INSTALL_VERSION, selftest_params.indicator_version, sizeof(selftest_params.indicator_version)), + OSSL_PARAM_utf8_ptr(OSSL_PROV_FIPS_PARAM_CONDITIONAL_ERRORS, + selftest_params.conditional_error_check, + sizeof(selftest_params.conditional_error_check)), OSSL_PARAM_END }; @@ -645,6 +648,10 @@ int OSSL_provider_init(const OSSL_CORE_HANDLE *handle, ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_GET_PARAMETER); return 0; } + /* Disable the conditional error check if is disabled in the fips config file*/ + if (selftest_params.conditional_error_check != NULL + && strcmp(selftest_params.conditional_error_check, "0") == 0) + SELF_TEST_disable_conditional_error_state(); /* Create a context. */ if ((*provctx = PROV_CTX_new()) == NULL diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c index b0df0863e2..9d95f0ccf1 100644 --- a/providers/fips/self_test.c +++ b/providers/fips/self_test.c @@ -44,6 +44,7 @@ #define MAC_NAME "HMAC" #define DIGEST_NAME "SHA256" +static int FIPS_conditional_error_check = 1; static int FIPS_state = FIPS_STATE_INIT; static CRYPTO_RWLOCK *self_test_lock = NULL; static unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS }; @@ -311,16 +312,27 @@ end: if (ok) FIPS_state = FIPS_STATE_RUNNING; else - ossl_set_error_state(); + ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE); CRYPTO_THREAD_unlock(self_test_lock); return ok; } -void ossl_set_error_state(void) +void SELF_TEST_disable_conditional_error_state(void) { - FIPS_state = FIPS_STATE_ERROR; - ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE); + FIPS_conditional_error_check = 0; +} + +void ossl_set_error_state(const char *type) +{ + int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0); + + if (!cond_test || (FIPS_conditional_error_check == 1)) { + FIPS_state = FIPS_STATE_ERROR; + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE); + } else { + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR); + } } int ossl_prov_is_running(void) diff --git a/providers/fips/self_test.h b/providers/fips/self_test.h index 20f8a12472..205623cc3d 100644 --- a/providers/fips/self_test.h +++ b/providers/fips/self_test.h @@ -21,6 +21,9 @@ typedef struct self_test_post_params_st { const char *indicator_data; /* data to perform MAC on */ const char *indicator_checksum_data; /* Expected MAC integrity value */ + /* Used for continuous tests */ + const char *conditional_error_check; + /* BIO callbacks supplied to the FIPS provider */ OSSL_FUNC_BIO_new_file_fn *bio_new_file_cb; OSSL_FUNC_BIO_new_membuf_fn *bio_new_buffer_cb; @@ -34,3 +37,5 @@ typedef struct self_test_post_params_st { int SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test); int SELF_TEST_kats(OSSL_SELF_TEST *event, OPENSSL_CTX *libctx); + +void SELF_TEST_disable_conditional_error_state(void); diff --git a/providers/implementations/rands/crngt.c b/providers/implementations/rands/crngt.c index 9a9e9c703b..e23485291b 100644 --- a/providers/implementations/rands/crngt.c +++ b/providers/implementations/rands/crngt.c @@ -16,6 +16,7 @@ #include <openssl/evp.h> #include <openssl/core_dispatch.h> #include <openssl/params.h> +#include <openssl/self_test.h> #include "prov/providercommon.h" #include "prov/provider_ctx.h" #include "internal/cryptlib.h" @@ -99,7 +100,7 @@ static int prov_crngt_compare_previous(const unsigned char *prev, const int res = memcmp(prev, cur, sz) != 0; if (!res) - ossl_set_error_state(); + ossl_set_error_state(OSSL_SELF_TEST_TYPE_CRNG); return res; } diff --git a/providers/prov_running.c b/providers/prov_running.c index 7e62dedf4d..379fd5d25c 100644 --- a/providers/prov_running.c +++ b/providers/prov_running.c @@ -11,11 +11,11 @@ #include "prov/providercommon.h" /* By default, our providers don't have an error state */ -void ossl_set_error_state(void) +void ossl_set_error_state(const char *type) { } -/* By default, out providers are always in a happy state */ +/* By default, our providers are always in a happy state */ int ossl_prov_is_running(void) { return 1; |