From a52145f04103aa59f2a85b10847b066babcb53ac9e344f64a14cd635f718a95b Mon Sep 17 00:00:00 2001 From: Pedro Monreal Gonzalez Date: Fri, 16 Sep 2022 21:00:13 +0000 Subject: [PATCH] Accepting request 1004104 from home:pmonrealgonzalez:branches:devel:libraries:c_c++ - FIPS: Get most of the entropy from rndjent_poll [bsc#1202117] * Add libgcrypt-FIPS-rndjent_poll.patch * Rebase libgcrypt-jitterentropy-3.4.0.patch - FIPS: Check keylength in gcry_fips_indicator_kdf() [bsc#1190700] * Consider approved keylength greater or equal to 112 bits. * Add libgcrypt-FIPS-kdf-leylength.patch - FIPS: Zeroize buffer and digest in check_binary_integrity() * Add libgcrypt-FIPS-Zeroize-hmac.patch [bsc#1191020] OBS-URL: https://build.opensuse.org/request/show/1004104 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=158 --- libgcrypt-FIPS-Zeroize-hmac.patch | 35 +++++++++ libgcrypt-FIPS-kdf-leylength.patch | 39 ++++++++++ libgcrypt-FIPS-rndjent_poll.patch | 114 ++++++++++++++++++++++++++++ libgcrypt-jitterentropy-3.4.0.patch | 89 ++++++---------------- libgcrypt.changes | 20 +++++ libgcrypt.spec | 6 ++ 6 files changed, 237 insertions(+), 66 deletions(-) create mode 100644 libgcrypt-FIPS-Zeroize-hmac.patch create mode 100644 libgcrypt-FIPS-kdf-leylength.patch create mode 100644 libgcrypt-FIPS-rndjent_poll.patch diff --git a/libgcrypt-FIPS-Zeroize-hmac.patch b/libgcrypt-FIPS-Zeroize-hmac.patch new file mode 100644 index 0000000..680c29d --- /dev/null +++ b/libgcrypt-FIPS-Zeroize-hmac.patch @@ -0,0 +1,35 @@ +Index: libgcrypt-1.9.4/src/fips.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/fips.c ++++ libgcrypt-1.9.4/src/fips.c +@@ -905,6 +905,10 @@ check_binary_integrity (void) + char *fname = NULL; + const char key[] = "orboDeJITITejsirpADONivirpUkvarP"; + ++ /* A buffer of 64 bytes plus one for a LF and one to ++ * detect garbage. */ ++ unsigned char buffer[64+1+1]; ++ + if (get_library_path ("libgcrypt.so.20", "gcry_check_version", libpath, sizeof(libpath))) + err = gpg_error_from_syserror (); + else +@@ -927,9 +931,6 @@ check_binary_integrity (void) + err = gpg_error_from_syserror (); + else + { +- /* A buffer of 64 bytes plus one for a LF and one to +- detect garbage. */ +- unsigned char buffer[64+1+1]; + const unsigned char *s; + int n; + +@@ -957,6 +958,9 @@ check_binary_integrity (void) + } + } + } ++ /* Zeroize digest and buffer */ ++ memset (digest, 0, sizeof(digest)); ++ memset (buffer, 0, sizeof(buffer)); + reporter ("binary", 0, fname, err? gpg_strerror (err):NULL); + #ifdef HAVE_SYSLOG + if (err) diff --git a/libgcrypt-FIPS-kdf-leylength.patch b/libgcrypt-FIPS-kdf-leylength.patch new file mode 100644 index 0000000..ceb8b64 --- /dev/null +++ b/libgcrypt-FIPS-kdf-leylength.patch @@ -0,0 +1,39 @@ +Index: libgcrypt-1.9.4/src/fips.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/fips.c ++++ libgcrypt-1.9.4/src/fips.c +@@ -475,10 +475,15 @@ int + _gcry_fips_indicator_kdf (va_list arg_ptr) + { + enum gcry_kdf_algos alg = va_arg (arg_ptr, enum gcry_kdf_algos); ++ unsigned int keylen = 0; + + switch (alg) + { + case GCRY_KDF_PBKDF2: ++ keylen = va_arg (arg_ptr, unsigned int); ++ if (keylen < 112) { ++ return GPG_ERR_NOT_SUPPORTED; ++ } + return GPG_ERR_NO_ERROR; + default: + return GPG_ERR_NOT_SUPPORTED; +Index: libgcrypt-1.9.4/doc/gcrypt.texi +=================================================================== +--- libgcrypt-1.9.4.orig/doc/gcrypt.texi ++++ libgcrypt-1.9.4/doc/gcrypt.texi +@@ -983,10 +983,12 @@ algorithm supports different key sizes). + this function returns @code{GPS_ERR_NO_ERROR}. Otherwise @code{GPG_ERR_NOT_SUPPORTED} + is returned. + +-@item GCRYCTL_FIPS_SERVICE_INDICATOR_KDF; Arguments: enum gcry_kdf_algos ++@item GCRYCTL_FIPS_SERVICE_INDICATOR_KDF; Arguments: enum gcry_kdf_algos [, unsigned int] + + Check if the given KDF is approved under the current FIPS 140-3 +-certification. If the KDF is approved, this function returns @code{GPG_ERR_NO_ERROR}. ++certification. The second parameter provides the keylength in bits. ++Keylength values of less that 112 bits are considered non-approved. ++If the KDF is approved, this function returns @code{GPG_ERR_NO_ERROR}. + Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned. + + @item GCRYCTL_FIPS_SERVICE_INDICATOR_PK; Arguments: enum gcry_pk_algos diff --git a/libgcrypt-FIPS-rndjent_poll.patch b/libgcrypt-FIPS-rndjent_poll.patch new file mode 100644 index 0000000..a0bb5b7 --- /dev/null +++ b/libgcrypt-FIPS-rndjent_poll.patch @@ -0,0 +1,114 @@ +Index: libgcrypt-1.9.4/random/rndlinux.c +=================================================================== +--- libgcrypt-1.9.4.orig/random/rndlinux.c ++++ libgcrypt-1.9.4/random/rndlinux.c +@@ -141,7 +141,7 @@ _gcry_rndlinux_gather_random (void (*add + volatile pid_t apid; + int fd; + int n; +- byte buffer[768]; ++ byte buffer[256]; + size_t n_hw; + size_t want = length; + size_t last_so_far = 0; +@@ -196,26 +196,43 @@ _gcry_rndlinux_gather_random (void (*add + my_pid = apid; + } + ++ if (fips_mode()) ++ { ++ if (level >= GCRY_VERY_STRONG_RANDOM) ++ { ++ size_t n; + +- /* First read from a hardware source. Note that _gcry_rndhw_poll_slow lets +- it account only for up to 50% (or 25% for RDRAND) of the requested +- bytes. */ +- n_hw = _gcry_rndhw_poll_slow (add, origin, length); +- if (length > 1) +- length -= n_hw; +- +- /* When using a blocking random generator try to get some entropy +- * from the jitter based RNG. In this case we take up to 50% of the +- * remaining requested bytes. */ +- if (level >= GCRY_VERY_STRONG_RANDOM) +- { +- n_hw = _gcry_rndjent_poll (add, origin, length/2); +- if (n_hw > length/2) +- n_hw = length/2; ++ n = _gcry_rndjent_poll (add, origin, length); ++ if (n == 0) ++ log_fatal ("unexpected error from rndjent: %s\n", ++ strerror (errno)); ++ if (n > length) ++ n = length; ++ if (length > 1) ++ length -= n; ++ } ++ } ++ else ++ { ++ /* First read from a hardware source. Note that _gcry_rndhw_poll_slow lets ++ it account only for up to 50% (or 25% for RDRAND) of the requested ++ bytes. */ ++ n_hw = _gcry_rndhw_poll_slow (add, origin, length); + if (length > 1) + length -= n_hw; +- } + ++ /* When using a blocking random generator try to get some entropy ++ * from the jitter based RNG. In this case we take up to 50% of the ++ * remaining requested bytes. */ ++ if (level >= GCRY_VERY_STRONG_RANDOM) ++ { ++ n_hw = _gcry_rndjent_poll (add, origin, length/2); ++ if (n_hw > length/2) ++ n_hw = length/2; ++ if (length > 1) ++ length -= n_hw; ++ } ++ } + + /* Open the requested device. The first time a device is to be + opened we fail with a fatal error if the device does not exists. +@@ -283,8 +301,6 @@ _gcry_rndlinux_gather_random (void (*add + do + { + nbytes = length < sizeof(buffer)? length : sizeof(buffer); +- if (nbytes > 256) +- nbytes = 256; + _gcry_pre_syscall (); + ret = getentropy (buffer, nbytes); + _gcry_post_syscall (); +Index: libgcrypt-1.9.4/random/rndjent.c +=================================================================== +--- libgcrypt-1.9.4.orig/random/rndjent.c ++++ libgcrypt-1.9.4/random/rndjent.c +@@ -279,13 +279,24 @@ _gcry_rndjent_poll (void (*add)(const vo + if (!jent_rng_is_initialized) + { + /* Auto-initialize. */ +- jent_rng_is_initialized = 1; + jent_entropy_collector_free (jent_rng_collector); + jent_rng_collector = NULL; + if ( !(_gcry_random_read_conf () & RANDOM_CONF_DISABLE_JENT)) + { +- if (!jent_entropy_init ()) +- jent_rng_collector = jent_entropy_collector_alloc (1, 0); ++ if (!jent_entropy_init_ex (1, 0)) ++ { ++ jent_rng_collector = jent_entropy_collector_alloc (1, 0); ++ jent_rng_is_initialized = 1; ++ } ++ } ++ } ++ ++ if (!jent_rng_collector) ++ { ++ if (!jent_entropy_init_ex (1, 0)) ++ { ++ jent_rng_collector = jent_entropy_collector_alloc (1, 0); ++ jent_rng_is_initialized = 1; + } + } + diff --git a/libgcrypt-jitterentropy-3.4.0.patch b/libgcrypt-jitterentropy-3.4.0.patch index 2ba40e3..997ef2a 100644 --- a/libgcrypt-jitterentropy-3.4.0.patch +++ b/libgcrypt-jitterentropy-3.4.0.patch @@ -57,9 +57,8 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c + * pros and cons considering that the SHA3 operation is not that + * expensive. */ --#ifndef JENT_CPU_JITTERENTROPY_SECURE_MEMORY + #ifndef JENT_CPU_JITTERENTROPY_SECURE_MEMORY - jent_random_data(ec); -+#ifndef CONFIG_CRYPTO_CPU_JITTERENTROPY_SECURE_MEMORY + jent_read_random_block(ec, NULL, 0); #endif @@ -72,19 +71,16 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c /* * Requesting disabling and forcing of internal timer -@@ -405,9 +415,8 @@ static struct rand_data +@@ -405,7 +415,7 @@ static struct rand_data return NULL; if (!(flags & JENT_DISABLE_MEMORY_ACCESS)) { - uint32_t memsize = jent_memsize(flags); -- -- entropy_collector->mem = _gcry_calloc (1, memsize); + memsize = jent_memsize(flags); -+ entropy_collector->mem = (unsigned char *)jent_zalloc(memsize); - #ifdef JENT_RANDOM_MEMACCESS - /* -@@ -431,13 +440,19 @@ static struct rand_data + entropy_collector->mem = _gcry_calloc (1, memsize); + +@@ -431,13 +441,19 @@ static struct rand_data entropy_collector->memaccessloops = JENT_MEMORY_ACCESSLOOPS; } @@ -105,7 +101,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c entropy_collector->fips_enabled = 1; /* Initialize the APT */ -@@ -469,7 +484,7 @@ static struct rand_data +@@ -469,7 +485,7 @@ static struct rand_data err: if (entropy_collector->mem != NULL) @@ -114,7 +110,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c jent_zfree(entropy_collector, sizeof(struct rand_data)); return NULL; } -@@ -511,6 +526,7 @@ JENT_PRIVATE_STATIC +@@ -511,6 +527,7 @@ JENT_PRIVATE_STATIC void jent_entropy_collector_free(struct rand_data *entropy_collector) { if (entropy_collector != NULL) { @@ -122,7 +118,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c jent_notime_disable(entropy_collector); if (entropy_collector->mem != NULL) { jent_zfree(entropy_collector->mem, -@@ -664,6 +680,7 @@ static inline int jent_entropy_init_comm +@@ -664,6 +681,7 @@ static inline int jent_entropy_init_comm int ret; jent_notime_block_switch(); @@ -130,7 +126,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c if (sha3_tester()) return EHASH; -@@ -710,6 +727,8 @@ int jent_entropy_init_ex(unsigned int os +@@ -710,6 +728,8 @@ int jent_entropy_init_ex(unsigned int os if (ret) return ret; @@ -139,17 +135,10 @@ Index: libgcrypt-1.9.4/random/jitterentropy-base.c /* Test without internal timer unless caller does not want it */ if (!(flags & JENT_FORCE_INTERNAL_TIMER)) ret = jent_time_entropy_init(osr, -@@ -725,10 +744,14 @@ int jent_entropy_init_ex(unsigned int os - return jent_entropy_init_common_post(ret); - } - --#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER - JENT_PRIVATE_STATIC - int jent_entropy_switch_notime_impl(struct jent_notime_thread *new_thread) - { +@@ -732,3 +752,9 @@ int jent_entropy_switch_notime_impl(stru return jent_notime_switch(new_thread); } --#endif + #endif + +JENT_PRIVATE_STATIC +int jent_set_fips_failure_callback(jent_fips_failure_cb cb) @@ -383,7 +372,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-noise.c } #define MAX_ACC_LOOP_BIT 7 -@@ -184,37 +202,37 @@ static inline uint32_t xoshiro128starsta +@@ -184,13 +202,12 @@ static inline uint32_t xoshiro128starsta static void jent_memaccess(struct rand_data *ec, uint64_t loop_cnt) { @@ -395,11 +384,10 @@ Index: libgcrypt-1.9.4/random/jitterentropy-noise.c } prngState = { .u = {0x8e93eec0, 0xce65608a, 0xa8d46b46, 0xe83cef69} }; uint32_t addressMask; - uint64_t acc_loop_cnt; -- -- if (NULL == ec || NULL == ec->mem) -- return; -- -- addressMask = ec->memmask; + + if (NULL == ec || NULL == ec->mem) + return; +@@ -199,7 +216,7 @@ static void jent_memaccess(struct rand_d /* Ensure that macros cannot overflow jent_loop_shuffle() */ BUILD_BUG_ON((MAX_ACC_LOOP_BIT + MIN_ACC_LOOP_BIT) > 63); @@ -407,18 +395,8 @@ Index: libgcrypt-1.9.4/random/jitterentropy-noise.c + uint64_t acc_loop_cnt = jent_loop_shuffle(ec, MAX_ACC_LOOP_BIT, MIN_ACC_LOOP_BIT); -+ if (NULL == ec || NULL == ec->mem) -+ return; -+ addressMask = ec->memmask; -+ /* - * Mix the current data into prngState - * - * Any time you see a PRNG in a noise source, you should be concerned. - * - * The PRNG doesn't directly produce the raw noise, it just adjusts the - * location being updated. The timing of the update is part of the raw - * sample. The main thing this process gets you isn't better +@@ -213,8 +230,10 @@ static void jent_memaccess(struct rand_d * "per-update: timing, it gets you mostly independent "per-update" * timing, so we can now benefit from the Central Limit Theorem! */ @@ -431,7 +409,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-noise.c /* * testing purposes -- allow test app to set the counter, not -@@ -358,21 +376,21 @@ unsigned int jent_measure_jitter(struct +@@ -358,21 +377,21 @@ unsigned int jent_measure_jitter(struct /** * Generator of one 256 bit random number @@ -458,7 +436,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy-noise.c /* If a stuck measurement is received, repeat measurement */ if (jent_measure_jitter(ec, 0, NULL)) continue; -@@ -385,3 +403,22 @@ void jent_random_data(struct rand_data * +@@ -385,3 +404,22 @@ void jent_random_data(struct rand_data * break; } } @@ -561,18 +539,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy.h =================================================================== --- libgcrypt-1.9.4.orig/random/jitterentropy.h +++ libgcrypt-1.9.4/random/jitterentropy.h -@@ -42,6 +42,10 @@ - #ifndef _JITTERENTROPY_H - #define _JITTERENTROPY_H - -+#ifdef __cplusplus -+extern "C" { -+#endif -+ - /*************************************************************************** - * Jitter RNG Configuration Section - * -@@ -49,7 +53,7 @@ +@@ -49,7 +49,7 @@ ***************************************************************************/ /* @@ -581,7 +548,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy.h * * In case the hardware is identified to not provide a high-resolution time * stamp, this option enables a built-in high-resolution time stamp mechanism. -@@ -166,7 +173,7 @@ struct rand_data +@@ -166,7 +166,7 @@ struct rand_data * of the RNG are marked as SENSITIVE. A user must not * access that information while the RNG executes its loops to * calculate the next random value. */ @@ -590,7 +557,7 @@ Index: libgcrypt-1.9.4/random/jitterentropy.h uint64_t prev_time; /* SENSITIVE Previous time stamp */ #define DATA_SIZE_BITS (SHA3_256_SIZE_DIGEST_BITS) -@@ -378,29 +389,34 @@ int jent_entropy_init(void); +@@ -378,28 +379,34 @@ int jent_entropy_init(void); JENT_PRIVATE_STATIC int jent_entropy_init_ex(unsigned int osr, unsigned int flags); @@ -627,19 +594,9 @@ Index: libgcrypt-1.9.4/random/jitterentropy.h }; -#ifdef JENT_CONF_ENABLE_INTERNAL_TIMER -- + JENT_PRIVATE_STATIC int jent_notime_init(void **ctx); - -@@ -448,4 +464,8 @@ uint64_t jent_lfsr_var_stat(struct rand_ - - /* -- END of statistical test function -- */ - -+#ifdef __cplusplus -+} -+#endif -+ - #endif /* _JITTERENTROPY_H */ Index: libgcrypt-1.9.4/random/jitterentropy-base-user.h =================================================================== --- libgcrypt-1.9.4.orig/random/jitterentropy-base-user.h diff --git a/libgcrypt.changes b/libgcrypt.changes index d61904f..1ab7201 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -1,3 +1,23 @@ +------------------------------------------------------------------- +Thu Sep 8 10:34:53 UTC 2022 - Pedro Monreal + +- FIPS: Get most of the entropy from rndjent_poll [bsc#1202117] + * Add libgcrypt-FIPS-rndjent_poll.patch + * Rebase libgcrypt-jitterentropy-3.4.0.patch + +------------------------------------------------------------------- +Wed Sep 7 22:03:51 UTC 2022 - Pedro Monreal + +- FIPS: Check keylength in gcry_fips_indicator_kdf() [bsc#1190700] + * Consider approved keylength greater or equal to 112 bits. + * Add libgcrypt-FIPS-kdf-leylength.patch + +------------------------------------------------------------------- +Wed Sep 7 12:53:14 UTC 2022 - Pedro Monreal + +- FIPS: Zeroize buffer and digest in check_binary_integrity() + * Add libgcrypt-FIPS-Zeroize-hmac.patch [bsc#1191020] + ------------------------------------------------------------------- Tue Aug 23 09:19:00 UTC 2022 - Pedro Monreal diff --git a/libgcrypt.spec b/libgcrypt.spec index f90d6bf..3249111 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -107,6 +107,12 @@ Patch45: libgcrypt-jitterentropy-3.3.0.patch Patch46: libgcrypt-jitterentropy-3.4.0.patch #PATCH-FIX-SUSE bsc#1182983 gpg: out of core handler ignored in FIPS mode while typing Tab key to Auto-Completion Patch47: libgcrypt-out-of-core-handler.patch +#PATCH-FIX-SUSE bsc#1191020 FIPS: Zeroize buffer and digest in check_binary_integrity() +Patch48: libgcrypt-FIPS-Zeroize-hmac.patch +#PATCH-FIX-SUSE bsc#1190700 FIPS: Check keylength in gcry_fips_indicator_kdf() +Patch49: libgcrypt-FIPS-kdf-leylength.patch +#PATCH-FIX-SUSE bsc#1202117 FIPS: Get most of the entropy from rndjent_poll +Patch50: libgcrypt-FIPS-rndjent_poll.patch BuildRequires: automake >= 1.14 BuildRequires: fipscheck BuildRequires: libgpg-error-devel >= 1.27