diff --git a/libgcrypt-1.8.3-fips-ctor.patch b/libgcrypt-1.8.3-fips-ctor.patch index e04201f..66abd59 100644 --- a/libgcrypt-1.8.3-fips-ctor.patch +++ b/libgcrypt-1.8.3-fips-ctor.patch @@ -1,196 +1,7 @@ -diff -up libgcrypt-1.8.3/cipher/md.c.fips-ctor libgcrypt-1.8.3/cipher/md.c ---- libgcrypt-1.8.3/cipher/md.c.fips-ctor 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.3/cipher/md.c 2018-07-12 13:24:54.088403006 +0200 -@@ -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; - } - } -diff -up libgcrypt-1.8.3/src/fips.c.fips-ctor libgcrypt-1.8.3/src/fips.c ---- libgcrypt-1.8.3/src/fips.c.fips-ctor 2018-07-12 13:24:54.075402698 +0200 -+++ libgcrypt-1.8.3/src/fips.c 2018-07-12 13:24:54.088403006 +0200 -@@ -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) -@@ -179,24 +203,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"); -@@ -359,16 +365,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 -@@ -384,9 +394,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; - } - -@@ -709,9 +721,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; -@@ -730,18 +758,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; - } -@@ -797,6 +819,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; -@@ -811,6 +834,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; diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c --- libgcrypt-1.8.3/src/global.c.fips-ctor 2017-11-23 19:25:58.000000000 +0100 -+++ libgcrypt-1.8.3/src/global.c 2018-07-17 19:15:43.933827112 +0200 -@@ -141,6 +141,29 @@ global_init (void) ++++ libgcrypt-1.8.3/src/global.c 2020-04-17 16:29:59.258218015 +0200 +@@ -141,6 +141,34 @@ global_init (void) } @@ -202,25 +13,30 @@ diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c +{ + 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. */ ++ 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; ++ /* force selftests */ ++ global_init(); + _gcry_fips_run_selftests (0); ++ if (!fips_mode()) ++ _gcry_random_close_fds (); ++ no_secure_memory = no_secmem_save; + } +} + /* 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 -@@ -671,8 +694,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, +@@ -671,8 +699,7 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, case GCRYCTL_FIPS_MODE_P: if (fips_mode () @@ -230,7 +46,7 @@ diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c rc = GPG_ERR_GENERAL; /* Used as TRUE value */ break; -@@ -749,9 +771,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, +@@ -749,9 +776,9 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, break; case GCRYCTL_SET_ENFORCED_FIPS_FLAG: @@ -242,15 +58,3 @@ diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c _gcry_set_preferred_rng_type (0); _gcry_set_enforced_fips_mode (); } -diff -up libgcrypt-1.8.3/src/g10lib.h.fips-ctor libgcrypt-1.8.3/src/g10lib.h ---- libgcrypt-1.8.3/src/g10lib.h.fips-ctor 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.3/src/g10lib.h 2018-07-12 13:24:54.089403030 +0200 -@@ -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-1.8.3-md-fips-enforce.patch b/libgcrypt-1.8.3-md-fips-enforce.patch index d040bfb..eed7fa5 100644 --- a/libgcrypt-1.8.3-md-fips-enforce.patch +++ b/libgcrypt-1.8.3-md-fips-enforce.patch @@ -1,12 +1,18 @@ diff -up libgcrypt-1.8.3/cipher/md.c.fips-enforce libgcrypt-1.8.3/cipher/md.c ---- libgcrypt-1.8.3/cipher/md.c.fips-enforce 2018-11-01 15:40:36.051865535 +0100 -+++ libgcrypt-1.8.3/cipher/md.c 2019-06-03 11:50:21.435401753 +0200 -@@ -409,7 +409,7 @@ md_enable (gcry_md_hd_t hd, int algorith +--- libgcrypt-1.8.3/cipher/md.c.fips-enforce 2017-11-23 19:16:58.000000000 +0100 ++++ libgcrypt-1.8.3/cipher/md.c 2020-04-17 15:07:31.364945130 +0200 +@@ -409,13 +409,10 @@ md_enable (gcry_md_hd_t hd, int algorith } - if (!err && algorithm == GCRY_MD_MD5 && fips_mode ()) + if (!err && !spec->flags.fips && 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; + } + } diff --git a/libgcrypt-1.8.5-fips-module.patch b/libgcrypt-1.8.5-fips-module.patch new file mode 100644 index 0000000..60b9ce2 --- /dev/null +++ b/libgcrypt-1.8.5-fips-module.patch @@ -0,0 +1,139 @@ +diff -up libgcrypt-1.8.5/src/fips.c.fips-module libgcrypt-1.8.5/src/fips.c +--- libgcrypt-1.8.5/src/fips.c.fips-module 2020-04-20 19:07:45.924919645 +0200 ++++ libgcrypt-1.8.5/src/fips.c 2020-04-20 19:10:33.690722470 +0200 +@@ -35,10 +35,6 @@ + #include "hmac256.h" + + +-/* The name of the file used to force libgcrypt into fips mode. */ +-#define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" +- +- + /* The states of the finite state machine used in fips mode. */ + enum module_states + { +@@ -122,54 +118,6 @@ _gcry_initialize_fips_mode (int force) + goto leave; + } + +- /* For testing the system it is useful to override the system +- provided detection of the FIPS mode and force FIPS mode using a +- file. The filename is hardwired so that there won't be any +- confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is +- actually used. The file itself may be empty. */ +- if ( !access (FIPS_FORCE_FILE, F_OK) ) +- { +- gcry_assert (!no_fips_mode_required); +- goto leave; +- } +- +- /* Checking based on /proc file properties. */ +- { +- static const char procfname[] = "/proc/sys/crypto/fips_enabled"; +- FILE *fp; +- int saved_errno; +- +- fp = fopen (procfname, "r"); +- if (fp) +- { +- char line[256]; +- +- if (fgets (line, sizeof line, fp) && atoi (line)) +- { +- /* System is in fips mode. */ +- fclose (fp); +- gcry_assert (!no_fips_mode_required); +- goto leave; +- } +- fclose (fp); +- } +- else if ((saved_errno = errno) != ENOENT +- && saved_errno != EACCES +- && !access ("/proc/version", F_OK) ) +- { +- /* Problem reading the fips file despite that we have the proc +- file system. We better stop right away. */ +- log_info ("FATAL: error reading `%s' in libgcrypt: %s\n", +- procfname, strerror (saved_errno)); +-#ifdef HAVE_SYSLOG +- syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " +- "reading `%s' failed: %s - abort", +- procfname, strerror (saved_errno)); +-#endif /*HAVE_SYSLOG*/ +- abort (); +- } +- } +- + /* Fips not not requested, set flag. */ + no_fips_mode_required = 1; + +diff -up libgcrypt-1.8.5/src/g10lib.h.fips-module libgcrypt-1.8.5/src/g10lib.h +--- libgcrypt-1.8.5/src/g10lib.h.fips-module 2020-04-20 19:07:45.918919759 +0200 ++++ libgcrypt-1.8.5/src/g10lib.h 2020-04-20 19:11:05.003125740 +0200 +@@ -422,6 +422,9 @@ gpg_err_code_t _gcry_sexp_vextract_param + + /*-- fips.c --*/ + ++/* The name of the file used to force libgcrypt into fips mode. */ ++#define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" ++ + void _gcry_initialize_fips_mode (int force); + + int _gcry_fips_mode (void); +diff -up libgcrypt-1.8.5/src/global.c.fips-module libgcrypt-1.8.5/src/global.c +--- libgcrypt-1.8.5/src/global.c.fips-module 2020-04-20 19:07:45.919919741 +0200 ++++ libgcrypt-1.8.5/src/global.c 2020-04-20 19:07:45.950919149 +0200 +@@ -160,6 +160,53 @@ void __attribute__ ((constructor)) _gcry + rv = access (FIPS_MODULE_PATH, F_OK); + if (rv < 0 && errno != ENOENT) + rv = 0; ++ ++ /* For testing the system it is useful to override the system ++ provided detection of the FIPS mode and force FIPS mode using a ++ file. The filename is hardwired so that there won't be any ++ confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is ++ actually used. The file itself may be empty. */ ++ if ( !access (FIPS_FORCE_FILE, F_OK) ) ++ { ++ rv = 0; ++ force_fips_mode = 1; ++ } ++ ++ /* Checking based on /proc file properties. */ ++ { ++ static const char procfname[] = "/proc/sys/crypto/fips_enabled"; ++ FILE *fp; ++ int saved_errno; ++ ++ fp = fopen (procfname, "r"); ++ if (fp) ++ { ++ char line[256]; ++ ++ if (fgets (line, sizeof line, fp) && atoi (line)) ++ { ++ /* System is in fips mode. */ ++ rv = 0; ++ force_fips_mode = 1; ++ } ++ fclose (fp); ++ } ++ else if ((saved_errno = errno) != ENOENT ++ && saved_errno != EACCES ++ && !access ("/proc/version", F_OK) ) ++ { ++ /* Problem reading the fips file despite that we have the proc ++ file system. We better stop right away. */ ++ log_info ("FATAL: error reading `%s' in libgcrypt: %s\n", ++ procfname, strerror (saved_errno)); ++#ifdef HAVE_SYSLOG ++ syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " ++ "reading `%s' failed: %s - abort", ++ procfname, strerror (saved_errno)); ++#endif /*HAVE_SYSLOG*/ ++ abort (); ++ } ++ } + + if (!rv) + { diff --git a/libgcrypt.spec b/libgcrypt.spec index d1ee3fd..214ccf2 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -1,6 +1,6 @@ Name: libgcrypt Version: 1.8.5 -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.gnupg.org/ Source0: libgcrypt-%{version}-hobbled.tar.xz # The original libgcrypt sources now contain potentially patented ECC @@ -36,7 +36,7 @@ Patch18: libgcrypt-1.8.3-fips-ctor.patch # Block some operations if in FIPS non-operational state Patch22: libgcrypt-1.7.3-fips-reqs.patch # Do not try to open /dev/urandom if getrandom() works -Patch24: libgcrypt-1.8.4-getrandom.patch +Patch24: libgcrypt-1.8.5-getrandom.patch # CMAC selftest for FIPS POST Patch25: libgcrypt-1.8.3-cmac-selftest.patch # Continuous FIPS entropy test @@ -47,6 +47,8 @@ Patch27: libgcrypt-1.8.3-md-fips-enforce.patch Patch28: libgcrypt-1.8.5-intel-cet.patch # Fix build on ARMv7 Patch29: libgcrypt-1.8.5-build.patch +# FIPS module is redefined a little bit (implicit by kernel FIPS mode) +Patch30: libgcrypt-1.8.5-fips-module.patch %define gcrylibdir %{_libdir} @@ -95,6 +97,7 @@ applications using libgcrypt. %patch27 -p1 -b .fips-enforce %patch28 -p1 -b .intel-cet %patch29 -p1 -b .build +%patch30 -p1 -b .fips-module cp %{SOURCE4} cipher/ cp %{SOURCE5} %{SOURCE6} tests/ @@ -194,6 +197,10 @@ install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/gcrypt/random.conf %license COPYING %changelog +* Mon Apr 20 2020 Tomáš Mráz 1.8.5-4 +- FIPS selftest is run directly from the constructor +- FIPS module is implicit with kernel FIPS flag + * Thu Jan 30 2020 Tomáš Mráz 1.8.5-3 - fix the build on ARMv7