cfec1a
diff -up openssl-1.0.2a/crypto/fips/fips.c.fips-ctor openssl-1.0.2a/crypto/fips/fips.c
cfec1a
--- openssl-1.0.2a/crypto/fips/fips.c.fips-ctor	2015-04-21 17:42:18.702765856 +0200
cfec1a
+++ openssl-1.0.2a/crypto/fips/fips.c	2015-04-21 17:42:18.742766794 +0200
cfec1a
@@ -60,6 +60,8 @@
cfec1a
 #include <dlfcn.h>
cfec1a
 #include <stdio.h>
cfec1a
 #include <stdlib.h>
cfec1a
+#include <unistd.h>
cfec1a
+#include <errno.h>
cfec1a
 #include "fips_locl.h"
cfec1a
 
cfec1a
 #ifdef OPENSSL_FIPS
cfec1a
@@ -201,7 +203,9 @@ static char *bin2hex(void *buf, size_t l
cfec1a
 }
cfec1a
 
cfec1a
 # define HMAC_PREFIX "."
cfec1a
-# define HMAC_SUFFIX ".hmac"
cfec1a
+# ifndef HMAC_SUFFIX
cfec1a
+#  define HMAC_SUFFIX ".hmac"
cfec1a
+# endif
cfec1a
 # define READ_BUFFER_LENGTH 16384
cfec1a
 
cfec1a
 static char *make_hmac_path(const char *origpath)
cfec1a
@@ -279,20 +283,14 @@ static int compute_file_hmac(const char
cfec1a
     return rv;
cfec1a
 }
cfec1a
 
