From c941c8db1e8b99bd5f2b3d277b5cdcf04191f8b8f899a1d9a6d07fc5f6c5e475 Mon Sep 17 00:00:00 2001 From: Pedro Monreal Gonzalez Date: Tue, 1 Feb 2022 13:12:14 +0000 Subject: [PATCH] Accepting request 950433 from home:pmonrealgonzalez:branches:devel:libraries:c_c++ - FIPS: Disable DSA in FIPS mode [bsc#1195385] * Upstream task: https://dev.gnupg.org/T5710 * Add libgcrypt-FIPS-disable-DSA.patch - FIPS: Service level indicator [bsc#1190700] * Provide an indicator to check wether the service utilizes an approved cryptographic algorithm or not. * Add patches: - libgcrypt-FIPS-service-indicators.patch - libgcrypt-FIPS-verify-unsupported-KDF-test.patch - libgcrypt-FIPS-HMAC-short-keylen.patch - FIPS: Define an entropy source SP800-90B compliant [bsc#1185140] * Disable jitter entropy by default in random.conf * Disable only-urandom option by default in random.conf - FIPS: RSA KeyGen/SigGen fail with 4096 bit key sizes [bsc#1192240] * rsa: Check RSA keylen constraints for key operations. * rsa: Fix regression in not returning an error for prime generation. * tests: Add 2k RSA key working in FIPS mode. * tests: pubkey: Replace RSA key to one of 2k. * tests: pkcs1v2: Skip tests with small keys in FIPS. * Add patches: - libgcrypt-FIPS-RSA-keylen.patch - libgcrypt-FIPS-RSA-keylen-tests.patch - FIPS: Disable 3DES/Triple-DES in FIPS mode [bsc#1185138] * Add libgcrypt-FIPS-disable-3DES.patch - FIPS: PBKDF requirements [bsc#1185137] OBS-URL: https://build.opensuse.org/request/show/950433 OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=153 --- libgcrypt-FIPS-HMAC-short-keylen.patch | 203 ++++++ libgcrypt-FIPS-RSA-keylen-tests.patch | 585 ++++++++++++++++++ libgcrypt-FIPS-RSA-keylen.patch | 250 ++++++++ libgcrypt-FIPS-disable-3DES.patch | 52 ++ libgcrypt-FIPS-disable-DSA.patch | 44 ++ libgcrypt-FIPS-fix-regression-tests.patch | 448 ++++++++++++++ libgcrypt-FIPS-hw-optimizations.patch | 31 + libgcrypt-FIPS-module-version.patch | 89 +++ libgcrypt-FIPS-service-indicators.patch | 380 ++++++++++++ ...ypt-FIPS-verify-unsupported-KDF-test.patch | 35 ++ libgcrypt.changes | 74 +++ libgcrypt.spec | 26 +- random.conf | 4 +- 13 files changed, 2216 insertions(+), 5 deletions(-) create mode 100644 libgcrypt-FIPS-HMAC-short-keylen.patch create mode 100644 libgcrypt-FIPS-RSA-keylen-tests.patch create mode 100644 libgcrypt-FIPS-RSA-keylen.patch create mode 100644 libgcrypt-FIPS-disable-3DES.patch create mode 100644 libgcrypt-FIPS-disable-DSA.patch create mode 100644 libgcrypt-FIPS-fix-regression-tests.patch create mode 100644 libgcrypt-FIPS-hw-optimizations.patch create mode 100644 libgcrypt-FIPS-module-version.patch create mode 100644 libgcrypt-FIPS-service-indicators.patch create mode 100644 libgcrypt-FIPS-verify-unsupported-KDF-test.patch diff --git a/libgcrypt-FIPS-HMAC-short-keylen.patch b/libgcrypt-FIPS-HMAC-short-keylen.patch new file mode 100644 index 0000000..c09acf3 --- /dev/null +++ b/libgcrypt-FIPS-HMAC-short-keylen.patch @@ -0,0 +1,203 @@ +From 76aad97dd312e83f2f9b8d086553f2b72ab6546f Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Wed, 19 Jan 2022 11:41:40 +0900 +Subject: [PATCH 2/2] fips: Reject shorter key for HMAC in FIPS mode. + +* cipher/md.c (prepare_macpads): Reject < 112-bit key. +* cipher/kdf.c (selftest_pbkdf2): Remove selftest cases with shorter +key. +* cipher/mac-hmac.c (selftests_sha224, selftests_sha256): Likewise. +(selftests_sha384, selftests_sha512, selftests_sha3): Likewise. +* tests/basic.c (check_one_hmac) Handle an error when shorter key +is rejected. +(check_one_mac): Likewise. +* tests/t-kdf.c (check_pbkdf2, check_scrypt): Likewise. + +-- + +GnuPG-bug-id: 5512 +Signed-off-by: NIIBE Yutaka +--- + cipher/kdf.c | 76 ++--------------------------------------------- + cipher/mac-hmac.c | 67 ----------------------------------------- + cipher/md.c | 3 ++ + tests/basic.c | 29 +++++++++++++++--- + tests/t-kdf.c | 38 ++++++++++++++++++++---- + 5 files changed, 62 insertions(+), 151 deletions(-) + +Index: libgcrypt-1.9.4/cipher/kdf.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/kdf.c ++++ libgcrypt-1.9.4/cipher/kdf.c +@@ -324,6 +324,10 @@ check_one (int algo, int hash_algo, + unsigned char key[512]; /* hardcoded to avoid allocation */ + size_t keysize = expectlen; + ++ /* Skip test with shoter passphrase in FIPS mode. */ ++ if (fips_mode () && passphraselen < 14) ++ return NULL; ++ + if (keysize > sizeof(key)) + return "invalid tests data"; + +Index: libgcrypt-1.9.4/cipher/mac-hmac.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/mac-hmac.c ++++ libgcrypt-1.9.4/cipher/mac-hmac.c +@@ -241,6 +241,11 @@ check_one (int algo, + const unsigned char *digest; + + /* printf ("HMAC algo %d\n", algo); */ ++ ++ /* Skip test with shoter key in FIPS mode. */ ++ if (fips_mode () && keylen < 14) ++ return NULL; ++ + if (trunc) + { + if (_gcry_md_get_algo_dlen (algo) < expectlen) +Index: libgcrypt-1.9.4/cipher/md.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/md.c ++++ libgcrypt-1.9.4/cipher/md.c +@@ -903,6 +903,9 @@ prepare_macpads (gcry_md_hd_t a, const u + { + GcryDigestEntry *r; + ++ if (fips_mode () && keylen < 14) ++ return GPG_ERR_INV_VALUE; ++ + if (!a->ctx->list) + return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */ + +Index: libgcrypt-1.9.4/tests/basic.c +=================================================================== +--- libgcrypt-1.9.4.orig/tests/basic.c ++++ libgcrypt-1.9.4/tests/basic.c +@@ -12016,7 +12016,19 @@ check_one_hmac (int algo, const char *da + return; + } + +- gcry_md_setkey( hd, key, keylen ); ++ err = gcry_md_setkey( hd, key, keylen ); ++ if (err) ++ { ++ if (in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, ++ " shorter key (%d) rejected correctly in fips mode\n", ++ keylen); ++ } ++ gcry_md_close (hd); ++ return; ++ } + + gcry_md_write (hd, data, datalen); + +@@ -12420,9 +12432,18 @@ check_one_mac (int algo, const char *dat + clutter_vector_registers(); + err = gcry_mac_setkey (hd, key, keylen); + if (err) +- fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err)); +- if (err) +- goto out; ++ { ++ if (in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, ++ " shorter key (%d) rejected correctly in fips mode\n", ++ keylen); ++ } ++ else ++ fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err)); ++ goto out; ++ } + + if (ivlen && iv) + { +Index: libgcrypt-1.9.4/tests/t-kdf.c +=================================================================== +--- libgcrypt-1.9.4.orig/tests/t-kdf.c ++++ libgcrypt-1.9.4/tests/t-kdf.c +@@ -31,6 +31,8 @@ + #define PGM "t-kdf" + #include "t-common.h" + ++static int in_fips_mode; ++ + + static void + dummy_consumer (volatile char *buffer, size_t buflen) +@@ -858,8 +860,7 @@ check_openpgp (void) + if (tv[tvidx].disabled) + continue; + /* MD5 isn't supported in fips mode */ +- if (gcry_fips_mode_active() +- && tv[tvidx].hashalgo == GCRY_MD_MD5) ++ if (in_fips_mode && tv[tvidx].hashalgo == GCRY_MD_MD5) + continue; + if (verbose) + fprintf (stderr, "checking S2K test vector %d\n", tvidx); +@@ -1104,7 +1105,7 @@ check_pbkdf2 (void) + GCRY_KDF_PBKDF2, tv[tvidx].hashalgo, + tv[tvidx].salt, tv[tvidx].saltlen, + tv[tvidx].c, tv[tvidx].dklen, outbuf); +- if (gcry_fips_mode_active() && tvidx > 6) ++ if (in_fips_mode && tvidx > 6) + { + if (!err) + fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n", +@@ -1112,7 +1113,17 @@ check_pbkdf2 (void) + continue; + } + if (err) +- fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err)); ++ { ++ if (in_fips_mode && tv[tvidx].plen < 14) ++ { ++ if (verbose) ++ fprintf (stderr, ++ " shorter key (%u) rejected correctly in fips mode\n", ++ (unsigned int)tv[tvidx].plen); ++ } ++ else ++ fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err)); ++ } + else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen)) + { + fail ("pbkdf2 test %d failed: mismatch\n", tvidx); +@@ -1209,7 +1220,17 @@ check_scrypt (void) + tv[tvidx].salt, tv[tvidx].saltlen, + tv[tvidx].parm_p, tv[tvidx].dklen, outbuf); + if (err) +- fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err)); ++ { ++ if (in_fips_mode && tv[tvidx].plen < 14) ++ { ++ if (verbose) ++ fprintf (stderr, ++ " shorter key (%u) rejected correctly in fips mode\n", ++ (unsigned int)tv[tvidx].plen); ++ } ++ else ++ fail ("scrypt test %d failed: %s\n", tvidx, gpg_strerror (err)); ++ } + else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen)) + { + fail ("scrypt test %d failed: mismatch\n", tvidx); +@@ -1281,7 +1302,12 @@ main (int argc, char **argv) + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + +- xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ ++ if (!in_fips_mode) ++ xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); ++ + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + if (debug) + xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); diff --git a/libgcrypt-FIPS-RSA-keylen-tests.patch b/libgcrypt-FIPS-RSA-keylen-tests.patch new file mode 100644 index 0000000..4cba8d3 --- /dev/null +++ b/libgcrypt-FIPS-RSA-keylen-tests.patch @@ -0,0 +1,585 @@ +From cc3571a1f2244bdf829d7d16dd546131711eb8a9 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Mon, 8 Nov 2021 13:57:18 +0900 +Subject: tests: Expect errors from algorithms not supported in + FIPS mode. + +* tests/basic.c (FLAG_NOFIPS): New. +(check_pubkey_sign): Pass and handle NOFIPS flag. +(check_pubkey_sign_ecdsa): Likewise. +(check_pubkey_crypt): Likewise. +(do_check_one_pubkey): Pass flags. +(check_pubkey): Mark explicitly algorithms expected not to work in +FIPS mode and make sure they fail. + +-- + +Co-authored-by: NIIBE Yutaka +Signed-off-by: Jakub Jelen +--- + tests/basic.c | 65 ++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 46 insertions(+), 19 deletions(-) + +Index: libgcrypt-1.9.4/tests/basic.c +=================================================================== +--- libgcrypt-1.9.4.orig/tests/basic.c ++++ libgcrypt-1.9.4/tests/basic.c +@@ -55,9 +55,10 @@ typedef struct test_spec_pubkey + } + test_spec_pubkey_t; + +-#define FLAG_CRYPT (1 << 0) +-#define FLAG_SIGN (1 << 1) +-#define FLAG_GRIP (1 << 2) ++#define FLAG_CRYPT (1 << 0) ++#define FLAG_SIGN (1 << 1) ++#define FLAG_GRIP (1 << 2) ++#define FLAG_NOFIPS (1 << 3) + + static int in_fips_mode; + +@@ -13509,7 +13510,8 @@ verify_one_signature (gcry_sexp_t pkey, + /* Test the public key sign function using the private key SKEY. PKEY + is used for verification. */ + static void +-check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) ++check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, ++ int flags) + { + gcry_error_t rc; + gcry_sexp_t sig, badhash, hash; +@@ -13588,6 +13590,7 @@ check_pubkey_sign (int n, gcry_sexp_t sk + if (rc) + die ("converting data failed: %s\n", gpg_strerror (rc)); + ++ sig = NULL; + for (dataidx = 0; datas[dataidx].data; dataidx++) + { + if (datas[dataidx].algo && datas[dataidx].algo != algo) +@@ -13603,12 +13606,19 @@ check_pubkey_sign (int n, gcry_sexp_t sk + die ("converting data failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_sign (&sig, hash, skey); ++ if (in_fips_mode && (flags & FLAG_NOFIPS)) ++ { ++ if (!rc) ++ fail ("gcry_pk_sign did not fail as expected in FIPS mode\n"); ++ goto next; ++ } + if (gcry_err_code (rc) != datas[dataidx].expected_rc) + fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc)); + + if (!rc) + verify_one_signature (pkey, hash, badhash, sig); + ++ next: + gcry_sexp_release (sig); + sig = NULL; + gcry_sexp_release (hash); +@@ -13622,7 +13632,8 @@ check_pubkey_sign (int n, gcry_sexp_t sk + /* Test the public key sign function using the private key SKEY. PKEY + is used for verification. This variant is only used for ECDSA. */ + static void +-check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey) ++check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey, ++ int flags) + { + gcry_error_t rc; + gcry_sexp_t sig, badhash, hash; +@@ -13704,6 +13715,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sex + + nbits = gcry_pk_get_nbits (skey); + ++ sig = NULL; + for (dataidx = 0; datas[dataidx].data; dataidx++) + { + if (datas[dataidx].nbits != nbits) +@@ -13723,6 +13735,12 @@ check_pubkey_sign_ecdsa (int n, gcry_sex + die ("converting data failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_sign (&sig, hash, skey); ++ if (in_fips_mode && (flags & FLAG_NOFIPS)) ++ { ++ if (!rc) ++ fail ("gcry_pk_sign did not fail as expected in FIPS mode\n"); ++ goto next; ++ } + if (gcry_err_code (rc) != datas[dataidx].expected_rc) + fail ("gcry_pk_sign failed: %s\n", gpg_strerror (rc)); + +@@ -13732,6 +13750,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sex + if (!rc) + verify_one_signature (pkey, hash, badhash, sig); + ++ next: + gcry_sexp_release (sig); + sig = NULL; + gcry_sexp_release (badhash); +@@ -13743,7 +13762,8 @@ check_pubkey_sign_ecdsa (int n, gcry_sex + + + static void +-check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) ++check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, ++ int flags) + { + gcry_error_t rc; + gcry_sexp_t plain = NULL; +@@ -13876,6 +13896,12 @@ check_pubkey_crypt (int n, gcry_sexp_t s + die ("converting data failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_encrypt (&ciph, data, pkey); ++ if (in_fips_mode && (flags & FLAG_NOFIPS)) ++ { ++ if (!rc) ++ fail ("gcry_pk_encrypt did not fail as expected in FIPS mode\n"); ++ goto next; ++ } + if (gcry_err_code (rc) != datas[dataidx].encrypt_expected_rc) + fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (rc)); + +@@ -13974,6 +14000,7 @@ check_pubkey_crypt (int n, gcry_sexp_t s + } + } + ++ next: + gcry_sexp_release (plain); + plain = NULL; + gcry_sexp_release (ciph); +@@ -14005,17 +14032,17 @@ static void + do_check_one_pubkey (int n, gcry_sexp_t skey, gcry_sexp_t pkey, + const unsigned char *grip, int algo, int flags) + { +- if (flags & FLAG_SIGN) ++ if ((flags & FLAG_SIGN)) + { + if (algo == GCRY_PK_ECDSA) +- check_pubkey_sign_ecdsa (n, skey, pkey); ++ check_pubkey_sign_ecdsa (n, skey, pkey, flags); + else +- check_pubkey_sign (n, skey, pkey, algo); ++ check_pubkey_sign (n, skey, pkey, algo, flags); + } +- if (flags & FLAG_CRYPT) +- check_pubkey_crypt (n, skey, pkey, algo); +- if (grip && (flags & FLAG_GRIP)) +- check_pubkey_grip (n, grip, skey, pkey, algo); ++ if ((flags & FLAG_CRYPT)) ++ check_pubkey_crypt (n, skey, pkey, algo, flags); ++ if (grip && (flags & FLAG_GRIP)) ++ check_pubkey_grip (n, grip, skey, pkey, algo); + } + + static void +@@ -14089,7 +14116,7 @@ check_pubkey (void) + { + static const test_spec_pubkey_t pubkeys[] = { + { +- GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP, ++ GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP | FLAG_NOFIPS, /* 1k RSA */ + { + "(private-key\n" + " (rsa\n" +@@ -14228,7 +14255,7 @@ check_pubkey (void) + "\x47\xdd\x69\x55\xdb\x3a\xac\x89\x6e\x40"} + }, + { +- GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP, ++ GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP | FLAG_NOFIPS, + { + "(private-key\n" + " (ELG\n" +@@ -14360,7 +14387,7 @@ check_pubkey (void) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } + }, + { /* GOST R 34.10-2001/2012 test 256 bit. */ +- GCRY_PK_ECDSA, FLAG_SIGN, ++ GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS, + { + "(private-key\n" + " (ecc\n" +@@ -14382,7 +14409,7 @@ check_pubkey (void) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } + }, + { /* GOST R 34.10-2012 test 512 bit. */ +- GCRY_PK_ECDSA, FLAG_SIGN, ++ GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS, + { + "(private-key\n" + " (ecc\n" +@@ -14433,7 +14460,7 @@ check_pubkey (void) + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" } + }, + { /* sm2 test */ +- GCRY_PK_ECDSA, FLAG_SIGN, ++ GCRY_PK_ECDSA, FLAG_SIGN | FLAG_NOFIPS, + { + "(private-key\n" + " (ecc\n" +From 66119e0c1a024f7cf059393c3db827eb338339b0 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Thu, 11 Nov 2021 13:03:58 +0900 +Subject: tests:pubkey: Replace RSA key to one of 2k. + +* tests/pubkey.c (sample_private_key_1): Use 2k key from basic.c. +(sample_private_key_1_1): Likewise. +(sample_private_key_1_2): Likewise. + +-- + +GnuPG-bug-id: 5512 +Signed-off-by: NIIBE Yutaka +--- + tests/pubkey.c | 126 ++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 88 insertions(+), 38 deletions(-) + +diff --git a/tests/pubkey.c b/tests/pubkey.c +index 8a482dc3..51ef0f51 100644 +--- a/tests/pubkey.c ++++ b/tests/pubkey.c +@@ -36,21 +36,40 @@ static int in_fips_mode; + static const char sample_private_key_1[] = + "(private-key\n" + " (openpgp-rsa\n" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +- "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +- "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +- "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" ++" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++" CB#)\n" + " (e #010001#)\n" +-" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" +- "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" +- "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" +- "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +-" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" +- "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" +-" (q #00f7a7ca5367c661f8e62df34f0d05c10c88e5492348dd7bddc942c9a8f369f9" +- "35a07785d2db805215ed786e4285df1658eed3ce84f469b81b50d358407b4ad361#)\n" +-" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" +- "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n" ++" (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" ++" 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" ++" 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" ++" 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" ++" 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" ++" EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" ++" 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" ++" 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" ++" #)\n" ++" (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" ++" 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" ++" 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" ++" 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" ++" 83#)\n" ++" (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" ++" 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" ++" 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" ++" 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9" ++" 19#)\n" ++" (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" ++" 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" ++" A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" ++" AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" ++" #)\n" + " )\n" + ")\n"; + +@@ -58,15 +77,25 @@ static const char sample_private_key_1[] = + static const char sample_private_key_1_1[] = + "(private-key\n" + " (openpgp-rsa\n" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +- "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +- "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +- "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" ++" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++" CB#)\n" + " (e #010001#)\n" +-" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" +- "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" +- "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" +- "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" ++" (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" ++" 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" ++" 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" ++" 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" ++" 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" ++" EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" ++" 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" ++" 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" ++" #)\n" + " )\n" + ")\n"; + +@@ -75,29 +104,50 @@ static const char sample_private_key_1_1[] = + static const char sample_private_key_1_2[] = + "(private-key\n" + " (openpgp-rsa\n" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +- "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +- "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +- "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" ++" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++" CB#)\n" + " (e #010001#)\n" +-" (d #046129F2489D71579BE0A75FE029BD6CDB574EBF57EA8A5B0FDA942CAB943B11" +- "7D7BB95E5D28875E0F9FC5FCC06A72F6D502464DABDED78EF6B716177B83D5BD" +- "C543DC5D3FED932E59F5897E92E6F58A0F33424106A3B6FA2CBF877510E4AC21" +- "C3EE47851E97D12996222AC3566D4CCB0B83D164074ABF7DE655FC2446DA1781#)\n" +-" (p #00e861b700e17e8afe6837e7512e35b6ca11d0ae47d8b85161c67baf64377213" +- "fe52d772f2035b3ca830af41d8a4120e1c1c70d12cc22f00d28d31dd48a8d424f1#)\n" +-" (u #304559a9ead56d2309d203811a641bb1a09626bc8eb36fffa23c968ec5bd891e" +- "ebbafc73ae666e01ba7c8990bae06cc2bbe10b75e69fcacb353a6473079d8e9b#)\n" ++" (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" ++" 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" ++" 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" ++" 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" ++" 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" ++" EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" ++" 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" ++" 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" ++" #)\n" ++" (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" ++" 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" ++" 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" ++" 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" ++" 83#)\n" ++" (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" ++" 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" ++" A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" ++" AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" ++" #)\n" + " )\n" + ")\n"; + + static const char sample_public_key_1[] = + "(public-key\n" + " (rsa\n" +-" (n #00e0ce96f90b6c9e02f3922beada93fe50a875eac6bcc18bb9a9cf2e84965caa" +- "2d1ff95a7f542465c6c0c19d276e4526ce048868a7a914fd343cc3a87dd74291" +- "ffc565506d5bbb25cbac6a0e2dd1f8bcaab0d4a29c2f37c950f363484bf269f7" +- "891440464baf79827e03a36e70b814938eebdc63e964247be75dc58b014b7ea251#)\n" ++" (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++" 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++" 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++" 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++" DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++" 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++" 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++" 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++" CB#)\n" + " (e #010001#)\n" + " )\n" + ")\n"; +-- +2.33.1 + +From 1481607cb9db977468a75f9f4638dc1cf3ade007 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Thu, 11 Nov 2021 13:44:40 +0900 +Subject: tests:pkcs1v2: Skip tests with small keys in FIPS + mode. + +* tests/pkcs1v2.c (in_fips_mode): New. +(check_oaep): Skip when key size is less than 2048 in FIPS mode. +(check_pss, check_v15crypt, check_v15sign): Likewise. + +-- + +GnuPG-bug-id: 5512 +Signed-off-by: NIIBE Yutaka +--- + tests/pkcs1v2.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 75 insertions(+), 3 deletions(-) + +diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c +index 968d3fea..f26e779b 100644 +--- a/tests/pkcs1v2.c ++++ b/tests/pkcs1v2.c +@@ -36,6 +36,8 @@ + #include "t-common.h" + + ++static int in_fips_mode; ++ + static void + show_sexp (const char *prefix, gcry_sexp_t a) + { +@@ -147,6 +149,18 @@ check_oaep (void) + gcry_free (rsa_e); + gcry_free (rsa_d); + ++ if (in_fips_mode) ++ { ++ unsigned int nbits = gcry_pk_get_nbits (pub_key); ++ ++ if (nbits < 2048) ++ { ++ if (verbose > 1) ++ info ("... skipped\n"); ++ goto next; ++ } ++ } ++ + for (mno = 0; mno < DIM (tbl[0].m); mno++) + { + void *mesg, *seed, *encr; +@@ -225,6 +239,7 @@ check_oaep (void) + ciph = NULL; + } + ++ next: + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +@@ -269,6 +284,18 @@ check_pss (void) + gcry_free (rsa_e); + gcry_free (rsa_d); + ++ if (in_fips_mode) ++ { ++ unsigned int nbits = gcry_pk_get_nbits (pub_key); ++ ++ if (nbits < 2048) ++ { ++ if (verbose > 1) ++ info ("... skipped\n"); ++ goto next; ++ } ++ } ++ + for (mno = 0; mno < DIM (tbl[0].m); mno++) + { + void *mesg, *salt, *sign; +@@ -347,6 +374,7 @@ check_pss (void) + sigtmpl = NULL; + } + ++ next: + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +@@ -391,6 +419,18 @@ check_v15crypt (void) + gcry_free (rsa_e); + gcry_free (rsa_d); + ++ if (in_fips_mode) ++ { ++ unsigned int nbits = gcry_pk_get_nbits (pub_key); ++ ++ if (nbits < 2048) ++ { ++ if (verbose > 1) ++ info ("... skipped\n"); ++ goto next; ++ } ++ } ++ + for (mno = 0; mno < DIM (tbl[0].m); mno++) + { + void *mesg, *seed, *encr; +@@ -469,6 +509,7 @@ check_v15crypt (void) + ciph = NULL; + } + ++ next: + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +@@ -513,6 +554,18 @@ check_v15sign (void) + gcry_free (rsa_e); + gcry_free (rsa_d); + ++ if (in_fips_mode) ++ { ++ unsigned int nbits = gcry_pk_get_nbits (pub_key); ++ ++ if (nbits < 2048) ++ { ++ if (verbose > 1) ++ info ("... skipped\n"); ++ goto next; ++ } ++ } ++ + for (mno = 0; mno < DIM (tbl[0].m); mno++) + { + void *mesg, *sign; +@@ -583,6 +636,7 @@ check_v15sign (void) + sigtmpl = NULL; + } + ++ next: + gcry_sexp_release (sec_key); + gcry_sexp_release (pub_key); + } +@@ -597,6 +651,7 @@ main (int argc, char **argv) + int run_pss = 0; + int run_v15c = 0; + int run_v15s = 0; ++ int use_fips = 0; + + if (argc) + { argc--; argv++; } +@@ -625,6 +680,11 @@ main (int argc, char **argv) + die_on_error = 1; + argc--; argv++; + } ++ else if (!strcmp (*argv, "--fips")) ++ { ++ use_fips = 1; ++ argc--; argv++; ++ } + else if (!strcmp (*argv, "--oaep")) + { + run_oaep = 1; +@@ -651,9 +711,21 @@ main (int argc, char **argv) + run_oaep = run_pss = run_v15c = run_v15s = 1; + + xgcry_control ((GCRYCTL_SET_VERBOSITY, (int)verbose)); +- xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); +- if (!gcry_check_version ("1.5.0")) +- die ("version mismatch\n"); ++ ++ if (use_fips) ++ xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); ++ ++ /* Check that we test exactly our version - including the patchlevel. */ ++ if (strcmp (GCRYPT_VERSION, gcry_check_version (NULL))) ++ die ("version mismatch; pgm=%s, library=%s\n", ++ GCRYPT_VERSION,gcry_check_version (NULL)); ++ ++ if ( gcry_fips_mode_active () ) ++ in_fips_mode = 1; ++ ++ if (!in_fips_mode) ++ xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); ++ + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + if (debug) + xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); +-- +2.33.1 + diff --git a/libgcrypt-FIPS-RSA-keylen.patch b/libgcrypt-FIPS-RSA-keylen.patch new file mode 100644 index 0000000..8417ffa --- /dev/null +++ b/libgcrypt-FIPS-RSA-keylen.patch @@ -0,0 +1,250 @@ +From 40d63d09b2d06631f4d2c3d1b167a620d50c99f8 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 5 Nov 2021 14:19:23 +0100 +Subject: [PATCH 198/200] rsa: Check keylen constraints for key operations. + +* cipher/rsa.c (rsa_check_keysize): New. +(generate_fips): Factor out the bits check. +(rsa_encrypt): Add checking key length. +(rsa_decrypt, rsa_sign, rsa_verify): Likewise. +-- + +GnuPG-bug-id: 5512 +Co-authored-by: NIIBE Yutaka +Signed-off-by: Jakub Jelen +--- + cipher/rsa.c | 58 ++++++++++++++++++++++++++++++++++++++-------------- + 1 file changed, 43 insertions(+), 15 deletions(-) + +Index: libgcrypt-1.9.4/cipher/rsa.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/rsa.c ++++ libgcrypt-1.9.4/cipher/rsa.c +@@ -301,14 +301,6 @@ generate_std (RSA_secret_key *sk, unsign + gcry_mpi_t f; + gcry_random_level_t random_level; + +- if (fips_mode ()) +- { +- if (nbits < 1024) +- return GPG_ERR_INV_VALUE; +- if (transient_key) +- return GPG_ERR_INV_VALUE; +- } +- + /* The random quality depends on the transient_key flag. */ + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; + +@@ -437,6 +429,17 @@ generate_std (RSA_secret_key *sk, unsign + } + + ++/* Check the RSA key length is acceptable for key generation or usage */ ++static gpg_err_code_t ++rsa_check_keysize (unsigned int nbits) ++{ ++ if (fips_mode() && nbits < 2048) ++ return GPG_ERR_INV_VALUE; ++ ++ return GPG_ERR_NO_ERROR; ++} ++ ++ + /**************** + * Generate a key pair with a key of size NBITS. + * USE_E = 0 let Libcgrypt decide what exponent to use. +@@ -466,12 +469,15 @@ generate_fips (RSA_secret_key *sk, unsig + unsigned int pbits = nbits/2; + unsigned int i; + int pqswitch; +- gpg_err_code_t ec = GPG_ERR_NO_PRIME; ++ gpg_err_code_t ec; + + if (nbits < 1024 || (nbits & 0x1FF)) + return GPG_ERR_INV_VALUE; +- if (fips_mode() && nbits < 2048) +- return GPG_ERR_INV_VALUE; ++ ec = rsa_check_keysize (nbits); ++ if (ec) ++ return ec; ++ ++ ec = GPG_ERR_NO_PRIME; + + /* The random quality depends on the transient_key flag. */ + random_level = transient_key ? GCRY_STRONG_RANDOM : GCRY_VERY_STRONG_RANDOM; +@@ -1360,9 +1366,13 @@ rsa_encrypt (gcry_sexp_t *r_ciph, gcry_s + gcry_mpi_t data = NULL; + RSA_public_key pk = {NULL, NULL}; + gcry_mpi_t ciph = NULL; ++ unsigned int nbits = rsa_get_nbits (keyparms); ++ ++ rc = rsa_check_keysize (nbits); ++ if (rc) ++ return rc; + +- _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, +- rsa_get_nbits (keyparms)); ++ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_ENCRYPT, nbits); + + /* Extract the data. */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); +@@ -1432,9 +1442,13 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ + gcry_mpi_t plain = NULL; + unsigned char *unpad = NULL; + size_t unpadlen = 0; ++ unsigned int nbits = rsa_get_nbits (keyparms); + +- _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, +- rsa_get_nbits (keyparms)); ++ rc = rsa_check_keysize (nbits); ++ if (rc) ++ return rc; ++ ++ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_DECRYPT, nbits); + + /* Extract the data. */ + rc = _gcry_pk_util_preparse_encval (s_data, rsa_names, &l1, &ctx); +@@ -1477,7 +1491,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ + mpi_fdiv_r (data, data, sk.n); + + /* Allocate MPI for the plaintext. */ +- plain = mpi_snew (ctx.nbits); ++ plain = mpi_snew (nbits); + + /* We use blinding by default to mitigate timing attacks which can + be practically mounted over the network as shown by Brumley and +@@ -1485,7 +1499,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ + if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) + secret (plain, data, &sk); + else +- secret_blinded (plain, data, &sk, ctx.nbits); ++ secret_blinded (plain, data, &sk, nbits); + + if (DBG_CIPHER) + log_printmpi ("rsa_decrypt res", plain); +@@ -1494,7 +1508,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ + switch (ctx.encoding) + { + case PUBKEY_ENC_PKCS1: +- rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, ctx.nbits, plain); ++ rc = _gcry_rsa_pkcs1_decode_for_enc (&unpad, &unpadlen, nbits, plain); + mpi_free (plain); + plain = NULL; + if (!rc) +@@ -1503,7 +1517,7 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_ + + case PUBKEY_ENC_OAEP: + rc = _gcry_rsa_oaep_decode (&unpad, &unpadlen, +- ctx.nbits, ctx.hash_algo, ++ nbits, ctx.hash_algo, + plain, ctx.label, ctx.labellen); + mpi_free (plain); + plain = NULL; +@@ -1548,9 +1562,13 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_ + RSA_public_key pk; + gcry_mpi_t sig = NULL; + gcry_mpi_t result = NULL; ++ unsigned int nbits = rsa_get_nbits (keyparms); ++ ++ rc = rsa_check_keysize (nbits); ++ if (rc) ++ return rc; + +- _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, +- rsa_get_nbits (keyparms)); ++ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_SIGN, nbits); + + /* Extract the data. */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); +@@ -1588,7 +1606,7 @@ rsa_sign (gcry_sexp_t *r_sig, gcry_sexp_ + if ((ctx.flags & PUBKEY_FLAG_NO_BLINDING)) + secret (sig, data, &sk); + else +- secret_blinded (sig, data, &sk, ctx.nbits); ++ secret_blinded (sig, data, &sk, nbits); + if (DBG_CIPHER) + log_printmpi ("rsa_sign res", sig); + +@@ -1650,9 +1668,13 @@ rsa_verify (gcry_sexp_t s_sig, gcry_sexp + gcry_mpi_t data = NULL; + RSA_public_key pk = { NULL, NULL }; + gcry_mpi_t result = NULL; ++ unsigned int nbits = rsa_get_nbits (keyparms); ++ ++ rc = rsa_check_keysize (nbits); ++ if (rc) ++ return rc; + +- _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, +- rsa_get_nbits (keyparms)); ++ _gcry_pk_util_init_encoding_ctx (&ctx, PUBKEY_OP_VERIFY, nbits); + + /* Extract the data. */ + rc = _gcry_pk_util_data_to_mpi (s_data, &data, &ctx); +Index: libgcrypt-1.9.4/tests/basic.c +=================================================================== +--- libgcrypt-1.9.4.orig/tests/basic.c ++++ libgcrypt-1.9.4/tests/basic.c +@@ -14172,6 +14172,62 @@ check_pubkey (void) + "\x4a\xa6\xf9\xeb\x23\xbf\xa9\x12\x2d\x5b" } + }, + { ++ GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN | FLAG_GRIP, /* 2k RSA */ ++ { ++ "(private-key" ++ " (rsa" ++ " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++ " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++ " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++ " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++ " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++ " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++ " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++ " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++ " CB#)\n" ++ " (e #010001#)\n" ++ " (d #07EF82500C403899934FE993AC5A36F14FF2DF38CF1EF315F205EE4C83EDAA19" ++ " 8890FC23DE9AA933CAFB37B6A8A8DBA675411958337287310D3FF2F1DDC0CB93" ++ " 7E70F57F75F833C021852B631D2B9A520E4431A03C5C3FCB5742DCD841D9FB12" ++ " 771AA1620DCEC3F1583426066ED9DC3F7028C5B59202C88FDF20396E2FA0EC4F" ++ " 5A22D9008F3043673931BC14A5046D6327398327900867E39CC61B2D1AFE2F48" ++ " EC8E1E3861C68D257D7425F4E6F99ABD77D61F10CA100EFC14389071831B33DD" ++ " 69CC8EABEF860D1DC2AAA84ABEAE5DFC91BC124DAF0F4C8EF5BBEA436751DE84" ++ " 3A8063E827A024466F44C28614F93B0732A100D4A0D86D532FE1E22C7725E401" ++ " #)\n" ++ " (p #00C29D438F115825779631CD665A5739367F3E128ADC29766483A46CA80897E0" ++ " 79B32881860B8F9A6A04C2614A904F6F2578DAE13EA67CD60AE3D0AA00A1FF9B" ++ " 441485E44B2DC3D0B60260FBFE073B5AC72FAF67964DE15C8212C389D20DB9CF" ++ " 54AF6AEF5C4196EAA56495DD30CF709F499D5AB30CA35E086C2A1589D6283F17" ++ " 83#)\n" ++ " (q #00D1984135231CB243FE959C0CBEF551EDD986AD7BEDF71EDF447BE3DA27AF46" ++ " 79C974A6FA69E4D52FE796650623DE70622862713932AA2FD9F2EC856EAEAA77" ++ " 88B4EA6084DC81C902F014829B18EA8B2666EC41586818E0589E18876065F97E" ++ " 8D22CE2DA53A05951EC132DCEF41E70A9C35F4ACC268FFAC2ADF54FA1DA110B9" ++ " 19#)\n" ++ " (u #67CF0FD7635205DD80FA814EE9E9C267C17376BF3209FB5D1BC42890D2822A04" ++ " 479DAF4D5B6ED69D0F8D1AF94164D07F8CD52ECEFE880641FA0F41DDAB1785E4" ++ " A37A32F997A516480B4CD4F6482B9466A1765093ED95023CA32D5EDC1E34CEE9" ++ " AF595BC51FE43C4BF810FA225AF697FB473B83815966188A4312C048B885E3F7" ++ " #)))\n", ++ ++ "(public-key\n" ++ " (rsa\n" ++ " (n #009F56231A3D82E3E7D613D59D53E9AB921BEF9F08A782AED0B6E46ADBC853EC" ++ " 7C71C422435A3CD8FA0DB9EFD55CD3295BADC4E8E2E2B94E15AE82866AB8ADE8" ++ " 7E469FAE76DC3577DE87F1F419C4EB41123DFAF8D16922D5EDBAD6E9076D5A1C" ++ " 958106F0AE5E2E9193C6B49124C64C2A241C4075D4AF16299EB87A6585BAE917" ++ " DEF27FCDD165764D069BC18D16527B29DAAB549F7BBED4A7C6A842D203ED6613" ++ " 6E2411744E432CD26D940132F25874483DCAEECDFD95744819CBCF1EA810681C" ++ " 42907EBCB1C7EAFBE75C87EC32C5413EA10476545D3FC7B2ADB1B66B7F200918" ++ " 664B0E5261C2895AA28B0DE321E921B3F877172CCCAB81F43EF98002916156F6" ++ " CB#)\n" ++ " (e #010001#)))\n", ++ ++ "\xe0\x08\x98\x9b\xb6\x44\xa2\x9a\x83\x37" ++ "\x47\xdd\x69\x55\xdb\x3a\xac\x89\x6e\x40"} ++ }, ++ { + GCRY_PK_ELG, FLAG_SIGN | FLAG_CRYPT | FLAG_GRIP, + { + "(private-key\n" diff --git a/libgcrypt-FIPS-disable-3DES.patch b/libgcrypt-FIPS-disable-3DES.patch new file mode 100644 index 0000000..47567f1 --- /dev/null +++ b/libgcrypt-FIPS-disable-3DES.patch @@ -0,0 +1,52 @@ +Index: libgcrypt-1.9.4/cipher/des.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/des.c ++++ libgcrypt-1.9.4/cipher/des.c +@@ -1498,7 +1498,7 @@ static gcry_cipher_oid_spec_t oids_tripl + + gcry_cipher_spec_t _gcry_cipher_spec_tripledes = + { +- GCRY_CIPHER_3DES, {0, 1}, ++ GCRY_CIPHER_3DES, {0, 0}, + "3DES", NULL, oids_tripledes, 8, 192, sizeof (struct _tripledes_ctx), + do_tripledes_setkey, do_tripledes_encrypt, do_tripledes_decrypt, + NULL, NULL, +Index: libgcrypt-1.9.4/cipher/mac-cmac.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/mac-cmac.c ++++ libgcrypt-1.9.4/cipher/mac-cmac.c +@@ -458,7 +458,7 @@ gcry_mac_spec_t _gcry_mac_type_spec_cmac + #endif + #if USE_DES + gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = { +- GCRY_MAC_CMAC_3DES, {0, 1}, "CMAC_3DES", ++ GCRY_MAC_CMAC_3DES, {0, 0}, "CMAC_3DES", + &cmac_ops + }; + #endif +Index: libgcrypt-1.9.4/src/fips.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/fips.c ++++ libgcrypt-1.9.4/src/fips.c +@@ -493,6 +493,10 @@ run_cipher_selftests (int extended) + + for (idx=0; algos[idx]; idx++) + { ++ /* Skip non-approved cipher in FIPS mode */ ++ if (fips_mode() && algos[idx] == GCRY_CIPHER_3DES) ++ continue; ++ + err = _gcry_cipher_selftest (algos[idx], extended, reporter); + reporter ("cipher", algos[idx], NULL, + err? gpg_strerror (err):NULL); +@@ -558,6 +562,10 @@ run_mac_selftests (int extended) + + for (idx=0; algos[idx]; idx++) + { ++ /* Skip non-approved MAC algorithm in FIPS mode */ ++ if (fips_mode() && algos[idx] == GCRY_MAC_CMAC_3DES) ++ continue; ++ + err = _gcry_mac_selftest (algos[idx], extended, reporter); + reporter ("mac", algos[idx], NULL, + err? gpg_strerror (err):NULL); diff --git a/libgcrypt-FIPS-disable-DSA.patch b/libgcrypt-FIPS-disable-DSA.patch new file mode 100644 index 0000000..e43d6e8 --- /dev/null +++ b/libgcrypt-FIPS-disable-DSA.patch @@ -0,0 +1,44 @@ +From ea362090fc11caa28643153fc6444442243c8765 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 8 Dec 2021 09:52:02 +0900 +Subject: [PATCH 0937/1000] fips: Disable DSA in FIPS mode. + +* cipher/dsa.c (run_selftests): Disable DSA spec in FIPS mode. +* src/fips.c (run_pubkey_selftests): Skip DSA power-on selftests. +-- + +GnuPG-bug-id: 5710 +Signed-off-by: Jakub Jelen +--- + cipher/dsa.c | 2 +- + src/fips.c | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/cipher/dsa.c b/cipher/dsa.c +index d5b00912..e559f9f5 100644 +--- a/cipher/dsa.c ++++ b/cipher/dsa.c +@@ -1441,7 +1441,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) + + gcry_pk_spec_t _gcry_pubkey_spec_dsa = + { +- GCRY_PK_DSA, { 0, 1 }, ++ GCRY_PK_DSA, { 0, 0 }, + GCRY_PK_USAGE_SIGN, + "DSA", dsa_names, + "pqgy", "pqgyx", "", "rs", "pqgy", +diff --git a/src/fips.c b/src/fips.c +index 0ab7fecc..bcadc5f2 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -522,7 +522,6 @@ run_pubkey_selftests (int extended) + static int algos[] = + { + GCRY_PK_RSA, +- GCRY_PK_DSA, + GCRY_PK_ECC, + 0 + }; +-- +2.34.1 + diff --git a/libgcrypt-FIPS-fix-regression-tests.patch b/libgcrypt-FIPS-fix-regression-tests.patch new file mode 100644 index 0000000..9f88fc9 --- /dev/null +++ b/libgcrypt-FIPS-fix-regression-tests.patch @@ -0,0 +1,448 @@ +Index: libgcrypt-1.9.4/cipher/pubkey.c +=================================================================== +--- libgcrypt-1.9.4.orig/cipher/pubkey.c ++++ libgcrypt-1.9.4/cipher/pubkey.c +@@ -224,7 +224,7 @@ check_pubkey_algo (int algo, unsigned us + gcry_pk_spec_t *spec; + + spec = spec_from_algo (algo); +- if (spec) ++ if (spec && !spec->flags.disabled) + { + if (((use & GCRY_PK_USAGE_SIGN) + && (! (spec->use & GCRY_PK_USAGE_SIGN))) +From 44c7c41af21c668826280abfee1257853020ba2d Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Mon, 16 Aug 2021 12:41:11 +0900 +Subject: [PATCH 161/200] tests: Skip tests when FIPS for keygrip computations. + +* tests/keygrip.c (check): Skip non-FIPS curves when FIPS. +(main): Check if FIPS is enabled. + +-- + +GnuPG-bug-id: 5520 +Signed-off-by: NIIBE Yutaka +--- + tests/keygrip.c | 37 ++++++++++++++++++++++++++++--------- + 1 file changed, 28 insertions(+), 9 deletions(-) + +diff --git a/tests/keygrip.c b/tests/keygrip.c +index cfccc06e..49bd71bc 100644 +--- a/tests/keygrip.c ++++ b/tests/keygrip.c +@@ -33,6 +33,9 @@ + + static int repetitions; + ++/* Whether fips mode was active at startup. */ ++static int in_fips_mode; ++ + + + static void +@@ -54,6 +57,7 @@ static struct + int algo; + const char *key; + const unsigned char grip[20]; ++ int skip_when_fips; + } key_grips[] = + { + { +@@ -155,7 +159,8 @@ static struct + /* */"436DD11A1756AFE56CD93408410FCDA9" + /* */"BA95024EB613BD481A14FCFEC27A448A#)))", + "\x52\xBA\xD4\xB4\xA3\x2D\x32\xA1\xDD\x06" +- "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4" ++ "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4", ++ 1 + }, + { /* Compressed form of above. */ + GCRY_PK_ECC, +@@ -165,7 +170,8 @@ static struct + " (q #022ECD8679930BE2DB4AD42B8600BA3F80" + /* */"2D4D539BFF2F69B83EC9B7BBAA7F3406#)))", + "\x52\xBA\xD4\xB4\xA3\x2D\x32\xA1\xDD\x06" +- "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4" ++ "\x5E\x99\x0B\xF1\xAB\xC1\x13\x3D\x84\xD4", ++ 1 + }, + { + GCRY_PK_ECC, +@@ -177,7 +183,8 @@ static struct + /* */"9EBBA41915313417BA54218EB0569C59" + /* */"0B156C76DBCAB6E84575E6EF68CE7B87#)))", + "\x99\x38\x6A\x82\x41\x96\x29\x9C\x89\x74" +- "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F" ++ "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F", ++ 1 + }, + { /* Compressed form of above. */ + GCRY_PK_ECC, +@@ -187,7 +194,8 @@ static struct + " (q #035B784CA008EE64AB3D85017EE0D2BE87" + /* */"558762C7300E0C8E06B1F9AF7C031458#)))", + "\x99\x38\x6A\x82\x41\x96\x29\x9C\x89\x74" +- "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F" ++ "\xD6\xE1\xBF\x43\xAC\x9B\x9A\x12\xE7\x3F", ++ 1 + }, + { /* Ed25519 standard */ + GCRY_PK_ECC, +@@ -199,7 +207,8 @@ static struct + " 47BD24842905C049257673B3F5249524E0A41FAA17B25B818D0F97E625F1A1D0#)" + " ))", + "\x0C\xCA\xB2\xFD\x48\x9A\x33\x40\x2C\xE8" +- "\xE0\x4A\x1F\xB2\x45\xEA\x80\x3D\x0A\xF1" ++ "\xE0\x4A\x1F\xB2\x45\xEA\x80\x3D\x0A\xF1", ++ 1 + }, + { /* Ed25519+EdDSA */ + GCRY_PK_ECC, +@@ -209,7 +218,8 @@ static struct + " (q #773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)" + " ))", + "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70" +- "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47" ++ "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47", ++ 1 + }, + { /* Ed25519+EdDSA (with compression prefix) */ + GCRY_PK_ECC, +@@ -220,7 +230,8 @@ static struct + " 773E72848C1FD5F9652B29E2E7AF79571A04990E96F2016BF4E0EC1890C2B7DB#)" + " ))", + "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70" +- "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47" ++ "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47", ++ 1 + }, + { /* Ed25519+EdDSA (same but uncompressed)*/ + GCRY_PK_ECC, +@@ -232,7 +243,8 @@ static struct + " 5bb7c29018ece0f46b01f2960e99041a5779afe7e2292b65f9d51f8c84723e77#)" + " ))", + "\x9D\xB6\xC6\x4A\x38\x83\x0F\x49\x60\x70" +- "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47" ++ "\x17\x89\x47\x55\x20\xBE\x8C\x82\x1F\x47", ++ 1 + }, + { /* Cv25519 */ + GCRY_PK_ECC, +@@ -243,7 +255,8 @@ static struct + " 918C1733127F6BF2646FAE3D081A18AE77111C903B906310B077505EFFF12740#)" + " ))", + "\x0F\x89\xA5\x65\xD3\xEA\x18\x7C\xE8\x39" +- "\x33\x23\x98\xF5\xD4\x80\x67\x7D\xF4\x9C" ++ "\x33\x23\x98\xF5\xD4\x80\x67\x7D\xF4\x9C", ++ 1 + }, + { /* Random key */ + GCRY_PK_RSA, +@@ -280,6 +293,9 @@ check (void) + + for (i = 0; i < (sizeof (key_grips) / sizeof (*key_grips)); i++) + { ++ if (in_fips_mode && key_grips[i].skip_when_fips) ++ continue; ++ + if (gcry_pk_test_algo (key_grips[i].algo)) + { + if (verbose) +@@ -379,6 +395,9 @@ main (int argc, char **argv) + if (debug) + xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + check (); + + return 0; +-- +2.33.0 + +From 3026148331523ec7ca81031339b5629431cafa23 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 09:20:18 +0200 +Subject: tests: Expect curves 25519/448 to fail in FIPS mode + +* tests/t-cv25519.c (test_cv_hl): Expect the operation to fail in FIPS + mode. + (test_cv_x25519, test_it): Ditto. + (main) Detect FIPS mode. +* tests/t-ed25519.c (one_test): Expect the operation to fail in FIPS + mode. + (main) Detect FIPS mode. +* tests/t-ed448.c (one_test): Expect the operation to fail in FIPS + mode. + (main) Detect FIPS mode. +* tests/t-x448.c (test_cv_hl): Expect the operation to fail in FIPS + mode. + (test_cv_x448, test_cv): Ditto. + (main) Detect FIPS mode. +-- +The ed25519, ed448, cv25519 and cv448 curves are not available in FIPS +mode. Some of the tests already skipped these, but it is always better +to make sure thy are failing, rather than just skipping these. + +Signed-off-by: Jakub Jelen +--- + tests/t-cv25519.c | 37 +++++++++++++++++++++++++++++++++++-- + tests/t-ed25519.c | 18 ++++++++++++++---- + tests/t-ed448.c | 18 ++++++++++++++---- + tests/t-x448.c | 41 +++++++++++++++++++++++++++++++++++++---- + 4 files changed, 100 insertions(+), 14 deletions(-) + +diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c +index 0de50a02..b4126f4c 100644 +--- a/tests/t-cv25519.c ++++ b/tests/t-cv25519.c +@@ -33,6 +33,7 @@ + #include "t-common.h" + #define N_TESTS 18 + ++static int in_fips_mode = 0; + + static void + print_mpi (const char *text, gcry_mpi_t a) +@@ -188,7 +189,17 @@ test_cv_hl (int testno, const char *k_str, const char *u_str, + xfree (buffer); + buffer = NULL; + +- if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) ++ err = gcry_pk_encrypt (&s_result, s_data, s_pk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_encrypt failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -281,7 +292,17 @@ test_cv_x25519 (int testno, const char *k_str, const char *u_str, + goto leave; + } + +- if ((err = gcry_ecc_mul_point (algo, result, scalar, point))) ++ err = gcry_ecc_mul_point (algo, result, scalar, point); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_ecc_mul_point failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -335,6 +356,15 @@ test_it (int testno, const char *k_str, int iter, const char *result_str) + info ("Running test %d: iteration=%d\n", testno, iter); + + gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); ++ if (in_fips_mode) ++ { ++ if (ctx) ++ fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ return; ++ } + Q = gcry_mpi_point_new (0); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) +@@ -640,6 +670,9 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + start_timer (); + check_cv25519 (); + stop_timer (); +diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c +index a5271c25..567bc797 100644 +--- a/tests/t-ed25519.c ++++ b/tests/t-ed25519.c +@@ -36,6 +36,7 @@ + static int sign_with_pk; + static int no_verify; + static int custom_data_file; ++static int in_fips_mode = 0; + + + static void +@@ -271,7 +272,17 @@ one_test (int testno, const char *sk, const char *pk, + goto leave; + } + +- if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) ++ err = gcry_pk_sign (&s_sig, s_msg, s_sk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); + if (debug) + show_sexp ("sig=", s_sig); +@@ -481,9 +492,8 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + +- /* Ed25519 isn't supported in fips mode */ +- if (gcry_fips_mode_active()) +- return 77; ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + + start_timer (); + check_ed25519 (fname); +diff --git a/tests/t-ed448.c b/tests/t-ed448.c +index 1f445ffc..f38cd10c 100644 +--- a/tests/t-ed448.c ++++ b/tests/t-ed448.c +@@ -36,6 +36,7 @@ + static int sign_with_pk; + static int no_verify; + static int custom_data_file; ++static int in_fips_mode = 0; + + + static void +@@ -302,7 +303,17 @@ one_test (int testno, int ph, const char *sk, const char *pk, + } + } + +- if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) ++ err = gcry_pk_sign (&s_sig, s_msg, s_sk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); + if (debug) + show_sexp ("sig=", s_sig); +@@ -521,9 +532,8 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + +- /* Ed448 isn't supported in fips mode */ +- if (gcry_fips_mode_active()) +- return 77; ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + + start_timer (); + check_ed448 (fname); +diff --git a/tests/t-x448.c b/tests/t-x448.c +index 5c3cbeb9..cc4b10fc 100644 +--- a/tests/t-x448.c ++++ b/tests/t-x448.c +@@ -34,6 +34,7 @@ + #include "t-common.h" + #define N_TESTS 9 + ++static int in_fips_mode = 0; + + static void + print_mpi (const char *text, gcry_mpi_t a) +@@ -179,8 +180,18 @@ test_cv_hl (int testno, const char *k_str, const char *u_str, + xfree (buffer); + buffer = NULL; + +- if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) +- fail ("gcry_pk_encrypt failed for test %d: %s", testno, ++ err = gcry_pk_encrypt (&s_result, s_data, s_pk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) ++ fail ("gcry_pk_encrypt goto leavefailed for test %d: %s", testno, + gpg_strerror (err)); + + s_tmp = gcry_sexp_find_token (s_result, "s", 0); +@@ -257,7 +268,17 @@ test_cv_x448 (int testno, const char *k_str, const char *u_str, + goto leave; + } + +- if ((err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point))) ++ err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point); ++ if (in_fips_mode) ++ { ++ if (err != GPG_ERR_NOT_SUPPORTED) ++ fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d: %s", ++ testno, gpg_strerror (err)); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_ecc_mul_point failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -296,7 +317,7 @@ test_cv (int testno, const char *k_str, const char *u_str, + static void + test_it (int testno, const char *k_str, int iter, const char *result_str) + { +- gcry_ctx_t ctx; ++ gcry_ctx_t ctx = NULL; + gpg_error_t err; + void *buffer = NULL; + size_t buflen; +@@ -311,6 +332,15 @@ test_it (int testno, const char *k_str, int iter, const char *result_str) + info ("Running test %d: iteration=%d\n", testno, iter); + + gcry_mpi_ec_new (&ctx, NULL, "X448"); ++ if (in_fips_mode) ++ { ++ if (ctx) ++ fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ return; ++ } + Q = gcry_mpi_point_new (0); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56) +@@ -583,6 +613,9 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + start_timer (); + check_x448 (); + stop_timer (); +-- +2.33.0 + diff --git a/libgcrypt-FIPS-hw-optimizations.patch b/libgcrypt-FIPS-hw-optimizations.patch new file mode 100644 index 0000000..08f7727 --- /dev/null +++ b/libgcrypt-FIPS-hw-optimizations.patch @@ -0,0 +1,31 @@ +From 70e6cec07d86332f1aaf7a69bec75c7138306f6a Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Thu, 29 Jul 2021 14:20:14 +0900 +Subject: [PATCH] hwfeatures: Enable hardware support also in FIPS mode. + +* src/hwfeatures.c (_gcry_detect_hw_features): Remove skipping in FIPS +mode. + +-- + +Reported-by: Jakub Jelen +GnuPG-bug-id: 5508 +Signed-off-by: NIIBE Yutaka +--- + src/hwfeatures.c | 3 --- + 1 file changed, 3 deletions(-) + +Index: libgcrypt-1.9.4/src/hwfeatures.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/hwfeatures.c ++++ libgcrypt-1.9.4/src/hwfeatures.c +@@ -213,9 +213,6 @@ _gcry_detect_hw_features (void) + { + hw_features = 0; + +- if (fips_mode ()) +- return; /* Hardware support is not to be evaluated. */ +- + parse_hwf_deny_file (); + + #if defined (HAVE_CPU_ARCH_X86) diff --git a/libgcrypt-FIPS-module-version.patch b/libgcrypt-FIPS-module-version.patch new file mode 100644 index 0000000..7d8713c --- /dev/null +++ b/libgcrypt-FIPS-module-version.patch @@ -0,0 +1,89 @@ +From c74fde0c3f6114c594332fb28a09c7b817969231 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 17 Sep 2021 17:11:30 +0200 +Subject: [PATCH 187/200] Allow passing FIPS module version + +* README: Document new --with-fips-module-version=version switch +* configure.ac: Implementation of the --with-fips-module-version +* src/global.c (print_config): Print FIPS module version from above +-- +Signed-off-by: Jakub Jelen + +Moved the module version to a 3rd field to keep the semantics of that +line. + +Signed-off-by: Werner Koch +GnuPG-bug-id: 1600 +--- + README | 4 ++++ + configure.ac | 7 +++++++ + src/global.c | 16 +++++++++++++--- + 3 files changed, 24 insertions(+), 3 deletions(-) + +Index: libgcrypt-1.9.4/README +=================================================================== +--- libgcrypt-1.9.4.orig/README ++++ libgcrypt-1.9.4/README +@@ -165,6 +165,10 @@ + against a HMAC checksum. This works only in FIPS + mode and on systems providing the dladdr function. + ++ --with-fips-module-version=version ++ Specify a string used as a module version for FIPS ++ certification purposes. ++ + --disable-padlock-support + Disable support for the PadLock engine of VIA + processors. The default is to use PadLock if +Index: libgcrypt-1.9.4/configure.ac +=================================================================== +--- libgcrypt-1.9.4.orig/configure.ac ++++ libgcrypt-1.9.4/configure.ac +@@ -599,6 +599,12 @@ if test "$use_hmac_binary_check" = yes ; + [Define to support an HMAC based integrity check]) + fi + ++# Implementation of the --with-fips-module-version. ++AC_ARG_WITH(fips-module-version, ++ [ --with-fips-module-version=VERSION], ++ fips_module_version="$withval", fips_module_version="" ) ++AC_DEFINE_UNQUOTED(FIPS_MODULE_VERSION, "$fips_module_version", ++ [Define FIPS module version for certification]) + + # Implementation of the --disable-jent-support switch. + AC_MSG_CHECKING([whether jitter entropy support is requested]) +@@ -3266,6 +3272,7 @@ GCRY_MSG_WRAP([Enabled pubkey algorithms + GCRY_MSG_SHOW([Random number generator: ],[$random]) + GCRY_MSG_SHOW([Try using jitter entropy: ],[$jentsupport]) + GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities]) ++GCRY_MSG_SHOW([FIPS module version: ],[$fips_module_version]) + GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport]) + GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport]) + GCRY_MSG_SHOW([Try using Intel SHAEXT: ],[$shaextsupport]) +Index: libgcrypt-1.9.4/src/global.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/global.c ++++ libgcrypt-1.9.4/src/global.c +@@ -379,10 +379,19 @@ print_config (const char *what, gpgrt_st + { + /* We use y/n instead of 1/0 for the stupid reason that + * Emacsen's compile error parser would accidentally flag that +- * line when printed during "make check" as an error. */ +- gpgrt_fprintf (fp, "fips-mode:%c:%c:\n", ++ * line when printed during "make check" as an error. The ++ * second field is obsolete and thus empty (used to be used for ++ * a so-called enforced-fips-mode). The third field has an ++ * option static string describing the module versions; this is ++ * an optional configure option. */ ++ gpgrt_fprintf (fp, "fips-mode:%c::%s:\n", + fips_mode ()? 'y':'n', +- _gcry_enforced_fips_mode ()? 'y':'n' ); ++#ifdef FIPS_MODULE_VERSION ++ fips_mode () ? FIPS_MODULE_VERSION : "" ++#else ++ "" ++#endif /* FIPS_MODULE_VERSION */ ++ ); + } + + if (!what || !strcmp (what, "rng-type")) diff --git a/libgcrypt-FIPS-service-indicators.patch b/libgcrypt-FIPS-service-indicators.patch new file mode 100644 index 0000000..c5e063d --- /dev/null +++ b/libgcrypt-FIPS-service-indicators.patch @@ -0,0 +1,380 @@ +Index: libgcrypt-1.9.4/src/fips.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/fips.c ++++ libgcrypt-1.9.4/src/fips.c +@@ -437,6 +437,59 @@ _gcry_fips_test_operational (void) + } + + ++int ++_gcry_fips_indicator_cipher (va_list arg_ptr) ++{ ++ enum gcry_cipher_algos alg = va_arg (arg_ptr, enum gcry_cipher_algos); ++ enum gcry_cipher_modes mode; ++ ++ switch (alg) ++ { ++ case GCRY_CIPHER_AES: ++ case GCRY_CIPHER_AES192: ++ case GCRY_CIPHER_AES256: ++ mode = va_arg (arg_ptr, enum gcry_cipher_modes); ++ switch (mode) ++ case GCRY_CIPHER_AES: ++ case GCRY_CIPHER_AES192: ++ case GCRY_CIPHER_AES256: ++ mode = va_arg (arg_ptr, enum gcry_cipher_modes); ++ switch (mode) ++ { ++ case GCRY_CIPHER_MODE_ECB: ++ case GCRY_CIPHER_MODE_CBC: ++ case GCRY_CIPHER_MODE_CFB: ++ case GCRY_CIPHER_MODE_CFB8: ++ case GCRY_CIPHER_MODE_OFB: ++ case GCRY_CIPHER_MODE_CTR: ++ case GCRY_CIPHER_MODE_CCM: ++ case GCRY_CIPHER_MODE_GCM: ++ case GCRY_CIPHER_MODE_XTS: ++ return GPG_ERR_NO_ERROR; ++ default: ++ return GPG_ERR_NOT_SUPPORTED; ++ } ++ default: ++ return GPG_ERR_NOT_SUPPORTED; ++ } ++} ++ ++ ++int ++_gcry_fips_indicator_kdf (va_list arg_ptr) ++{ ++ enum gcry_kdf_algos alg = va_arg (arg_ptr, enum gcry_kdf_algos); ++ ++ switch (alg) ++ { ++ case GCRY_KDF_PBKDF2: ++ return GPG_ERR_NO_ERROR; ++ default: ++ return GPG_ERR_NOT_SUPPORTED; ++ } ++} ++ ++ + /* This is a test on whether the library is in the error or + operational state. */ + int +Index: libgcrypt-1.9.4/src/g10lib.h +=================================================================== +--- libgcrypt-1.9.4.orig/src/g10lib.h ++++ libgcrypt-1.9.4/src/g10lib.h +@@ -487,6 +487,9 @@ void _gcry_fips_signal_error (const char + _gcry_fips_signal_error (__FILE__, __LINE__, NULL, 1, (a)) + #endif + ++int _gcry_fips_indicator_cipher (va_list arg_ptr); ++int _gcry_fips_indicator_kdf (va_list arg_ptr); ++ + int _gcry_fips_is_operational (void); + + /* Return true if the library is in the operational state. */ +Index: libgcrypt-1.9.4/src/gcrypt.h.in +=================================================================== +--- libgcrypt-1.9.4.orig/src/gcrypt.h.in ++++ libgcrypt-1.9.4/src/gcrypt.h.in +@@ -334,7 +334,9 @@ enum gcry_ctl_cmds + GCRYCTL_GET_TAGLEN = 76, + GCRYCTL_REINIT_SYSCALL_CLAMP = 77, + GCRYCTL_AUTO_EXPAND_SECMEM = 78, +- GCRYCTL_SET_ALLOW_WEAK_KEY = 79 ++ GCRYCTL_SET_ALLOW_WEAK_KEY = 79, ++ GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER = 81, ++ GCRYCTL_FIPS_SERVICE_INDICATOR_KDF = 82 + }; + + /* Perform various operations defined by CMD. */ +Index: libgcrypt-1.9.4/src/global.c +=================================================================== +--- libgcrypt-1.9.4.orig/src/global.c ++++ libgcrypt-1.9.4/src/global.c +@@ -755,6 +755,19 @@ _gcry_vcontrol (enum gcry_ctl_cmds cmd, + rc = _gcry_fips_run_selftests (1); + break; + ++ case GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER: ++ /* Get FIPS Service Indicator for a given symmetric algorithm and ++ * optional mode. Returns GPG_ERR_NO_ERROR if algorithm is allowed or ++ * GPG_ERR_NOT_SUPPORTED otherwise */ ++ rc = _gcry_fips_indicator_cipher (arg_ptr); ++ break; ++ ++ case GCRYCTL_FIPS_SERVICE_INDICATOR_KDF: ++ /* Get FIPS Service Indicator for a given KDF. Returns GPG_ERR_NO_ERROR ++ * if algorithm is allowed or GPG_ERR_NOT_SUPPORTED otherwise */ ++ rc = _gcry_fips_indicator_kdf (arg_ptr); ++ break; ++ + case PRIV_CTL_INIT_EXTRNG_TEST: /* Init external random test. */ + rc = GPG_ERR_NOT_SUPPORTED; + break; +Index: libgcrypt-1.9.4/tests/basic.c +=================================================================== +--- libgcrypt-1.9.4.orig/tests/basic.c ++++ libgcrypt-1.9.4/tests/basic.c +@@ -6383,6 +6383,16 @@ do_check_ocb_cipher (int inplace) + assert (tv[tidx].taglen <= ciphlen); + assert (tv[tidx].taglen <= sizeof tag); + ++ /* Verify the FIPS indicator marks this as non-approved */ ++ if (in_fips_mode) ++ { ++ err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER, ++ tv[tidx].algo, GCRY_CIPHER_MODE_OCB); ++ if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) ++ fail ("cipher-ocb, gcry_control did not fail as expected (tv %d): %s\n", ++ tidx, gpg_strerror (err)); ++ } ++ + err = gcry_cipher_open (&hde, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[tidx].algo, GCRY_CIPHER_MODE_OCB, 0); +@@ -6644,6 +6654,16 @@ check_ocb_cipher_largebuf_split (int alg + memcpy(inbuf + i, hash, 16); + } + ++ /* Verify the FIPS indicator marks this as non-approved */ ++ if (in_fips_mode) ++ { ++ err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER, ++ algo, GCRY_CIPHER_MODE_OCB); ++ if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) ++ fail ("cipher-ocb, gcry_control did not fail as expected (large, algo %d): %s\n", ++ algo, gpg_strerror (err)); ++ } ++ + err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) + err = gcry_cipher_open (&hdd, algo, GCRY_CIPHER_MODE_OCB, 0); +@@ -6842,7 +6862,17 @@ check_ocb_cipher_checksum (int algo, int + blk[byteidx] |= 1 << bitpos; + } + +- err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0); ++ /* Verify the FIPS indicator marks this as non-approved */ ++ if (in_fips_mode) ++ { ++ err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER, ++ algo, GCRY_CIPHER_MODE_OCB); ++ if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) ++ fail ("cipher-ocb, gcry_control did not fail as expected (checksum, algo %d): %s\n", ++ algo, gpg_strerror (err)); ++ } ++ ++ err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) + err = gcry_cipher_open (&hde2, algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) +@@ -7110,6 +7140,16 @@ check_ocb_cipher_splitaad (void) + aad[2] = tv[tidx].aad2? hex2buffer (tv[tidx].aad2, aadlen+2) : NULL; + aad[3] = tv[tidx].aad3? hex2buffer (tv[tidx].aad3, aadlen+3) : NULL; + ++ /* Verify the FIPS indicator marks this as non-approved */ ++ if (in_fips_mode) ++ { ++ err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER, ++ GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB); ++ if (gpg_err_code (err) != GPG_ERR_NOT_SUPPORTED) ++ fail ("cipher-ocb-splitaad, gcry_control did not fail as expected: %s\n", ++ gpg_strerror (err)); ++ } ++ + err = gcry_cipher_open (&hde, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_OCB, 0); + if (err) + { +@@ -9044,6 +9084,17 @@ check_bulk_cipher_modes (void) + fprintf (stderr, " checking bulk encryption for %s [%i], mode %d\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo, tv[i].mode); ++ ++ /* Verify the FIPS indicator marks approved cipher/modes combinations */ ++ if (in_fips_mode) ++ { ++ err = gcry_control (GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER, ++ tv[i].algo, tv[i].mode); ++ if (gpg_err_code (err) != GPG_ERR_NO_ERROR) ++ fail ("gcry_control unexpectedly failed for algo = %s, mode = %d : %s\n", ++ gcry_cipher_algo_name (tv[i].algo), tv[i].mode, gpg_strerror (err)); ++ } ++ + err = gcry_cipher_open (&hde, tv[i].algo, tv[i].mode, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, tv[i].mode, 0); +Index: libgcrypt-1.9.4/doc/gcrypt.texi +=================================================================== +--- libgcrypt-1.9.4.orig/doc/gcrypt.texi ++++ libgcrypt-1.9.4/doc/gcrypt.texi +@@ -961,6 +961,19 @@ been registered with Libgpg-error and ad + clamp again. Obviously this control code may only be used before a + second thread is started in a process. + ++@item GCRYCTL_FIPS_SERVICE_INDICATOR_CIPHER; Arguments: enum gcry_cipher_algos [, enum gcry_cipher_modes] ++ ++Check if the given symmetric cipher and optional cipher mode combination ++is approved under the current FIPS 140-3 certification. If the ++combination is approved, this function returns @code{GPG_ERR_NO_ERROR}. ++Otherwise @code{GPG_ERR_NOT_SUPPORTED} is returned. ++ ++@item GCRYCTL_FIPS_SERVICE_INDICATOR_KDF; Arguments: enum gcry_kdf_algos ++ ++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}. Otherwise @code{GPG_ERR_NOT_SUPPORTED} ++is returned. + + @end table + +@@ -980,7 +993,7 @@ descriptive message to the user and canc + + Some error values do not indicate a system error or an error in the + operation, but the result of an operation that failed properly. For +-example, if you try to decrypt a tempered message, the decryption will ++example, if you try to decrypt a tampered message, the decryption will + fail. Another error value actually means that the end of a data + buffer or list has been reached. The following descriptions explain + for many error codes what they mean usually. Some error values have +@@ -6320,25 +6333,6 @@ The following symmetric encryption algor + power-up: + + @table @asis +-@item 3DES +-To test the 3DES 3-key EDE encryption in ECB mode these tests are +-run: +-@enumerate +-@item +-A known answer test is run on a 64 bit test vector processed by 64 +-rounds of Single-DES block encryption and decryption using a key +-changed with each round. +-@item +-A known answer test is run on a 64 bit test vector processed by 16 +-rounds of 2-key and 3-key Triple-DES block encryption and decryptions +-using a key changed with each round. +-@item +-10 known answer tests using 3-key Triple-DES EDE encryption, comparing +-the ciphertext to the known value, then running a decryption and +-comparing it to the initial plaintext. +-@end enumerate +-(@code{cipher/des.c:selftest}) +- + @item AES-128 + A known answer tests is run using one test vector and one test + key with AES in ECB mode. (@code{cipher/rijndael.c:selftest_basic_128}) +@@ -6394,6 +6388,9 @@ A known answer test using 28 byte of dat + @item HMAC SHA-512 + A known answer test using 28 byte of data and a 4 byte key is run. + (@code{cipher/hmac-tests.c:selftests_sha512}) ++@item CMAC AES ++A known answer test using 40 byte of data and a 16 byte key is run. ++(@code{cipher/mac-cmac.c:selftests_cmac_aes}) + @end table + + @subsection Random Number Power-Up Test +@@ -6416,7 +6413,7 @@ The public key algorithms are tested dur + + @table @asis + @item RSA +-A pre-defined 1024 bit RSA key is used and these tests are run ++A pre-defined 2048 bit RSA key is used and these tests are run + in turn: + @enumerate + @item +@@ -6426,14 +6423,14 @@ Conversion of S-expression to internal f + Private key consistency check. + (@code{cipher/@/rsa.c:@/selftests_rsa}) + @item +-A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-1. ++A pre-defined 20 byte value is signed with PKCS#1 padding for SHA-256. + The result is verified using the public key against the original data +-and against modified data. (@code{cipher/@/rsa.c:@/selftest_sign_1024}) ++and against modified data. (@code{cipher/@/rsa.c:@/selftest_sign_2048}) + @item +-A 1000 bit random value is encrypted and checked that it does not +-match the original random value. The encrypted result is then ++A predefined 66 byte value is encrypted and checked that it matches ++reference encyrpted message. The encrypted result is then + decrypted and checked that it matches the original random value. +-(@code{cipher/@/rsa.c:@/selftest_encr_1024}) ++(@code{cipher/@/rsa.c:@/selftest_encr_2048}) + @end enumerate + + @item DSA +@@ -6463,15 +6461,6 @@ of the same name but with a single dot a + @file{.hmac}. + + +-@subsection Critical Functions Power-Up Tests +- +-The 3DES weak key detection is tested during power-up by calling the +-detection function with keys taken from a table listening all weak +-keys. The table itself is protected using a SHA-1 hash. +-(@code{cipher/@/des.c:@/selftest}) +- +- +- + @c -------------------------------- + @section Conditional Tests + +@@ -6645,8 +6634,6 @@ If Libgcrypt is used in FIPS mode these + The cryptographic algorithms are restricted to this list: + + @table @asis +-@item GCRY_CIPHER_3DES +-3 key EDE Triple-DES symmetric encryption. + @item GCRY_CIPHER_AES128 + AES 128 bit symmetric encryption. + @item GCRY_CIPHER_AES192 +@@ -6673,6 +6660,8 @@ HMAC using a SHA-256 message digest. + HMAC using a SHA-384 message digest. + @item GCRY_MD_SHA512,GCRY_MD_FLAG_HMAC + HMAC using a SHA-512 message digest. ++@item GCRY_MAC_CMAC_AES ++CMAC using a AES key. + @item GCRY_PK_RSA + RSA encryption and signing. + @item GCRY_PK_DSA +@@ -6683,8 +6672,8 @@ Note that the CRC algorithms are not con + and thus are in addition available. + + @item +-RSA key generation refuses to create a key with a keysize of +-less than 1024 bits. ++RSA key generation refuses to create and uyse ea key with a keysize of ++less than 2048 bits. + + @item + DSA key generation refuses to create a key with a keysize other +@@ -6697,8 +6686,9 @@ The @code{transient-key} flag for RSA an + Support for the VIA Padlock engine is disabled. + + @item +-FIPS mode may only be used on systems with a /dev/random device. +-Switching into FIPS mode on other systems will fail at runtime. ++FIPS mode may only be used on systems with a /dev/random device or ++with a getentropy syscall. Switching into FIPS mode on other systems ++will fail at runtime. + + @item + Saving and loading a random seed file is ignored. +@@ -6731,11 +6721,15 @@ disables FIPS mode unless Enforced FIPS + Libgcrypt will enter the error state. + + @item ++The signatures using SHA-1 digest algorithm may not be used. ++ ++@item + In Enforced FIPS mode the command @code{GCRYCTL_DISABLE_SECMEM} is + ignored. In standard FIPS mode it disables FIPS mode. + + @item + A handler set by @code{gcry_set_outofcore_handler} is ignored. ++ + @item + A handler set by @code{gcry_set_fatalerror_handler} is ignored. + diff --git a/libgcrypt-FIPS-verify-unsupported-KDF-test.patch b/libgcrypt-FIPS-verify-unsupported-KDF-test.patch new file mode 100644 index 0000000..6e440b5 --- /dev/null +++ b/libgcrypt-FIPS-verify-unsupported-KDF-test.patch @@ -0,0 +1,35 @@ +From 0ab4e8063729147fb9abd463055785aac831bf5c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 16:58:54 +0200 +Subject: [PATCH 348/500] tests: Verify unsupported KDF tests fail in FIPS mode + +* tests/t-kdf.c (check_pbkdf2): Verify tests based on algorithms + unsupported in FIPS mode fail. +-- + +Signed-off-by: Jakub Jelen +--- + tests/t-kdf.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/tests/t-kdf.c b/tests/t-kdf.c +index 7a48e98a..48309b9a 100644 +--- a/tests/t-kdf.c ++++ b/tests/t-kdf.c +@@ -1104,6 +1104,13 @@ check_pbkdf2 (void) + GCRY_KDF_PBKDF2, tv[tvidx].hashalgo, + tv[tvidx].salt, tv[tvidx].saltlen, + tv[tvidx].c, tv[tvidx].dklen, outbuf); ++ if (gcry_fips_mode_active() && tvidx > 6) ++ { ++ if (!err) ++ fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n", ++ tvidx, gpg_strerror (err)); ++ continue; ++ } + if (err) + fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err)); + else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen)) +-- +2.34.1 + diff --git a/libgcrypt.changes b/libgcrypt.changes index 4d89438..a4b4595 100644 --- a/libgcrypt.changes +++ b/libgcrypt.changes @@ -1,3 +1,21 @@ +------------------------------------------------------------------- +Tue Feb 1 11:28:51 UTC 2022 - Pedro Monreal + +- FIPS: Disable DSA in FIPS mode [bsc#1195385] + * Upstream task: https://dev.gnupg.org/T5710 + * Add libgcrypt-FIPS-disable-DSA.patch + +------------------------------------------------------------------- +Wed Jan 19 08:36:58 UTC 2022 - Pedro Monreal + +- FIPS: Service level indicator [bsc#1190700] + * Provide an indicator to check wether the service utilizes an + approved cryptographic algorithm or not. + * Add patches: + - libgcrypt-FIPS-service-indicators.patch + - libgcrypt-FIPS-verify-unsupported-KDF-test.patch + - libgcrypt-FIPS-HMAC-short-keylen.patch + ------------------------------------------------------------------- Tue Dec 7 09:41:01 UTC 2021 - Pedro Monreal @@ -5,6 +23,62 @@ Tue Dec 7 09:41:01 UTC 2021 - Pedro Monreal * gcry_mpi_sub_ui: fix subtracting from negative value * Add libgcrypt-FIPS-fix-gcry_mpi_sub_ui.patch +------------------------------------------------------------------- +Tue Nov 30 09:42:23 UTC 2021 - Pedro Monreal + +- FIPS: Define an entropy source SP800-90B compliant [bsc#1185140] + * Disable jitter entropy by default in random.conf + * Disable only-urandom option by default in random.conf + +------------------------------------------------------------------- +Fri Nov 26 13:10:29 UTC 2021 - Pedro Monreal + +- FIPS: RSA KeyGen/SigGen fail with 4096 bit key sizes [bsc#1192240] + * rsa: Check RSA keylen constraints for key operations. + * rsa: Fix regression in not returning an error for prime generation. + * tests: Add 2k RSA key working in FIPS mode. + * tests: pubkey: Replace RSA key to one of 2k. + * tests: pkcs1v2: Skip tests with small keys in FIPS. + * Add patches: + - libgcrypt-FIPS-RSA-keylen.patch + - libgcrypt-FIPS-RSA-keylen-tests.patch + +------------------------------------------------------------------- +Mon Nov 8 10:21:39 UTC 2021 - Pedro Monreal + +- FIPS: Disable 3DES/Triple-DES in FIPS mode [bsc#1185138] + * Add libgcrypt-FIPS-disable-3DES.patch + +------------------------------------------------------------------- +Tue Nov 2 11:31:19 UTC 2021 - Pedro Monreal + +- FIPS: PBKDF requirements [bsc#1185137] + * The PBKDF2 selftests were introduced in libgcrypt version + 1.9.1 in the function selftest_pbkdf2() + * Upstream task: https://dev.gnupg.org/T5182 + +------------------------------------------------------------------- +Thu Oct 28 19:48:06 UTC 2021 - Pedro Monreal + +- FIPS: Fix regression tests in FIPS mode [bsc#1192131] + * Add libgcrypt-FIPS-fix-regression-tests.patch + * Upstream task: https://dev.gnupg.org/T5520 + +------------------------------------------------------------------- +Thu Sep 21 11:25:06 UTC 2021 - Pedro Monreal + +- FIPS: Provide a module name/identifier and version that can be + mapped to the validation records. [bsc#1190706] + * Add libgcrypt-FIPS-module-version.patch + * Upstream task: https://dev.gnupg.org/T5600 + +------------------------------------------------------------------- +Thu Sep 21 10:23:44 UTC 2021 - Pedro Monreal + +- FIPS: Enable hardware support also in FIPS mode [bsc#1187110] + * Add libgcrypt-FIPS-hw-optimizations.patch + * Upstream task: https://dev.gnupg.org/T5508 + ------------------------------------------------------------------- Mon Aug 23 12:08:24 UTC 2021 - Pedro Monreal diff --git a/libgcrypt.spec b/libgcrypt.spec index ada00f6..56f1f25 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -1,7 +1,7 @@ # # spec file for package libgcrypt # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -27,7 +27,7 @@ Release: 0 Summary: The GNU Crypto Library License: GPL-2.0-or-later AND LGPL-2.1-or-later AND GPL-3.0-or-later Group: Development/Libraries/C and C++ -URL: https://directory.fsf.org/wiki/Libgcrypt +URL: https://gnupg.org/software/libgcrypt Source: https://gnupg.org/ftp/gcrypt/libgcrypt/%{name}-%{version}.tar.bz2 Source1: https://gnupg.org/ftp/gcrypt/libgcrypt/%{name}-%{version}.tar.bz2.sig Source2: baselibs.conf @@ -77,12 +77,30 @@ Patch28: libgcrypt-PCT-ECC.patch Patch29: libgcrypt-fips_selftest_trigger_file.patch #PATCH-FIX-SUSE bsc#1189745 The t-lock test is not build with phtread in gcc7, works in gcc11 Patch30: libgcrypt-pthread-in-t-lock-test.patch +#PATCH-FIX-UPSTREAM bsc#1187110 FIPS: Enable hardware support also in FIPS mode +Patch31: libgcrypt-FIPS-hw-optimizations.patch +#PATCH-FIX-UPSTREAM bsc#1190706 FIPS: Provide module name/identifier and version +Patch32: libgcrypt-FIPS-module-version.patch +#PATCH-FIX-SUSE bsc#1185138 FIPS: Disable 3DES/Triple-DES in FIPS mode +Patch33: libgcrypt-FIPS-disable-3DES.patch +#PATCH-FIX-UPSTREAM bsc#1192131 FIPS: Fix regression tests in FIPS mode +Patch34: libgcrypt-FIPS-fix-regression-tests.patch +#PATCH-FIX-UPSTREAM bsc#1192240 FIPS: RSA KeyGen/SigGen fail with 4096 bit key sizes +Patch35: libgcrypt-FIPS-RSA-keylen.patch +Patch36: libgcrypt-FIPS-RSA-keylen-tests.patch #PATCH-FIX-UPSTREAM bsc#1193480 FIPS: gcry_mpi_sub_ui: fix subtracting from negative value -Patch31: libgcrypt-FIPS-fix-gcry_mpi_sub_ui.patch +Patch37: libgcrypt-FIPS-fix-gcry_mpi_sub_ui.patch +#PATCH-FIX-UPSTREAM bsc#1190700 FIPS: Provide a service-level indicator +Patch38: libgcrypt-FIPS-verify-unsupported-KDF-test.patch +Patch39: libgcrypt-FIPS-HMAC-short-keylen.patch +Patch40: libgcrypt-FIPS-service-indicators.patch +#PATCH-FIX-UPSTREAM bsc#1195385 FIPS: Disable DSA in FIPS mode +Patch41: libgcrypt-FIPS-disable-DSA.patch BuildRequires: automake >= 1.14 BuildRequires: fipscheck BuildRequires: libgpg-error-devel >= 1.27 BuildRequires: libtool +BuildRequires: makeinfo BuildRequires: pkgconfig %description @@ -165,6 +183,7 @@ date=$(date -u +%{Y}-%{m}-%{dT}%{H}:%{M}+0000 -r %{SOURCE99}) sed -e "s,BUILD_TIMESTAMP=.*,BUILD_TIMESTAMP=$date," -i configure export CFLAGS="%{optflags} $(getconf LFS_CFLAGS)" %configure \ + --with-fips-module-version="Libgcrypt version %{version}-%{release}" \ --enable-noexecstack \ --disable-static \ --enable-m-guard \ @@ -173,6 +192,7 @@ export CFLAGS="%{optflags} $(getconf LFS_CFLAGS)" %endif --enable-hmac-binary-check \ --enable-random=linux + %make_build %if 0%{?build_hmac256} diff --git a/random.conf b/random.conf index 9168e43..5ccb076 100644 --- a/random.conf +++ b/random.conf @@ -3,7 +3,7 @@ # Always use the non-blocking /dev/urandom or the respective # system call instead of the blocking /dev/random. -only-urandom +# only-urandom # Disable the use of the jitter based entropy generator. -#disable-jent +disable-jent