Blame SOURCES/libgcrypt-1.8.3-fips-ctor.patch

66e42d
diff -up libgcrypt-1.8.3/cipher/md.c.fips-ctor libgcrypt-1.8.3/cipher/md.c
66e42d
--- libgcrypt-1.8.3/cipher/md.c.fips-ctor	2017-11-23 19:16:58.000000000 +0100
66e42d
+++ libgcrypt-1.8.3/cipher/md.c	2018-07-12 13:24:54.088403006 +0200
66e42d
@@ -411,11 +411,8 @@ md_enable (gcry_md_hd_t hd, int algorith
66e42d
 
66e42d
   if (!err && algorithm == GCRY_MD_MD5 && fips_mode ())
66e42d
     {
66e42d
-      _gcry_inactivate_fips_mode ("MD5 used");
66e42d
       if (_gcry_enforced_fips_mode () )
66e42d
         {
66e42d
-          /* We should never get to here because we do not register
66e42d
-             MD5 in enforced fips mode. But better throw an error.  */
66e42d
           err = GPG_ERR_DIGEST_ALGO;
66e42d
         }
66e42d
     }
66e42d
diff -up libgcrypt-1.8.3/src/fips.c.fips-ctor libgcrypt-1.8.3/src/fips.c
66e42d
--- libgcrypt-1.8.3/src/fips.c.fips-ctor	2018-07-12 13:24:54.075402698 +0200
66e42d
+++ libgcrypt-1.8.3/src/fips.c	2018-07-12 13:24:54.088403006 +0200
66e42d
@@ -91,6 +91,31 @@ static void fips_new_state (enum module_
66e42d
 
66e42d
 
66e42d
 
66e42d
+/* Initialize the FSM lock - this function may only
66e42d
+   be called once and is intended to be run from the library
66e42d
+   constructor  */
66e42d
+void
66e42d
+_gcry_initialize_fsm_lock (void)
66e42d
+{
66e42d
+  gpg_error_t err;
66e42d
+  /* Intitialize the lock to protect the FSM.  */
66e42d
+  err = gpgrt_lock_init (&fsm_lock);
66e42d
+  if (err)
66e42d
+    {
66e42d
+      /* If that fails we can't do anything but abort the
66e42d
+         process. We need to use log_info so that the FSM won't
66e42d
+         get involved.  */
66e42d
+      log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
66e42d
+                gpg_strerror (err));
66e42d
+#ifdef HAVE_SYSLOG
66e42d
+      syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
66e42d
+              "creating FSM lock failed: %s - abort",
66e42d
+              gpg_strerror (err));
66e42d
+#endif /*HAVE_SYSLOG*/
66e42d
+      abort ();
66e42d
+    }
66e42d
+}
66e42d
+
66e42d
 /* Check whether the OS is in FIPS mode and record that in a module
66e42d
    local variable.  If FORCE is passed as true, fips mode will be
66e42d
    enabled anyway. Note: This function is not thread-safe and should
66e42d
@@ -100,7 +125,6 @@ void
66e42d
 _gcry_initialize_fips_mode (int force)
66e42d
 {
66e42d
   static int done;
66e42d
-  gpg_error_t err;
66e42d
 
66e42d
   /* Make sure we are not accidentally called twice.  */
66e42d
   if (done)
66e42d
@@ -179,24 +203,6 @@ _gcry_initialize_fips_mode (int force)
66e42d
       /* Yes, we are in FIPS mode.  */
66e42d
       FILE *fp;
66e42d
 
66e42d
-      /* Intitialize the lock to protect the FSM.  */
66e42d
-      err = gpgrt_lock_init (&fsm_lock);
66e42d
-      if (err)
66e42d
-        {
66e42d
-          /* If that fails we can't do anything but abort the
66e42d
-             process. We need to use log_info so that the FSM won't
66e42d
-             get involved.  */
66e42d
-          log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
66e42d
-                    gpg_strerror (err));
66e42d
-#ifdef HAVE_SYSLOG
66e42d
-          syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
66e42d
-                  "creating FSM lock failed: %s - abort",
66e42d
-                  gpg_strerror (err));
66e42d
-#endif /*HAVE_SYSLOG*/
66e42d
-          abort ();
66e42d
-        }
66e42d
-
66e42d
-
66e42d
       /* If the FIPS force files exists, is readable and has a number
66e42d
          != 0 on its first line, we enable the enforced fips mode.  */
