diff --git a/gnutls-FIPS-SLI-pbkdf2-verify-keylengths-only-SHA.patch b/gnutls-FIPS-SLI-pbkdf2-verify-keylengths-only-SHA.patch new file mode 100644 index 0000000..3ec109f --- /dev/null +++ b/gnutls-FIPS-SLI-pbkdf2-verify-keylengths-only-SHA.patch @@ -0,0 +1,114 @@ +Index: gnutls-3.7.7/lib/crypto-api.c +=================================================================== +--- gnutls-3.7.7.orig/lib/crypto-api.c ++++ gnutls-3.7.7/lib/crypto-api.c +@@ -2228,7 +2228,12 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac + if (!is_mac_algo_allowed(mac)) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); + return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); +- } else if (!is_mac_algo_approved_in_fips(mac)) { ++ } else if (!is_mac_algo_approved_for_pbkdf2_in_fips(mac)) { ++ not_approved = true; ++ } ++ ++ /* Key lengthes less than 112 bits are not approved */ ++ if (length < 14 || key->size < 14) { + not_approved = true; + } + +Index: gnutls-3.7.7/lib/fips.h +=================================================================== +--- gnutls-3.7.7.orig/lib/fips.h ++++ gnutls-3.7.7/lib/fips.h +@@ -100,6 +100,25 @@ is_mac_algo_approved_in_fips(gnutls_mac_ + } + + inline static bool ++is_mac_algo_approved_for_pbkdf2_in_fips(gnutls_mac_algorithm_t algo) ++{ ++ switch (algo) { ++ case GNUTLS_MAC_SHA1: ++ case GNUTLS_MAC_SHA256: ++ case GNUTLS_MAC_SHA384: ++ case GNUTLS_MAC_SHA512: ++ case GNUTLS_MAC_SHA224: ++ case GNUTLS_MAC_SHA3_224: ++ case GNUTLS_MAC_SHA3_256: ++ case GNUTLS_MAC_SHA3_384: ++ case GNUTLS_MAC_SHA3_512: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++inline static bool + is_mac_algo_allowed_in_fips(gnutls_mac_algorithm_t algo) + { + return is_mac_algo_approved_in_fips(algo); +Index: gnutls-3.7.7/lib/crypto-selftests.c +=================================================================== +--- gnutls-3.7.7.orig/lib/crypto-selftests.c ++++ gnutls-3.7.7/lib/crypto-selftests.c +@@ -3090,30 +3090,6 @@ struct pbkdf2_vectors_st { + }; + + const struct pbkdf2_vectors_st pbkdf2_sha256_vectors[] = { +- /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ +- { +- STR(key, key_size, "passwd"), +- STR(salt, salt_size, "salt"), +- .iter_count = 1, +- STR(output, output_size, +- "\x55\xac\x04\x6e\x56\xe3\x08\x9f\xec\x16\x91\xc2\x25\x44" +- "\xb6\x05\xf9\x41\x85\x21\x6d\xde\x04\x65\xe6\x8b\x9d\x57" +- "\xc2\x0d\xac\xbc\x49\xca\x9c\xcc\xf1\x79\xb6\x45\x99\x16" +- "\x64\xb3\x9d\x77\xef\x31\x7c\x71\xb8\x45\xb1\xe3\x0b\xd5" +- "\x09\x11\x20\x41\xd3\xa1\x97\x83"), +- }, +- /* RFC 7914: 11. Test Vectors for PBKDF2 with HMAC-SHA-256 */ +- { +- STR(key, key_size, "Password"), +- STR(salt, salt_size, "NaCl"), +- .iter_count = 80000, +- STR(output, output_size, +- "\x4d\xdc\xd8\xf6\x0b\x98\xbe\x21\x83\x0c\xee\x5e\xf2\x27" +- "\x01\xf9\x64\x1a\x44\x18\xd0\x4c\x04\x14\xae\xff\x08\x87" +- "\x6b\x34\xab\x56\xa1\xd4\x25\xa1\x22\x58\x33\x54\x9a\xdb" +- "\x84\x1b\x51\xc9\xb3\x17\x6a\x27\x2b\xde\xbb\xa1\xd0\x78" +- "\x47\x8f\x62\xb3\x97\xf3\x3c\x8d"), +- }, + /* Test vector extracted from: + * https://dev.gnupg.org/source/libgcrypt/browse/master/cipher/kdf.c */ + { +Index: gnutls-3.7.7/tests/kdf-api.c +=================================================================== +--- gnutls-3.7.7.orig/tests/kdf-api.c ++++ gnutls-3.7.7/tests/kdf-api.c +@@ -192,14 +192,19 @@ doit(void) + "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865"); + +- /* Test vector from RFC 6070. More thorough testing is done +- * in nettle. */ +- test_pbkdf2(GNUTLS_MAC_SHA1, +- "70617373776f7264", /* "password" */ +- "73616c74", /* "salt" */ ++ /* Test vector extracted from: ++ * https://dev.gnupg.org/source/libgcrypt/browse/master/cipher/kdf.c */ ++ test_pbkdf2(GNUTLS_MAC_SHA256, ++ "70617373776f726450415353" ++ "574f524470617373776f7264", /* "passwordPASSWORDpassword" */ ++ "73616c7453414c5473616c74" ++ "53414c5473616c7453414c54" ++ "73616c7453414c5473616c74", /* "saltSALTsaltSALTsaltSALTsaltSALTsalt" */ + 4096, +- 20, +- "4b007901b765489abead49d926f721d065a429c1"); ++ 40, ++ "348c89dbcbd32b2f32d814b8" ++ "116e84cf2b17347ebc180018" ++ "1c4e2a1fb8dd53e1c635518c7dac47e9"); + + gnutls_fips140_context_deinit(fips_context); + } diff --git a/gnutls-FIPS-jitterentropy.patch b/gnutls-FIPS-jitterentropy.patch new file mode 100644 index 0000000..8f46739 --- /dev/null +++ b/gnutls-FIPS-jitterentropy.patch @@ -0,0 +1,195 @@ +Index: gnutls-3.7.3/lib/nettle/sysrng-linux.c +=================================================================== +--- gnutls-3.7.3.orig/lib/nettle/sysrng-linux.c ++++ gnutls-3.7.3/lib/nettle/sysrng-linux.c +@@ -49,6 +49,12 @@ + get_entropy_func _rnd_get_system_entropy = NULL; + + #if defined(__linux__) ++# ifdef ENABLE_FIPS140 ++# define HAVE_JENT ++# include ++static int jent_initialized = 0; ++static struct rand_data* ec = NULL; ++# endif + # ifdef HAVE_GETRANDOM + # include + # else +@@ -66,6 +72,96 @@ static ssize_t _getrandom0(void *buf, si + # endif + # endif + ++# if defined(HAVE_JENT) ++/* check whether the CPU Jitter entropy collector is available. */ ++static unsigned FIPS_jent_entropy_init(void) ++{ ++ unsigned int rv = 1; ++ unsigned int osr = 1; /* Oversampling rate */ ++ unsigned int flags = 0; /* JENT_FORCE_FIPS ++ * JENT_DISABLE_MEMORY_ACCESS ++ * JENT_DISABLE_INTERNAL_TIMER ++ * JENT_FORCE_INTERNAL_TIMER ++ * JENT_MAX_MEMSIZE_{32,64,128,256,512}kB ++ * JENT_MAX_MEMSIZE_{1,2,4,8,16,32,64,128,256,512}MB ++ */ ++ ++ /* Set the FIPS flag. */ ++ flags |= JENT_FORCE_FIPS; ++ ++ /* Do not re-initialize jent. */ ++ if (jent_initialized == 0) { ++ if (jent_entropy_init_ex(osr, flags)) ++ return 0; ++ jent_initialized = 1; ++ } ++ ++ /* Allocate the entropy collector. */ ++ if (ec == NULL) { ++ ec = jent_entropy_collector_alloc(osr, flags); ++ if (ec == NULL) { ++ rv = 0; ++ } ++ } ++ ++ return rv; ++} ++ ++void FIPS_jent_entropy_deinit(void) ++{ ++ /* Free the entropy collector. */ ++ if (ec != NULL) { ++ jent_entropy_collector_free(ec); ++ ec = NULL; ++ } ++ ++ return; ++} ++ ++/* returns exactly the amount of bytes requested */ ++static int force_jent(void *buf, size_t buflen, unsigned int flags, ++ unsigned int osr) ++{ ++ static int jent_bytes = -1; ++ ++ if (buf == NULL || buflen == 0) { ++ return -1; ++ } ++ ++ /* Ensure the entropy source has been fully initiated. */ ++ if (jent_initialized == 0 || ec == NULL) { ++ if (!FIPS_jent_entropy_init()) { ++ return -1; ++ } ++ } ++ ++ /* Get entropy bytes. */ ++ jent_bytes = jent_read_entropy_safe(&ec, (char *)buf, buflen); ++ ++ return jent_bytes; ++} ++ ++static int _rnd_get_system_entropy_jent(void* _rnd, size_t size) ++{ ++ int ret; ++ unsigned int osr = 1; ++ unsigned int flags = 0; ++ ++ /* Set the FIPS flag. */ ++ flags |= JENT_FORCE_FIPS; ++ ++ ret = force_jent(_rnd, size, flags, osr); ++ if (ret < 0) { ++ int e = errno; ++ gnutls_assert(); ++ _gnutls_debug_log("Failed to use jent: %s\n", strerror(e)); ++ FIPS_jent_entropy_deinit(); ++ return GNUTLS_E_RANDOM_DEVICE_ERROR; ++ } ++ ++ return 0; ++} ++# endif + + static unsigned have_getrandom(void) + { +@@ -164,6 +260,16 @@ int _rnd_system_entropy_init(void) + int urandom_fd; + + #if defined(__linux__) ++# if defined(HAVE_JENT) ++ /* Enable jitterentropy usage if available */ ++ if (FIPS_jent_entropy_init()) { ++ _rnd_get_system_entropy = _rnd_get_system_entropy_jent; ++ _gnutls_debug_log("jitterentropy random generator was selected\n"); ++ return 0; ++ } else { ++ _gnutls_debug_log("jitterentropy is not available\n"); ++ } ++# endif + /* Enable getrandom() usage if available */ + if (have_getrandom()) { + _rnd_get_system_entropy = _rnd_get_system_entropy_getrandom; +@@ -193,6 +299,11 @@ int _rnd_system_entropy_init(void) + void _rnd_system_entropy_deinit(void) + { + /* A no-op now when we open and close /dev/urandom every time */ ++#if defined(__linux__) ++# if defined(HAVE_JENT) ++ FIPS_jent_entropy_deinit(); ++# endif ++#endif + return; + } + +Index: gnutls-3.7.3/lib/nettle/Makefile.in +=================================================================== +--- gnutls-3.7.3.orig/lib/nettle/Makefile.in ++++ gnutls-3.7.3/lib/nettle/Makefile.in +@@ -398,7 +398,7 @@ am__v_CC_1 = + CCLD = $(CC) + LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ +- $(AM_LDFLAGS) $(LDFLAGS) -o $@ ++ $(AM_LDFLAGS) $(LDFLAGS) -ljitterentropy -o $@ + AM_V_CCLD = $(am__v_CCLD_@AM_V@) + am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) + am__v_CCLD_0 = @echo " CCLD " $@; +Index: gnutls-3.7.3/lib/nettle/Makefile.am +=================================================================== +--- gnutls-3.7.3.orig/lib/nettle/Makefile.am ++++ gnutls-3.7.3/lib/nettle/Makefile.am +@@ -20,7 +20,7 @@ + + include $(top_srcdir)/lib/common.mk + +-AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS) ++AM_CFLAGS += $(HOGWEED_CFLAGS) $(GMP_CFLAGS) -ljitterentropy + + AM_CPPFLAGS = \ + -I$(srcdir)/int \ +Index: gnutls-3.7.3/lib/nettle/rnd-fips.c +=================================================================== +--- gnutls-3.7.3.orig/lib/nettle/rnd-fips.c ++++ gnutls-3.7.3/lib/nettle/rnd-fips.c +@@ -129,6 +129,10 @@ static int drbg_init(struct fips_ctx *fc + uint8_t buffer[DRBG_AES_SEED_SIZE]; + int ret; + ++ ret = _rnd_get_system_entropy(buffer, sizeof(buffer)); ++ if (ret < 0) ++ return gnutls_assert_val(ret); ++ + ret = get_entropy(fctx, buffer, sizeof(buffer)); + if (ret < 0) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); +@@ -153,6 +157,10 @@ static int drbg_reseed(struct fips_ctx * + uint8_t buffer[DRBG_AES_SEED_SIZE]; + int ret; + ++ ret = _rnd_get_system_entropy(buffer, sizeof(buffer)); ++ if (ret < 0) ++ return gnutls_assert_val(ret); ++ + ret = get_entropy(fctx, buffer, sizeof(buffer)); + if (ret < 0) { + _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); diff --git a/gnutls.changes b/gnutls.changes index 2aa59be..00efdcc 100644 --- a/gnutls.changes +++ b/gnutls.changes @@ -4,6 +4,23 @@ Tue Sep 13 18:08:03 UTC 2022 - Andreas Stieger - provide a libgnutls30-hmac-32bit to avoid uninstallable wine when pattern-base-fips is installed [boo#1203353] +------------------------------------------------------------------- +Tue Sep 6 16:17:12 UTC 2022 - Pedro Monreal + +- FIPS: Additional modifications to the SLI. [bsc#1190698] + * Mark CMAC and GMAC and non-approved in gnutls_pbkfd2(). + * Mark HMAC keylength less than 112 bits as non-approved in + gnutls_pbkfd2(). + * Adapt the pbkdf2 selftest and the regression tests accordingly. + * Add gnutls-FIPS-SLI-pbkdf2-verify-keylengths-only-SHA.patch + +------------------------------------------------------------------- +Mon Aug 8 16:41:19 UTC 2022 - Pedro Monreal + +- FIPS: Port GnuTLS to use jitterentropy [bsc#1202146, jsc#SLE-24941] + * Add new dependency on jitterentropy + * Add gnutls-FIPS-jitterentropy.patch + ------------------------------------------------------------------- Fri Jul 29 14:29:17 UTC 2022 - Pedro Monreal @@ -53,6 +70,15 @@ Fri Jul 29 14:29:17 UTC 2022 - Pedro Monreal - gnutls-FIPS-PBKDF2-KAT-requirements.patch - https://gitlab.com/gnutls/gnutls/merge_requests/1561 +------------------------------------------------------------------- +Wed Jun 29 15:56:59 UTC 2022 - Richard Costa + +- FIPS: + * Add gnutls_ECDSA_signing.patch [bsc#1190698] + - Check minimum keylength for symmetric key generation + - Only allows ECDSA signature with valid set of hashes + (SHA2 and SHA3) + ------------------------------------------------------------------- Fri May 27 16:56:26 UTC 2022 - Antoine Belvire diff --git a/gnutls.spec b/gnutls.spec index a6cb5c6..d5d3271 100644 --- a/gnutls.spec +++ b/gnutls.spec @@ -50,6 +50,13 @@ Patch0: gnutls-3.5.11-skip-trust-store-tests.patch Patch1: gnutls-3.6.6-set_guile_site_dir.patch Patch2: gnutls-FIPS-TLS_KDF_selftest.patch Patch3: gnutls-FIPS-disable-failing-tests.patch +Patch4: gnutls_ECDSA_signing.patch +%if 0%{?suse_version} >= 1550 || 0%{?sle_version} >= 150400 +#PATCH-FIX-SUSE bsc#1202146 FIPS: Port gnutls to use jitterentropy +Patch5: gnutls-FIPS-jitterentropy.patch +%endif +#PATCH-FIX-SUSE bsc#1190698 FIPS: SLI gnutls_pbkdf2: verify keylengths and allow SHA only +Patch6: gnutls-FIPS-SLI-pbkdf2-verify-keylengths-only-SHA.patch BuildRequires: autogen BuildRequires: automake BuildRequires: datefudge @@ -94,6 +101,8 @@ BuildRequires: guile-devel > 1.8 %if 0%{?suse_version} >= 1550 || 0%{?sle_version} >= 150400 BuildRequires: crypto-policies Requires: crypto-policies +BuildRequires: jitterentropy-devel >= 3.4.0 +Requires: libjitterentropy3 >= 3.4.0 %endif %description diff --git a/gnutls_ECDSA_signing.patch b/gnutls_ECDSA_signing.patch new file mode 100644 index 0000000..9ad998b --- /dev/null +++ b/gnutls_ECDSA_signing.patch @@ -0,0 +1,172 @@ +Index: gnutls-3.7.7/lib/crypto-api.c +=================================================================== +--- gnutls-3.7.7.orig/lib/crypto-api.c ++++ gnutls-3.7.7/lib/crypto-api.c +@@ -1056,6 +1056,7 @@ gnutls_hash_hd_t gnutls_hash_copy(gnutls + int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size) + { + int ret; ++ bool not_approved = false; + + FAIL_IF_LIB_ERROR; + +@@ -1066,6 +1067,10 @@ int gnutls_key_generate(gnutls_datum_t * + if (_gnutls_fips_mode_enabled() != 0 && + key_size > FIPS140_RND_KEY_SIZE) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ++ if (key_size < 14) { ++ not_approved = true; ++ } ++ + #endif + + key->size = key_size; +@@ -1082,6 +1087,15 @@ int gnutls_key_generate(gnutls_datum_t * + return ret; + } + ++#ifdef ENABLE_FIPS140 ++ if (not_approved) { ++ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED); ++ } else { ++ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED); ++ } ++ ++#endif ++ + return 0; + } + +Index: gnutls-3.7.7/lib/fips.h +=================================================================== +--- gnutls-3.7.7.orig/lib/fips.h ++++ gnutls-3.7.7/lib/fips.h +@@ -145,6 +145,30 @@ is_cipher_algo_allowed_in_fips(gnutls_ci + } + } + ++inline static bool ++is_digest_algo_approved_for_sign_in_fips(gnutls_digest_algorithm_t algo) ++{ ++ switch (algo) { ++ case GNUTLS_DIG_SHA224: ++ case GNUTLS_DIG_SHA256: ++ case GNUTLS_DIG_SHA384: ++ case GNUTLS_DIG_SHA512: ++ case GNUTLS_DIG_SHA3_224: ++ case GNUTLS_DIG_SHA3_256: ++ case GNUTLS_DIG_SHA3_384: ++ case GNUTLS_DIG_SHA3_512: ++ return true; ++ default: ++ return false; ++ } ++} ++ ++inline static bool ++is_digest_algo_allowed_for_sign_in_fips(gnutls_digest_algorithm_t algo) ++{ ++ return is_digest_algo_approved_for_sign_in_fips(algo); ++} ++ + #ifdef ENABLE_FIPS140 + /* This will test the condition when in FIPS140-2 mode + * and return an error if necessary or ignore */ +@@ -205,9 +229,33 @@ is_cipher_algo_allowed(gnutls_cipher_alg + + return true; + } ++ ++inline static bool ++is_digest_algo_allowed_for_sign(gnutls_digest_algorithm_t algo) ++{ ++ gnutls_fips_mode_t mode = _gnutls_fips_mode_enabled(); ++ if (_gnutls_get_lib_state() != LIB_STATE_SELFTEST && ++ !is_digest_algo_allowed_for_sign_in_fips(algo)) { ++ switch (mode) { ++ case GNUTLS_FIPS140_LOG: ++ _gnutls_audit_log(NULL, "fips140-2: allowing access to %s\n", ++ gnutls_cipher_get_name(algo)); ++ FALLTHROUGH; ++ case GNUTLS_FIPS140_DISABLED: ++ case GNUTLS_FIPS140_LAX: ++ return true; ++ default: ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + #else + # define is_mac_algo_allowed(x) true + # define is_cipher_algo_allowed(x) true ++# define is_digest_algo_allowed_for_sign(x) true + # define FIPS_RULE(condition, ret_error, ...) + #endif + +Index: gnutls-3.7.7/lib/privkey.c +=================================================================== +--- gnutls-3.7.7.orig/lib/privkey.c ++++ gnutls-3.7.7/lib/privkey.c +@@ -1284,10 +1284,24 @@ privkey_sign_and_hash_data(gnutls_privke + int ret; + gnutls_datum_t digest; + const mac_entry_st *me; ++ bool not_approved = false; + + if (unlikely(se == NULL)) + return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); + ++ if (se->pk == GNUTLS_PK_ECDSA && !is_digest_algo_allowed_for_sign(se->hash)) { ++ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR); ++ return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM); ++ } else if (se->pk == GNUTLS_PK_ECDSA && !is_digest_algo_approved_for_sign_in_fips(se->hash)) { ++ not_approved = true; ++ } ++ ++ if (not_approved) { ++ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED); ++ } else { ++ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED); ++ } ++ + if (_gnutls_pk_is_not_prehashed(se->pk)) { + return privkey_sign_raw_data(signer, se, data, signature, params); + } +Index: gnutls-3.7.7/tests/fips-test.c +=================================================================== +--- gnutls-3.7.7.orig/tests/fips-test.c ++++ gnutls-3.7.7/tests/fips-test.c +@@ -38,6 +38,7 @@ static void tls_log_func(int level, cons + fprintf(stderr, "<%d>| %s", level, str); + } + ++static uint8_t key13[13]; + static uint8_t key16[16]; + static uint8_t iv16[16]; + uint8_t key_data[64]; +@@ -269,6 +270,7 @@ void doit(void) + gnutls_pubkey_t pubkey; + gnutls_x509_privkey_t xprivkey; + gnutls_privkey_t privkey; ++ gnutls_datum_t key_invalid = { key13, sizeof(key13) }; + gnutls_datum_t key = { key16, sizeof(key16) }; + gnutls_datum_t iv = { iv16, sizeof(iv16) }; + gnutls_datum_t signature; +@@ -309,6 +311,14 @@ void doit(void) + /* Try crypto.h functionality */ + test_ciphers(); + ++ /* Try creating key with less than 112 bits: not approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_key_generate(&key_invalid, 13); ++ if (ret < 0) { ++ fail("gnutls_generate_key failed\n"); ++ } ++ FIPS_POP_CONTEXT(NOT_APPROVED); ++ + FIPS_PUSH_CONTEXT(); + ret = gnutls_cipher_init(&ch, GNUTLS_CIPHER_AES_128_CBC, &key, &iv); + if (ret < 0) {