forked from pool/libgcrypt
Pedro Monreal Gonzalez
dea0435690
- 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
255 lines
7.0 KiB
Diff
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;
|