Fix missing global initialization in fips_is_operational
authorJussi Kivilinna <jussi.kivilinna@iki.fi>
Sat, 27 Oct 2018 12:48:29 +0000 (15:48 +0300)
committerJussi Kivilinna <jussi.kivilinna@iki.fi>
Sat, 27 Oct 2018 12:57:22 +0000 (15:57 +0300)
* src/g10lib.h (_gcry_global_any_init_done): New extern.
(fips_is_operational): Check for _gcry_global_any_init_done and call
_gcry_global_is_operational.
* src/global.c (any_init_done): Rename to ...
(_gcry_global_any_init_done): ... this and make externally available.
--

Commit b6e6ace324440f564df664e27f8276ef01f76795 "Add fast path for
_gcry_fips_is_operational" inadvertently replaced function call to
_gcry_global_is_operational with call to _gcry_fips_is_operational
in fips_is_operational macro. This can cause libgcrypt to miss
initialization. This patch restores _gcry_global_is_operational
functionality to fips_is_operational macro while keeping fast-path
to reduce call-overhead to gcry_* functions.

Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
src/g10lib.h
src/global.c

index d52eef3..c1f84ee 100644 (file)
 \f
 
 /*-- src/global.c -*/
+extern int _gcry_global_any_init_done;
 int _gcry_global_is_operational (void);
 gcry_err_code_t _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr);
 void _gcry_check_heap (const void *a);
@@ -466,7 +467,9 @@ int _gcry_fips_is_operational (void);
 
 /* Return true if the library is in the operational state.  */
 #define fips_is_operational()   \
-       (!fips_mode () || _gcry_fips_is_operational ())
+        (!_gcry_global_any_init_done ? \
+                _gcry_global_is_operational() : \
+                (!fips_mode () || _gcry_global_is_operational ()))
 
 #define fips_not_operational()  (GPG_ERR_NOT_OPERATIONAL)
 
index 6c2486c..d82c680 100644 (file)
@@ -54,7 +54,7 @@ static unsigned int debug_flags;
 static int force_fips_mode;
 
 /* Controlled by global_init().  */
-static int any_init_done;
+int _gcry_global_any_init_done;
 
 /*
  * Functions called before and after blocking syscalls.
@@ -91,9 +91,9 @@ global_init (void)
 {
   gcry_error_t err = 0;
 
-  if (any_init_done)
+  if (_gcry_global_any_init_done)
     return;
-  any_init_done = 1;
+  _gcry_global_any_init_done = 1;
 
   /* Tell the random module that we have seen an init call.  */
   _gcry_set_preferred_rng_type (0);
@@ -161,7 +161,7 @@ global_init (void)
 int
 _gcry_global_is_operational (void)
 {
-  if (!any_init_done)
+  if (!_gcry_global_any_init_done)
     {
 #ifdef HAVE_SYSLOG
       syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: "
@@ -570,7 +570,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_ANY_INITIALIZATION_P:
-      if (any_init_done)
+      if (_gcry_global_any_init_done)
        rc = GPG_ERR_GENERAL;
       break;
 
@@ -682,7 +682,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
          selftest is triggered.  It is not possible to put the libraty
          into fips mode after having passed the initialization. */
       _gcry_set_preferred_rng_type (0);
-      if (!any_init_done)
+      if (!_gcry_global_any_init_done)
         {
           /* Not yet initialized at all.  Set a flag so that we are put
              into fips mode during initialization.  */
@@ -749,7 +749,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       break;
 
     case GCRYCTL_SET_ENFORCED_FIPS_FLAG:
-      if (!any_init_done)
+      if (!_gcry_global_any_init_done)
         {
           /* Not yet initialized at all.  Set the enforced fips mode flag */
           _gcry_set_preferred_rng_type (0);
@@ -773,7 +773,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
       {
         int *ip = va_arg (arg_ptr, int*);
         if (ip)
-          *ip = _gcry_get_rng_type (!any_init_done);
+          *ip = _gcry_get_rng_type (!_gcry_global_any_init_done);
       }
       break;
 
@@ -801,7 +801,8 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, va_list arg_ptr)
         int npers = va_arg (arg_ptr, int);
         if (va_arg (arg_ptr, void *) || npers < 0)
           rc = GPG_ERR_INV_ARG;
-        else if (_gcry_get_rng_type (!any_init_done) != GCRY_RNG_TYPE_FIPS)
+        else if (_gcry_get_rng_type (!_gcry_global_any_init_done)
+                 != GCRY_RNG_TYPE_FIPS)
           rc = GPG_ERR_NOT_SUPPORTED;
         else
           rc = _gcry_rngdrbg_reinit (flagstr, pers, npers);