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

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