From c4cee27f9b6292034625d2488347e822ac12daab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Sun, 14 Oct 2018 14:32:02 +0200 Subject: [PATCH] Add support for enabling and enforcing FIPS mode in OpenSSL: * Add configure option --enable-fips-mode that detects and enables FIPS mode * Add a function to enable FIPS mode and call it on crypto init * Log an OpenSSL error when FIPS_mode_set() fails and exit * Report FIPS mode status in a separate log message from named --- bin/named/server.c | 11 ++++++++++- config.h.in | 3 +++ configure | 42 ++++++++++++++++++++++++++++++++++++++++++ configure.in | 15 +++++++++++++++ lib/dns/openssl_link.c | 19 +++++++++++++++++++ 5 files changed, 89 insertions(+), 1 deletion(-) diff --git a/bin/named/server.c b/bin/named/server.c index d94b05ef3e..af3bc162b1 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -9243,8 +9243,17 @@ view_loaded(void *arg) { "forcing zone maintenance"); named_os_started(); + +#ifdef HAVE_FIPS_MODE isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, - NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, "running"); + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "FIPS mode is %s", + FIPS_mode() ? "enabled" : "disabled"); +#endif + + isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL, + NAMED_LOGMODULE_SERVER, ISC_LOG_NOTICE, + "running"); } return (ISC_R_SUCCESS); diff --git a/config.h.in b/config.h.in index 18cd748b74..ad008059fc 100644 --- a/config.h.in +++ b/config.h.in @@ -147,6 +147,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H +/* Define to 1 if you have the `FIPS_mode' function. */ +#undef HAVE_FIPS_MODE + /* Build with GeoIP support */ #undef HAVE_GEOIP diff --git a/configure b/configure index aa53344c96..05ed9a2412 100755 --- a/configure +++ b/configure @@ -899,6 +899,7 @@ with_geoip with_locktype with_libtool with_openssl +enable_fips_mode with_cc_alg enable_native_pkcs11 with_pkcs11 @@ -1595,6 +1596,7 @@ Optional Features: --enable-kqueue use BSD kqueue when available [default=yes] --enable-epoll use Linux epoll when available [default=auto] --enable-devpoll use /dev/poll when available [default=yes] + --enable-fips-mode enable FIPS mode in OpenSSL library [default=no] --enable-native-pkcs11 use native PKCS11 for public-key crypto [default=no] --enable-largefile 64-bit file support --enable-backtrace log stack backtrace on abort [default=yes] @@ -15715,6 +15717,46 @@ fi done +# +# Check whether FIPS mode is available and whether we should enable it +# +# Check whether --enable-fips-mode was given. +if test "${enable_fips_mode+set}" = set; then : + enableval=$enable_fips_mode; +else + enable_fips_mode="no" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable FIPS mode in OpenSSL library" >&5 +$as_echo_n "checking whether to enable FIPS mode in OpenSSL library... " >&6; } +case $enable_fips_mode in #( + yes) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + for ac_func in FIPS_mode +do : + ac_fn_c_check_func "$LINENO" "FIPS_mode" "ac_cv_func_FIPS_mode" +if test "x$ac_cv_func_FIPS_mode" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FIPS_MODE 1 +_ACEOF + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "OpenSSL FIPS mode requested but not available. +See \`config.log' for more details" "$LINENO" 5; } +fi +done + ;; #( + no) : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } ;; #( + *) : + ;; +esac + CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" diff --git a/configure.in b/configure.in index 284c8ab0d3..e26918d20d 100644 --- a/configure.in +++ b/configure.in @@ -836,6 +836,21 @@ AC_CHECK_FUNCS([EVP_aes_128_ecb EVP_aes_192_ecb EVP_aes_256_ecb], [:], # AC_CHECK_FUNCS([DH_get0_key ECDSA_SIG_get0 RSA_set0_key DSA_get0_pqg]) +# +# Check whether FIPS mode is available and whether we should enable it +# +AC_ARG_ENABLE([fips-mode], + [AS_HELP_STRING([--enable-fips-mode], + [enable FIPS mode in OpenSSL library [default=no]])], + [], [enable_fips_mode="no"]) + +AC_MSG_CHECKING([whether to enable FIPS mode in OpenSSL library]) +AS_CASE([$enable_fips_mode], + [yes], [AC_MSG_RESULT([yes]) + AC_CHECK_FUNCS([FIPS_mode], + [], [AC_MSG_FAILURE([OpenSSL FIPS mode requested but not available.])])], + [no], [AC_MSG_RESULT([no])]) + CFLAGS="$save_CFLAGS" LIBS="$save_LIBS" LDFLAGS="$save_LDFLAGS" diff --git a/lib/dns/openssl_link.c b/lib/dns/openssl_link.c index d24b4f438c..8e75849e02 100644 --- a/lib/dns/openssl_link.c +++ b/lib/dns/openssl_link.c @@ -53,6 +53,23 @@ static int nlocks; static ENGINE *e = NULL; #endif +static void +enable_fips_mode(void) { +#ifdef HAVE_FIPS_MODE + if (FIPS_mode() != 0) { + /* + * FIPS mode is already enabled. + */ + return; + } + + if (FIPS_mode_set(1) == 0) { + dst__openssl_toresult2("FIPS_mode_set", DST_R_OPENSSLFAILURE); + exit(1); + } +#endif /* HAVE_FIPS_MODE */ +} + #if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER) static void lock_callback(int mode, int type, const char *file, int line) { @@ -145,6 +162,8 @@ dst__openssl_init(const char *engine) { UNUSED(engine); #endif + enable_fips_mode(); + #ifdef DNS_CRYPTO_LEAKS CRYPTO_malloc_debug_init(); CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);