From 5736923f12af58fea158c86291307c41c9f2c859 Mon Sep 17 00:00:00 2001 From: Pauli Date: Thu, 10 Sep 2020 07:08:57 +1000 Subject: [PATCH] FIPS: error mode is set from failed self tests and produced a limited number of errors when algorithm accesses are attempted Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/12801) --- crypto/err/openssl.txt | 2 ++ .../common/include/prov/providercommon.h | 4 +++ .../common/include/prov/providercommonerr.h | 2 ++ providers/common/provider_err.c | 4 +++ providers/fips/self_test.c | 29 +++++++++++++++++-- providers/prov_running.c | 6 ++++ 6 files changed, 44 insertions(+), 3 deletions(-) diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt index d0ba9c47be5..6c2e81efb9b 100644 --- a/crypto/err/openssl.txt +++ b/crypto/err/openssl.txt @@ -2877,6 +2877,8 @@ 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_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 PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE:165:\ illegal or unsupported padding mode diff --git a/providers/common/include/prov/providercommon.h b/providers/common/include/prov/providercommon.h index f6d27dababd..280d2d2072c 100644 --- a/providers/common/include/prov/providercommon.h +++ b/providers/common/include/prov/providercommon.h @@ -19,4 +19,8 @@ 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); + +/* 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 68bcfb48284..d4d3c7e8e8e 100644 --- a/providers/common/include/prov/providercommonerr.h +++ b/providers/common/include/prov/providercommonerr.h @@ -75,6 +75,8 @@ 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_ENTERING_ERROR_STATE 224 +# define PROV_R_FIPS_MODULE_IN_ERROR_STATE 225 # define PROV_R_GENERATE_ERROR 191 # define PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE 165 # define PROV_R_INAVLID_UKM_LENGTH 146 diff --git a/providers/common/provider_err.c b/providers/common/provider_err.c index 75f24f88d7c..329bb279ebb 100644 --- a/providers/common/provider_err.c +++ b/providers/common/provider_err.c @@ -58,6 +58,10 @@ 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_ENTERING_ERROR_STATE), + "fips module entering error state"}, + {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_FIPS_MODULE_IN_ERROR_STATE), + "fips module in error state"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_GENERATE_ERROR), "generate error"}, {ERR_PACK(ERR_LIB_PROV, 0, PROV_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE), "illegal or unsupported padding mode"}, diff --git a/providers/fips/self_test.c b/providers/fips/self_test.c index 8a70bdee7cf..b0df0863e26 100644 --- a/providers/fips/self_test.c +++ b/providers/fips/self_test.c @@ -32,6 +32,12 @@ #define FIPS_STATE_RUNNING 2 #define FIPS_STATE_ERROR 3 +/* + * The number of times the module will report it is in the error state + * before going quiet. + */ +#define FIPS_ERROR_REPORTING_RATE_LIMIT 10 + /* The size of a temp buffer used to read in data */ #define INTEGRITY_BUF_SIZE (4096) #define MAX_MD_SIZE 64 @@ -302,15 +308,32 @@ end: (*st->bio_free_cb)(bio_indicator); (*st->bio_free_cb)(bio_module); } - FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR; + if (ok) + FIPS_state = FIPS_STATE_RUNNING; + else + ossl_set_error_state(); CRYPTO_THREAD_unlock(self_test_lock); return ok; } +void ossl_set_error_state(void) +{ + FIPS_state = FIPS_STATE_ERROR; + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE); +} int ossl_prov_is_running(void) { - return FIPS_state == FIPS_STATE_RUNNING - || FIPS_state == FIPS_STATE_SELFTEST; + const int res = FIPS_state == FIPS_STATE_RUNNING + || FIPS_state == FIPS_STATE_SELFTEST; + static unsigned int rate_limit = 0; + + if (res) { + rate_limit = 0; + } else if (FIPS_state == FIPS_STATE_ERROR) { + if (rate_limit++ < FIPS_ERROR_REPORTING_RATE_LIMIT) + ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE); + } + return res; } diff --git a/providers/prov_running.c b/providers/prov_running.c index a65e4978d07..7e62dedf4d4 100644 --- a/providers/prov_running.c +++ b/providers/prov_running.c @@ -10,6 +10,12 @@ #include #include "prov/providercommon.h" +/* By default, our providers don't have an error state */ +void ossl_set_error_state(void) +{ +} + +/* By default, out providers are always in a happy state */ int ossl_prov_is_running(void) { return 1; -- 2.47.2