Hello community, here is the log from the commit of package libgcrypt for openSUSE:Leap:15.2 checked in at 2020-04-12 15:37:55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Leap:15.2/libgcrypt (Old) and /work/SRC/openSUSE:Leap:15.2/.libgcrypt.new.3248 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "libgcrypt" Sun Apr 12 15:37:55 2020 rev:43 rq:791689 version:1.8.2 Changes: -------- --- /work/SRC/openSUSE:Leap:15.2/libgcrypt/libgcrypt.changes 2020-03-20 05:52:26.508044915 +0100 +++ /work/SRC/openSUSE:Leap:15.2/.libgcrypt.new.3248/libgcrypt.changes 2020-04-12 15:37:58.401993146 +0200 @@ -1,0 +2,28 @@ +Thu Mar 26 19:28:18 UTC 2020 - Pedro Monreal Gonzalez <[email protected]> + +- FIPS: Fix drbg to be threadsafe [bsc#1167674] + * Detect fork and re-open devices in_gcry_rndlinux_gather_random + * libgcrypt-check-re-open-dev_random-after-fork.patch + +------------------------------------------------------------------- +Thu Mar 26 18:09:47 UTC 2020 - Pedro Monreal Gonzalez <[email protected]> + +- FIPS: Run self-tests from constructor during power-on [bsc#1166748] + * Set up global_init as the constructor function: + - libgcrypt-global_init-constructor.patch + * Relax the entropy requirements on selftest. This is especially + important for virtual machines to boot properly before the RNG + is available: + - libgcrypt-random_selftests-testentropy.patch + - libgcrypt-rsa-no-blinding.patch + - libgcrypt-ecc-ecdsa-no-blinding.patch + * Fix benchmark regression test in FIPS mode: + - libgcrypt-FIPS-GMAC_AES-benckmark.patch + +------------------------------------------------------------------- +Thu Mar 12 16:54:33 UTC 2020 - Pedro Monreal Gonzalez <[email protected]> + +- Remove check not needed in _gcry_global_constructor [bsc#1164950] + * Update libgcrypt-Restore-self-tests-from-constructor.patch + +------------------------------------------------------------------- New: ---- libgcrypt-FIPS-GMAC_AES-benckmark.patch libgcrypt-Restore-self-tests-from-constructor.patch libgcrypt-check-re-open-dev_random-after-fork.patch libgcrypt-ecc-ecdsa-no-blinding.patch libgcrypt-global_init-constructor.patch libgcrypt-random_selftests-testentropy.patch libgcrypt-rsa-no-blinding.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ libgcrypt.spec ++++++ --- /var/tmp/diff_new_pack.4Fi5oE/_old 2020-04-12 15:37:59.605994058 +0200 +++ /var/tmp/diff_new_pack.4Fi5oE/_new 2020-04-12 15:37:59.609994060 +0200 @@ -86,6 +86,15 @@ Patch55: libgcrypt-ECDSA_check_coordinates_range.patch #PATCH-FIX-SUSE bsc#1164950 Run self-tests from the constructor Patch56: libgcrypt-invoke-global_init-from-constructor.patch +#PATCH-FIX-SUSE bsc#1164950 Restore the self-tests from the constructor +Patch57: libgcrypt-Restore-self-tests-from-constructor.patch +Patch58: libgcrypt-FIPS-GMAC_AES-benckmark.patch +Patch59: libgcrypt-global_init-constructor.patch +Patch60: libgcrypt-random_selftests-testentropy.patch +Patch61: libgcrypt-rsa-no-blinding.patch +Patch62: libgcrypt-ecc-ecdsa-no-blinding.patch +#PATCH-FIX-UPSTREAM bsc#1167674 FIPS: Fix drbg to be threadsafe +Patch63: libgcrypt-check-re-open-dev_random-after-fork.patch BuildRequires: automake >= 1.14 BuildRequires: fipscheck BuildRequires: libgpg-error-devel >= 1.25 @@ -201,6 +210,13 @@ %patch54 -p1 %patch55 -p1 %patch56 -p1 +%patch57 -p1 +%patch58 -p1 +%patch59 -p1 +%patch60 -p1 +%patch61 -p1 +%patch62 -p1 +%patch63 -p1 %build echo building with build_hmac256 set to %{build_hmac256} ++++++ libgcrypt-FIPS-GMAC_AES-benckmark.patch ++++++ Index: libgcrypt-1.8.2/tests/benchmark.c =================================================================== --- libgcrypt-1.8.2.orig/tests/benchmark.c +++ libgcrypt-1.8.2/tests/benchmark.c @@ -598,7 +598,7 @@ mac_bench ( const char *algoname ) if (!algoname) { for (i=1; i < 600; i++) - if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) + if (in_fips_mode && (i == GCRY_MAC_HMAC_MD5 || i == GCRY_MAC_GMAC_AES)) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_mac_test_algo (i) ) mac_bench (gcry_mac_algo_name (i)); ++++++ libgcrypt-Restore-self-tests-from-constructor.patch ++++++ Index: libgcrypt-1.8.2/src/global.c =================================================================== --- libgcrypt-1.8.2.orig/src/global.c +++ libgcrypt-1.8.2/src/global.c @@ -140,8 +140,9 @@ global_init (void) /* We always need the FSM lock to be functional. */ _gcry_initialize_fsm_lock (); - /* Run the self-tests from the constructor. */ - global_init (); + /* 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 ++++++ libgcrypt-check-re-open-dev_random-after-fork.patch ++++++ >From 319f55e6e5793c59f1ba4cfe481b562bca42194d Mon Sep 17 00:00:00 2001 From: Werner Koch <[email protected]> Date: Fri, 26 Oct 2018 13:22:16 +0200 Subject: [PATCH] random: Make sure to re-open /dev/random after a fork * random/rndlinux.c (_gcry_rndlinux_gather_random): Detect fork and re-open devices. -- This mitigates about ill-behaving software which has closed the standard fds but later dups them to /dev/null. GnuPG-bug-id: 3491 Signed-off-by: Werner Koch <[email protected]> --- random/rndlinux.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) Index: libgcrypt-1.8.2/random/rndlinux.c =================================================================== --- libgcrypt-1.8.2.orig/random/rndlinux.c +++ libgcrypt-1.8.2/random/rndlinux.c @@ -108,9 +108,10 @@ open_device (const char *name, int retry /* Note that the caller needs to make sure that this function is only - called by one thread at a time. The function returns 0 on success - or true on failure (in which case the caller will signal a fatal - error). */ + * called by one thread at a time. The function returns 0 on success + * or true on failure (in which case the caller will signal a fatal + * error). This function should be entered only by one thread at a + * time. */ int _gcry_rndlinux_gather_random (void (*add)(const void*, size_t, enum random_origins), @@ -122,6 +123,11 @@ _gcry_rndlinux_gather_random (void (*add static int fd_configured = -1; static int only_urandom = -1; static unsigned char ever_opened; + static volatile pid_t my_pid; /* The volatile is there to make sure + * the compiler does not optimize the + * code away in case the getpid + * function is badly attributed. */ + volatile pid_t apid; int fd; int n; byte buffer[768]; @@ -135,13 +141,13 @@ _gcry_rndlinux_gather_random (void (*add * use only urandom. */ if (only_urandom == -1) { + my_pid = getpid (); if ((_gcry_random_read_conf () & RANDOM_CONF_ONLY_URANDOM)) only_urandom = 1; else only_urandom = 0; } - if (!add) { /* Special mode to close the descriptors. */ @@ -163,6 +169,25 @@ _gcry_rndlinux_gather_random (void (*add return 0; } + /* Detect a fork and close the devices so that we don't use the old + * file descriptors. Note that open_device will be called in retry + * mode if the devices was opened by the parent process. */ + apid = getpid (); + if (my_pid != apid) + { + if (fd_random != -1) + { + close (fd_random); + fd_random = -1; + } + if (fd_urandom != -1) + { + close (fd_urandom); + fd_urandom = -1; + } + my_pid = apid; + } + /* First read from a hardware source. However let it account only for up to 50% (or 25% for RDRAND) of the requested bytes. */ ++++++ libgcrypt-ecc-ecdsa-no-blinding.patch ++++++ Index: libgcrypt-1.8.2/cipher/ecc.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/ecc.c +++ libgcrypt-1.8.2/cipher/ecc.c @@ -2058,11 +2058,11 @@ selftest_sign (gcry_sexp_t pkey, gcry_se { /* Sample data from RFC 6979 section A.2.5, hash is of message "sample" */ static const char sample_data[] = - "(data (flags rfc6979)" + "(data (flags rfc6979 no-blinding)" " (hash sha256 #af2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" /**/ "62113d8a62add1bf#))"; static const char sample_data_bad[] = - "(data (flags rfc6979)" + "(data (flags rfc6979 no-blinding)" " (hash sha256 #bf2bdbe1aa9b6ec1e2ade1d694f41fc71a831d0268e98915" /**/ "62113d8a62add1bf#))"; static const char signature_r[] = Index: libgcrypt-1.8.2/cipher/ecc-ecdsa.c =================================================================== --- libgcrypt-1.8.2.orig/cipher/ecc-ecdsa.c +++ libgcrypt-1.8.2/cipher/ecc-ecdsa.c @@ -52,6 +52,7 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, mpi_ec_t ctx; gcry_mpi_t b; /* Random number needed for blinding. */ gcry_mpi_t bi; /* multiplicative inverse of B. */ + int with_blinding = !(flags & PUBKEY_FLAG_NO_BLINDING); if (DBG_CIPHER) log_mpidump ("ecdsa sign hash ", input ); @@ -65,12 +66,15 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, b = mpi_snew (qbits); bi = mpi_snew (qbits); - do + if (with_blinding) { - _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM); - mpi_mod (b, b, skey->E.n); + do + { + _gcry_mpi_randomize (b, qbits, GCRY_WEAK_RANDOM); + mpi_mod (b, b, skey->E.n); + } + while (!mpi_invm (bi, b, skey->E.n)); } - while (!mpi_invm (bi, b, skey->E.n)); k = NULL; dr = mpi_alloc (0); @@ -128,11 +132,19 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, } while (!mpi_cmp_ui (r, 0)); - mpi_mulm (dr, b, skey->d, skey->E.n); - mpi_mulm (dr, dr, r, skey->E.n); /* dr = d*r mod n (blinded with b) */ - mpi_mulm (sum, b, hash, skey->E.n); - mpi_addm (sum, sum, dr, skey->E.n); /* sum = hash + (d*r) mod n (blinded with b) */ - mpi_mulm (sum, bi, sum, skey->E.n); /* undo blinding by b^-1 */ + if (!with_blinding) + { + mpi_mulm (dr, skey->d, r, skey->E.n); /* dr = d*r mod n */ + mpi_addm (sum, hash, dr, skey->E.n); /* sum = hash + (d*r) mod n */ + } + else + { + mpi_mulm (dr, b, skey->d, skey->E.n); + mpi_mulm (dr, dr, r, skey->E.n); /* dr = d*r mod n (blinded with b) */ + mpi_mulm (sum, b, hash, skey->E.n); + mpi_addm (sum, sum, dr, skey->E.n); /* sum = hash + (d*r) mod n (blinded with b) */ + mpi_mulm (sum, bi, sum, skey->E.n); /* undo blinding by b^-1 */ + } mpi_invm (k_1, k, skey->E.n); /* k_1 = k^(-1) mod n */ mpi_mulm (s, k_1, sum, skey->E.n); /* s = k^(-1)*(hash+(d*r)) mod n */ } ++++++ libgcrypt-global_init-constructor.patch ++++++ Index: libgcrypt-1.8.2/src/global.c =================================================================== --- libgcrypt-1.8.2.orig/src/global.c +++ libgcrypt-1.8.2/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.8.2/src/fips.c =================================================================== --- libgcrypt-1.8.2.orig/src/fips.c +++ libgcrypt-1.8.2/src/fips.c @@ -169,6 +169,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) @@ -258,6 +259,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"); @@ -658,10 +676,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); @@ -676,6 +694,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 () @@ -700,25 +751,10 @@ check_binary_integrity () 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) @@ -776,6 +812,32 @@ check_binary_integrity () #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. */ @@ -784,26 +846,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; @@ -813,6 +862,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 ()) @@ -826,7 +878,8 @@ _gcry_fips_run_selftests (int extended) ec = 0; leave: - fips_new_state (result); + if (fips_mode ()) + fips_new_state (result); return ec; } @@ -882,7 +935,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; @@ -897,8 +949,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; ++++++ libgcrypt-random_selftests-testentropy.patch ++++++ Index: libgcrypt-1.8.2/random/random-drbg.c =================================================================== --- libgcrypt-1.8.2.orig/random/random-drbg.c +++ libgcrypt-1.8.2/random/random-drbg.c @@ -2428,6 +2428,10 @@ drbg_healthcheck_sanity (struct gcry_drb /* if the following tests fail, it is likely that there is a buffer * overflow and we get a SIGSEV */ + test_data.testentropy = &testentropy; + test_data.fail_seed_source = 0; + drbg_string_fill (&testentropy, test->entropy, test->entropylen); + drbg->test_data = &test_data; ret = drbg_instantiate (drbg, NULL, coreref, 1); if (ret) goto outbuf; ++++++ libgcrypt-rsa-no-blinding.patch ++++++ --- libgcrypt-1.8.2.orig/cipher/rsa.c 2020-03-26 07:23:17.392861551 +0100 +++ libgcrypt-1.8.2.orig/cipher/rsa.c 2020-03-26 15:43:29.556282072 +0100 @@ -91,10 +91,16 @@ static const char sample_secret_key[] = " 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" " 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" " 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B919#)" +"))"; +/* We need to get rid of the u value, in order to end in + * secret_core_std when called from secret. It's not used anyway. */ + +/* " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7#)))"; +*/ /* A sample 2048 bit RSA key used for the selftests (public only). */ static const char sample_public_key[] = @@ -1252,8 +1258,8 @@ rsa_check_secret_key (gcry_sexp_t keypar RSA_secret_key sk = {NULL, NULL, NULL, NULL, NULL, NULL}; /* To check the key we need the optional parameters. */ - rc = sexp_extract_param (keyparms, NULL, "nedpqu", - &sk.n, &sk.e, &sk.d, &sk.p, &sk.q, &sk.u, + rc = sexp_extract_param (keyparms, NULL, "npq", + &sk.n, &sk.p, &sk.q, NULL); if (rc) goto leave; @@ -1263,11 +1269,8 @@ rsa_check_secret_key (gcry_sexp_t keypar leave: _gcry_mpi_release (sk.n); - _gcry_mpi_release (sk.e); - _gcry_mpi_release (sk.d); _gcry_mpi_release (sk.p); _gcry_mpi_release (sk.q); - _gcry_mpi_release (sk.u); if (DBG_CIPHER) log_debug ("rsa_testkey => %s\n", gpg_strerror (rc)); return rc; @@ -1710,11 +1713,11 @@ static const char * selftest_sign_2048 (gcry_sexp_t pkey, gcry_sexp_t skey) { static const char sample_data[] = - "(data (flags pkcs1)" + "(data (flags pkcs1 no-blinding)" " (hash sha256 #11223344556677889900aabbccddeeff" /**/ "102030405060708090a0b0c0d0f01121#))"; static const char sample_data_bad[] = - "(data (flags pkcs1)" + "(data (flags pkcs1 no-blinding)" " (hash sha256 #11223344556677889900aabbccddeeff" /**/ "802030405060708090a0b0c0d0f01121#))"; @@ -1857,7 +1860,7 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc gcry_mpi_t ref_mpi = NULL; /* Put the plaintext into an S-expression. */ - err = sexp_build (&plain, NULL, "(data (flags raw) (value %s))", plaintext); + err = sexp_build (&plain, NULL, "(data (flags raw no-blinding) (value %s))", plaintext); if (err) { errtxt = "converting data failed"; @@ -1897,6 +1900,26 @@ selftest_encr_2048 (gcry_sexp_t pkey, gc goto leave; } + /* This sexp trickery is to prevent the use of blinding. + * The flag doesn't get inherited by encr, so we have to + * derive a new sexp from the ciphertext */ + char buf[1024]; + memset(buf, 0, sizeof(buf)); + err = _gcry_mpi_print (GCRYMPI_FMT_STD, buf, sizeof buf, NULL, ciphertext); + if (err) + { + errtxt = "Dumping ciphertext mpi to buffer failed"; + goto leave; + } + + sexp_release (encr); + err = sexp_build (&encr, NULL, "(enc-val (flags no-blinding) (rsa (a %s)))", buf); + if (err) + { + errtxt = "Adding no-blinding flag to ciphertext failed"; + goto leave; + } + /* Decrypt. */ err = _gcry_pk_decrypt (&decr, encr, skey); if (err)
