From 655523d262f82cd41b0adaf3ed21440bc7e38170bd6be6e047eea0e9940d76ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Mon, 25 Mar 2019 18:52:00 +0000 Subject: [PATCH] Accepting request 688356 from home:vitezslav_cizek:branches:devel:libraries:c_c++ - Don't run full self-tests from constructor (bsc#1097073) * Don't call global_init() from the constructor, _gcry_global_constructor() from libgcrypt-1.8.3-fips-ctor.patch takes care of the binary integrity check instead. * Only the binary checksum will be verified, the remaining self-tests will be run upon the library initialization - Add libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch - Drop libgcrypt-init-at-elf-load-fips.patch and libgcrypt-fips_run_selftest_at_constructor.patch obsoleted by libgcrypt-1.8.3-fips-ctor.patch - Skip all the self-tests except for binary integrity when called from the constructor (bsc#1097073) * Added libgcrypt-1.8.3-fips-ctor.patch from Fedora OBS-URL: https://build.opensuse.org/request/show/688356 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=121 --- libgcrypt-1.8.3-fips-ctor.patch | 260 +++++++++++++++++++ libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch | 28 ++ libgcrypt.changes | 21 ++ libgcrypt.spec | 19 +- 4 files changed, 313 insertions(+), 15 deletions(-) create mode 100644 libgcrypt-1.8.3-fips-ctor.patch create mode 100644 libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch diff --git a/libgcrypt-1.8.3-fips-ctor.patch b/libgcrypt-1.8.3-fips-ctor.patch new file mode 100644 index 0000000..34a5e95 --- /dev/null +++ b/libgcrypt-1.8.3-fips-ctor.patch @@ -0,0 +1,260 @@ +Index: libgcrypt-1.8.4/cipher/md.c +=================================================================== +--- libgcrypt-1.8.4.orig/cipher/md.c 2019-03-25 16:58:52.844354398 +0100 ++++ libgcrypt-1.8.4/cipher/md.c 2019-03-25 16:58:53.512358321 +0100 +@@ -411,11 +411,8 @@ md_enable (gcry_md_hd_t hd, int algorith + + if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) + { +- _gcry_inactivate_fips_mode ("MD5 used"); + if (_gcry_enforced_fips_mode () ) + { +- /* We should never get to here because we do not register +- MD5 in enforced fips mode. But better throw an error. */ + err = GPG_ERR_DIGEST_ALGO; + } + } +Index: libgcrypt-1.8.4/src/fips.c +=================================================================== +--- libgcrypt-1.8.4.orig/src/fips.c 2019-03-25 16:58:52.844354398 +0100 ++++ libgcrypt-1.8.4/src/fips.c 2019-03-25 16:58:53.516358344 +0100 +@@ -91,6 +91,31 @@ static void fips_new_state (enum module_ + + + ++/* Initialize the FSM lock - this function may only ++ be called once and is intended to be run from the library ++ constructor */ ++void ++_gcry_initialize_fsm_lock (void) ++{ ++ gpg_error_t err; ++ /* 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 (); ++ } ++} ++ + /* Check whether the OS is in FIPS mode and record that in a module + local variable. If FORCE is passed as true, fips mode will be + enabled anyway. Note: This function is not thread-safe and should +@@ -100,7 +125,6 @@ void + _gcry_initialize_fips_mode (int force) + { + static int done; +- gpg_error_t err; + + /* Make sure we are not accidentally called twice. */ + if (done) +@@ -190,24 +214,6 @@ _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"); +@@ -370,16 +376,20 @@ _gcry_fips_is_operational (void) + { + int result; + +- if (!fips_mode ()) ++ lock_fsm (); ++ if (current_state == STATE_POWERON && !fips_mode ()) ++ /* If we are at this point in POWERON state it means the FIPS ++ module installation was not completed. (/etc/system-fips ++ is not present.) */ + result = 1; + else + { +- lock_fsm (); +- if (current_state == STATE_INIT) ++ if (current_state == STATE_INIT || current_state == STATE_SELFTEST) + { +- /* If we are still in the INIT state, we need to run the +- selftests so that the FSM can eventually get into +- operational state. Given that we would need a 2-phase ++ /* If we are still in the INIT (or SELFTEST) state, ++ we need to run (or finish) the selftests so ++ that the FSM can eventually get into operational ++ state. Given that we would need a 2-phase + initialization of libgcrypt, but that has traditionally + not been enforced, we use this on demand self-test + checking. Note that Proper applications would do the +@@ -395,9 +405,11 @@ _gcry_fips_is_operational (void) + lock_fsm (); + } + +- result = (current_state == STATE_OPERATIONAL); +- unlock_fsm (); ++ result = (current_state == STATE_OPERATIONAL) || !fips_mode (); ++ /* We always run the selftests but ignore the result ++ in non-FIPS mode. */ + } ++ unlock_fsm (); + return result; + } + +@@ -722,9 +734,25 @@ _gcry_fips_run_selftests (int extended) + { + enum module_states result = STATE_ERROR; + gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED; ++ int in_poweron; + +- if (fips_mode ()) +- fips_new_state (STATE_SELFTEST); ++ 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) ++ return 0; + + if (run_cipher_selftests (extended)) + goto leave; +@@ -743,18 +771,12 @@ _gcry_fips_run_selftests (int extended) + if (run_pubkey_selftests (extended)) + goto leave; + +- /* Now check the integrity of the binary. We do this this after +- having checked the HMAC code. */ +- if (check_binary_integrity ()) +- goto leave; +- + /* All selftests passed. */ + result = STATE_OPERATIONAL; + ec = 0; + + leave: +- if (fips_mode ()) +- fips_new_state (result); ++ fips_new_state (result); + + return ec; + } +@@ -810,6 +832,7 @@ 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; +@@ -824,6 +847,8 @@ 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; +Index: libgcrypt-1.8.4/src/global.c +=================================================================== +--- libgcrypt-1.8.4.orig/src/global.c 2019-03-25 16:58:52.844354398 +0100 ++++ libgcrypt-1.8.4/src/global.c 2019-03-25 16:58:53.516358344 +0100 +@@ -145,6 +145,29 @@ global_init (void) + } + + ++#ifndef FIPS_MODULE_PATH ++#define FIPS_MODULE_PATH "/etc/system-fips" ++#endif ++ ++void __attribute__ ((constructor)) _gcry_global_constructor (void) ++{ ++ int rv; ++ ++ /* We always need the FSM lock to be functional. */ ++ _gcry_initialize_fsm_lock (); ++ ++ rv = access (FIPS_MODULE_PATH, F_OK); ++ if (rv < 0 && errno != ENOENT) ++ rv = 0; ++ ++ if (!rv) ++ { ++ /* 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 +@@ -675,8 +698,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + + case GCRYCTL_FIPS_MODE_P: + if (fips_mode () +- && !_gcry_is_fips_mode_inactive () +- && !no_secure_memory) ++ && !_gcry_is_fips_mode_inactive ()) + rc = GPG_ERR_GENERAL; /* Used as TRUE value */ + break; + +@@ -753,9 +775,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + break; + + case GCRYCTL_SET_ENFORCED_FIPS_FLAG: +- if (!any_init_done) ++ if (fips_mode ()) + { +- /* Not yet initialized at all. Set the enforced fips mode flag */ ++ /* We are in FIPS mode, we can set the enforced fips mode flag. */ + _gcry_set_preferred_rng_type (0); + _gcry_set_enforced_fips_mode (); + } +Index: libgcrypt-1.8.4/src/g10lib.h +=================================================================== +--- libgcrypt-1.8.4.orig/src/g10lib.h 2019-03-25 16:58:52.844354398 +0100 ++++ libgcrypt-1.8.4/src/g10lib.h 2019-03-25 16:58:53.516358344 +0100 +@@ -422,6 +422,8 @@ gpg_err_code_t _gcry_sexp_vextract_param + + /*-- fips.c --*/ + ++void _gcry_initialize_fsm_lock (void); ++ + void _gcry_initialize_fips_mode (int force); + + int _gcry_fips_mode (void); diff --git a/libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch b/libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch new file mode 100644 index 0000000..62bd6b5 --- /dev/null +++ b/libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch @@ -0,0 +1,28 @@ +Index: libgcrypt-1.8.4/src/global.c +=================================================================== +--- libgcrypt-1.8.4.orig/src/global.c 2019-03-25 16:58:45.880313488 +0100 ++++ libgcrypt-1.8.4/src/global.c 2019-03-25 16:58:45.896313582 +0100 +@@ -144,11 +144,6 @@ global_init (void) + BUG (); + } + +- +-#ifndef FIPS_MODULE_PATH +-#define FIPS_MODULE_PATH "/etc/system-fips" +-#endif +- + void __attribute__ ((constructor)) _gcry_global_constructor (void) + { + int rv; +@@ -156,11 +151,6 @@ void __attribute__ ((constructor)) _gcry + /* We always need the FSM lock to be functional. */ + _gcry_initialize_fsm_lock (); + +- rv = access (FIPS_MODULE_PATH, F_OK); +- if (rv < 0 && errno != ENOENT) +- rv = 0; +- +- if (!rv) + { + /* We run the integrity check at this point. The remaining + selftests are run before use of the library by application. */ diff --git a/libgcrypt.changes b/libgcrypt.changes index 2cd2107..672f16b 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -1,3 +1,24 @@ +------------------------------------------------------------------- +Fri Mar 22 14:13:05 UTC 2019 - Vítězslav Čížek + +- Don't run full self-tests from constructor (bsc#1097073) + * Don't call global_init() from the constructor, _gcry_global_constructor() + from libgcrypt-1.8.3-fips-ctor.patch takes care of the binary + integrity check instead. + * Only the binary checksum will be verified, the remaining + self-tests will be run upon the library initialization +- Add libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch +- Drop libgcrypt-init-at-elf-load-fips.patch and + libgcrypt-fips_run_selftest_at_constructor.patch obsoleted + by libgcrypt-1.8.3-fips-ctor.patch + +------------------------------------------------------------------- +Thu Mar 7 10:53:40 UTC 2019 - Pedro Monreal Gonzalez + +- Skip all the self-tests except for binary integrity when called + from the constructor (bsc#1097073) + * Added libgcrypt-1.8.3-fips-ctor.patch from Fedora + ------------------------------------------------------------------- Mon Nov 26 17:09:47 UTC 2018 - Vítězslav Čížek diff --git a/libgcrypt.spec b/libgcrypt.spec index e69ef7d..12f684f 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -1,7 +1,7 @@ # # spec file for package libgcrypt # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -58,6 +58,8 @@ Patch35: libgcrypt-fipsdrv-enable-algo-for-dsa-sign.patch #PATCH-FIX-UPSTREAM bsc#1064455 fipsdrv patch to enable --algo for dsa-verify Patch36: libgcrypt-fipsdrv-enable-algo-for-dsa-verify.patch Patch37: libgcrypt-binary_integrity_in_non-FIPS.patch +Patch39: libgcrypt-1.8.3-fips-ctor.patch +Patch40: libgcrypt-fips_ignore_FIPS_MODULE_PATH.patch BuildRequires: automake >= 1.14 BuildRequires: fipscheck BuildRequires: libgpg-error-devel >= 1.25 @@ -137,20 +139,7 @@ understanding of applied cryptography is required to use Libgcrypt. %prep %setup -q -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch7 -p1 -%patch12 -p1 -%patch28 -p1 -%patch29 -p1 -%patch30 -p1 -%patch32 -p1 -%patch13 -p1 -%patch14 -p1 -%patch35 -p1 -%patch36 -p1 -%patch37 -p1 +%autopatch -p1 %build echo building with build_hmac256 set to %{build_hmac256}