SHA256
1
0
forked from pool/libgcrypt
libgcrypt/libgcrypt-global_init-constructor.patch
Vítězslav Čížek 9a7cde5372 Accepting request 805624 from home:pmonrealgonzalez:branches:devel:libraries:c_c++
- FIPS: libgcrypt: Double free in test_keys() on failed signature
  verification [bsc#1169944]
  * Use safer gcry_mpi_release() instead of mpi_free()
- Update patches:
  * libgcrypt-PCT-DSA.patch
  * libgcrypt-PCT-RSA.patch
  * libgcrypt-PCT-ECC.patch

- Ship the FIPS checksum file in the shared library package and
  create a separate trigger file for the FIPS selftests (bsc#1169569)
  * add libgcrypt-fips_selftest_trigger_file.patch
  * refresh libgcrypt-global_init-constructor.patch
- Remove libgcrypt-binary_integrity_in_non-FIPS.patch obsoleted
  by libgcrypt-global_init-constructor.patch

- FIPS: Verify that the generated signature and the original input
  differ in test_keys function for RSA, DSA and ECC: [bsc#1165539]
- Add zero-padding when qx and qy have different lengths when
  assembling the Q point from affine coordinates.
- Refreshed patches:
  * libgcrypt-PCT-DSA.patch
  * libgcrypt-PCT-RSA.patch
  * libgcrypt-PCT-ECC.patch

- FIPS: Switch the PCT to use the new signature operation [bsc#1165539]
  * Patches for DSA, RSA and ECDSA test_keys functions:
    - libgcrypt-PCT-DSA.patch
    - libgcrypt-PCT-RSA.patch
    - libgcrypt-PCT-ECC.patch
- Update patch: libgcrypt-FIPS-RSA-DSA-ECDSA-hashing-operation.patch

OBS-URL: https://build.opensuse.org/request/show/805624
OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=134
2020-05-14 15:39:34 +00:00

271 lines
7.3 KiB
Diff

Index: libgcrypt-1.8.2/src/global.c
===================================================================
--- libgcrypt-1.8.2.orig/src/global.c 2020-04-16 21:13:28.252717330 +0200
+++ libgcrypt-1.8.2/src/global.c 2020-04-16 21:13:47.960822991 +0200
@@ -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.8.2/src/fips.c
===================================================================
--- libgcrypt-1.8.2.orig/src/fips.c 2020-04-16 21:13:28.252717330 +0200
+++ libgcrypt-1.8.2/src/fips.c 2020-04-16 21:14:44.781127616 +0200
@@ -125,6 +125,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)
@@ -214,6 +215,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");
@@ -614,10 +632,10 @@ get_library_path(const char *libname, co
void *dl, *sym;
int rv = -1;
- dl = dlopen(libname, RTLD_LAZY);
- if (dl == NULL) {
- return -1;
- }
+ dl = dlopen(libname, RTLD_LAZY);
+ if (dl == NULL) {
+ return -1;
+ }
sym = dlsym(dl, symbolname);
@@ -632,6 +650,39 @@ get_library_path(const char *libname, co
return rv;
}
+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)
@@ -656,25 +707,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;
- 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");
-
+ FILE *fp;
+ err = get_hmac_path(&fname);
+ if (!err)
+ {
/* Open the file. */
fp = fopen (fname, "r");
if (!fp)
@@ -725,6 +761,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. */
@@ -733,26 +795,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;
@@ -762,6 +811,9 @@ _gcry_fips_run_selftests (int extended)
if (run_mac_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 ())
@@ -775,7 +827,8 @@ _gcry_fips_run_selftests (int extended)
ec = 0;
leave:
- fips_new_state (result);
+ if (fips_mode ())
+ fips_new_state (result);
return ec;
}
@@ -831,7 +884,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;
@@ -846,8 +898,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;