cfec1a
-static int FIPSCHECK_verify(const char *libname, const char *symbolname)
cfec1a
+static int FIPSCHECK_verify(const char *path)
cfec1a
 {
cfec1a
-    char path[PATH_MAX + 1];
cfec1a
-    int rv;
cfec1a
+    int rv = 0;
cfec1a
     FILE *hf;
cfec1a
     char *hmacpath, *p;
cfec1a
     char *hmac = NULL;
cfec1a
     size_t n;
cfec1a
 
cfec1a
-    rv = get_library_path(libname, symbolname, path, sizeof(path));
cfec1a
-
cfec1a
-    if (rv < 0)
cfec1a
-        return 0;
cfec1a
-
cfec1a
     hmacpath = make_hmac_path(path);
cfec1a
     if (hmacpath == NULL)
cfec1a
         return 0;
cfec1a
@@ -343,6 +341,51 @@ static int FIPSCHECK_verify(const char *
cfec1a
     return 1;
cfec1a
 }
cfec1a
 
cfec1a
+static int verify_checksums(void)
cfec1a
+{
cfec1a
+    int rv;
cfec1a
+    char path[PATH_MAX + 1];
cfec1a
+    char *p;
cfec1a
+
cfec1a
+    /* we need to avoid dlopening libssl, assume both libcrypto and libssl
cfec1a
+       are in the same directory */
cfec1a
+
cfec1a
+    rv = get_library_path("libcrypto.so." SHLIB_VERSION_NUMBER,
cfec1a
+                          "FIPS_mode_set", path, sizeof(path));
cfec1a
+    if (rv < 0)
cfec1a
+        return 0;
cfec1a
+
cfec1a
+    rv = FIPSCHECK_verify(path);
cfec1a
+    if (!rv)
cfec1a
+        return 0;
cfec1a
+
cfec1a
+    /* replace libcrypto with libssl */
cfec1a
+    while ((p = strstr(path, "libcrypto.so")) != NULL) {
cfec1a
+        p = stpcpy(p, "libssl");
cfec1a
+        memmove(p, p + 3, strlen(p + 2));
cfec1a
+    }
cfec1a
+
cfec1a
+    rv = FIPSCHECK_verify(path);
cfec1a
+    if (!rv)
cfec1a
+        return 0;
cfec1a
+    return 1;
cfec1a
+}
cfec1a
+
cfec1a
+# ifndef FIPS_MODULE_PATH
cfec1a
+#  define FIPS_MODULE_PATH "/etc/system-fips"
cfec1a
+# endif
cfec1a
+
cfec1a
+int FIPS_module_installed(void)
cfec1a
+{
cfec1a
+    int rv;
cfec1a
+    rv = access(FIPS_MODULE_PATH, F_OK);
cfec1a
+    if (rv < 0 && errno != ENOENT)
cfec1a
+        rv = 0;
cfec1a
+
cfec1a
+    /* Installed == true */
cfec1a
+    return !rv;
cfec1a
+}
cfec1a
+
cfec1a
 int FIPS_module_mode_set(int onoff, const char *auth)
cfec1a
 {
cfec1a
     int ret = 0;
cfec1a
@@ -380,17 +423,7 @@ int FIPS_module_mode_set(int onoff, cons
cfec1a
         }
cfec1a
 # endif
cfec1a
 
cfec1a
-        if (!FIPSCHECK_verify
cfec1a
-            ("libcrypto.so." SHLIB_VERSION_NUMBER, "FIPS_mode_set")) {
cfec1a
-            FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,
cfec1a
-                    FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
cfec1a
-            fips_selftest_fail = 1;
cfec1a
-            ret = 0;
cfec1a
-            goto end;
cfec1a
-        }
cfec1a
-
cfec1a
-        if (!FIPSCHECK_verify
cfec1a
-            ("libssl.so." SHLIB_VERSION_NUMBER, "SSL_CTX_new")) {
cfec1a
+        if (!verify_checksums()) {
cfec1a
             FIPSerr(FIPS_F_FIPS_MODULE_MODE_SET,
cfec1a
                     FIPS_R_FINGERPRINT_DOES_NOT_MATCH);
cfec1a
             fips_selftest_fail = 1;
cfec1a
diff -up openssl-1.0.2a/crypto/fips/fips.h.fips-ctor openssl-1.0.2a/crypto/fips/fips.h
cfec1a
--- openssl-1.0.2a/crypto/fips/fips.h.fips-ctor	2015-04-21 17:42:18.739766724 +0200
cfec1a
+++ openssl-1.0.2a/crypto/fips/fips.h	2015-04-21 17:42:18.743766818 +0200
cfec1a
@@ -74,6 +74,7 @@ extern "C" {
cfec1a
 
cfec1a
     int FIPS_module_mode_set(int onoff, const char *auth);
cfec1a
     int FIPS_module_mode(void);
cfec1a
+    int FIPS_module_installed(void);
cfec1a
     const void *FIPS_rand_check(void);
cfec1a
     int FIPS_selftest(void);
cfec1a
     int FIPS_selftest_failed(void);
cfec1a
diff -up openssl-1.0.2a/crypto/o_init.c.fips-ctor openssl-1.0.2a/crypto/o_init.c
cfec1a
--- openssl-1.0.2a/crypto/o_init.c.fips-ctor	2015-04-21 17:42:18.732766559 +0200
cfec1a
+++ openssl-1.0.2a/crypto/o_init.c	2015-04-21 17:45:02.662613173 +0200
cfec1a
@@ -74,6 +74,9 @@ static void init_fips_mode(void)
cfec1a
     char buf[2] = "0";
cfec1a
     int fd;
cfec1a
 
cfec1a
+    /* Ensure the selftests always run */
cfec1a
+    FIPS_mode_set(1);
cfec1a
+
cfec1a
     if (secure_getenv("OPENSSL_FORCE_FIPS_MODE") != NULL) {
cfec1a
         buf[0] = '1';
cfec1a
     } else if ((fd = open(FIPS_MODE_SWITCH_FILE, O_RDONLY)) >= 0) {
cfec1a
@@ -85,8 +88,12 @@ static void init_fips_mode(void)
cfec1a
      * otherwise..
cfec1a
      */
cfec1a
 
cfec1a
-    if (buf[0] == '1') {
cfec1a
-        FIPS_mode_set(1);
cfec1a
+    if (buf[0] != '1') {
cfec1a
+        /* drop down to non-FIPS mode if it is not requested */
cfec1a
+        FIPS_mode_set(0);
cfec1a
+    } else {
cfec1a
+        /* abort if selftest failed */
cfec1a
+        FIPS_selftest_check();
cfec1a
     }
cfec1a
 }
cfec1a
 #endif
cfec1a
@@ -96,13 +103,16 @@ static void init_fips_mode(void)
cfec1a
  * sets FIPS callbacks
cfec1a
  */
cfec1a
 
cfec1a
-void OPENSSL_init_library(void)
cfec1a
+void __attribute__ ((constructor)) OPENSSL_init_library(void)
cfec1a
 {
cfec1a
     static int done = 0;
cfec1a
     if (done)
cfec1a
         return;
cfec1a
     done = 1;
cfec1a
 #ifdef OPENSSL_FIPS
cfec1a
+    if (!FIPS_module_installed()) {
cfec1a
+        return;
cfec1a
+    }
cfec1a
     RAND_init_fips();
cfec1a
     init_fips_mode();
cfec1a
     if (!FIPS_mode()) {