File libgcrypt-fips_run_selftest_at_constructor.patch of Package libgcrypt.7109

Index: libgcrypt-1.6.1/src/global.c
===================================================================
--- libgcrypt-1.6.1.orig/src/global.c	2015-09-03 14:18:15.843893341 +0200
+++ libgcrypt-1.6.1/src/global.c	2015-09-03 14:29:40.803466149 +0200
@@ -125,6 +125,16 @@ global_init (void)
   if (err)
     goto fail;
 
+  int no_secmem_save;
+  /* it should be always 0 at this point but let's keep on the safe side */
+  no_secmem_save = no_secure_memory;
+  no_secure_memory = 1;
+  err = _gcry_fips_run_selftests (0);
+  no_secure_memory = no_secmem_save;
+
+  if (err)
+    goto fail;
+
   return;
 
  fail:
@@ -542,8 +552,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd,
 
     case GCRYCTL_FIPS_MODE_P:
       if (fips_mode ()
-          && !_gcry_is_fips_mode_inactive ()
-          && !no_secure_memory)
+          && !_gcry_is_fips_mode_inactive ())
 	rc = GPG_ERR_GENERAL; /* Used as TRUE value */
       break;
 
Index: libgcrypt-1.6.1/src/fips.c
===================================================================
--- libgcrypt-1.6.1.orig/src/fips.c	2015-09-03 14:18:15.843893341 +0200
+++ libgcrypt-1.6.1/src/fips.c	2015-09-03 14:18:17.954919825 +0200
@@ -607,6 +607,39 @@ get_library_path(const char *symbolname,
     return rv;
 }
 
+static gpg_error_t
+get_hmac_path(char **fname)
+{
+  char libpath[4096];
+  gpg_error_t err;
+
+  if (get_library_path ("gcry_check_version", libpath, sizeof(libpath)))
+    err = gpg_error_from_syserror ();
+  else
+    {
+      *fname = _gcry_malloc (strlen (libpath) + 1 + 5 + 1 );
+      if (!*fname)
+        err = gpg_error_from_syserror ();
+      else
+        {
+          char *p;
+
+          /* Prefix the basename with a dot.  */
+          strcpy (*fname, libpath);
+          p = strrchr (*fname, '/');
+          if (p)
+            p++;
+          else
+            p = *fname;
+          memmove (p+1, p, strlen (p)+1);
+          *p = '.';
+          strcat (*fname, ".hmac");
+          err = 0;
+        }
+    }
+  return err;
+}
+
 /* Run an integrity check on the binary.  Returns 0 on success.  */
 static int
 check_binary_integrity (void)
@@ -631,25 +664,9 @@ check_binary_integrity (void)
         err = gpg_error (GPG_ERR_INTERNAL);
       else
         {
-          fname = _gcry_malloc (strlen (libpath) + 1 + 5 + 1 );
-          if (!fname)
-            err = gpg_error_from_syserror ();
-          else
-            {
-              FILE *fp;
-              char *p;
-
-              /* Prefix the basename with a dot.  */
-              strcpy (fname, libpath);
-              p = strrchr (fname, '/');
-              if (p)
-                p++;
-              else
-                p = fname;
-              memmove (p+1, p, strlen (p)+1);
-              *p = '.';
-              strcat (fname, ".hmac");
-
+            FILE *fp;
+            err = get_hmac_path(&fname);
+            if (!err) {
               /* Open the file.  */
               fp = fopen (fname, "r");
               if (!fp)
@@ -696,6 +713,33 @@ check_binary_integrity (void)
 #endif
 }
 
+int
+can_skip_selftests(void)
+{
+  char *fname = NULL;
+  int ret = 0;
+
+  if (fips_mode())
+    return 0;
+
+  if (get_hmac_path(&fname))
+    return 0;
+
+  /* check the hmac presence */
+  if (access(fname, F_OK))
+      /* no hmac file is present, don't run the tests */
+      if (errno == ENOENT)
+          ret = 1;
+  /* otherwise one of these events happened:
+     access() returned 0
+       -> run the tests
+     some error other than ENOENT occurred
+       -> run the tests anyway and let them fail
+  */
+
+  xfree(fname);
+  return ret;
+}
 
 /* Run the self-tests.  If EXTENDED is true, extended versions of the
    selftest are run, that is more tests than required by FIPS.  */
@@ -705,6 +749,9 @@ _gcry_fips_run_selftests (int extended)
   enum module_states result = STATE_ERROR;
   gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
 
+  if (can_skip_selftests())
+    return 0;
+
   if (fips_mode ())
     fips_new_state (STATE_SELFTEST);