libgcrypt/libgcrypt-global_init-constructor.patch
Pedro Monreal Gonzalez dea0435690 Accepting request 868925 from home:pmonrealgonzalez:branches:devel:libraries:c_c++
- Update to 1.9.1
   * *Fix exploitable bug* in hash functions introduced with
     1.9.0. [bsc#1181632, CVE-2021-3345]
   * Return an error if a negative MPI is used with sexp scan
     functions.
   * Check for operational FIPS in the random and KDF functions.
   * Fix compile error on ARMv7 with NEON disabled.
   * Fix self-test in KDF module.
   * Improve assembler checks for better LTO support.
   * Fix 32-bit cross build on x86.
   * Fix non-NEON ARM assembly implementation for SHA512.
   * Fix build problems with the cipher_bulk_ops_t typedef.
   * Fix Ed25519 private key handling for preceding ZEROs.
   * Fix overflow in modular inverse implementation.
   * Fix register access for AVX/AVX2 implementations of Blake2.
   * Add optimized cipher and hash functions for s390x/zSeries.
   * Use hardware bit counting functionx when available.
   * Update DSA functions to match FIPS 186-3.
   * New self-tests for CMACs and KDFs.
   * Add bulk cipher functions for OFB and GCM modes.
- Update libgpg-error required version

- Use the suffix variable correctly in get_hmac_path()
- Rebase libgcrypt-fips_selftest_trigger_file.patch

- Add the global config file /etc/gcrypt/random.conf
  * This file can be used to globally change parameters of the random
    generator with the options: only-urandom and disable-jent.

- Update to 1.9.0:

OBS-URL: https://build.opensuse.org/request/show/868925
OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=142
2021-02-03 12:44:42 +00:00

255 lines
7.0 KiB
Diff

Index: libgcrypt-1.9.1/src/global.c
===================================================================
--- libgcrypt-1.9.1.orig/src/global.c
+++ libgcrypt-1.9.1/src/global.c
@@ -86,7 +86,7 @@ static gpg_err_code_t external_lock_test
likely to be called at startup. The suggested way for an
application to make sure that this has been called is by using
gcry_check_version. */
-static void
+static void __attribute__((constructor))
global_init (void)
{
gcry_error_t err = 0;
@@ -134,6 +134,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:
@@ -141,16 +151,6 @@ global_init (void)
}
-void __attribute__ ((constructor)) _gcry_global_constructor (void)
-{
- /* We always need the FSM lock to be functional. */
- _gcry_initialize_fsm_lock ();
-
- /* We run the integrity check at this point. The remaining
- selftests are run before use of the library by application. */
- _gcry_fips_run_selftests (0);
-}
-
/* This function is called by the macro fips_is_operational and makes
sure that the minimal initialization has been done. This is far
from a perfect solution and hides problems with an improper
Index: libgcrypt-1.9.1/src/fips.c
===================================================================
--- libgcrypt-1.9.1.orig/src/fips.c
+++ libgcrypt-1.9.1/src/fips.c
@@ -124,6 +124,7 @@ void
_gcry_initialize_fips_mode (int force)
{
static int done;
+ gpg_error_t err;
/* Make sure we are not accidentally called twice. */
if (done)
@@ -213,6 +214,23 @@ _gcry_initialize_fips_mode (int force)
/* Yes, we are in FIPS mode. */
FILE *fp;
+ /* Intitialize the lock to protect the FSM. */
+ err = gpgrt_lock_init (&fsm_lock);
+ if (err)
+ {
+ /* If that fails we can't do anything but abort the
+ * process. We need to use log_info so that the FSM won't
+ * get involved. */
+ log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n",
+ gpg_strerror (err));
+#ifdef HAVE_SYSLOG
+ syslog (LOG_USER|LOG_ERR, "Libgcrypt error: "
+ "creating FSM lock failed: %s - abort",
+ gpg_strerror (err));
+#endif /*HAVE_SYSLOG*/
+ abort ();
+ }
+
/* If the FIPS force files exists, is readable and has a number
!= 0 on its first line, we enable the enforced fips mode. */
fp = fopen (FIPS_FORCE_FILE, "r");
@@ -641,6 +659,39 @@ get_library_path(const char *libname, co
}
#endif
+static gpg_error_t
+get_hmac_path(char **fname)
+{
+ char libpath[4096];
+ gpg_error_t err;
+
+ if (get_library_path ("libgcrypt.so.20", "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)
@@ -665,25 +716,10 @@ check_binary_integrity (void)
err = gpg_error (GPG_ERR_INTERNAL);
else
{
- fname = xtrymalloc (strlen (libpath) + 1 + 5 + 1 );
- if (!fname)
- err = gpg_error_from_syserror ();
- else
+ FILE *fp;
+ err = get_hmac_path(&fname);
+ if (!err)
{
- 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");
-
/* Open the file. */
fp = fopen (fname, "r");
if (!fp)
@@ -734,6 +770,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. */
@@ -742,26 +805,13 @@ _gcry_fips_run_selftests (int extended)
{
enum module_states result = STATE_ERROR;
gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED;
- int in_poweron;
-
- lock_fsm ();
- in_poweron = (current_state == STATE_POWERON);
- unlock_fsm ();
-
- fips_new_state (STATE_SELFTEST);
- /* We first check the integrity of the binary.
- If run from the constructor we are in POWERON state,
- we return and finish the remaining selftests before
- real use of the library. It will be in the POWERON
- state meanwhile. */
- if (in_poweron)
- if (check_binary_integrity ())
- goto leave;
-
- if (in_poweron)
+ if (can_skip_selftests())
return 0;
+ if (fips_mode ())
+ fips_new_state (STATE_SELFTEST);
+
if (run_cipher_selftests (extended))
goto leave;
@@ -774,6 +824,9 @@ _gcry_fips_run_selftests (int extended)
if (run_kdf_selftests (extended))
goto leave;
+ if (check_binary_integrity ())
+ goto leave;
+
/* Run random tests before the pubkey tests because the latter
require random. */
if (run_random_selftests ())
@@ -787,7 +840,8 @@ _gcry_fips_run_selftests (int extended)
ec = 0;
leave:
- fips_new_state (result);
+ if (fips_mode ())
+ fips_new_state (result);
return ec;
}
@@ -843,7 +897,6 @@ fips_new_state (enum module_states new_s
{
case STATE_POWERON:
if (new_state == STATE_INIT
- || new_state == STATE_SELFTEST
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;
@@ -858,8 +911,6 @@ fips_new_state (enum module_states new_s
case STATE_SELFTEST:
if (new_state == STATE_OPERATIONAL
- || new_state == STATE_INIT
- || new_state == STATE_SELFTEST
|| new_state == STATE_ERROR
|| new_state == STATE_FATALERROR)
ok = 1;