From f4ab4f07e366b70e69c43c2e1b03cf5dac4993e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ayd=C4=B1n=20Mercan?= Date: Mon, 16 Dec 2024 15:31:15 +0300 Subject: [PATCH] unify fips handling to isc_crypto and make the toggle one way Since algorithm fetching is handled purely in libisc, FIPS mode toggling can be purely done in within the library instead of provider fetching in the binary for OpenSSL >=3.0. Disabling FIPS mode isn't a realistic requirement and isn't done anywhere in the codebase. Make the FIPS mode toggle enable-only to reflect the situation. --- bin/delv/delv.c | 38 +------- bin/dig/dig.c | 38 +------- bin/dnssec/Makefile.am | 8 ++ bin/dnssec/dnssec-keygen.c | 56 ++--------- bin/dnssec/dnssec-ksr.c | 33 ++----- bin/dnssec/dnssec-signzone.c | 43 +-------- bin/named/main.c | 38 +------- bin/named/server.c | 3 +- bin/tests/system/feature-test.c | 6 +- lib/dns/dst_api.c | 2 +- lib/dns/opensslecdsa_link.c | 3 +- lib/isc/Makefile.am | 2 - lib/isc/crypto.c | 163 ++++++++++++++++++++++++++------ lib/isc/fips.c | 55 ----------- lib/isc/include/isc/crypto.h | 14 +++ lib/isc/include/isc/fips.h | 40 -------- lib/isc/tls.c | 1 - lib/isccfg/kaspconf.c | 6 +- tests/dns/dst_test.c | 4 +- tests/isc/hmac_test.c | 6 +- tests/isc/md_test.c | 9 +- 21 files changed, 200 insertions(+), 368 deletions(-) delete mode 100644 lib/isc/fips.c delete mode 100644 lib/isc/include/isc/fips.h diff --git a/bin/delv/delv.c b/bin/delv/delv.c index 1d63d143fd..c489df8671 100644 --- a/bin/delv/delv.c +++ b/bin/delv/delv.c @@ -26,16 +26,12 @@ #include #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif #include #include #include #include -#include +#include #include #include #include @@ -167,10 +163,6 @@ static dns_fixedname_t qfn; /* Default trust anchors */ static char anchortext[] = TRUST_ANCHORS; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -static OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif - /* * Static function prototypes */ @@ -1619,24 +1611,7 @@ preparse_args(int argc, char **argv) { while (strpbrk(option, single_dash_opts) == &option[0]) { switch (option[0]) { case 'F': -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - ERR_clear_error(); - fatal("Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - ERR_clear_error(); - fatal("Failed to load base provider"); - } -#endif - /* Already in FIPS mode? */ - if (isc_fips_mode()) { - break; - } - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { fatal("setting FIPS mode failed"); } break; @@ -2309,14 +2284,5 @@ cleanup: isc_managers_destroy(&mctx, &loopmgr, &netmgr); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - if (base != NULL) { - OSSL_PROVIDER_unload(base); - } - if (fips != NULL) { - OSSL_PROVIDER_unload(fips); - } -#endif - return 0; } diff --git a/bin/dig/dig.c b/bin/dig/dig.c index b7a1a24cd6..23f5b57130 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -20,8 +20,8 @@ #include #include +#include #include -#include #include #include #include @@ -73,14 +73,6 @@ static bool short_form = false, printcmd = true, plusquest = false, static uint32_t splitwidth = 0xffffffff; #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif - -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -static OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif /*% opcode text */ static const char *const opcodetext[] = { @@ -2931,24 +2923,7 @@ preparse_args(int argc, char **argv) { debugging = true; break; case 'F': -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - ERR_clear_error(); - fatal("Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - ERR_clear_error(); - fatal("Failed to load base provider"); - } -#endif - /* Already in FIPS mode? */ - if (isc_fips_mode()) { - break; - } - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { fatal("setting FIPS mode failed"); } break; @@ -3476,14 +3451,5 @@ main(int argc, char **argv) { dig_startup(); dig_shutdown(); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - if (base != NULL) { - OSSL_PROVIDER_unload(base); - } - if (fips != NULL) { - OSSL_PROVIDER_unload(fips); - } -#endif - return exitcode; } diff --git a/bin/dnssec/Makefile.am b/bin/dnssec/Makefile.am index 0268fc196b..bc4654e72b 100644 --- a/bin/dnssec/Makefile.am +++ b/bin/dnssec/Makefile.am @@ -41,6 +41,14 @@ dnssec_keygen_LDADD = \ $(LDADD) \ $(OPENSSL_LIBS) +dnssec_ksr_CPPFLAGS= \ + $(AM_CPPFLAGS) \ + $(OPENSSL_CFLAGS) + +dnssec_ksr_LDADD = \ + $(LDADD) \ + $(OPENSSL_LIBS) + dnssec_signzone_CPPFLAGS = \ $(AM_CPPFLAGS) \ $(OPENSSL_CFLAGS) diff --git a/bin/dnssec/dnssec-keygen.c b/bin/dnssec/dnssec-keygen.c index e04f73bd11..adc98f07be 100644 --- a/bin/dnssec/dnssec-keygen.c +++ b/bin/dnssec/dnssec-keygen.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include #include #include #include @@ -58,11 +58,6 @@ #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif - #include "dnssectool.h" const char *program = "dnssec-keygen"; @@ -151,7 +146,7 @@ usage(void) { fprintf(stderr, " -l : configuration file with dnssec-policy " "statement\n"); fprintf(stderr, " -a :\n"); - if (!isc_fips_mode()) { + if (!isc_crypto_fips_mode()) { fprintf(stderr, " RSASHA1 | NSEC3RSASHA1 |\n"); } fprintf(stderr, " RSASHA256 | RSASHA512 |\n"); @@ -159,7 +154,7 @@ usage(void) { fprintf(stderr, " ED25519 | ED448\n"); fprintf(stderr, " -3: use NSEC3-capable algorithm\n"); fprintf(stderr, " -b :\n"); - if (!isc_fips_mode()) { + if (!isc_crypto_fips_mode()) { fprintf(stderr, " RSASHA1:\t[%d..%d]\n", min_rsa, MAX_RSA); fprintf(stderr, " NSEC3RSASHA1:\t[%d..%d]\n", min_rsa, @@ -288,7 +283,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { fatal("unsupported algorithm: %s", algstr); } - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { /* verify only in FIPS mode */ switch (ctx->alg) { case DST_ALG_RSASHA1: @@ -341,7 +336,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { switch (ctx->alg) { case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { fatal("key size not specified (-b " "option)"); } @@ -501,7 +496,7 @@ keygen(keygen_ctx_t *ctx, isc_mem_t *mctx, int argc, char **argv) { switch (ctx->alg) { case DNS_KEYALG_RSASHA1: case DNS_KEYALG_NSEC3RSASHA1: - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { fatal("SHA1 based keys not supported in FIPS mode"); } FALLTHROUGH; @@ -847,10 +842,6 @@ main(int argc, char **argv) { isc_textregion_t r; unsigned char c; int ch; - bool set_fips_mode = false; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif keygen_ctx_t ctx = { .options = DST_TYPE_PRIVATE | DST_TYPE_PUBLIC, @@ -1109,7 +1100,9 @@ main(int argc, char **argv) { ctx.prepub = strtottl(isc_commandline_argument); break; case 'F': - set_fips_mode = true; + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } break; case '?': if (isc_commandline_option != '?') { @@ -1136,32 +1129,11 @@ main(int argc, char **argv) { ctx.quiet = true; } - if (set_fips_mode) { -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - ERR_clear_error(); - fatal("Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - ERR_clear_error(); - fatal("Failed to load base provider"); - } -#endif - if (!isc_fips_mode()) { - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { - fatal("setting FIPS mode failed"); - } - } - } - /* * The DST subsystem will set FIPS mode if requested at build time. * The minimum sizes are both raised to 2048. */ - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { min_rsa = min_dh = 2048; } @@ -1310,14 +1282,6 @@ main(int argc, char **argv) { } isc_mem_destroy(&mctx); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - if (base != NULL) { - OSSL_PROVIDER_unload(base); - } - if (fips != NULL) { - OSSL_PROVIDER_unload(fips); - } -#endif if (freeit != NULL) { free(freeit); } diff --git a/bin/dnssec/dnssec-ksr.c b/bin/dnssec/dnssec-ksr.c index 3260e3ff64..9954eebf37 100644 --- a/bin/dnssec/dnssec-ksr.c +++ b/bin/dnssec/dnssec-ksr.c @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -362,7 +362,7 @@ create_key(ksr_ctx_t *ksr, dns_kasp_t *kasp, dns_kasp_key_t *kaspkey, switch (ksr->alg) { case DST_ALG_RSASHA1: case DST_ALG_NSEC3RSASHA1: - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { /* verify-only in FIPS mode */ fatal("unsupported algorithm: %s", algstr); } @@ -1348,10 +1348,6 @@ main(int argc, char *argv[]) { isc_buffer_t buf; int ch; char *endp; - bool set_fips_mode = false; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif ksr_ctx_t ksr = { .now = isc_stdtime_now(), }; @@ -1371,7 +1367,9 @@ main(int argc, char *argv[]) { ksr.now, &ksr.setend); break; case 'F': - set_fips_mode = true; + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } break; case 'f': ksr.file = isc_commandline_argument; @@ -1425,31 +1423,12 @@ main(int argc, char *argv[]) { * The DST subsystem will set FIPS mode if requested at build time. * The minimum sizes are both raised to 2048. */ - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { min_rsa = min_dh = 2048; } setup_logging(); - if (set_fips_mode) { -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - fatal("Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - fatal("Failed to load base provider"); - } -#endif - if (!isc_fips_mode()) { - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { - fatal("setting FIPS mode failed"); - } - } - } - /* zone */ namestr = argv[1]; name = dns_fixedname_initname(&fname); diff --git a/bin/dnssec/dnssec-signzone.c b/bin/dnssec/dnssec-signzone.c index caf8f125d1..06fd6b686b 100644 --- a/bin/dnssec/dnssec-signzone.c +++ b/bin/dnssec/dnssec-signzone.c @@ -42,7 +42,6 @@ #include #include #include -#include #include #include #include @@ -90,10 +89,6 @@ #include #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif #include "dnssectool.h" @@ -3380,10 +3375,6 @@ main(int argc, char *argv[]) { bool set_optout = false; bool set_iter = false; bool nonsecify = false; - bool set_fips_mode = false; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif atomic_init(&shuttingdown, false); atomic_init(&finished, false); @@ -3672,7 +3663,9 @@ main(int argc, char *argv[]) { break; case 'F': - set_fips_mode = true; + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { + fatal("setting FIPS mode failed"); + } break; case '?': @@ -3743,27 +3736,6 @@ main(int argc, char *argv[]) { isc_managers_create(&mctx, nloops, &loopmgr, &netmgr); - if (set_fips_mode) { -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - ERR_clear_error(); - fatal("Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - ERR_clear_error(); - fatal("Failed to load base provider"); - } -#endif - if (!isc_fips_mode()) { - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { - fatal("setting FIPS mode failed"); - } - } - } - setup_logging(); argc -= isc_commandline_index; @@ -4135,15 +4107,6 @@ main(int argc, char *argv[]) { isc_mem_stats(mctx, stdout); } -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - if (base != NULL) { - OSSL_PROVIDER_unload(base); - } - if (fips != NULL) { - OSSL_PROVIDER_unload(fips); - } -#endif - isc_managers_destroy(&mctx, &loopmgr, &netmgr); if (printstats) { diff --git a/bin/named/main.c b/bin/named/main.c index 81af56c153..6b21a2d420 100644 --- a/bin/named/main.c +++ b/bin/named/main.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include #include @@ -91,10 +90,6 @@ #include #include #include -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -#include -#include -#endif #ifdef HAVE_LIBXML2 #include #include @@ -155,10 +150,6 @@ static bool transferstuck = false; static bool disable6 = false; static bool disable4 = false; -#if OPENSSL_VERSION_NUMBER >= 0x30000000L -static OSSL_PROVIDER *fips = NULL, *base = NULL; -#endif - void named_main_earlywarning(const char *format, ...) { va_list args; @@ -952,25 +943,7 @@ parse_command_line(int argc, char *argv[]) { named_main_earlyfatal("option '-X' has been removed"); break; case 'F': -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - fips = OSSL_PROVIDER_load(NULL, "fips"); - if (fips == NULL) { - ERR_clear_error(); - named_main_earlyfatal( - "Failed to load FIPS provider"); - } - base = OSSL_PROVIDER_load(NULL, "base"); - if (base == NULL) { - OSSL_PROVIDER_unload(fips); - ERR_clear_error(); - named_main_earlyfatal( - "Failed to load base provider"); - } -#endif - if (isc_fips_mode()) { /* Already in FIPS mode. */ - break; - } - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { named_main_earlyfatal( "setting FIPS mode failed"); } @@ -1574,15 +1547,6 @@ main(int argc, char *argv[]) { named_os_shutdown(); -#if OPENSSL_VERSION_NUMBER >= 0x30000000L - if (base != NULL) { - OSSL_PROVIDER_unload(base); - } - if (fips != NULL) { - OSSL_PROVIDER_unload(fips); - } -#endif - #ifdef HAVE_GPERFTOOLS_PROFILER ProfilerStop(); #endif /* ifdef HAVE_GPERFTOOLS_PROFILER */ diff --git a/bin/named/server.c b/bin/named/server.c index 236eadf612..2ddc529bd4 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -9377,7 +9376,7 @@ view_loaded(void *arg) { isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, "FIPS mode is %s", - isc_fips_mode() ? "enabled" : "disabled"); + isc_crypto_fips_mode() ? "enabled" : "disabled"); #if HAVE_LIBSYSTEMD sd_notifyf(0, diff --git a/bin/tests/system/feature-test.c b/bin/tests/system/feature-test.c index f39922dcbc..8f58e133f1 100644 --- a/bin/tests/system/feature-test.c +++ b/bin/tests/system/feature-test.c @@ -23,7 +23,7 @@ #include #endif -#include +#include #include #include #include @@ -134,7 +134,7 @@ main(int argc, char **argv) { return 1; #endif #else - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { #if OPENSSL_VERSION_NUMBER >= 0x30000000L return 0; #else @@ -149,7 +149,7 @@ main(int argc, char **argv) { #if defined(ENABLE_FIPS_MODE) return 0; #else - return isc_fips_mode() ? 0 : 1; + return isc_crypto_fips_mode() ? 0 : 1; #endif } diff --git a/lib/dns/dst_api.c b/lib/dns/dst_api.c index 444eb8fbfd..6446de1f6a 100644 --- a/lib/dns/dst_api.c +++ b/lib/dns/dst_api.c @@ -38,9 +38,9 @@ #include #include +#include #include #include -#include #include #include #include diff --git a/lib/dns/opensslecdsa_link.c b/lib/dns/opensslecdsa_link.c index 74cab51ec2..821a50289d 100644 --- a/lib/dns/opensslecdsa_link.c +++ b/lib/dns/opensslecdsa_link.c @@ -26,7 +26,6 @@ #include #endif -#include #include #include #include @@ -707,7 +706,7 @@ opensslecdsa_createctx(dst_key_t *key, dst_context_t *dctx) { } #if OPENSSL_VERSION_NUMBER >= 0x30200000L - if (!isc_fips_mode()) { + if (!isc_crypto_fips_mode()) { ret = opensslecdsa_set_deterministic( pctx, dctx->key->key_alg); if (ret != ISC_R_SUCCESS) { diff --git a/lib/isc/Makefile.am b/lib/isc/Makefile.am index 4359b517b7..4978ab4ed1 100644 --- a/lib/isc/Makefile.am +++ b/lib/isc/Makefile.am @@ -25,7 +25,6 @@ libisc_la_HEADERS = \ include/isc/errno.h \ include/isc/error.h \ include/isc/file.h \ - include/isc/fips.h \ include/isc/formatcheck.h \ include/isc/fuzz.h \ include/isc/getaddresses.h \ @@ -133,7 +132,6 @@ libisc_la_SOURCES = \ errno2result.h \ error.c \ file.c \ - fips.c \ getaddresses.c \ hash.c \ hashmap.c \ diff --git a/lib/isc/crypto.c b/lib/isc/crypto.c index b3ab28c4c5..209f49e90c 100644 --- a/lib/isc/crypto.c +++ b/lib/isc/crypto.c @@ -11,13 +11,17 @@ * information regarding copyright ownership. */ +#include #include #include #include #include +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ + #include -#include #include #include #include @@ -25,6 +29,10 @@ static isc_mem_t *isc__crypto_mctx = NULL; +#if OPENSSL_VERSION_NUMBER >= 0x30000000L +static OSSL_PROVIDER *base = NULL, *fips = NULL; +#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ + const EVP_MD *isc__crypto_md5 = NULL; const EVP_MD *isc__crypto_sha1 = NULL; const EVP_MD *isc__crypto_sha224 = NULL; @@ -49,7 +57,6 @@ const EVP_MD *isc__crypto_sha512 = NULL; isc__crypto_##alg = NULL; \ } \ } - #else /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ #define md_register_algorithm(alg, algname) \ { \ @@ -61,6 +68,34 @@ const EVP_MD *isc__crypto_sha512 = NULL; #define md_unregister_algorithm(alg) #endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ +static isc_result_t +register_algorithms(void) { + if (!isc_crypto_fips_mode()) { + md_register_algorithm(md5, "MD5"); + } + + md_register_algorithm(sha1, "SHA1"); + md_register_algorithm(sha224, "SHA224"); + md_register_algorithm(sha256, "SHA256"); + md_register_algorithm(sha384, "SHA384"); + md_register_algorithm(sha512, "SHA512"); + + return ISC_R_SUCCESS; +} + +static void +unregister_algorithms(void) { + md_unregister_algorithm(sha512); + md_unregister_algorithm(sha384); + md_unregister_algorithm(sha256); + md_unregister_algorithm(sha224); + md_unregister_algorithm(sha1); + md_unregister_algorithm(md5); +} + +#undef md_unregister_algorithm +#undef md_register_algorithm + #if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L /* * This was crippled with LibreSSL, so just skip it: @@ -132,6 +167,82 @@ isc__crypto_free_ex(void *ptr, const char *file, int line) { #endif /* !defined(LIBRESSL_VERSION_NUMBER) */ +#if defined(HAVE_EVP_DEFAULT_PROPERTIES_ENABLE_FIPS) +bool +isc_crypto_fips_mode(void) { + return EVP_default_properties_is_fips_enabled(NULL) != 0; +} + +isc_result_t +isc_crypto_fips_enable(void) { + if (isc_crypto_fips_mode()) { + return ISC_R_SUCCESS; + } + + INSIST(fips == NULL); + fips = OSSL_PROVIDER_load(NULL, "fips"); + if (fips == NULL) { + return isc_tlserr2result( + ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, + "OSSL_PROVIDER_load", ISC_R_CRYPTOFAILURE); + } + + INSIST(base == NULL); + base = OSSL_PROVIDER_load(NULL, "base"); + if (base == NULL) { + OSSL_PROVIDER_unload(fips); + return isc_tlserr2result( + ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, + "OSS_PROVIDER_load", ISC_R_CRYPTOFAILURE); + } + + if (EVP_default_properties_enable_fips(NULL, 1) == 0) { + return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_CRYPTO, + "EVP_default_properties_enable_fips", + ISC_R_CRYPTOFAILURE); + } + + unregister_algorithms(); + register_algorithms(); + + return ISC_R_SUCCESS; +} +#elif defined(HAVE_FIPS_MODE) +bool +isc_crypto_fips_mode(void) { + return FIPS_mode() != 0; +} + +isc_result_t +isc_crypto_fips_enable(void) { + if (isc_crypto_fips_mode()) { + return ISC_R_SUCCESS; + } + + if (FIPS_mode_set(1) == 0) { + return isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, + ISC_LOGMODULE_CRYPTO, "FIPS_mode_set", + ISC_R_CRYPTOFAILURE); + } + + unregister_algorithms(); + register_algorithms(); + + return ISC_R_SUCCESS; +} +#else +bool +isc_crypto_fips_mode(void) { + return false; +} + +isc_result_t +isc_crypto_fips_enable(void) { + return ISC_R_NOTIMPLEMENTED; +} +#endif + void isc__crypto_setdestroycheck(bool check) { isc_mem_setdestroycheck(isc__crypto_mctx, check); @@ -167,6 +278,16 @@ isc__crypto_initialize(void) { RUNTIME_CHECK(OPENSSL_init_ssl(opts, NULL) == 1); + register_algorithms(); + +#if defined(ENABLE_FIPS_MODE) + if (isc_crypto_fips_enable() != ISC_R_SUCCESS) { + ERR_clear_error(); + FATAL_ERROR("Failed to toggle FIPS mode but is " + "required for this build"); + } +#endif + /* Protect ourselves against unseeded PRNG */ if (RAND_status() != 1) { isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_CRYPTO, @@ -175,39 +296,23 @@ isc__crypto_initialize(void) { "cannot be initialized (see the `PRNG not " "seeded' message in the OpenSSL FAQ)"); } - -#if defined(ENABLE_FIPS_MODE) - if (!isc_fips_mode()) { - if (isc_fips_set_mode(1) != ISC_R_SUCCESS) { - isc_tlserr2result(ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_CRYPTO, "FIPS_mode_set", - ISC_R_CRYPTOFAILURE); - exit(EXIT_FAILURE); - } - } -#endif - - md_register_algorithm(md5, "MD5"); - md_register_algorithm(sha1, "SHA1"); - md_register_algorithm(sha224, "SHA224"); - md_register_algorithm(sha256, "SHA256"); - md_register_algorithm(sha384, "SHA384"); - md_register_algorithm(sha512, "SHA512"); } void isc__crypto_shutdown(void) { - md_unregister_algorithm(sha512); - md_unregister_algorithm(sha384); - md_unregister_algorithm(sha256); - md_unregister_algorithm(sha224); - md_unregister_algorithm(sha1); - md_unregister_algorithm(md5); + unregister_algorithms(); + +#if OPENSSL_VERSION_NUMBER >= 0x30000000L + if (base != NULL) { + OSSL_PROVIDER_unload(base); + } + + if (fips != NULL) { + OSSL_PROVIDER_unload(fips); + } +#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */ OPENSSL_cleanup(); isc_mem_destroy(&isc__crypto_mctx); } - -#undef md_unregister_algorithm -#undef md_register_algorithm diff --git a/lib/isc/fips.c b/lib/isc/fips.c deleted file mode 100644 index 43454516bb..0000000000 --- a/lib/isc/fips.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -/*! \file */ - -#include -#include - -#if defined(HAVE_EVP_DEFAULT_PROPERTIES_ENABLE_FIPS) -#include -bool -isc_fips_mode(void) { - return EVP_default_properties_is_fips_enabled(NULL) != 0; -} - -isc_result_t -isc_fips_set_mode(int mode) { - return EVP_default_properties_enable_fips(NULL, mode) != 0 - ? ISC_R_SUCCESS - : ISC_R_FAILURE; -} -#elif defined(HAVE_FIPS_MODE) -#include - -bool -isc_fips_mode(void) { - return FIPS_mode() != 0; -} - -isc_result_t -isc_fips_set_mode(int mode) { - return FIPS_mode_set(mode) != 0 ? ISC_R_SUCCESS : ISC_R_FAILURE; -} -#else -bool -isc_fips_mode(void) { - return false; -} - -isc_result_t -isc_fips_set_mode(int mode) { - UNUSED(mode); - return ISC_R_NOTIMPLEMENTED; -} -#endif diff --git a/lib/isc/include/isc/crypto.h b/lib/isc/include/isc/crypto.h index 9119205ce7..14bdd46933 100644 --- a/lib/isc/include/isc/crypto.h +++ b/lib/isc/include/isc/crypto.h @@ -24,6 +24,20 @@ extern const EVP_MD *isc__crypto_sha256; extern const EVP_MD *isc__crypto_sha384; extern const EVP_MD *isc__crypto_sha512; +bool +isc_crypto_fips_mode(void); +/* + * Return if FIPS mode is currently enabled or not. + */ + +isc_result_t +isc_crypto_fips_enable(void); +/* + * Enable FIPS mode. It cannot be disabled afterwards. + * + * This function is NOT thread safe. + */ + /** * Private */ diff --git a/lib/isc/include/isc/fips.h b/lib/isc/include/isc/fips.h deleted file mode 100644 index 087197b8d3..0000000000 --- a/lib/isc/include/isc/fips.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) Internet Systems Consortium, Inc. ("ISC") - * - * SPDX-License-Identifier: MPL-2.0 - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, you can obtain one at https://mozilla.org/MPL/2.0/. - * - * See the COPYRIGHT file distributed with this work for additional - * information regarding copyright ownership. - */ - -#pragma once - -/***** -***** Module Info -*****/ - -/*** - *** Imports - ***/ - -#include - -/*** - *** Functions - ***/ - -bool -isc_fips_mode(void); -/* - * Return if FIPS mode is currently enabled or not - */ - -isc_result_t -isc_fips_set_mode(int mode); -/* - * Enable FIPS mode. - */ diff --git a/lib/isc/tls.c b/lib/isc/tls.c index b98c7721ed..0a646837bb 100644 --- a/lib/isc/tls.c +++ b/lib/isc/tls.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/lib/isccfg/kaspconf.c b/lib/isccfg/kaspconf.c index 9ab717a66f..a258f06d24 100644 --- a/lib/isccfg/kaspconf.c +++ b/lib/isccfg/kaspconf.c @@ -15,7 +15,7 @@ #include #include -#include +#include #include #include #include @@ -227,7 +227,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp, goto cleanup; } - if (check_algorithms && isc_fips_mode() && + if (check_algorithms && isc_crypto_fips_mode() && (key->algorithm == DNS_KEYALG_RSASHA1 || key->algorithm == DNS_KEYALG_NSEC3RSASHA1)) { @@ -259,7 +259,7 @@ cfg_kaspkey_fromconfig(const cfg_obj_t *config, dns_kasp_t *kasp, case DNS_KEYALG_NSEC3RSASHA1: case DNS_KEYALG_RSASHA256: case DNS_KEYALG_RSASHA512: - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { min = 2048; } else { min = DNS_KEYALG_RSASHA512 ? 1024 : 512; diff --git a/tests/dns/dst_test.c b/tests/dns/dst_test.c index 10bb24bc9b..46d46a5c02 100644 --- a/tests/dns/dst_test.c +++ b/tests/dns/dst_test.c @@ -30,8 +30,8 @@ #define UNIT_TESTING #include +#include #include -#include #include #include #include @@ -471,7 +471,7 @@ ISC_RUN_TEST_IMPL(ecdsa_determinism_test) { dst_context_destroy(&ctx); #if OPENSSL_VERSION_NUMBER >= 0x30200000L - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { assert_memory_not_equal(sigbuf1->base, sigbuf2->base, siglen); } else { assert_memory_equal(sigbuf1->base, sigbuf2->base, siglen); diff --git a/tests/isc/hmac_test.c b/tests/isc/hmac_test.c index 75c604b50d..67483c9d4e 100644 --- a/tests/isc/hmac_test.c +++ b/tests/isc/hmac_test.c @@ -32,7 +32,7 @@ #include #include -#include +#include #include #include #include @@ -134,7 +134,7 @@ ISC_RUN_TEST_IMPL(isc_hmac_init) { assert_int_equal(isc_hmac_init(hmac_st, "", 0, NULL), ISC_R_NOTIMPLEMENTED); - if (!isc_fips_mode()) { + if (!isc_crypto_fips_mode()) { expect_assert_failure(isc_hmac_init(NULL, "", 0, ISC_MD_MD5)); expect_assert_failure( @@ -229,7 +229,7 @@ ISC_RUN_TEST_IMPL(isc_hmac_final) { ISC_RUN_TEST_IMPL(isc_hmac_md5) { isc_hmac_t *hmac_st = *state; - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { skip(); return; } diff --git a/tests/isc/md_test.c b/tests/isc/md_test.c index 4ef72383df..e8cdeeb4ae 100644 --- a/tests/isc/md_test.c +++ b/tests/isc/md_test.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include #include #include @@ -120,7 +120,10 @@ ISC_RUN_TEST_IMPL(isc_md_init) { assert_int_equal(isc_md_init(md, NULL), ISC_R_NOTIMPLEMENTED); - if (!isc_fips_mode()) { + if (isc_crypto_fips_mode()) { + assert_int_equal(isc_md_init(md, ISC_MD_MD5), + ISC_R_NOTIMPLEMENTED); + } else { assert_int_equal(isc_md_init(md, ISC_MD_MD5), ISC_R_SUCCESS); assert_int_equal(isc_md_reset(md), ISC_R_SUCCESS); } @@ -199,7 +202,7 @@ ISC_RUN_TEST_IMPL(isc_md_final) { ISC_RUN_TEST_IMPL(isc_md_md5) { isc_md_t *md = *state; - if (isc_fips_mode()) { + if (isc_crypto_fips_mode()) { skip(); return; }