66e42d
       fp = fopen (FIPS_FORCE_FILE, "r");
66e42d
@@ -359,16 +365,20 @@ _gcry_fips_is_operational (void)
66e42d
 {
66e42d
   int result;
66e42d
 
66e42d
-  if (!fips_mode ())
66e42d
+  lock_fsm ();
66e42d
+  if (current_state == STATE_POWERON && !fips_mode ())
66e42d
+    /* If we are at this point in POWERON state it means the FIPS
66e42d
+       module installation was not completed. (/etc/system-fips
66e42d
+      is not present.) */
66e42d
     result = 1;
66e42d
   else
66e42d
     {
66e42d
-      lock_fsm ();
66e42d
-      if (current_state == STATE_INIT)
66e42d
+      if (current_state == STATE_INIT || current_state == STATE_SELFTEST)
66e42d
         {
66e42d
-          /* If we are still in the INIT state, we need to run the
66e42d
-             selftests so that the FSM can eventually get into
66e42d
-             operational state.  Given that we would need a 2-phase
66e42d
+          /* If we are still in the INIT (or SELFTEST) state,
66e42d
+             we need to run (or finish) the selftests so
66e42d
+             that the FSM can eventually get into operational
66e42d
+             state. Given that we would need a 2-phase
66e42d
              initialization of libgcrypt, but that has traditionally
66e42d
              not been enforced, we use this on demand self-test
66e42d
              checking.  Note that Proper applications would do the
66e42d
@@ -384,9 +394,11 @@ _gcry_fips_is_operational (void)
66e42d
           lock_fsm ();
66e42d
         }
66e42d
 
66e42d
-      result = (current_state == STATE_OPERATIONAL);
66e42d
-      unlock_fsm ();
66e42d
+      result = (current_state == STATE_OPERATIONAL) || !fips_mode ();
66e42d
+      /* We always run the selftests but ignore the result
66e42d
+         in non-FIPS mode. */
66e42d
     }
66e42d
+  unlock_fsm ();
66e42d
   return result;
66e42d
 }
66e42d
 
66e42d
@@ -709,9 +721,25 @@ _gcry_fips_run_selftests (int extended)
66e42d
 {
66e42d
   enum module_states result = STATE_ERROR;
66e42d
   gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
66e42d
+  int in_poweron;
66e42d
 
66e42d
-  if (fips_mode ())
66e42d
-    fips_new_state (STATE_SELFTEST);
66e42d
+  lock_fsm ();
66e42d
+  in_poweron = (current_state == STATE_POWERON);
66e42d
+  unlock_fsm ();
66e42d
+
66e42d
+  fips_new_state (STATE_SELFTEST);
66e42d
+
66e42d
+  /* We first check the integrity of the binary.
66e42d
+     If run from the constructor we are in POWERON state,
66e42d
+     we return and finish the remaining selftests before
66e42d
+     real use of the library. It will be in the POWERON
66e42d
+     state meanwhile.  */
66e42d
+  if (in_poweron)
66e42d
+    if (check_binary_integrity ())
66e42d
+      goto leave;
66e42d
+
66e42d
+  if (in_poweron)
66e42d
+    return 0;
66e42d
 
66e42d
   if (run_cipher_selftests (extended))
66e42d
     goto leave;
66e42d
@@ -730,18 +758,12 @@ _gcry_fips_run_selftests (int extended)
66e42d
   if (run_pubkey_selftests (extended))
66e42d
     goto leave;
66e42d
 
66e42d
-  /* Now check the integrity of the binary.  We do this this after
66e42d
-     having checked the HMAC code.  */
66e42d
-  if (check_binary_integrity ())
66e42d
-    goto leave;
66e42d
-
66e42d
   /* All selftests passed.  */
66e42d
   result = STATE_OPERATIONAL;
66e42d
   ec = 0;
66e42d
 
66e42d
  leave:
66e42d
-  if (fips_mode ())
66e42d
-    fips_new_state (result);
66e42d
+  fips_new_state (result);
66e42d
 
66e42d
   return ec;
66e42d
 }
66e42d
@@ -797,6 +819,7 @@ fips_new_state (enum module_states new_s
66e42d
     {
66e42d
     case STATE_POWERON:
66e42d
       if (new_state == STATE_INIT
66e42d
+          || new_state == STATE_SELFTEST
66e42d
           || new_state == STATE_ERROR
66e42d
           || new_state == STATE_FATALERROR)
66e42d
         ok = 1;
66e42d
@@ -811,6 +834,8 @@ fips_new_state (enum module_states new_s
66e42d
 
66e42d
     case STATE_SELFTEST:
66e42d
       if (new_state == STATE_OPERATIONAL
66e42d
+          || new_state == STATE_INIT
66e42d
+          || new_state == STATE_SELFTEST
66e42d
           || new_state == STATE_ERROR
66e42d
           || new_state == STATE_FATALERROR)
66e42d
         ok = 1;
66e42d
diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c
66e42d
--- libgcrypt-1.8.3/src/global.c.fips-ctor	2017-11-23 19:25:58.000000000 +0100
66e42d
+++ libgcrypt-1.8.3/src/global.c	2018-07-17 19:15:43.933827112 +0200
66e42d
@@ -141,6 +141,29 @@ global_init (void)
66e42d
 }
66e42d
 
66e42d
 
66e42d
+#ifndef FIPS_MODULE_PATH
66e42d
+#define FIPS_MODULE_PATH "/etc/system-fips"
66e42d
+#endif
66e42d
+
66e42d
+void __attribute__ ((constructor)) _gcry_global_constructor (void)
66e42d
+{
66e42d
+  int rv;
66e42d
+
66e42d
+  /* We always need the FSM lock to be functional. */
66e42d
+  _gcry_initialize_fsm_lock ();
66e42d
+
66e42d
+  rv = access (FIPS_MODULE_PATH, F_OK);
66e42d
+  if (rv < 0 && errno != ENOENT)
66e42d
+    rv = 0;
66e42d
+
66e42d
+  if (!rv)
66e42d
+    {
66e42d
+      /* We run the integrity check at this point. The remaining
66e42d
+         selftests are run before use of the library by application. */
66e42d
+      _gcry_fips_run_selftests (0);
66e42d
+    }
66e42d
+}
66e42d
+
66e42d
 /* This function is called by the macro fips_is_operational and makes
66e42d
    sure that the minimal initialization has been done.  This is far
66e42d
    from a perfect solution and hides problems with an improper
66e42d
@@ -671,8 +694,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd,
66e42d
 
66e42d
     case GCRYCTL_FIPS_MODE_P:
66e42d
       if (fips_mode ()
66e42d
-          && !_gcry_is_fips_mode_inactive ()
66e42d
-          && !no_secure_memory)
66e42d
+          && !_gcry_is_fips_mode_inactive ())
66e42d
 	rc = GPG_ERR_GENERAL; /* Used as TRUE value */
66e42d
       break;
66e42d
 
66e42d
@@ -749,9 +771,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd,
66e42d
       break;
66e42d
 
66e42d
     case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
66e42d
-      if (!any_init_done)
66e42d
+      if (fips_mode ())
66e42d
         {
66e42d
-          /* Not yet initialized at all.  Set the enforced fips mode flag */
66e42d
+          /* We are in FIPS mode, we can set the enforced fips mode flag. */
66e42d
           _gcry_set_preferred_rng_type (0);
66e42d
           _gcry_set_enforced_fips_mode ();
66e42d
         }
66e42d
diff -up libgcrypt-1.8.3/src/g10lib.h.fips-ctor libgcrypt-1.8.3/src/g10lib.h
66e42d
--- libgcrypt-1.8.3/src/g10lib.h.fips-ctor	2017-11-23 19:16:58.000000000 +0100
66e42d
+++ libgcrypt-1.8.3/src/g10lib.h	2018-07-12 13:24:54.089403030 +0200
66e42d
@@ -422,6 +422,8 @@ gpg_err_code_t _gcry_sexp_vextract_param
66e42d
 
66e42d
 /*-- fips.c --*/
66e42d
 
66e42d
+void _gcry_initialize_fsm_lock (void);
66e42d
+
66e42d
 void _gcry_initialize_fips_mode (int force);
66e42d
 
66e42d
 int _gcry_fips_mode (void);