diff -up openssl-1.0.1e/crypto/fips/fips.c.fips-ctor openssl-1.0.1e/crypto/fips/fips.c --- openssl-1.0.1e/crypto/fips/fips.c.fips-ctor 2013-09-26 13:52:30.767885457 +0200 +++ openssl-1.0.1e/crypto/fips/fips.c 2013-09-26 14:01:29.406010187 +0200 @@ -60,6 +60,8 @@ #include #include #include +#include +#include #include "fips_locl.h" #ifdef OPENSSL_FIPS @@ -198,8 +200,10 @@ bin2hex(void *buf, size_t len) return hex; } -#define HMAC_PREFIX "." -#define HMAC_SUFFIX ".hmac" +#define HMAC_PREFIX "." +#ifndef HMAC_SUFFIX +#define HMAC_SUFFIX ".hmac" +#endif #define READ_BUFFER_LENGTH 16384 static char * @@ -279,19 +283,13 @@ end: } static int -FIPSCHECK_verify(const char *libname, const char *symbolname) +FIPSCHECK_verify(const char *path) { - char path[PATH_MAX+1]; - int rv; + int rv = 0; FILE *hf; char *hmacpath, *p; char *hmac = NULL; size_t n; - - rv = get_library_path(libname, symbolname, path, sizeof(path)); - - if (rv < 0) - return 0; hmacpath = make_hmac_path(path); if (hmacpath == NULL) @@ -341,6 +339,53 @@ end: return 1; } +static int +verify_checksums(void) + { + int rv; + char path[PATH_MAX+1]; + char *p; + + /* we need to avoid dlopening libssl, assume both libcrypto and libssl + are in the same directory */ + + rv = get_library_path("libcrypto.so." SHLIB_VERSION_NUMBER, "FIPS_mode_set", path, sizeof(path)); + if (rv < 0) + return 0; + + rv = FIPSCHECK_verify(path); + if (!rv) + return 0; + + /* replace libcrypto with libssl */ + while ((p = strstr(path, "libcrypto.so")) != NULL) + { + p = stpcpy(p, "libssl"); + memmove(p, p+3, strlen(p+2)); + } + + rv = FIPSCHECK_verify(path); + if (!rv) + return 0; + return 1; + } + +#ifndef FIPS_MODULE_PATH +#define FIPS_MODULE_PATH "/etc/system-fips" +#endif + +int +FIPS_module_installed(void) + { + int rv; + rv = access(FIPS_MODULE_PATH, F_OK); + if (rv < 0 && errno != ENOENT) + rv = 0; + + /* Installed == true */ + return !rv; + } + int FIPS_module_mode_set(int onoff, const char *auth) { int ret = 0; @@ -379,15 +424,7 @@ int FIPS_module_mode_set(int onoff, cons } #endif - if(!FIPSCHECK_verify("libcrypto.so." SHLIB_VERSION_NUMBER,"FIPS_mode_set")) - { - FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH); - fips_selftest_fail = 1; - ret = 0; - goto end; - } - - if(!FIPSCHECK_verify("libssl.so." SHLIB_VERSION_NUMBER,"SSL_CTX_new")) + if(!verify_checksums()) { FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,FIPS_R_FINGERPRINT_DOES_NOT_MATCH); fips_selftest_fail = 1; diff -up openssl-1.0.1e/crypto/fips/fips.h.fips-ctor openssl-1.0.1e/crypto/fips/fips.h --- openssl-1.0.1e/crypto/fips/fips.h.fips-ctor 2013-09-26 13:52:30.814886515 +0200 +++ openssl-1.0.1e/crypto/fips/fips.h 2013-09-26 13:52:30.816886560 +0200 @@ -74,6 +74,7 @@ struct hmac_ctx_st; int FIPS_module_mode_set(int onoff, const char *auth); int FIPS_module_mode(void); +int FIPS_module_installed(void); const void *FIPS_rand_check(void); int FIPS_selftest(void); int FIPS_selftest_failed(void); diff -up openssl-1.0.1e/crypto/o_init.c.fips-ctor openssl-1.0.1e/crypto/o_init.c --- openssl-1.0.1e/crypto/o_init.c.fips-ctor 2013-09-26 13:52:30.807886357 +0200 +++ openssl-1.0.1e/crypto/o_init.c 2013-09-26 14:00:21.000000000 +0200 @@ -71,6 +71,9 @@ static void init_fips_mode(void) char buf[2] = "0"; int fd; + /* Ensure the selftests always run */ + FIPS_mode_set(1); + if (__secure_getenv("OPENSSL_FORCE_FIPS_MODE") != NULL) { buf[0] = '1'; @@ -85,9 +88,15 @@ static void init_fips_mode(void) * otherwise. */ - if (buf[0] == '1') + if (buf[0] != '1') + { + /* drop down to non-FIPS mode if it is not requested */ + FIPS_mode_set(0); + } + else { - FIPS_mode_set(1); + /* abort if selftest failed */ + FIPS_selftest_check(); } } #endif @@ -96,13 +105,17 @@ static void init_fips_mode(void) * Currently only sets FIPS callbacks */ -void OPENSSL_init_library(void) +void __attribute__ ((constructor)) OPENSSL_init_library(void) { static int done = 0; if (done) return; done = 1; #ifdef OPENSSL_FIPS + if (!FIPS_module_installed()) + { + return; + } RAND_init_fips(); init_fips_mode(); if (!FIPS_mode())