From c45d41ea550dafc1f6852ac68a039022f9bca342 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Tue, 28 Mar 2023 09:09:48 +0000 Subject: [PATCH] import libgcrypt-1.10.0-9.el9_1 --- .../libgcrypt-1.10.0-allow-short-salt.patch | 26 + .../libgcrypt-1.10.0-fips-disable-oaep.patch | 151 --- ...ibgcrypt-1.10.0-fips-disable-pkcs1.5.patch | 219 ---- SOURCES/libgcrypt-1.10.0-fips-getrandom.patch | 17 +- SOURCES/libgcrypt-1.10.0-fips-indicator.patch | 55 + SOURCES/libgcrypt-1.10.0-fips-integrity.patch | 1008 +++++++++++++++++ .../libgcrypt-1.10.0-fips-integrity2.patch | 158 +++ SOURCES/libgcrypt-1.10.0-fips-kdf.patch | 129 +++ SOURCES/libgcrypt-1.10.0-fips-keygen.patch | 55 + SOURCES/libgcrypt-1.10.0-fips-rsa-pss.patch | 109 ++ SOURCES/libgcrypt-1.10.0-fips-selftest.patch | 276 +++++ SOURCES/libgcrypt-1.10.0-fips-x931.patch | 139 +++ SOURCES/libgcrypt-1.10.0-sha3-large.patch | 621 ++++++++++ SPECS/libgcrypt.spec | 73 +- 14 files changed, 2652 insertions(+), 384 deletions(-) delete mode 100644 SOURCES/libgcrypt-1.10.0-fips-disable-oaep.patch delete mode 100644 SOURCES/libgcrypt-1.10.0-fips-disable-pkcs1.5.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-indicator.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-integrity.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-integrity2.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-kdf.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-keygen.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-rsa-pss.patch create mode 100644 SOURCES/libgcrypt-1.10.0-fips-x931.patch create mode 100644 SOURCES/libgcrypt-1.10.0-sha3-large.patch diff --git a/SOURCES/libgcrypt-1.10.0-allow-short-salt.patch b/SOURCES/libgcrypt-1.10.0-allow-short-salt.patch index 46054cf..6800cf6 100644 --- a/SOURCES/libgcrypt-1.10.0-allow-short-salt.patch +++ b/SOURCES/libgcrypt-1.10.0-allow-short-salt.patch @@ -48,4 +48,30 @@ index c98247d8..aee5bffb 100644 -- 2.37.1 +commit 02718ade6ab5eee38169c2102097166770a2456d +Author: Jakub Jelen +Date: Thu Oct 20 16:33:11 2022 +0200 + visiblity: Check the HMAC key length in FIPS mode + + --- + * src/visibility.c (gcry_md_setkey): Check the HMAC key length in FIPS + mode also in the md_ API. + + Signed-off-by: Jakub Jelen + +diff --git a/src/visibility.c b/src/visibility.c +index 150b197d..73db3dea 100644 +--- a/src/visibility.c ++++ b/src/visibility.c +@@ -1357,6 +1357,10 @@ gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) + { + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); ++ ++ if (fips_mode () && keylen < 14) ++ return GPG_ERR_INV_VALUE; ++ + return gpg_error (_gcry_md_setkey (hd, key, keylen)); + } + diff --git a/SOURCES/libgcrypt-1.10.0-fips-disable-oaep.patch b/SOURCES/libgcrypt-1.10.0-fips-disable-oaep.patch deleted file mode 100644 index 3de63c8..0000000 --- a/SOURCES/libgcrypt-1.10.0-fips-disable-oaep.patch +++ /dev/null @@ -1,151 +0,0 @@ -From 34d8fc576b3a06dd205f45327a971eb6771e808c Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 17 Aug 2022 09:01:44 +0200 -Subject: [PATCH 1/2] Disable RSA-OAEP padding in FIPS mode - -* cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Block OAEP padding - in FIPS mode for encryption -* cipher/rsa.c (rsa_decrypt): Block OAEP padding in FIPS mode for - decryption ---- - -Signed-off-by: Jakub Jelen ---- - cipher/pubkey-util.c | 5 ++++- - cipher/rsa.c | 3 ++- - 2 files changed, 6 insertions(+), 2 deletions(-) - -diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c -index 4953caf3..244dd5d4 100644 ---- a/cipher/pubkey-util.c -+++ b/cipher/pubkey-util.c -@@ -1092,7 +1092,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, - const void * value; - size_t valuelen; - -- if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) -+ /* The RSA OAEP encryption requires some more assurances in FIPS */ -+ if (fips_mode ()) -+ rc = GPG_ERR_INV_FLAG; -+ else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) - rc = GPG_ERR_INV_OBJ; - else - { -diff --git a/cipher/rsa.c b/cipher/rsa.c -index 96dba090..87f57b55 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1457,7 +1457,8 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - rc = GPG_ERR_INV_DATA; - goto leave; - } -- if (fips_mode () && (ctx.encoding == PUBKEY_ENC_PKCS1)) -+ if (fips_mode () && (ctx.encoding == PUBKEY_ENC_PKCS1 || -+ ctx.encoding == PUBKEY_ENC_OAEP)) - { - rc = GPG_ERR_INV_FLAG; - goto leave; --- -2.37.1 - - -From c6d64e697c2748a49e875060aa753fc568c5f772 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 17 Aug 2022 10:31:19 +0200 -Subject: [PATCH 2/2] tests: Expect the OEAP tests to fail in FIPS mode - -* tests/basic.c (check_pubkey_crypt): Expect the OAEP padding encryption - to fail in FIPS mode -* tests/pkcs1v2.c (check_oaep): Expect the OAEP tests to fail in FIPS - mode ---- - -Signed-off-by: Jakub Jelen ---- - tests/basic.c | 14 +++++++++----- - tests/pkcs1v2.c | 13 +++++++++++++ - 2 files changed, 22 insertions(+), 5 deletions(-) - -diff --git a/tests/basic.c b/tests/basic.c -index 26980e15..b4102c9f 100644 ---- a/tests/basic.c -+++ b/tests/basic.c -@@ -16892,21 +16892,24 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - "(flags oaep)", - 1, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { GCRY_PK_RSA, - "(data\n (flags oaep)\n (hash-algo sha1)\n" - " (value #11223344556677889900AA#))\n", - "(flags oaep)(hash-algo sha1)", - 1, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { GCRY_PK_RSA, - "(data\n (flags oaep)\n (hash-algo sha1)\n (label \"test\")\n" - " (value #11223344556677889900AA#))\n", - "(flags oaep)(hash-algo sha1)(label \"test\")", - 1, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { GCRY_PK_RSA, - "(data\n (flags oaep)\n (hash-algo sha1)\n (label \"test\")\n" - " (value #11223344556677889900AA#)\n" -@@ -16914,7 +16917,8 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - "(flags oaep)(hash-algo sha1)(label \"test\")", - 1, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { 0, - "(data\n (flags )\n" " (value #11223344556677889900AA#))\n", - NULL, -@@ -16960,7 +16964,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - "(flags pkcs1)", - 1, - 0, -- GPG_ERR_ENCODING_PROBLEM, FLAG_SPECIAL }, -+ GPG_ERR_ENCODING_PROBLEM, FLAG_SPECIAL | FLAG_NOFIPS }, - { 0, - "(data\n (flags pss)\n" - " (value #11223344556677889900AA#))\n", -diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c -index 6c7f3d81..2fd495d5 100644 ---- a/tests/pkcs1v2.c -+++ b/tests/pkcs1v2.c -@@ -186,11 +186,24 @@ check_oaep (void) - err = gcry_pk_encrypt (&ciph, plain, pub_key); - if (err) - { -+ if (in_fips_mode) -+ { -+ gcry_sexp_release (plain); -+ plain = NULL; -+ continue; -+ } - show_sexp ("plain:\n", ciph); - fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); - } - else - { -+ if (in_fips_mode) -+ { -+ fail ("The OAEP encryption unexpectedly worked in FIPS mode\n"); -+ gcry_sexp_release (plain); -+ plain = NULL; -+ continue; -+ } - if (extract_cmp_data (ciph, "a", tbl[tno].m[mno].encr, - tbl[tno].m[mno].desc)) - { --- -2.37.1 - diff --git a/SOURCES/libgcrypt-1.10.0-fips-disable-pkcs1.5.patch b/SOURCES/libgcrypt-1.10.0-fips-disable-pkcs1.5.patch deleted file mode 100644 index 325b2fd..0000000 --- a/SOURCES/libgcrypt-1.10.0-fips-disable-pkcs1.5.patch +++ /dev/null @@ -1,219 +0,0 @@ -From c7709f7b23848abf4ba65cb99cb2a9e9c7ebdefc Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 1 Apr 2022 18:29:08 +0200 -Subject: [PATCH 1/3] Do not allow PKCS #1.5 padding for encryption in FIPS - -* cipher/pubkey-util.c (_gcry_pk_util_data_to_mpi): Block PKCS #1.5 - padding for encryption in FIPS mode -* cipher/rsa.c (rsa_decrypt): Block PKCS #1.5 decryption in FIPS mode --- - -GnuPG-bug-id: 5918 -Signed-off-by: Jakub Jelen ---- - cipher/pubkey-util.c | 5 ++++- - cipher/rsa.c | 5 +++++ - 2 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c -index 68defea6..4953caf3 100644 ---- a/cipher/pubkey-util.c -+++ b/cipher/pubkey-util.c -@@ -957,7 +957,10 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t input, gcry_mpi_t *ret_mpi, - void *random_override = NULL; - size_t random_override_len = 0; - -- if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) -+ /* The RSA PKCS#1.5 encryption is no longer supported by FIPS */ -+ if (fips_mode ()) -+ rc = GPG_ERR_INV_FLAG; -+ else if ( !(value=sexp_nth_data (lvalue, 1, &valuelen)) || !valuelen ) - rc = GPG_ERR_INV_OBJ; - else - { -diff --git a/cipher/rsa.c b/cipher/rsa.c -index 771413b3..c6319b67 100644 ---- a/cipher/rsa.c -+++ b/cipher/rsa.c -@@ -1391,6 +1391,11 @@ rsa_decrypt (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) - rc = GPG_ERR_INV_DATA; - goto leave; - } -+ if (fips_mode () && (ctx.encoding == PUBKEY_ENC_PKCS1)) -+ { -+ rc = GPG_ERR_INV_FLAG; -+ goto leave; -+ } - - /* Extract the key. */ - rc = sexp_extract_param (keyparms, NULL, "nedp?q?u?", --- -2.34.1 - - -From 299e2f93415984919181e0ee651719bbf83bdd2f Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 1 Apr 2022 18:31:05 +0200 -Subject: [PATCH 2/3] tests: Replace custom bit with more generic flags - -* tests/basic.c (global): New flag FLAG_SPECIAL - (check_pubkey_crypt): Change to use bitfield flags - --- - -GnuPG-bug-id: 5918 -Signed-off-by: Jakub Jelen ---- - tests/basic.c | 19 ++++++++++--------- - 1 file changed, 10 insertions(+), 9 deletions(-) - -diff --git a/tests/basic.c b/tests/basic.c -index a0ad33eb..1c6cb40b 100644 ---- a/tests/basic.c -+++ b/tests/basic.c -@@ -55,11 +55,12 @@ 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_NOFIPS (1 << 3) --#define FLAG_CFB8 (1 << 4) -+#define FLAG_CRYPT (1 << 0) -+#define FLAG_SIGN (1 << 1) -+#define FLAG_GRIP (1 << 2) -+#define FLAG_NOFIPS (1 << 3) -+#define FLAG_CFB8 (1 << 4) -+#define FLAG_SPECIAL (1 << 5) - - static int in_fips_mode; - -@@ -15558,7 +15559,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - int unpadded; - int encrypt_expected_rc; - int decrypt_expected_rc; -- int special; -+ int flags; - } datas[] = - { - { GCRY_PK_RSA, -@@ -15642,14 +15643,14 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - "(flags oaep)", - 1, - 0, -- GPG_ERR_ENCODING_PROBLEM, 1 }, -+ GPG_ERR_ENCODING_PROBLEM, FLAG_SPECIAL }, - { GCRY_PK_RSA, - "(data\n (flags oaep)\n" - " (value #11223344556677889900AA#))\n", - "(flags pkcs1)", - 1, - 0, -- GPG_ERR_ENCODING_PROBLEM, 1 }, -+ GPG_ERR_ENCODING_PROBLEM, FLAG_SPECIAL }, - { 0, - "(data\n (flags pss)\n" - " (value #11223344556677889900AA#))\n", -@@ -15725,7 +15726,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - ciph = list; - } - rc = gcry_pk_decrypt (&plain, ciph, skey); -- if (!rc && datas[dataidx].special == 1) -+ if (!rc && (datas[dataidx].flags & FLAG_SPECIAL)) - { - /* It may happen that OAEP formatted data which is - decrypted as pkcs#1 data returns a valid pkcs#1 --- -2.34.1 - - -From f736f3c70182d9c948f9105eb769c47c5578df35 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 1 Apr 2022 18:34:42 +0200 -Subject: [PATCH 3/3] tests: Expect the RSA PKCS #1.5 encryption to fail in - FIPS mode - -* tests/basic.c (check_pubkey_crypt): Expect RSA PKCS #1.5 encryption to - fail in FIPS mode. Expect failure when wrong padding is selected -* tests/pkcs1v2.c (check_v15crypt): Expect RSA PKCS #1.5 encryption to - fail in FIPS mode --- - -GnuPG-bug-id: 5918 -Signed-off-by: Jakub Jelen ---- - tests/basic.c | 11 +++++++---- - tests/pkcs1v2.c | 14 +++++++++++++- - 2 files changed, 20 insertions(+), 5 deletions(-) - -diff --git a/tests/basic.c b/tests/basic.c -index 1c6cb40b..85764591 100644 ---- a/tests/basic.c -+++ b/tests/basic.c -@@ -15568,14 +15568,16 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - NULL, - 0, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { GCRY_PK_RSA, - "(data\n (flags pkcs1)\n" - " (value #11223344556677889900AA#))\n", - "(flags pkcs1)", - 1, - 0, -- 0 }, -+ 0, -+ FLAG_NOFIPS }, - { GCRY_PK_RSA, - "(data\n (flags oaep)\n" - " (value #11223344556677889900AA#))\n", -@@ -15677,7 +15679,8 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - die ("converting data failed: %s\n", gpg_strerror (rc)); - - rc = gcry_pk_encrypt (&ciph, data, pkey); -- if (in_fips_mode && (flags & FLAG_NOFIPS)) -+ if (in_fips_mode && ((flags & FLAG_NOFIPS) || -+ (datas[dataidx].flags & FLAG_NOFIPS))) - { - if (!rc) - fail ("gcry_pk_encrypt did not fail as expected in FIPS mode\n"); -@@ -15726,7 +15729,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, - ciph = list; - } - rc = gcry_pk_decrypt (&plain, ciph, skey); -- if (!rc && (datas[dataidx].flags & FLAG_SPECIAL)) -+ if ((!rc || in_fips_mode) && (datas[dataidx].flags & FLAG_SPECIAL)) - { - /* It may happen that OAEP formatted data which is - decrypted as pkcs#1 data returns a valid pkcs#1 -diff --git a/tests/pkcs1v2.c b/tests/pkcs1v2.c -index f26e779b..6c7f3d81 100644 ---- a/tests/pkcs1v2.c -+++ b/tests/pkcs1v2.c -@@ -454,7 +454,19 @@ check_v15crypt (void) - gcry_free (seed); - - err = gcry_pk_encrypt (&ciph, plain, pub_key); -- if (err) -+ if (in_fips_mode) -+ { -+ if (!err) -+ { -+ fail ("gcry_pk_encrypt should have failed in FIPS mode:\n"); -+ } -+ gcry_sexp_release (plain); -+ plain = NULL; -+ gcry_sexp_release (ciph); -+ ciph = NULL; -+ continue; -+ } -+ else if (err) - { - show_sexp ("plain:\n", ciph); - fail ("gcry_pk_encrypt failed: %s\n", gpg_strerror (err)); --- -2.34.1 - diff --git a/SOURCES/libgcrypt-1.10.0-fips-getrandom.patch b/SOURCES/libgcrypt-1.10.0-fips-getrandom.patch index 39ac59c..b0d5bf2 100644 --- a/SOURCES/libgcrypt-1.10.0-fips-getrandom.patch +++ b/SOURCES/libgcrypt-1.10.0-fips-getrandom.patch @@ -24,15 +24,24 @@ diff --git a/random/rndgetentropy.c b/random/rndgetentropy.c index 7580873e..db4b09ed 100644 --- a/random/rndgetentropy.c +++ b/random/rndgetentropy.c -@@ -82,7 +82,10 @@ _gcry_rndgetentropy_gather_random (void (*add)(const void*, size_t, +@@ -82,9 +82,18 @@ _gcry_rndgetentropy_gather_random (void (*add)(const void*, size_t, + * never blocking once the kernel is seeded. */ + do { - nbytes = length < sizeof (buffer)? length : sizeof (buffer); +- nbytes = length < sizeof (buffer)? length : sizeof (buffer); _gcry_pre_syscall (); - ret = getentropy (buffer, nbytes); + if (fips_mode ()) -+ ret = getrandom (buffer, nbytes, GRND_RANDOM); ++ { ++ /* The getrandom API returns maximum 32 B of strong entropy */ ++ nbytes = length < 32 ? length : 32; ++ ret = getrandom (buffer, nbytes, GRND_RANDOM); ++ } + else -+ ret = getentropy (buffer, nbytes); ++ { ++ nbytes = length < sizeof (buffer) ? length : sizeof (buffer); ++ ret = getentropy (buffer, nbytes); ++ } _gcry_post_syscall (); } while (ret == -1 && errno == EINTR); diff --git a/SOURCES/libgcrypt-1.10.0-fips-indicator.patch b/SOURCES/libgcrypt-1.10.0-fips-indicator.patch new file mode 100644 index 0000000..2fdf808 --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-indicator.patch @@ -0,0 +1,55 @@ +From c34c9e70055ee43e5ef257384fa15941f064e5a4 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 15 Nov 2022 10:47:18 +0100 +Subject: [PATCH] fips: Mark AES key wrapping as approved. + +* src/fips.c (_gcry_fips_indicator_cipher): Add key wrapping mode as +approved. + +-- + +GnuPG-bug-id: 5512 +Signed-off-by: Jakub Jelen +--- + src/fips.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/fips.c b/src/fips.c +index 6599121c..272aabae 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -367,6 +367,7 @@ _gcry_fips_indicator_cipher (va_list arg_ptr) + case GCRY_CIPHER_MODE_CCM: + case GCRY_CIPHER_MODE_GCM: + case GCRY_CIPHER_MODE_XTS: ++ case GCRY_CIPHER_MODE_AESWRAP: + return GPG_ERR_NO_ERROR; + default: + return GPG_ERR_NOT_SUPPORTED; +-- + +commit d6117b04e0e4d5d68df8fb731f618b0d5126ee14 +Author: Jakub Jelen +Date: Tue Jan 17 14:39:34 2023 +0100 + + fips: Remove GCM mode from the allowed FIPS indicators + + * src/fips.c (_gcry_fips_indicator_cipher): Do not mark GCM mode as FIPS + approved. + --- + + Signed-off-by: Jakub Jelen + +diff --git a/src/fips.c b/src/fips.c +index 272aabae..774e7b4c 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -365,7 +365,6 @@ _gcry_fips_indicator_cipher (va_list arg_ptr) + 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: + case GCRY_CIPHER_MODE_AESWRAP: + return GPG_ERR_NO_ERROR; +-- diff --git a/SOURCES/libgcrypt-1.10.0-fips-integrity.patch b/SOURCES/libgcrypt-1.10.0-fips-integrity.patch new file mode 100644 index 0000000..8254381 --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-integrity.patch @@ -0,0 +1,1008 @@ +From beb5d6df5c5785db7c32a24a5d2a351cb964bfbc Mon Sep 17 00:00:00 2001 +From: Clemens Lang via Gcrypt-devel +Date: Mon, 14 Feb 2022 18:49:59 +0100 +Subject: [PATCH] fips: Use ELF header to find hmac file offset + +* src/fips.c [ENABLE_HMAC_BINARY_CHECK] (hmac256_check): Use ELF headers + to locate the file offset for the HMAC in addition to information from + the loader + +-- + +The previous method of locating the offset of the .rodata1 section in +the ELF file on disk used information obtained from the loader. This +computed the address of the value in memory at runtime, but the offset +in the file can be different. Specifically, the old code computed +a value relative to ElfW(Phdr).p_vaddr, but the offset in the file is +relative to ElfW(Phdr).p_offset. These values can differ, so the +computed address at runtime must be translated into a file offset +relative to p_offset. + +This is largely cosmetic, since the text section that should contain the +HMAC usually has both p_vaddr and p_offset set to 0. + +Signed-off-by: Clemens Lang +--- + README | 3 ++- + src/fips.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 69 insertions(+), 7 deletions(-) + +diff --git a/README b/README +index 3b465c1b..4d7697dd 100644 +--- a/README ++++ b/README +@@ -157,7 +157,8 @@ + --enable-hmac-binary-check + Include support to check the binary at runtime + against a HMAC checksum. This works only in FIPS +- mode and on systems providing the dladdr function. ++ mode on systems providing the dladdr function and using ++ the ELF binary format. + + --with-fips-module-version=version + Specify a string used as a module version for FIPS +diff --git a/src/fips.c b/src/fips.c +index 391b94f1..c40274d9 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -25,6 +25,8 @@ + #include + #ifdef ENABLE_HMAC_BINARY_CHECK + # include ++# include ++# include + # include + #endif + #ifdef HAVE_SYSLOG +@@ -594,6 +596,57 @@ run_random_selftests (void) + static const unsigned char __attribute__ ((section (".rodata1"))) + hmac_for_the_implementation[HMAC_LEN]; + ++/** ++ * Determine the offset of the given virtual address in the ELF file opened as ++ * fp and return it in offset. Rewinds fp to the beginning on success. ++ */ ++static gpg_error_t ++get_file_offset (FILE *fp, unsigned long paddr, unsigned long *offset) ++{ ++ ElfW (Ehdr) ehdr; ++ ElfW (Phdr) phdr; ++ uint16_t e_phidx; ++ ++ // read the ELF header ++ if (0 != fseek (fp, 0, SEEK_SET)) ++ return gpg_error_from_syserror (); ++ if (1 != fread (&ehdr, sizeof (ehdr), 1, fp)) ++ return gpg_error_from_syserror (); ++ ++ // the section header entry size should match the size of the shdr struct ++ if (ehdr.e_phentsize != sizeof (phdr)) ++ return gpg_error (GPG_ERR_INV_OBJ); ++ if (ehdr.e_phoff == 0) ++ return gpg_error (GPG_ERR_INV_OBJ); ++ ++ // jump to the first program header ++ if (0 != fseek (fp, ehdr.e_phoff, SEEK_SET)) ++ return gpg_error_from_syserror (); ++ ++ // iterate over the program headers, compare their virtual addresses with the ++ // address we are looking for, and if the program header matches, calculate ++ // the offset of the given paddr in the file using the program header's ++ // p_offset field. ++ for (e_phidx = 0; e_phidx < ehdr.e_phnum; e_phidx++) ++ { ++ if (1 != fread (&phdr, sizeof (phdr), 1, fp)) ++ return gpg_error_from_syserror (); ++ if (phdr.p_type == PT_LOAD && phdr.p_vaddr <= paddr ++ && phdr.p_vaddr + phdr.p_memsz > paddr) ++ { ++ // found section, compute the offset of paddr in the file ++ *offset = phdr.p_offset + (paddr - phdr.p_vaddr); ++ ++ if (0 != fseek (fp, 0, SEEK_SET)) ++ return gpg_error_from_syserror (); ++ return 0; ++ } ++ } ++ ++ // section not found in the file ++ return gpg_error (GPG_ERR_INV_OBJ); ++} ++ + static gpg_error_t + hmac256_check (const char *filename, const char *key, struct link_map *lm) + { +@@ -603,6 +656,7 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + size_t buffer_size, nread; + char *buffer; + unsigned long paddr; ++ unsigned long offset = 0; + unsigned long off = 0; + + paddr = (unsigned long)hmac_for_the_implementation - lm->l_addr; +@@ -611,6 +665,13 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + if (!fp) + return gpg_error (GPG_ERR_INV_OBJ); + ++ err = get_file_offset (fp, paddr, &offset); ++ if (err) ++ { ++ fclose (fp); ++ return err; ++ } ++ + err = _gcry_md_open (&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC); + if (err) + { +@@ -651,14 +712,14 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + nread = fread (buffer+HMAC_LEN, 1, buffer_size, fp); + if (nread < buffer_size) + { +- if (off - HMAC_LEN <= paddr && paddr <= off + nread) +- memset (buffer + HMAC_LEN + paddr - off, 0, HMAC_LEN); ++ if (off - HMAC_LEN <= offset && offset <= off + nread) ++ memset (buffer + HMAC_LEN + offset - off, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread+HMAC_LEN); + break; + } + +- if (off - HMAC_LEN <= paddr && paddr <= off + nread) +- memset (buffer + HMAC_LEN + paddr - off, 0, HMAC_LEN); ++ if (off - HMAC_LEN <= offset && offset <= off + nread) ++ memset (buffer + HMAC_LEN + offset - off, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread); + memcpy (buffer, buffer+buffer_size, HMAC_LEN); + off += nread; +@@ -694,8 +755,8 @@ check_binary_integrity (void) + const char *key = KEY_FOR_BINARY_CHECK; + void *extra_info; + +- if (!dladdr1 (hmac_for_the_implementation, +- &info, &extra_info, RTLD_DL_LINKMAP)) ++ if (!dladdr1 (hmac_for_the_implementation, &info, &extra_info, ++ RTLD_DL_LINKMAP)) + err = gpg_error_from_syserror (); + else + err = hmac256_check (info.dli_fname, key, extra_info); +-- +2.39.0 + + +From 521500624b4b11538d206137205e2a511dad7072 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Tue, 15 Feb 2022 20:38:02 +0900 +Subject: [PATCH] fips: Fix previous commit. + +-- + +Coding style fix. + +Signed-off-by: NIIBE Yutaka +--- + src/fips.c | 64 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 32 insertions(+), 32 deletions(-) + +diff --git a/src/fips.c b/src/fips.c +index c40274d9..f16bce8b 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -596,54 +596,55 @@ run_random_selftests (void) + static const unsigned char __attribute__ ((section (".rodata1"))) + hmac_for_the_implementation[HMAC_LEN]; + +-/** +- * Determine the offset of the given virtual address in the ELF file opened as +- * fp and return it in offset. Rewinds fp to the beginning on success. ++/* ++ * In the ELF file opened as FP, determine the offset of the given ++ * virtual address ADDR and return it in OFFSET. Rewinds FP to the ++ * beginning on success. + */ + static gpg_error_t +-get_file_offset (FILE *fp, unsigned long paddr, unsigned long *offset) ++get_file_offset (FILE *fp, unsigned long addr, unsigned long *offset) + { + ElfW (Ehdr) ehdr; + ElfW (Phdr) phdr; + uint16_t e_phidx; + +- // read the ELF header +- if (0 != fseek (fp, 0, SEEK_SET)) ++ /* Read the ELF header */ ++ if (fseek (fp, 0, SEEK_SET) != 0) + return gpg_error_from_syserror (); +- if (1 != fread (&ehdr, sizeof (ehdr), 1, fp)) ++ if (fread (&ehdr, sizeof (ehdr), 1, fp) != 1) + return gpg_error_from_syserror (); + +- // the section header entry size should match the size of the shdr struct ++ /* The program header entry size should match the size of the phdr struct */ + if (ehdr.e_phentsize != sizeof (phdr)) + return gpg_error (GPG_ERR_INV_OBJ); + if (ehdr.e_phoff == 0) + return gpg_error (GPG_ERR_INV_OBJ); + +- // jump to the first program header +- if (0 != fseek (fp, ehdr.e_phoff, SEEK_SET)) ++ /* Jump to the first program header */ ++ if (fseek (fp, ehdr.e_phoff, SEEK_SET) != 0) + return gpg_error_from_syserror (); + +- // iterate over the program headers, compare their virtual addresses with the +- // address we are looking for, and if the program header matches, calculate +- // the offset of the given paddr in the file using the program header's +- // p_offset field. ++ /* Iterate over the program headers, compare their virtual addresses ++ with the address we are looking for, and if the program header ++ matches, calculate the offset of the given ADDR in the file using ++ the program header's p_offset field. */ + for (e_phidx = 0; e_phidx < ehdr.e_phnum; e_phidx++) + { +- if (1 != fread (&phdr, sizeof (phdr), 1, fp)) ++ if (fread (&phdr, sizeof (phdr), 1, fp) != 1) + return gpg_error_from_syserror (); +- if (phdr.p_type == PT_LOAD && phdr.p_vaddr <= paddr +- && phdr.p_vaddr + phdr.p_memsz > paddr) ++ if (phdr.p_type == PT_LOAD ++ && phdr.p_vaddr <= addr && addr < phdr.p_vaddr + phdr.p_memsz) + { +- // found section, compute the offset of paddr in the file +- *offset = phdr.p_offset + (paddr - phdr.p_vaddr); ++ /* Found segment, compute the offset of ADDR in the file */ ++ *offset = phdr.p_offset + (addr - phdr.p_vaddr); + +- if (0 != fseek (fp, 0, SEEK_SET)) ++ if (fseek (fp, 0, SEEK_SET) != 0) + return gpg_error_from_syserror (); + return 0; + } + } + +- // section not found in the file ++ /* Segment not found in the file */ + return gpg_error (GPG_ERR_INV_OBJ); + } + +@@ -655,17 +656,16 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + gcry_md_hd_t hd; + size_t buffer_size, nread; + char *buffer; +- unsigned long paddr; ++ unsigned long addr; + unsigned long offset = 0; +- unsigned long off = 0; +- +- paddr = (unsigned long)hmac_for_the_implementation - lm->l_addr; ++ unsigned long pos = 0; + ++ addr = (unsigned long)hmac_for_the_implementation - lm->l_addr; + fp = fopen (filename, "rb"); + if (!fp) + return gpg_error (GPG_ERR_INV_OBJ); + +- err = get_file_offset (fp, paddr, &offset); ++ err = get_file_offset (fp, addr, &offset); + if (err) + { + fclose (fp); +@@ -698,7 +698,7 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + } + + nread = fread (buffer, 1, HMAC_LEN, fp); +- off += nread; ++ pos += nread; + if (nread < HMAC_LEN) + { + xfree (buffer); +@@ -712,17 +712,17 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + nread = fread (buffer+HMAC_LEN, 1, buffer_size, fp); + if (nread < buffer_size) + { +- if (off - HMAC_LEN <= offset && offset <= off + nread) +- memset (buffer + HMAC_LEN + offset - off, 0, HMAC_LEN); ++ if (pos - HMAC_LEN <= offset && offset <= pos + nread) ++ memset (buffer + HMAC_LEN + offset - pos, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread+HMAC_LEN); + break; + } + +- if (off - HMAC_LEN <= offset && offset <= off + nread) +- memset (buffer + HMAC_LEN + offset - off, 0, HMAC_LEN); ++ if (pos - HMAC_LEN <= offset && offset <= pos + nread) ++ memset (buffer + HMAC_LEN + offset - pos, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread); + memcpy (buffer, buffer+buffer_size, HMAC_LEN); +- off += nread; ++ pos += nread; + } + + if (ferror (fp)) +-- +2.39.1 + + +From 9dcf9305962b90febdf2d7cc73b49feadbf6a01f Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Wed, 16 Feb 2022 14:06:02 +0900 +Subject: [PATCH] fips: Integrity check improvement, with only loadable + segments. + +* configure.ac (READELF): Check the tool. +* src/Makefile.am (libgcrypt.so.hmac): Use genhmac.sh with hmac256. +* src/fips.c (get_file_offsets): Rename from get_file_offset. +Determine the OFFSET2 at the end of loadable segments, too. +Add fixup of the ELF header to exclude section information. +(hmac256_check): Finish scanning at the end of loadble segments. +* src/genhmac.sh: New. + +-- + +This change fixes the build with ld.gold. + +GnuPG-bug-id: 5835 +Signed-off-by: NIIBE Yutaka +--- + configure.ac | 1 + + src/Makefile.am | 4 +-- + src/fips.c | 73 +++++++++++++++++++++++++++++-------------- + src/genhmac.sh | 83 +++++++++++++++++++++++++++++++++++++++++++++++++ + 4 files changed, 136 insertions(+), 25 deletions(-) + create mode 100755 src/genhmac.sh + +diff --git a/configure.ac b/configure.ac +index f0f1637f..ea01f5a6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -579,6 +579,7 @@ else + AC_DEFINE(ENABLE_HMAC_BINARY_CHECK,1, + [Define to support an HMAC based integrity check]) + AC_CHECK_TOOL(OBJCOPY, [objcopy]) ++ AC_CHECK_TOOL(READELF, [readelf]) + if test "$use_hmac_binary_check" != yes ; then + DEF_HMAC_BINARY_CHECK=-DKEY_FOR_BINARY_CHECK="'\"$use_hmac_binary_check\"'" + fi +diff --git a/src/Makefile.am b/src/Makefile.am +index 018d5761..72100671 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -24,7 +24,7 @@ pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = libgcrypt.pc + + EXTRA_DIST = libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \ +- gcrypt.h.in libgcrypt.def libgcrypt.pc.in ++ gcrypt.h.in libgcrypt.def libgcrypt.pc.in genhmac.sh + + bin_SCRIPTS = libgcrypt-config + m4datadir = $(datadir)/aclocal +@@ -149,7 +149,7 @@ libgcrypt.la.done: libgcrypt.so.hmac + @touch libgcrypt.la.done + + libgcrypt.so.hmac: hmac256 libgcrypt.la +- ./hmac256 --stdkey --binary < .libs/libgcrypt.so > $@ ++ READELF=$(READELF) AWK=$(AWK) $(srcdir)/genhmac.sh > $@ + else !USE_HMAC_BINARY_CHECK + libgcrypt.la.done: libgcrypt.la + @touch libgcrypt.la.done +diff --git a/src/fips.c b/src/fips.c +index f16bce8b..134d0eae 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -598,50 +598,68 @@ hmac_for_the_implementation[HMAC_LEN]; + + /* + * In the ELF file opened as FP, determine the offset of the given +- * virtual address ADDR and return it in OFFSET. Rewinds FP to the ++ * virtual address ADDR and return it in R_OFFSET1. Determine the ++ * offset of last loadable section in R_OFFSET2. Rewinds FP to the + * beginning on success. + */ + static gpg_error_t +-get_file_offset (FILE *fp, unsigned long addr, unsigned long *offset) ++get_file_offsets (FILE *fp, unsigned long addr, ElfW (Ehdr) *ehdr_p, ++ unsigned long *r_offset1, unsigned long *r_offset2) + { +- ElfW (Ehdr) ehdr; + ElfW (Phdr) phdr; + uint16_t e_phidx; ++ long pos = 0; + + /* Read the ELF header */ + if (fseek (fp, 0, SEEK_SET) != 0) + return gpg_error_from_syserror (); +- if (fread (&ehdr, sizeof (ehdr), 1, fp) != 1) ++ if (fread (ehdr_p, sizeof (*ehdr_p), 1, fp) != 1) + return gpg_error_from_syserror (); + ++ /* Fix up the ELF header, clean all section information. */ ++ ehdr_p->e_shoff = 0; ++ ehdr_p->e_shentsize = 0; ++ ehdr_p->e_shnum = 0; ++ ehdr_p->e_shstrndx = 0; ++ + /* The program header entry size should match the size of the phdr struct */ +- if (ehdr.e_phentsize != sizeof (phdr)) ++ if (ehdr_p->e_phentsize != sizeof (phdr)) + return gpg_error (GPG_ERR_INV_OBJ); +- if (ehdr.e_phoff == 0) ++ if (ehdr_p->e_phoff == 0) + return gpg_error (GPG_ERR_INV_OBJ); + + /* Jump to the first program header */ +- if (fseek (fp, ehdr.e_phoff, SEEK_SET) != 0) ++ if (fseek (fp, ehdr_p->e_phoff, SEEK_SET) != 0) + return gpg_error_from_syserror (); + + /* Iterate over the program headers, compare their virtual addresses + with the address we are looking for, and if the program header + matches, calculate the offset of the given ADDR in the file using + the program header's p_offset field. */ +- for (e_phidx = 0; e_phidx < ehdr.e_phnum; e_phidx++) ++ for (e_phidx = 0; e_phidx < ehdr_p->e_phnum; e_phidx++) + { + if (fread (&phdr, sizeof (phdr), 1, fp) != 1) + return gpg_error_from_syserror (); +- if (phdr.p_type == PT_LOAD +- && phdr.p_vaddr <= addr && addr < phdr.p_vaddr + phdr.p_memsz) +- { +- /* Found segment, compute the offset of ADDR in the file */ +- *offset = phdr.p_offset + (addr - phdr.p_vaddr); + +- if (fseek (fp, 0, SEEK_SET) != 0) +- return gpg_error_from_syserror (); +- return 0; +- } ++ if (phdr.p_type == PT_PHDR) ++ continue; ++ ++ if (phdr.p_type != PT_LOAD) ++ break; ++ ++ pos = phdr.p_offset + phdr.p_filesz; ++ if (phdr.p_vaddr <= addr && addr < phdr.p_vaddr + phdr.p_memsz) ++ /* Found segment, compute the offset of ADDR in the file */ ++ *r_offset1 = phdr.p_offset + (addr - phdr.p_vaddr); ++ } ++ ++ if (*r_offset1) ++ { ++ if (fseek (fp, 0, SEEK_SET) != 0) ++ return gpg_error_from_syserror (); ++ ++ *r_offset2 = (unsigned long)pos; ++ return 0; + } + + /* Segment not found in the file */ +@@ -657,15 +675,17 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + size_t buffer_size, nread; + char *buffer; + unsigned long addr; +- unsigned long offset = 0; ++ unsigned long offset1 = 0; ++ unsigned long offset2 = 0; + unsigned long pos = 0; ++ ElfW (Ehdr) ehdr; + + addr = (unsigned long)hmac_for_the_implementation - lm->l_addr; + fp = fopen (filename, "rb"); + if (!fp) + return gpg_error (GPG_ERR_INV_OBJ); + +- err = get_file_offset (fp, addr, &offset); ++ err = get_file_offsets (fp, addr, &ehdr, &offset1, &offset2); + if (err) + { + fclose (fp); +@@ -710,16 +730,23 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + while (1) + { + nread = fread (buffer+HMAC_LEN, 1, buffer_size, fp); ++ if (pos + nread >= offset2) ++ nread = offset2 - pos; ++ ++ /* Copy, fixed ELF header at the beginning. */ ++ if (pos - HMAC_LEN == 0) ++ memcpy (buffer, &ehdr, sizeof (ehdr)); ++ + if (nread < buffer_size) + { +- if (pos - HMAC_LEN <= offset && offset <= pos + nread) +- memset (buffer + HMAC_LEN + offset - pos, 0, HMAC_LEN); ++ if (pos - HMAC_LEN <= offset1 && offset1 <= pos + nread) ++ memset (buffer + HMAC_LEN + offset1 - pos, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread+HMAC_LEN); + break; + } + +- if (pos - HMAC_LEN <= offset && offset <= pos + nread) +- memset (buffer + HMAC_LEN + offset - pos, 0, HMAC_LEN); ++ if (pos - HMAC_LEN <= offset1 && offset1 <= pos + nread) ++ memset (buffer + HMAC_LEN + offset1 - pos, 0, HMAC_LEN); + _gcry_md_write (hd, buffer, nread); + memcpy (buffer, buffer+buffer_size, HMAC_LEN); + pos += nread; +diff --git a/src/genhmac.sh b/src/genhmac.sh +new file mode 100755 +index 00000000..bb33b9c6 +--- /dev/null ++++ b/src/genhmac.sh +@@ -0,0 +1,83 @@ ++#! /bin/sh ++ ++# ++# genhmac.sh - Build tool to generate hmac hash ++# ++# Copyright (C) 2022 g10 Code GmbH ++# ++# This file is part of libgcrypt. ++# ++# libgcrypt is free software; you can redistribute it and/or ++# modify it under the terms of the GNU Lesser General Public License ++# as published by the Free Software Foundation; either version 2.1 of ++# the License, or (at your option) any later version. ++# ++# libgcrypt is distributed in the hope that it will be useful, but ++# WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++# Lesser General Public License for more details. ++# ++# You should have received a copy of the GNU Lesser General Public ++# License along with this program; if not, see . ++# ++ ++set -e ++ ++# ++# Following variables should be defined to invoke this script ++# ++# READELF ++# AWK ++# ++ ++AWK_VERSION_OUTPUT=$($AWK 'BEGIN { print PROCINFO["version"] }') ++if test -n "$AWK_VERSION_OUTPUT"; then ++ # It's GNU awk, which supports PROCINFO. ++ AWK_OPTION=--non-decimal-data ++fi ++ ++FILE=.libs/libgcrypt.so ++ ++# ++# Fixup the ELF header to clean up section information ++# ++printf '%b' '\002' > 2.bin ++dd ibs=1 skip=4 count=1 if=$FILE status=none > class-byte.bin ++if cmp class-byte.bin 2.bin; then ++ CLASS=64 ++ HEADER_SIZE=64 ++else ++ CLASS=32 ++ HEADER_SIZE=52 ++fi ++ ++if test $CLASS -eq 64; then ++ dd ibs=1 count=40 if=$FILE status=none ++ dd ibs=1 count=8 if=/dev/zero status=none ++ dd ibs=1 skip=48 count=10 if=$FILE status=none ++ dd ibs=1 count=6 if=/dev/zero status=none ++else ++ dd ibs=1 count=32 if=$FILE status=none ++ dd ibs=1 count=4 if=/dev/zero status=none ++ dd ibs=1 skip=36 count=10 if=$FILE status=none ++ dd ibs=1 count=6 if=/dev/zero status=none ++fi > header-fixed.bin ++ ++# Compute the end of loadable segment. ++# ++# This require computation in hexadecimal, and GNU awk needs ++# --non-decimal-data option ++# ++OFFSET=$($READELF --wide --program-headers $FILE | \ ++ $AWK $AWK_OPTION "/^ LOAD/ { offset=\$2+\$5-$HEADER_SIZE }\ ++END { print offset}") ++ ++# ++# Feed the header fixed and loadable segments to HMAC256 ++# to generate hmac hash of the FILE ++# ++(cat header-fixed.bin; \ ++ dd ibs=1 skip=$HEADER_SIZE count=$OFFSET if=$FILE status=none) \ ++ | ./hmac256 --stdkey --binary ++ ++rm -f 2.bin class-byte.bin header-fixed.bin +-- +2.39.1 + + +From a340e980388243ceae6df57d101036f3f2a955be Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Wed, 16 Feb 2022 20:08:15 +0900 +Subject: [PATCH] fips: More portable integrity check. + +* src/Makefile.am (EXTRA_DIST): Change the name of the script. +(libgcrypt.la.done): Invoce OBJCOPY with --add-section. +(libgcrypt.so.hmac): Specify ECHO_N. +* src/fips.c (get_file_offset): Rename from get_file_offsets. +Find the note section and return the value in HMAC. +(hmac256_check): Simplify by HMAC from the note section, not loaded. +(check_binary_integrity): Use dladdr instead of dladdr1. +* src/gen-note-integrity.sh: Rename from genhmac.sh. +Generate ElfN_Nhdr, and then the hmac. + +-- + +The idea of use of .note is by Daiki Ueno. + https://gitlab.com/dueno/integrity-notes + +Further, instead of NOTE segment loaded onto memory, use noload +section in the file. + +Thanks to Clemens Lang for initiating this direction of improvement. + +The namespace "FDO" would need to be changed. + +GnuPG-bug-id: 5835 +Signed-off-by: NIIBE Yutaka +--- + src/Makefile.am | 8 +- + src/fips.c | 167 +++++++++++++--------- + src/{genhmac.sh => gen-note-integrity.sh} | 34 ++++- + 3 files changed, 134 insertions(+), 75 deletions(-) + rename src/{genhmac.sh => gen-note-integrity.sh} (78%) + +diff --git a/src/Makefile.am b/src/Makefile.am +index 72100671..b8bb187a 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -24,7 +24,7 @@ pkgconfigdir = $(libdir)/pkgconfig + pkgconfig_DATA = libgcrypt.pc + + EXTRA_DIST = libgcrypt-config.in libgcrypt.m4 libgcrypt.vers \ +- gcrypt.h.in libgcrypt.def libgcrypt.pc.in genhmac.sh ++ gcrypt.h.in libgcrypt.def libgcrypt.pc.in gen-note-integrity.sh + + bin_SCRIPTS = libgcrypt-config + m4datadir = $(datadir)/aclocal +@@ -143,13 +143,15 @@ if USE_HMAC_BINARY_CHECK + CLEANFILES += libgcrypt.so.hmac + + libgcrypt.la.done: libgcrypt.so.hmac +- $(OBJCOPY) --update-section .rodata1=libgcrypt.so.hmac \ ++ $(OBJCOPY) --add-section .note.fdo.integrity=libgcrypt.so.hmac \ ++ --set-section-flags .note.fdo.integrity=noload,readonly \ + .libs/libgcrypt.so .libs/libgcrypt.so.new + mv -f .libs/libgcrypt.so.new .libs/libgcrypt.so.*.* + @touch libgcrypt.la.done + + libgcrypt.so.hmac: hmac256 libgcrypt.la +- READELF=$(READELF) AWK=$(AWK) $(srcdir)/genhmac.sh > $@ ++ ECHO_N=$(ECHO_N) READELF=$(READELF) AWK=$(AWK) \ ++ $(srcdir)/gen-note-integrity.sh > $@ + else !USE_HMAC_BINARY_CHECK + libgcrypt.la.done: libgcrypt.la + @touch libgcrypt.la.done +diff --git a/src/fips.c b/src/fips.c +index 134d0eae..d798d577 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -593,22 +593,20 @@ run_random_selftests (void) + # endif + #define HMAC_LEN 32 + +-static const unsigned char __attribute__ ((section (".rodata1"))) +-hmac_for_the_implementation[HMAC_LEN]; +- + /* +- * In the ELF file opened as FP, determine the offset of the given +- * virtual address ADDR and return it in R_OFFSET1. Determine the +- * offset of last loadable section in R_OFFSET2. Rewinds FP to the +- * beginning on success. ++ * In the ELF file opened as FP, fill the ELF header to the pointer ++ * EHDR_P, determine the offset of last loadable segment in R_OFFSET. ++ * Also, find the section which contains the hmac value and return it ++ * in HMAC. Rewinds FP to the beginning on success. + */ + static gpg_error_t +-get_file_offsets (FILE *fp, unsigned long addr, ElfW (Ehdr) *ehdr_p, +- unsigned long *r_offset1, unsigned long *r_offset2) ++get_file_offset (FILE *fp, ElfW (Ehdr) *ehdr_p, ++ unsigned long *r_offset, unsigned char hmac[HMAC_LEN]) + { + ElfW (Phdr) phdr; +- uint16_t e_phidx; +- long pos = 0; ++ ElfW (Shdr) shdr; ++ int i; ++ unsigned long off_segment = 0; + + /* Read the ELF header */ + if (fseek (fp, 0, SEEK_SET) != 0) +@@ -616,12 +614,6 @@ get_file_offsets (FILE *fp, unsigned long addr, ElfW (Ehdr) *ehdr_p, + if (fread (ehdr_p, sizeof (*ehdr_p), 1, fp) != 1) + return gpg_error_from_syserror (); + +- /* Fix up the ELF header, clean all section information. */ +- ehdr_p->e_shoff = 0; +- ehdr_p->e_shentsize = 0; +- ehdr_p->e_shnum = 0; +- ehdr_p->e_shstrndx = 0; +- + /* The program header entry size should match the size of the phdr struct */ + if (ehdr_p->e_phentsize != sizeof (phdr)) + return gpg_error (GPG_ERR_INV_OBJ); +@@ -632,11 +624,9 @@ get_file_offsets (FILE *fp, unsigned long addr, ElfW (Ehdr) *ehdr_p, + if (fseek (fp, ehdr_p->e_phoff, SEEK_SET) != 0) + return gpg_error_from_syserror (); + +- /* Iterate over the program headers, compare their virtual addresses +- with the address we are looking for, and if the program header +- matches, calculate the offset of the given ADDR in the file using +- the program header's p_offset field. */ +- for (e_phidx = 0; e_phidx < ehdr_p->e_phnum; e_phidx++) ++ /* Iterate over the program headers, determine the last loadable ++ segment. */ ++ for (i = 0; i < ehdr_p->e_phnum; i++) + { + if (fread (&phdr, sizeof (phdr), 1, fp) != 1) + return gpg_error_from_syserror (); +@@ -647,45 +637,100 @@ get_file_offsets (FILE *fp, unsigned long addr, ElfW (Ehdr) *ehdr_p, + if (phdr.p_type != PT_LOAD) + break; + +- pos = phdr.p_offset + phdr.p_filesz; +- if (phdr.p_vaddr <= addr && addr < phdr.p_vaddr + phdr.p_memsz) +- /* Found segment, compute the offset of ADDR in the file */ +- *r_offset1 = phdr.p_offset + (addr - phdr.p_vaddr); ++ off_segment = phdr.p_offset + phdr.p_filesz; + } + +- if (*r_offset1) ++ if (!off_segment) ++ /* The segment not found in the file */ ++ return gpg_error (GPG_ERR_INV_OBJ); ++ ++ /* The section header entry size should match the size of the shdr struct */ ++ if (ehdr_p->e_shentsize != sizeof (shdr)) ++ return gpg_error (GPG_ERR_INV_OBJ); ++ if (ehdr_p->e_shoff == 0) ++ return gpg_error (GPG_ERR_INV_OBJ); ++ ++ /* Jump to the first section header */ ++ if (fseek (fp, ehdr_p->e_shoff, SEEK_SET) != 0) ++ return gpg_error_from_syserror (); ++ ++ /* Iterate over the section headers, determine the note section, ++ read the hmac value. */ ++ for (i = 0; i < ehdr_p->e_shnum; i++) + { +- if (fseek (fp, 0, SEEK_SET) != 0) ++ long off; ++ ++ if (fread (&shdr, sizeof (shdr), 1, fp) != 1) + return gpg_error_from_syserror (); + +- *r_offset2 = (unsigned long)pos; +- return 0; ++ off = ftell (fp); ++ if (shdr.sh_type == SHT_NOTE && shdr.sh_flags == 0 && shdr.sh_size == 48) ++ { ++ const char header_of_the_note[] = { ++ 0x04, 0x00, 0x00, 0x00, ++ 0x20, 0x00, 0x00, 0x00, ++ 0xca, 0xfe, 0x2a, 0x8e, ++ 'F', 'D', 'O', 0x00 ++ }; ++ unsigned char header[16]; ++ ++ /* Jump to the note section. */ ++ if (fseek (fp, shdr.sh_offset, SEEK_SET) != 0) ++ return gpg_error_from_syserror (); ++ ++ if (fread (header, sizeof (header), 1, fp) != 1) ++ return gpg_error_from_syserror (); ++ ++ if (!memcmp (header, header_of_the_note, 16)) ++ { ++ /* Found. Read the hmac value into HMAC. */ ++ if (fread (hmac, HMAC_LEN, 1, fp) != 1) ++ return gpg_error_from_syserror (); ++ break; ++ } ++ ++ /* Back to the next section header. */ ++ if (fseek (fp, off, SEEK_SET) != 0) ++ return gpg_error_from_syserror (); ++ } + } + +- /* Segment not found in the file */ +- return gpg_error (GPG_ERR_INV_OBJ); ++ if (i == ehdr_p->e_shnum) ++ /* The note section not found. */ ++ return gpg_error (GPG_ERR_INV_OBJ); ++ ++ /* Fix up the ELF header, clean all section information. */ ++ ehdr_p->e_shoff = 0; ++ ehdr_p->e_shentsize = 0; ++ ehdr_p->e_shnum = 0; ++ ehdr_p->e_shstrndx = 0; ++ ++ *r_offset = off_segment; ++ if (fseek (fp, 0, SEEK_SET) != 0) ++ return gpg_error_from_syserror (); ++ ++ return 0; + } + + static gpg_error_t +-hmac256_check (const char *filename, const char *key, struct link_map *lm) ++hmac256_check (const char *filename, const char *key) + { + gpg_error_t err; + FILE *fp; + gcry_md_hd_t hd; +- size_t buffer_size, nread; ++ const size_t buffer_size = 32768; ++ size_t nread; + char *buffer; +- unsigned long addr; +- unsigned long offset1 = 0; +- unsigned long offset2 = 0; ++ unsigned long offset = 0; + unsigned long pos = 0; + ElfW (Ehdr) ehdr; ++ unsigned char hmac[HMAC_LEN]; + +- addr = (unsigned long)hmac_for_the_implementation - lm->l_addr; + fp = fopen (filename, "rb"); + if (!fp) + return gpg_error (GPG_ERR_INV_OBJ); + +- err = get_file_offsets (fp, addr, &ehdr, &offset1, &offset2); ++ err = get_file_offset (fp, &ehdr, &offset, hmac); + if (err) + { + fclose (fp); +@@ -707,8 +752,7 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + return err; + } + +- buffer_size = 32768; +- buffer = xtrymalloc (buffer_size + HMAC_LEN); ++ buffer = xtrymalloc (buffer_size); + if (!buffer) + { + err = gpg_error_from_syserror (); +@@ -717,38 +761,21 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + return err; + } + +- nread = fread (buffer, 1, HMAC_LEN, fp); +- pos += nread; +- if (nread < HMAC_LEN) +- { +- xfree (buffer); +- fclose (fp); +- _gcry_md_close (hd); +- return gpg_error (GPG_ERR_TOO_SHORT); +- } +- + while (1) + { +- nread = fread (buffer+HMAC_LEN, 1, buffer_size, fp); +- if (pos + nread >= offset2) +- nread = offset2 - pos; ++ nread = fread (buffer, 1, buffer_size, fp); ++ if (pos + nread >= offset) ++ nread = offset - pos; + +- /* Copy, fixed ELF header at the beginning. */ +- if (pos - HMAC_LEN == 0) ++ /* Copy the fixed ELF header at the beginning. */ ++ if (pos == 0) + memcpy (buffer, &ehdr, sizeof (ehdr)); + ++ _gcry_md_write (hd, buffer, nread); ++ + if (nread < buffer_size) +- { +- if (pos - HMAC_LEN <= offset1 && offset1 <= pos + nread) +- memset (buffer + HMAC_LEN + offset1 - pos, 0, HMAC_LEN); +- _gcry_md_write (hd, buffer, nread+HMAC_LEN); +- break; +- } ++ break; + +- if (pos - HMAC_LEN <= offset1 && offset1 <= pos + nread) +- memset (buffer + HMAC_LEN + offset1 - pos, 0, HMAC_LEN); +- _gcry_md_write (hd, buffer, nread); +- memcpy (buffer, buffer+buffer_size, HMAC_LEN); + pos += nread; + } + +@@ -759,7 +786,7 @@ hmac256_check (const char *filename, const char *key, struct link_map *lm) + unsigned char *digest; + + digest = _gcry_md_read (hd, 0); +- if (!memcmp (digest, hmac_for_the_implementation, HMAC_LEN)) ++ if (!memcmp (digest, hmac, HMAC_LEN)) + /* Success. */ + err = 0; + else +@@ -780,13 +807,11 @@ check_binary_integrity (void) + gpg_error_t err; + Dl_info info; + const char *key = KEY_FOR_BINARY_CHECK; +- void *extra_info; + +- if (!dladdr1 (hmac_for_the_implementation, &info, &extra_info, +- RTLD_DL_LINKMAP)) ++ if (!dladdr (hmac256_check, &info)) + err = gpg_error_from_syserror (); + else +- err = hmac256_check (info.dli_fname, key, extra_info); ++ err = hmac256_check (info.dli_fname, key); + + reporter ("binary", 0, NULL, err? gpg_strerror (err):NULL); + #ifdef HAVE_SYSLOG +diff --git a/src/genhmac.sh b/src/gen-note-integrity.sh +similarity index 78% +rename from src/genhmac.sh +rename to src/gen-note-integrity.sh +index bb33b9c6..969fdca6 100755 +--- a/src/genhmac.sh ++++ b/src/gen-note-integrity.sh +@@ -1,7 +1,7 @@ + #! /bin/sh + + # +-# genhmac.sh - Build tool to generate hmac hash ++# gen-note-integrity.sh - Build tool to generate hmac hash section + # + # Copyright (C) 2022 g10 Code GmbH + # +@@ -28,8 +28,40 @@ set -e + # + # READELF + # AWK ++# ECHO_N + # + ++######## Emit ElfN_Nhdr for note.fdo.integrity ######## ++ ++NOTE_NAME="FDO" ++ ++# n_namesz = 4 including NUL ++printf '%b' '\004' ++printf '%b' '\000' ++printf '%b' '\000' ++printf '%b' '\000' ++ ++# n_descsz = 32 ++printf '%b' '\040' ++printf '%b' '\000' ++printf '%b' '\000' ++printf '%b' '\000' ++ ++# n_type: NT_FDO_INTEGRITY=0xCAFE2A8E ++printf '%b' '\312' ++printf '%b' '\376' ++printf '%b' '\052' ++printf '%b' '\216' ++ ++# the name ++echo $ECHO_N $NOTE_NAME ++printf '%b' '\000' ++ ++# Here comes the alignment. As the size of name is 4, it's none. ++# NO PADDING HERE. ++ ++######## Rest is to generate hmac hash ######## ++ + AWK_VERSION_OUTPUT=$($AWK 'BEGIN { print PROCINFO["version"] }') + if test -n "$AWK_VERSION_OUTPUT"; then + # It's GNU awk, which supports PROCINFO. +-- +2.39.1 + + diff --git a/SOURCES/libgcrypt-1.10.0-fips-integrity2.patch b/SOURCES/libgcrypt-1.10.0-fips-integrity2.patch new file mode 100644 index 0000000..c1b7d9e --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-integrity2.patch @@ -0,0 +1,158 @@ +From 3c8b6c4a9cad59c5e1db5706f6774a3141b60210 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Thu, 17 Feb 2022 10:28:05 +0900 +Subject: [PATCH] fips: Fix gen-note-integrity.sh script not to use cmp + utility. + +* src/gen-note-integrity.sh: Simplify detecting 32-bit machine +or 64-bit machine. + +-- + +GnuPG-bug-id: 5835 +Signed-off-by: NIIBE Yutaka +--- + src/gen-note-integrity.sh | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/gen-note-integrity.sh b/src/gen-note-integrity.sh +index 969fdca6..878d7095 100755 +--- a/src/gen-note-integrity.sh ++++ b/src/gen-note-integrity.sh +@@ -73,9 +73,9 @@ FILE=.libs/libgcrypt.so + # + # Fixup the ELF header to clean up section information + # +-printf '%b' '\002' > 2.bin +-dd ibs=1 skip=4 count=1 if=$FILE status=none > class-byte.bin +-if cmp class-byte.bin 2.bin; then ++BYTE002=$(printf '%b' '\002') ++CLASS_BYTE=$(dd ibs=1 skip=4 count=1 if=$FILE status=none) ++if test "$CLASS_BYTE" = "$BYTE002"; then + CLASS=64 + HEADER_SIZE=64 + else +@@ -112,4 +112,4 @@ END { print offset}") + dd ibs=1 skip=$HEADER_SIZE count=$OFFSET if=$FILE status=none) \ + | ./hmac256 --stdkey --binary + +-rm -f 2.bin class-byte.bin header-fixed.bin ++rm -f header-fixed.bin +-- +2.39.1 + + +From 052c5ef4cea56772b7015e36f231fa0bcbf91410 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Thu, 17 Feb 2022 11:21:35 +0900 +Subject: [PATCH] fips: Clarify what to be hashed for the integrity check. + +* src/fips.c (get_file_offset): Compute the maximum offset +of segments. +* src/gen-note-integrity.sh: Likewise. + +-- + +The result is same (in current format of ELF program). +Semantics is more clear. It hashes: + + - From the start of shared library file, + - fixed up the ELF header to exclude link-time information, + - up to the last segment. + +Signed-off-by: NIIBE Yutaka +--- + src/fips.c | 20 +++++++++----------- + src/gen-note-integrity.sh | 20 ++++++++++++++------ + 2 files changed, 23 insertions(+), 17 deletions(-) + +diff --git a/src/fips.c b/src/fips.c +index d798d577..89f8204b 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -595,7 +595,7 @@ run_random_selftests (void) + + /* + * In the ELF file opened as FP, fill the ELF header to the pointer +- * EHDR_P, determine the offset of last loadable segment in R_OFFSET. ++ * EHDR_P, determine the maximum offset of segments in R_OFFSET. + * Also, find the section which contains the hmac value and return it + * in HMAC. Rewinds FP to the beginning on success. + */ +@@ -624,24 +624,22 @@ get_file_offset (FILE *fp, ElfW (Ehdr) *ehdr_p, + if (fseek (fp, ehdr_p->e_phoff, SEEK_SET) != 0) + return gpg_error_from_syserror (); + +- /* Iterate over the program headers, determine the last loadable +- segment. */ ++ /* Iterate over the program headers, determine the last offset of ++ segments. */ + for (i = 0; i < ehdr_p->e_phnum; i++) + { ++ unsigned long off; ++ + if (fread (&phdr, sizeof (phdr), 1, fp) != 1) + return gpg_error_from_syserror (); + +- if (phdr.p_type == PT_PHDR) +- continue; +- +- if (phdr.p_type != PT_LOAD) +- break; +- +- off_segment = phdr.p_offset + phdr.p_filesz; ++ off = phdr.p_offset + phdr.p_filesz; ++ if (off_segment < off) ++ off_segment = off; + } + + if (!off_segment) +- /* The segment not found in the file */ ++ /* No segment found in the file */ + return gpg_error (GPG_ERR_INV_OBJ); + + /* The section header entry size should match the size of the shdr struct */ +diff --git a/src/gen-note-integrity.sh b/src/gen-note-integrity.sh +index 878d7095..50071bf5 100755 +--- a/src/gen-note-integrity.sh ++++ b/src/gen-note-integrity.sh +@@ -95,21 +95,29 @@ else + dd ibs=1 count=6 if=/dev/zero status=none + fi > header-fixed.bin + +-# Compute the end of loadable segment. ++# ++# Compute the end of segments, and emit the COUNT to read ++# (For each segment in program headers, calculate the offset ++# and select the maximum) + # + # This require computation in hexadecimal, and GNU awk needs + # --non-decimal-data option + # +-OFFSET=$($READELF --wide --program-headers $FILE | \ +- $AWK $AWK_OPTION "/^ LOAD/ { offset=\$2+\$5-$HEADER_SIZE }\ +-END { print offset}") ++COUNT=$($READELF --wide --program-headers $FILE | \ ++ $AWK $AWK_OPTION \ ++"BEGIN { max_offset=0 } ++/^\$/ { if (program_headers_start) program_headers_end=1 } ++(program_headers_start && !program_headers_end) { offset = \$2 + \$5 } ++(max_offset < offset) { max_offset = offset } ++/^ Type/ { program_headers_start=1 } ++END { print max_offset- $HEADER_SIZE }") + + # +-# Feed the header fixed and loadable segments to HMAC256 ++# Feed the header fixed and all segments to HMAC256 + # to generate hmac hash of the FILE + # + (cat header-fixed.bin; \ +- dd ibs=1 skip=$HEADER_SIZE count=$OFFSET if=$FILE status=none) \ ++ dd ibs=1 skip=$HEADER_SIZE count=$COUNT if=$FILE status=none) \ + | ./hmac256 --stdkey --binary + + rm -f header-fixed.bin +-- +2.39.1 + + diff --git a/SOURCES/libgcrypt-1.10.0-fips-kdf.patch b/SOURCES/libgcrypt-1.10.0-fips-kdf.patch new file mode 100644 index 0000000..021476a --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-kdf.patch @@ -0,0 +1,129 @@ +From 3c04b692de1e7b45b764ff8d66bf84609b012e3a Mon Sep 17 00:00:00 2001 +From: Tobias Heider +Date: Tue, 27 Sep 2022 13:31:05 +0900 +Subject: [PATCH] kdf:pkdf2: Check minimum allowed key size when running in + FIPS mode. + +* cipher/kdf.c (_gcry_kdf_pkdf2): Add output length check. + +-- + +GnuPG-bug-id: 6219 +--- + cipher/kdf.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/cipher/kdf.c b/cipher/kdf.c +index 81523320..67c60df8 100644 +--- a/cipher/kdf.c ++++ b/cipher/kdf.c +@@ -160,6 +160,10 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, + return GPG_ERR_INV_VALUE; + #endif + ++ /* Check minimum key size */ ++ if (fips_mode () && dklen < 14) ++ return GPG_ERR_INV_VALUE; ++ + + /* Step 2 */ + l = ((dklen - 1)/ hlen) + 1; +-- +2.37.3 +From e5a5e847b66eb6b80e60a2dffa347268f059aee3 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 4 Oct 2022 12:44:54 +0200 +Subject: [PATCH] tests: Reproducer for short dklen in FIPS mode + +* tests/t-kdf.c (check_pbkdf2): Add test vector with short dklen and + verify it fails in FIPS mode +-- + +GnuPG-bug-id: 6219 +Signed-off-by: Jakub Jelen +--- + tests/t-kdf.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/tests/t-kdf.c b/tests/t-kdf.c +index c0192d7b..716fb53e 100644 +--- a/tests/t-kdf.c ++++ b/tests/t-kdf.c +@@ -909,6 +909,14 @@ check_pbkdf2 (void) + "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" + "\xb5\x24\xaf\x60\x12\x06\x2f\xe0\x37\xa6" + }, ++ { ++ "password", 8, ++ "salt", 4, ++ GCRY_MD_SHA1, ++ 1, ++ 10, /* too short dklen for FIPS */ ++ "\x0c\x60\xc8\x0f\x96\x1f\x0e\x71\xf3\xa9" ++ }, + { + "password", 8, + "salt", 4, +@@ -1109,7 +1117,7 @@ check_pbkdf2 (void) + GCRY_KDF_PBKDF2, tv[tvidx].hashalgo, + tv[tvidx].salt, tv[tvidx].saltlen, + tv[tvidx].c, tv[tvidx].dklen, outbuf); +- if (in_fips_mode && tvidx > 6) ++ if (in_fips_mode && tvidx > 7) + { + if (!err) + fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n", +@@ -1118,7 +1126,7 @@ check_pbkdf2 (void) + } + if (err) + { +- if (in_fips_mode && tv[tvidx].plen < 14) ++ if (in_fips_mode && (tv[tvidx].plen < 14 || tv[tvidx].dklen < 14)) + { + if (verbose) + fprintf (stderr, +-- +2.37.3 + +From f4a861f3e5ae82f278284061e4829c03edf9c3a7 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 18 Nov 2022 09:49:50 +0900 +Subject: [PATCH] pkdf2: Add checks for FIPS. + +* cipher/kdf.c (_gcry_kdf_pkdf2): Require 8 chars passphrase for FIPS. +Set bounds for salt length and iteration count in FIPS mode. + +-- + +GnuPG-bug-id: 6039 +Signed-off-by: Jakub Jelen +--- + cipher/kdf.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/cipher/kdf.c b/cipher/kdf.c +index d22584da..823c744e 100644 +--- a/cipher/kdf.c ++++ b/cipher/kdf.c +@@ -160,6 +160,18 @@ _gcry_kdf_pkdf2 (const void *passphrase, size_t passphraselen, + return GPG_ERR_INV_VALUE; + #endif + ++ /* FIPS requires minimum passphrase length, see FIPS 140-3 IG D.N */ ++ if (fips_mode () && passphraselen < 8) ++ return GPG_ERR_INV_VALUE; ++ ++ /* FIPS requires minimum salt length of 128 b (SP 800-132 sec. 5.1, p.6) */ ++ if (fips_mode () && saltlen < 16) ++ return GPG_ERR_INV_VALUE; ++ ++ /* FIPS requires minimum iterations bound (SP 800-132 sec 5.2, p.6) */ ++ if (fips_mode () && iterations < 1000) ++ return GPG_ERR_INV_VALUE; ++ + /* Check minimum key size */ + if (fips_mode () && dklen < 14) + return GPG_ERR_INV_VALUE; +-- +2.39.0 + diff --git a/SOURCES/libgcrypt-1.10.0-fips-keygen.patch b/SOURCES/libgcrypt-1.10.0-fips-keygen.patch new file mode 100644 index 0000000..6df1429 --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-keygen.patch @@ -0,0 +1,55 @@ +From cd30ed3c0d715aa0c58a32a29cfb1476163a5b94 Mon Sep 17 00:00:00 2001 +From: NIIBE Yutaka +Date: Wed, 20 Apr 2022 15:09:41 +0900 +Subject: [PATCH] cipher: Change the bounds for RSA key generation round. + +* cipher/rsa.c (generate_fips): Use 10 for p, 20 for q. + +-- + +Constants from FIPS 186-5-draft. + +GnuPG-bug-id: 5919 +Signed-off-by: NIIBE Yutaka +--- + cipher/rsa.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/cipher/rsa.c b/cipher/rsa.c +index 486a34f0..771413b3 100644 +--- a/cipher/rsa.c ++++ b/cipher/rsa.c +@@ -476,7 +476,7 @@ generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, + + retry: + /* generate p and q */ +- for (i = 0; i < 5 * pbits; i++) ++ for (i = 0; i < 10 * pbits; i++) + { + ploop: + if (!testparms) +@@ -506,10 +506,10 @@ generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, + else if (testparms) + goto err; + } +- if (i >= 5 * pbits) ++ if (i >= 10 * pbits) + goto err; + +- for (i = 0; i < 5 * pbits; i++) ++ for (i = 0; i < 20 * pbits; i++) + { + qloop: + if (!testparms) +@@ -555,7 +555,7 @@ generate_fips (RSA_secret_key *sk, unsigned int nbits, unsigned long use_e, + else if (testparms) + goto err; + } +- if (i >= 5 * pbits) ++ if (i >= 20 * pbits) + goto err; + + if (testparms) +-- +2.37.3 + diff --git a/SOURCES/libgcrypt-1.10.0-fips-rsa-pss.patch b/SOURCES/libgcrypt-1.10.0-fips-rsa-pss.patch new file mode 100644 index 0000000..af3f772 --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-rsa-pss.patch @@ -0,0 +1,109 @@ +From bf1e62e59200b2046680d1d3d1599facc88cfe63 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 29 Nov 2022 14:04:59 +0100 +Subject: [PATCH] rsa: Prevent usage of long salt in FIPS mode + +* cipher/rsa-common.c (_gcry_rsa_pss_encode): Prevent usage of large + salt lengths + (_gcry_rsa_pss_verify): Ditto. +* tests/basic.c (check_pubkey_sign): Check longer salt length fails in + FIPS mode +* tests/t-rsa-pss.c (one_test_sexp): Fix function name in error message +--- + cipher/rsa-common.c | 14 ++++++++++++++ + tests/basic.c | 19 ++++++++++++++++++- + tests/t-rsa-pss.c | 2 +- + 3 files changed, 33 insertions(+), 2 deletions(-) + +diff --git a/cipher/rsa-common.c b/cipher/rsa-common.c +index 233ddb2d..61cd60a4 100644 +--- a/cipher/rsa-common.c ++++ b/cipher/rsa-common.c +@@ -809,6 +809,13 @@ _gcry_rsa_pss_encode (gcry_mpi_t *r_result, unsigned int nbits, int algo, + hlen = _gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + ++ /* The FIPS 186-4 Section 5.5 allows only 0 <= sLen <= hLen */ ++ if (fips_mode () && saltlen > hlen) ++ { ++ rc = GPG_ERR_INV_ARG; ++ goto leave; ++ } ++ + /* Allocate a help buffer and setup some pointers. */ + buflen = 8 + hlen + saltlen + (emlen - hlen - 1); + buf = xtrymalloc (buflen); +@@ -950,6 +957,13 @@ _gcry_rsa_pss_verify (gcry_mpi_t value, int hashed_already, + hlen = _gcry_md_get_algo_dlen (algo); + gcry_assert (hlen); /* We expect a valid ALGO here. */ + ++ /* The FIPS 186-4 Section 5.5 allows only 0 <= sLen <= hLen */ ++ if (fips_mode () && saltlen > hlen) ++ { ++ rc = GPG_ERR_INV_ARG; ++ goto leave; ++ } ++ + /* Allocate a help buffer and setup some pointers. + This buffer is used for two purposes: + +------------------------------+-------+ +diff --git a/tests/basic.c b/tests/basic.c +index 77e2fd93..429bd237 100644 +--- a/tests/basic.c ++++ b/tests/basic.c +@@ -16602,6 +16602,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, + const char *data; + int algo; + int expected_rc; ++ int flags; + } datas[] = + { + { "(data\n (flags pkcs1)\n" +@@ -16672,6 +16673,22 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, + " (random-override #4253647587980912233445566778899019283747#))\n", + GCRY_PK_RSA, + 0 }, ++ { "(data\n (flags pss)\n" ++ " (hash-algo sha256)\n" ++ " (value #11223344556677889900AABBCCDDEEFF#)\n" ++ " (salt-length 2:32)\n" ++ " (random-override #42536475879809122334455667788990192837465564738291" ++ "00122334455667#))\n", ++ GCRY_PK_RSA, ++ 0 }, ++ { "(data\n (flags pss)\n" ++ " (hash-algo sha256)\n" ++ " (value #11223344556677889900AABBCCDDEEFF#)\n" ++ " (salt-length 2:33)\n" ++ " (random-override #42536475879809122334455667788990192837465564738291" ++ "0012233445566778#))\n", ++ GCRY_PK_RSA, ++ 0, FLAG_NOFIPS }, + { NULL } + }; + +@@ -16695,7 +16712,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo, + die ("converting data failed: %s\n", gpg_strerror (rc)); + + rc = gcry_pk_sign (&sig, hash, skey); +- if (in_fips_mode && (flags & FLAG_NOFIPS)) ++ if (in_fips_mode && (flags & FLAG_NOFIPS || datas[dataidx].flags & FLAG_NOFIPS)) + { + if (!rc) + fail ("gcry_pk_sign did not fail as expected in FIPS mode\n"); +diff --git a/tests/t-rsa-pss.c b/tests/t-rsa-pss.c +index c5f90116..82dd54b3 100644 +--- a/tests/t-rsa-pss.c ++++ b/tests/t-rsa-pss.c +@@ -340,7 +340,7 @@ one_test_sexp (const char *n, const char *e, const char *d, + snprintf (p, 3, "%02x", out[i]); + if (strcmp (sig_string, s)) + { +- fail ("gcry_pkhash_sign failed: %s", ++ fail ("gcry_pk_hash_sign failed: %s", + "wrong value returned"); + info (" expected: '%s'", s); + info (" got: '%s'", sig_string); +-- +2.39.0 + diff --git a/SOURCES/libgcrypt-1.10.0-fips-selftest.patch b/SOURCES/libgcrypt-1.10.0-fips-selftest.patch index 6840c07..7486f4a 100644 --- a/SOURCES/libgcrypt-1.10.0-fips-selftest.patch +++ b/SOURCES/libgcrypt-1.10.0-fips-selftest.patch @@ -921,3 +921,279 @@ index 78c26f2f..9d14a474 100644 -- 2.37.1 + +-- + +ACVP testing uses the test-parms option to specify p and q to be checked +for primality. When test-parms is specified, generate_fips() always +returns keys with p=q=0. These keys then fail the pairwise consistency +test, because they cannot be used to successfully sign a message and +verify the signature. + +Skip the PCT when test-parms is specified. + +Add a regression test to check that this functionality continues to work +in the future. + +Signed-off-by: Clemens Lang +--- + cipher/rsa.c | 5 +- + tests/Makefile.am | 2 +- + tests/t-rsa-testparm.c | 130 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 135 insertions(+), 2 deletions(-) + create mode 100644 tests/t-rsa-testparm.c + +diff --git a/cipher/rsa.c b/cipher/rsa.c +index 87f57b55..1a935d80 100644 +--- a/cipher/rsa.c ++++ b/cipher/rsa.c +@@ -1218,6 +1218,7 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) + int flags = 0; + gcry_sexp_t l1; + gcry_sexp_t swap_info = NULL; ++ int testparms = 0; + + memset (&sk, 0, sizeof sk); + +@@ -1274,6 +1275,8 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) + } + deriveparms = (genparms? sexp_find_token (genparms, "test-parms", 0) + /**/ : NULL); ++ if (deriveparms) ++ testparms = 1; + + /* Generate. */ + if (deriveparms || fips_mode ()) +@@ -1311,7 +1314,7 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) + mpi_free (sk.u); + sexp_release (swap_info); + +- if (!ec && fips_mode () && test_keys_fips (*r_skey)) ++ if (!ec && !testparms && fips_mode () && test_keys_fips (*r_skey)) + { + sexp_release (*r_skey); *r_skey = NULL; + fips_signal_error ("self-test after key generation failed"); +diff --git a/tests/Makefile.am b/tests/Makefile.am +index f65725bc..302d923b 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -28,7 +28,7 @@ tests_bin = \ + t-mpi-bit t-mpi-point curves t-lock \ + prime basic keygen pubkey hmac hashtest t-kdf keygrip \ + fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 \ +- t-dsa t-ecdsa t-rsa-pss t-rsa-15 \ ++ t-dsa t-ecdsa t-rsa-pss t-rsa-15 t-rsa-testparm \ + t-ed25519 t-cv25519 t-x448 t-ed448 + + tests_bin_last = benchmark bench-slope +diff --git a/tests/t-rsa-testparm.c b/tests/t-rsa-testparm.c +new file mode 100644 +index 00000000..65617855 +--- /dev/null ++++ b/tests/t-rsa-testparm.c +@@ -0,0 +1,130 @@ ++/* t-rsa-testparm.c - Check the RSA Key Generation test-parm parameter ++ * Copyright (C) 2022 g10 Code GmbH ++ * ++ * This file is part of Libgcrypt. ++ * ++ * Libgcrypt is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU Lesser General Public License as ++ * published by the Free Software Foundation; either version 2.1 of ++ * the License, or (at your option) any later version. ++ * ++ * Libgcrypt is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include ++#endif ++#include ++#include ++#include ++#include ++ ++#include "stopwatch.h" ++ ++#define PGM "t-rsa-testparm" ++#include "t-common.h" ++ ++ ++static void ++check_rsa_testparm () ++{ ++ gpg_error_t err; ++ gcry_sexp_t keyspec = NULL; ++ gcry_sexp_t key = NULL; ++ const char *sexp = "(genkey (rsa (nbits \"2048\") (test-parms " ++ "(e \"65537\")" ++ "(p #00bbccabcee15d343944a47e492d4b1f4de79633e20cbb46f7d2d6813392a807ad048" ++ "cf77528edd19f77e7453f25173b9dcb70423afa2037aae147b81a33d541fc58f875ef" ++ "f1e852ab55e2e09a3debfbc151b3b0d17fef6f74d81fca14fbae531418e211ef81859" ++ "2af70de5cec3b92795cc3578572bf456099cd8727150e523261#)" ++ "(q #00ca87ecf2883f4ed00a9ec65abdeba81d28edbfcc34ecc563d587f166b52d42bfbe2" ++ "2bbc095b0b8426a2f8bbc55baaa8859b42cbc376ed3067db3ef7b135b63481322911e" ++ "bbd7014db83aa051e0ca2dbf302b75cd37f2ae8df90e134226e92f6353a284b28bb30" ++ "af0bbf925b345b955328379866ebac11d55bc80fe84f105d415#)" ++ ")))"; ++ ++ info ("Checking RSA KeyGen test-parm parameter.\n"); ++ ++ err = gcry_sexp_build (&keyspec, NULL, sexp); ++ if (err) ++ { ++ fail ("error building SEXP for test: %s", gpg_strerror (err)); ++ goto leave; ++ } ++ ++ err = gcry_pk_genkey (&key, keyspec); ++ if (err) ++ { ++ fail ("gcry_pk_genkey failed for test: %s", gpg_strerror (err)); ++ goto leave; ++ } ++ ++leave: ++ if (key) ++ gcry_sexp_release (key); ++ if (keyspec) ++ gcry_sexp_release (keyspec); ++} ++ ++ ++int ++main (int argc, char **argv) ++{ ++ int last_argc = -1; ++ ++ if (argc) ++ { argc--; argv++; } ++ ++ while (argc && last_argc != argc ) ++ { ++ last_argc = argc; ++ if (!strcmp (*argv, "--")) ++ { ++ argc--; argv++; ++ break; ++ } ++ else if (!strcmp (*argv, "--help")) ++ { ++ fputs ("usage: " PGM " [options]\n" ++ "Options:\n" ++ " --verbose print timings etc.\n" ++ " --debug flyswatter\n", ++ stdout); ++ exit (0); ++ } ++ else if (!strcmp (*argv, "--verbose")) ++ { ++ verbose++; ++ argc--; argv++; ++ } ++ else if (!strcmp (*argv, "--debug")) ++ { ++ verbose += 2; ++ debug++; ++ argc--; argv++; ++ } ++ else if (!strncmp (*argv, "--", 2)) ++ die ("unknown option '%s'", *argv); ++ ++ } ++ ++ xgcry_control ((GCRYCTL_DISABLE_SECMEM, 0)); ++ if (!gcry_check_version (GCRYPT_VERSION)) ++ die ("version mismatch\n"); ++ if (debug) ++ xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 0xffffffff, 0)); ++ ++ start_timer (); ++ check_rsa_testparm (); ++ stop_timer (); ++ ++ info ("All tests completed in %s. Errors: %d\n", ++ elapsed_time (1), error_count); ++ return !!error_count; ++} +-- +2.37.3 +From 149f6f8654fdeaf7aa1ff8ac3d00d7454c0e6eff Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Wed, 5 Oct 2022 16:50:08 +0200 +Subject: [PATCH] fips: Mark gcry_pk_encrypt/decrypt function non-approved + +* src/fips.c (_gcry_fips_indicator_function): Fix typo in sign/verify + function names and add gcry_pk_encrypt and gcry_pk_decrypt. +-- + +Signed-off-by: Jakub Jelen +--- + src/fips.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/src/fips.c b/src/fips.c +index 9a524ea4..6599121c 100644 +--- a/src/fips.c ++++ b/src/fips.c +@@ -395,8 +395,10 @@ _gcry_fips_indicator_function (va_list arg_ptr) + { + const char *function = va_arg (arg_ptr, const char *); + +- if (strcmp (function, "gcry_sign") == 0 || +- strcmp (function, "gcry_verify") == 0) ++ if (strcmp (function, "gcry_pk_sign") == 0 || ++ strcmp (function, "gcry_pk_verify") == 0 || ++ strcmp (function, "gcry_pk_encrypt") == 0 || ++ strcmp (function, "gcry_pk_decrypt") == 0) + return GPG_ERR_NOT_SUPPORTED; + + return GPG_ERR_NO_ERROR; +-- +2.37.3 + +From f91a0ab12d242815f74bf26c6076e9cf7a790023 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Thu, 6 Oct 2022 09:30:24 +0200 +Subject: [PATCH] cipher: Do not run RSA encryption selftest by default + +* cipher/rsa.c (selftests_rsa): Skip encryption selftest as this + operation is not claimed as part of the certification. +--- + +Signed-off-by: Jakub Jelen +--- + cipher/rsa.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/cipher/rsa.c b/cipher/rsa.c +index 56dde3d1..df4af94b 100644 +--- a/cipher/rsa.c ++++ b/cipher/rsa.c +@@ -2169,10 +2169,13 @@ selftests_rsa (selftest_report_func_t report, int extended) + if (errtxt) + goto failed; + +- what = "encrypt"; +- errtxt = selftest_encr_2048 (pkey, skey); +- if (errtxt) +- goto failed; ++ if (extended) ++ { ++ what = "encrypt"; ++ errtxt = selftest_encr_2048 (pkey, skey); ++ if (errtxt) ++ goto failed; ++ } + + sexp_release (pkey); + sexp_release (skey); +-- +2.37.3 + diff --git a/SOURCES/libgcrypt-1.10.0-fips-x931.patch b/SOURCES/libgcrypt-1.10.0-fips-x931.patch new file mode 100644 index 0000000..b4a99ba --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-fips-x931.patch @@ -0,0 +1,139 @@ +From 06ea5b5332ffdb44a0a394d766be8989bcb6a95c Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 6 Dec 2022 10:03:47 +0900 +Subject: [PATCH] fips,rsa: Prevent usage of X9.31 keygen in FIPS mode. + +* cipher/rsa.c (rsa_generate): Do not accept use-x931 or derive-parms +in FIPS mode. +* tests/pubkey.c (get_keys_x931_new): Expect failure in FIPS mode. +(check_run): Skip checking X9.31 keys in FIPS mode. +* doc/gcrypt.texi: Document "test-parms" and clarify some cases around +the X9.31 keygen. + +-- + +Signed-off-by: Jakub Jelen +--- + cipher/rsa.c | 5 +++++ + doc/gcrypt.texi | 41 ++++++++++++++++++++++++++++++++++++----- + tests/pubkey.c | 15 +++++++++++++-- + 3 files changed, 54 insertions(+), 7 deletions(-) + +diff --git a/cipher/rsa.c b/cipher/rsa.c +index df4af94b..45523e6b 100644 +--- a/cipher/rsa.c ++++ b/cipher/rsa.c +@@ -1256,6 +1256,11 @@ rsa_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) + if (deriveparms || (flags & PUBKEY_FLAG_USE_X931)) + { + int swapped; ++ if (fips_mode ()) ++ { ++ sexp_release (deriveparms); ++ return GPG_ERR_INV_SEXP; ++ } + ec = generate_x931 (&sk, nbits, evalue, deriveparms, &swapped); + sexp_release (deriveparms); + if (!ec && swapped) +diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi +index d0372f3e..e845a4dd 100644 +--- a/doc/gcrypt.texi ++++ b/doc/gcrypt.texi +@@ -2699,8 +2699,7 @@ achieve fastest ECC key generation. + Force the use of the ANSI X9.31 key generation algorithm instead of + the default algorithm. This flag is only meaningful for RSA key + generation and usually not required. Note that this algorithm is +-implicitly used if either @code{derive-parms} is given or Libgcrypt is +-in FIPS mode. ++implicitly used if either @code{derive-parms} is given. + + @item use-fips186 + @cindex FIPS 186 +@@ -3310,9 +3309,9 @@ This is currently only implemented for RSA and DSA keys. It is not + allowed to use this together with a @code{domain} specification. If + given, it is used to derive the keys using the given parameters. + +-If given for an RSA key the X9.31 key generation algorithm is used +-even if libgcrypt is not in FIPS mode. If given for a DSA key, the +-FIPS 186 algorithm is used even if libgcrypt is not in FIPS mode. ++If given for an RSA key, the X9.31 key generation algorithm is used. ++If given for a DSA key, the FIPS 186 algorithm is used even if ++libgcrypt is not in FIPS mode. + + @example + (genkey +@@ -3342,6 +3341,38 @@ FIPS 186 algorithm is used even if libgcrypt is not in FIPS mode. + (seed @var{seed-mpi})))) + @end example + ++@item test-parms @var{list} ++This is currently only implemented for RSA keys. If given, the ++libgcrypt will not generate parameter, but tests whether the p,q is ++probably prime. Returns key with zeroes. ++ ++The FIPS key generation algorithm is used even if libgcrypt is not ++in FIPS mode. ++ ++@example ++(genkey ++ (rsa ++ (nbits 4:1024) ++ (rsa-use-e 1:3) ++ (test-parms ++ (e "65537") ++ (p #00bbccabcee15d343944a47e492d4b1f4de79633e2 ++ 0cbb46f7d2d6813392a807ad048cf77528edd19f77 ++ e7453f25173b9dcb70423afa2037aae147b81a33d5 ++ 41fc58f875eff1e852ab55e2e09a3debfbc151b3b0 ++ d17fef6f74d81fca14fbae531418e211ef818592af ++ 70de5cec3b92795cc3578572bf456099cd8727150e ++ 523261#) ++ (q #00ca87ecf2883f4ed00a9ec65abdeba81d28edbfcc ++ 34ecc563d587f166b52d42bfbe22bbc095b0b8426a ++ 2f8bbc55baaa8859b42cbc376ed3067db3ef7b135b ++ 63481322911ebbd7014db83aa051e0ca2dbf302b75 ++ cd37f2ae8df90e134226e92f6353a284b28bb30af0 ++ bbf925b345b955328379866ebac11d55bc80fe84f1 ++ 05d415#) ++ ++@end example ++ + + @item flags @var{flaglist} + This is preferred way to define flags. @var{flaglist} may contain any +diff --git a/tests/pubkey.c b/tests/pubkey.c +index bc44f3a5..2669b41a 100644 +--- a/tests/pubkey.c ++++ b/tests/pubkey.c +@@ -430,7 +430,17 @@ get_keys_x931_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); + if (rc) +- die ("error generating RSA key: %s\n", gcry_strerror (rc)); ++ { ++ if (in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, "The X9.31 RSA keygen is not available in FIPS modee.\n"); ++ return; ++ } ++ die ("error generating RSA key: %s\n", gcry_strerror (rc)); ++ } ++ else if (in_fips_mode) ++ die ("generating X9.31 RSA key unexpected worked in FIPS mode\n"); + + if (verbose > 1) + show_sexp ("generated RSA (X9.31) key:\n", key); +@@ -777,7 +787,8 @@ check_run (void) + if (verbose) + fprintf (stderr, "Checking generated RSA key (X9.31).\n"); + get_keys_x931_new (&pkey, &skey); +- check_keys (pkey, skey, 800, 0); ++ if (!in_fips_mode) ++ check_keys (pkey, skey, 800, 0); + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + pkey = skey = NULL; +-- +2.39.0 + diff --git a/SOURCES/libgcrypt-1.10.0-sha3-large.patch b/SOURCES/libgcrypt-1.10.0-sha3-large.patch new file mode 100644 index 0000000..d03407e --- /dev/null +++ b/SOURCES/libgcrypt-1.10.0-sha3-large.patch @@ -0,0 +1,621 @@ +From 2c1bb2f34f2812888f75c476037afae6d9e21798 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 23 Sep 2022 18:39:20 +0200 +Subject: [PATCH] keccak: Use size_t to avoid integer overflow + +Any input to the SHA3 functions > 4GB was giving wrong result when it +was invoked in one-shot, while working correctly when it was fed by +chunks. It turned out that the calculation in the `keccak_write` +overflows the `unsigned int` type (`nlanes * 8` does not fit 32b when +the `inlen` > 4GB). + +* cipher/keccak-armv7-neon.S: Fix function name in comment and change + parameter type to size_t +* cipher/keccak.c (keccak_ops_t): Change absorb function signature to + use size_t + (keccak_absorb_lanes64_avx512): Change nlanes type to size_t + (_gcry_keccak_absorb_lanes64_armv7_neon): Ditto. + (keccak_absorb_lanes64_armv7_neon): Ditto. + (keccak_absorb_lanes32bi): Ditto. + (keccak_absorb_lanes32bi_bmi2): Ditto. + (keccak_write): Change nlanes variable to use size_t and avoid + overflow when calculating count. +* cipher/keccak_permute_64.h (KECCAK_F1600_ABSORB_FUNC_NAME): Change + nlanes argument to use size_t. + +--- + +Signed-off-by: Jakub Jelen +--- + cipher/keccak-armv7-neon.S | 10 +++++----- + cipher/keccak.c | 20 ++++++++++---------- + cipher/keccak_permute_64.h | 2 +- + 3 files changed, 16 insertions(+), 16 deletions(-) + +diff --git a/cipher/keccak-armv7-neon.S b/cipher/keccak-armv7-neon.S +index 0bec8d50..28a284a1 100644 +--- a/cipher/keccak-armv7-neon.S ++++ b/cipher/keccak-armv7-neon.S +@@ -467,11 +467,11 @@ _gcry_keccak_permute_armv7_neon: + .ltorg + .size _gcry_keccak_permute_armv7_neon,.-_gcry_keccak_permute_armv7_neon; + +-@//unsigned _gcry_keccak_permute_armv7_neon(u64 *state, @r4 +-@ int pos, @r1 +-@ const byte *lanes, @r2 +-@ unsigned int nlanes, @r3 +-@ int blocklanes) @ r5 callable from C ++@//unsigned _gcry_keccak_absorb_lanes64_armv7_neon(u64 *state, @r4 ++@ int pos, @r1 ++@ const byte *lanes, @r2 ++@ size_t nlanes, @r3 ++@ int blocklanes) @ r5 callable from C + .p2align 3 + .global _gcry_keccak_absorb_lanes64_armv7_neon + .type _gcry_keccak_absorb_lanes64_armv7_neon,%function; +diff --git a/cipher/keccak.c b/cipher/keccak.c +index e7e42473..6c385f71 100644 +--- a/cipher/keccak.c ++++ b/cipher/keccak.c +@@ -131,7 +131,7 @@ typedef struct + { + unsigned int (*permute)(KECCAK_STATE *hd); + unsigned int (*absorb)(KECCAK_STATE *hd, int pos, const byte *lanes, +- unsigned int nlanes, int blocklanes); ++ size_t nlanes, int blocklanes); + unsigned int (*extract) (KECCAK_STATE *hd, unsigned int pos, byte *outbuf, + unsigned int outlen); + } keccak_ops_t; +@@ -513,7 +513,7 @@ static const keccak_ops_t keccak_avx512_64_ops = + unsigned int _gcry_keccak_permute_armv7_neon(u64 *state); + unsigned int _gcry_keccak_absorb_lanes64_armv7_neon(u64 *state, int pos, + const byte *lanes, +- unsigned int nlanes, ++ size_t nlanes, + int blocklanes); + + static unsigned int keccak_permute64_armv7_neon(KECCAK_STATE *hd) +@@ -523,7 +523,7 @@ static unsigned int keccak_permute64_armv7_neon(KECCAK_STATE *hd) + + static unsigned int + keccak_absorb_lanes64_armv7_neon(KECCAK_STATE *hd, int pos, const byte *lanes, +- unsigned int nlanes, int blocklanes) ++ size_t nlanes, int blocklanes) + { + if (blocklanes < 0) + { +@@ -571,7 +571,7 @@ static const keccak_ops_t keccak_armv7_neon_64_ops = + + static unsigned int + keccak_absorb_lanes32bi(KECCAK_STATE *hd, int pos, const byte *lanes, +- unsigned int nlanes, int blocklanes) ++ size_t nlanes, int blocklanes) + { + unsigned int burn = 0; + +@@ -653,7 +653,7 @@ keccak_absorb_lane32bi_bmi2(u32 *lane, u32 x0, u32 x1) + + static unsigned int + keccak_absorb_lanes32bi_bmi2(KECCAK_STATE *hd, int pos, const byte *lanes, +- unsigned int nlanes, int blocklanes) ++ size_t nlanes, int blocklanes) + { + unsigned int burn = 0; + +@@ -873,7 +873,8 @@ keccak_write (void *context, const void *inbuf_arg, size_t inlen) + const byte *inbuf = inbuf_arg; + unsigned int nburn, burn = 0; + unsigned int count, i; +- unsigned int pos, nlanes; ++ unsigned int pos; ++ size_t nlanes; + + #ifdef USE_S390X_CRYPTO + if (ctx->kimd_func) +@@ -918,8 +919,7 @@ keccak_write (void *context, const void *inbuf_arg, size_t inlen) + burn = nburn > burn ? nburn : burn; + inlen -= nlanes * 8; + inbuf += nlanes * 8; +- count += nlanes * 8; +- count = count % bsize; ++ count = ((size_t) count + nlanes * 8) % bsize; + } + + if (inlen) +diff --git a/cipher/keccak_permute_64.h b/cipher/keccak_permute_64.h +index b28c871e..45ef462f 100644 +--- a/cipher/keccak_permute_64.h ++++ b/cipher/keccak_permute_64.h +@@ -292,7 +292,7 @@ KECCAK_F1600_PERMUTE_FUNC_NAME(KECCAK_STATE *hd) + + static unsigned int + KECCAK_F1600_ABSORB_FUNC_NAME(KECCAK_STATE *hd, int pos, const byte *lanes, +- unsigned int nlanes, int blocklanes) ++ size_t nlanes, int blocklanes) + { + unsigned int burn = 0; + +-- +GitLab + + + +From 910dcbcef36e1cd3de3dde192d829a1513273e14 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +Date: Sun, 25 Sep 2022 22:23:22 +0300 +Subject: [PATCH] tests/hashtest: add hugeblock & disable-hwf options and 6 gig + test vectors + +* .gitignore: Add 'tests/hashtest-6g'. +* configure.ac: Add 'tests/hashtest-6g'. +* tests/Makefile: Add 'hashtest-6g'. +* tests/hashtest-6g.in: New. +* tests/hashtest-256g.in: Add SHA3-512 to algos. +* tests/hashtest.c (use_hugeblock): New. +(testvectors): Add 256 GiB test vectors for BLAKE2S, BLAKE2B and +whirlpool; Add 6 GiB test vectors for SHA1, SHA256, SHA512, SHA3, SM3, +BLAKE2S, BLAKE2B, WHIRLPOOL, CRC32 and CRC24. +(run_longtest); Use huge 5 GiB pattern block when requested. +(main): Add '--hugeblock' and '--disable-hwf' options. +* tests/testdrv.c: Add 'hashtest-6g'; Add SHA3 to 'hashtest-256g'. +--- + +Signed-off-by: Jussi Kivilinna +--- + .gitignore | 1 + + configure.ac | 1 + + tests/Makefile.am | 9 +- + tests/hashtest-256g.in | 2 +- + tests/hashtest-6g.in | 7 ++ + tests/hashtest.c | 249 +++++++++++++++++++++++++++++++++++++++-- + tests/testdrv.c | 7 +- + 7 files changed, 261 insertions(+), 15 deletions(-) + create mode 100644 tests/hashtest-6g.in + +diff --git a/configure.ac b/configure.ac +index c8f24dcc..c39257b5 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3511,6 +3511,7 @@ src/libgcrypt.pc + src/versioninfo.rc + tests/Makefile + ]) ++AC_CONFIG_FILES([tests/hashtest-6g], [chmod +x tests/hashtest-6g]) + AC_CONFIG_FILES([tests/hashtest-256g], [chmod +x tests/hashtest-256g]) + AC_CONFIG_FILES([tests/basic-disable-all-hwf], [chmod +x tests/basic-disable-all-hwf]) + AC_OUTPUT +diff --git a/tests/Makefile.am b/tests/Makefile.am +index 302d923b..75aa5cf7 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -44,13 +44,14 @@ tests_bin_last = benchmark bench-slope + + tests_sh = basic-disable-all-hwf + +-tests_sh_last = hashtest-256g ++tests_sh_last = hashtest-6g hashtest-256g + + TESTS = $(tests_bin) $(tests_sh) $(tests_bin_last) $(tests_sh_last) + + # Force sequential run of some tests. + bench-slope.log: benchmark.log +-hashtest-256g.log: bench-slope.log ++hashtest-6g.log: bench-slope.log ++hashtest-256g.log: hashtest-6g.log + + + TESTS_ENVIRONMENT = GCRYPT_IN_REGRESSION_TEST=1 +@@ -76,8 +77,8 @@ CLEANFILES = testdrv-build + EXTRA_DIST = README rsa-16k.key \ + pkcs1v2-oaep.h pkcs1v2-pss.h pkcs1v2-v15c.h pkcs1v2-v15s.h \ + t-ed25519.inp t-ed448.inp t-dsa.inp t-ecdsa.inp t-rsa-15.inp \ +- t-rsa-pss.inp stopwatch.h hashtest-256g.in sha3-224.h \ +- sha3-256.h sha3-384.h sha3-512.h blake2b.h blake2s.h \ ++ t-rsa-pss.inp stopwatch.h hashtest-6g.in hashtest-256g.in \ ++ sha3-224.h sha3-256.h sha3-384.h sha3-512.h blake2b.h blake2s.h \ + basic-disable-all-hwf.in basic_all_hwfeature_combinations.sh + + LDADD = $(standard_ldadd) $(GPG_ERROR_LIBS) @LDADD_FOR_TESTS_KLUDGE@ +diff --git a/tests/hashtest-256g.in b/tests/hashtest-256g.in +index a52b8692..44b69897 100755 +--- a/tests/hashtest-256g.in ++++ b/tests/hashtest-256g.in +@@ -1,6 +1,6 @@ + #!/bin/sh + +-algos="SHA1 SHA256 SHA512 SM3" ++algos="SHA1 SHA256 SHA512 SHA3-512 SM3" + + test "@RUN_LARGE_DATA_TESTS@" = yes || exit 77 + echo " now running 256 GiB tests for $algos - this takes looong" +diff --git a/tests/hashtest-6g.in b/tests/hashtest-6g.in +new file mode 100644 +index 00000000..b3f3e2ff +--- /dev/null ++++ b/tests/hashtest-6g.in +@@ -0,0 +1,7 @@ ++#!/bin/sh ++ ++algos="SHA1 SHA256 SHA512 SHA3-512 SM3 BLAKE2S_256 BLAKE2B_512 CRC32 CRC24RFC2440" ++ ++test "@RUN_LARGE_DATA_TESTS@" = yes || exit 77 ++echo " now running 6 GiB tests for $algos - this can take long" ++exec ./hashtest@EXEEXT@ --hugeblock --gigs 6 $algos +diff --git a/tests/hashtest.c b/tests/hashtest.c +index 4c9704f3..9389e50c 100644 +--- a/tests/hashtest.c ++++ b/tests/hashtest.c +@@ -34,6 +34,7 @@ + #define PGM "hashtest" + #include "t-common.h" + ++static int use_hugeblock; + static int missing_test_vectors; + + static struct { +@@ -113,6 +114,169 @@ static struct { + { GCRY_MD_SM3, 256, +64, + "ed34869dbadd62e3bec1f511004d7bbfc9cafa965477cc48843b248293bbe867" }, + ++ { GCRY_MD_BLAKE2S_256, 256, -64, ++ "8a3d4f712275e8e8da70c76501cce364c75f8dd09748be58cf63c9ce38d62627" }, ++ { GCRY_MD_BLAKE2S_256, 256, -1, ++ "0c01c9ad1e60e27dc889f2c9034a949ca8b9a9dc90dd99be64963af306d47b92" }, ++ { GCRY_MD_BLAKE2S_256, 256, +0, ++ "f8c43d5c4bad93aca702c8c466987c5ac5e640a29b37dd9904252ff27b2348a0" }, ++ { GCRY_MD_BLAKE2S_256, 256, +1, ++ "24c34b167b4eea1a7eb7d572ff3cf669a9856ea91bb112e9ef2ccd4b1aceccb4" }, ++ { GCRY_MD_BLAKE2S_256, 256, +64, ++ "2f8d754f98e2d4ed7744389f89d0bdb9b770c9fa215b8badd3129ea1364af867" }, ++ ++ { GCRY_MD_BLAKE2B_512, 256, -64, ++ "36d32ae4deeacab4119401c52e2aec5545675bd2dce4f67871ddc73671a05f94" ++ "e8332c2a31f32f5601878606a571aa7b43029dac3ae71cf9ef141d05651dc4bf" }, ++ { GCRY_MD_BLAKE2B_512, 256, -1, ++ "b5dc439f51664a6c9cbc87e2de98ce608ac4064a779e5140909d75d2120c9b2a" ++ "a1d4ae7be9c1ba97025be91ddcfbe42c791c3231cffbfa4b5368ba18f9590e1b" }, ++ { GCRY_MD_BLAKE2B_512, 256, +0, ++ "c413d011ba9abbf118dd96bfc827f5fd94493d8350df9f7aff834faace5adba2" ++ "0c3037069dfb2c81718ffc7b418ce1c1320d334b6fe8cddfb5d2dd19eb530853" }, ++ { GCRY_MD_BLAKE2B_512, 256, +1, ++ "b6dfb821f1c8167fb33995c29485010da56abd539c3d04ab9c222844301b8bba" ++ "6f57a48e45a748e40847084b93f26706aae82212550671c736becffcc6fb1496" }, ++ { GCRY_MD_BLAKE2B_512, 256, +64, ++ "8c21316a4a02044e302d503d0fe669d905c40d9d80ecd5aafc8e30f1df06736f" ++ "51fdaf6002160bb8fe4e868eaad9623fc5ecdd728bcbfee4a19b386503710f48" }, ++ ++ { GCRY_MD_WHIRLPOOL, 256, -64, ++ "aabf62344c1aa82d2dc7605f339b3571d540f1f320f97e6a8c0229645ee61f1f" ++ "da796acde2f96caa1c56eb2c2f9a6029a6242ad690479def66feac44334cc3af" }, ++ { GCRY_MD_WHIRLPOOL, 256, -1, ++ "9a35ec14aa9cefd40e04295d45d39f3111a98c2d76d90c54a7d2b8f2f5b9302b" ++ "79663eab6b6674625c3ae3e4b5dbb3b0a2f5b2f49a7a59cd1723e2b16a3efea2" }, ++ { GCRY_MD_WHIRLPOOL, 256, +0, ++ "818ad31a5110b6217cc6ffa099d554aaadc9566bf5291e104a5d58b21d51ae4d" ++ "c216c6de888d1359066c584e24e6606f530a3fce80ef78aed8564de4a28801c8" }, ++ { GCRY_MD_WHIRLPOOL, 256, +1, ++ "298805f5fc68488712427c1bcb27581d91aa04337c1c6b4657489ed3d239bb8b" ++ "c70ef654065d380ac1f5596aca5cb59e6da8044b5a067e32ea4cd94ca606f9f3" }, ++ { GCRY_MD_WHIRLPOOL, 256, +64, ++ "7bd35c3bee621bc0fb8907904b3b84d6cf4fae4c22cc64fbc744c8c5c8de806d" ++ "0f11a27892d531dc907426597737762c83e3ddcdc62f50d16d130aaefaeec436" }, ++ ++ { GCRY_MD_SHA1, 6, -64, ++ "eeee82d952403313bd63d6d7c8e342df0a1eea77" }, ++ { GCRY_MD_SHA1, 6, -1, ++ "8217b9f987d67db5880bcfff1d6763a6514d629f" }, ++ { GCRY_MD_SHA1, 6, +0, ++ "2b38aa63c05668217e5331320a4aee0adad7fc3b" }, ++ { GCRY_MD_SHA1, 6, +1, ++ "f3222de4d0704554cff0a537bc95b30f15daa94f" }, ++ { GCRY_MD_SHA1, 6, +64, ++ "b3bdd8065bb92d8208d55d28fad2281c6fbf2601" }, ++ ++ { GCRY_MD_SHA256, 6, -64, ++ "a2d5add5be904b70d6ef9bcd5feb9c6cfc2be0799732a122d9eccb576ff5a922" }, ++ { GCRY_MD_SHA256, 6, -1, ++ "88293b7e0e5a47fdef1148c6e510f95272770db6b5296958380209ba57db7a5d" }, ++ { GCRY_MD_SHA256, 6, +0, ++ "ccee8e8dfc366eba67471e49c45057b0041be0d2206c6de1aa765ce07ecfc434" }, ++ { GCRY_MD_SHA256, 6, +1, ++ "f4a89e92b38e0e61ee17079dc31411de06cfe1f77c83095ae1a2e7aa0205d94b" }, ++ { GCRY_MD_SHA256, 6, +64, ++ "338708608c2356ed2927a85b08fe745223c6140243fb3a87f309e12b31b946a8" }, ++ ++ { GCRY_MD_SHA512, 6, -64, ++ "658f52850932633c00b2f1d65b874c540ab84e2c0fe84a8a6c35f8e90e6f6a9c" ++ "2f7e0ccca5064783562a42ad8f47eab48687aaf6998b04ee94441e82c14e834d" }, ++ { GCRY_MD_SHA512, 6, -1, ++ "9ead6d66b46a3a72d77c7990874cfebc1575e5bfda6026430d76b3db6cc62d52" ++ "4ca0dd2674b9c24208b2e780d75542572eee8df6724acadcc23a03eed8f82f0a" }, ++ { GCRY_MD_SHA512, 6, +0, ++ "03e4549eb28bd0fb1606c321f1498503b5e889bec8d799cf0688567c7f8ac0d9" ++ "a7ec4e84d1d729d6a359797656e286617c3ef82abb51991bb576aaf05f7b6573" }, ++ { GCRY_MD_SHA512, 6, +1, ++ "ffe52f6385ccde6fa7d45845787d8f9993fdcb5833fb58b13c424a84e39ea50f" ++ "52d40e254fe667cb0104ffe3837dc8d0eee3c81721cb8eac10d5851dfb1f91db" }, ++ { GCRY_MD_SHA512, 6, +64, ++ "4a19da3d5eaaa79ac1eaff5e4062f23ee56573411f8d302f7bf3c6da8779bd00" ++ "a936e9ad7f535597a49162ed308b0cced7724667f97a1bb24540152fcfe3ec95" }, ++ ++ { GCRY_MD_SHA3_512, 6, -64, ++ "a99f2913d3beb9b45273402e30daa4d25c7a5e9eb8cf6039996eb2292a45c04c" ++ "b9e3a1a187f71920626f465ed6cf7dc34047ec5578e05516374bb9c56683903a" }, ++ { GCRY_MD_SHA3_512, 6, -1, ++ "fca50bde79c55e5fc4c9d97e66eb5cfacef7032395848731e645ca42f07f8d38" ++ "be1d593727c2a82b9a9bc058ebc9744971f867fa920cfa902023448243ac017b" }, ++ { GCRY_MD_SHA3_512, 6, +0, ++ "c61bb345c0a553edaa89fd38114ac9799b6d307ba8e3cde53552ad4c77cfe4b7" ++ "2671d82c1519c8e7b23153a9268e2939239564fc7c2060608aa42955e938840d" }, ++ { GCRY_MD_SHA3_512, 6, +1, ++ "502a83d8d1b977312806382a45c1cc9c0e7db437ca962e37eb181754d59db686" ++ "14d91df286d510411adf69f7c9befc1027bdc0c33a48a5dd6ae0957b9061e7ca" }, ++ { GCRY_MD_SHA3_512, 6, +64, ++ "207bfb83ae788ddd4531188567f0892bbddbbc88d69bc196b2357bee3e668706" ++ "c27f832ecb50e9ae5b63e9f384bdc37373958d4a14f3825146d2f6b1a65d8e51" }, ++ ++ { GCRY_MD_SM3, 6, -64, ++ "41d96d19cef4c942b0f5f4cdc3e1afe440dc62c0bc103a2c0e9eee9e1733a74a" }, ++ { GCRY_MD_SM3, 6, -1, ++ "b7689cc4ef6c7dc795b9e5e6998e5cc3dc1daec02bc1181cdbef8d6812b4957a" }, ++ { GCRY_MD_SM3, 6, +0, ++ "c6eae4a82052423cf98017bde4dee8769947c66120a1a2ff79f0f0dc945a3272" }, ++ { GCRY_MD_SM3, 6, +1, ++ "f6590f161fee11529585c7a9dfc725f8b81951e49b616844097a3dbdc9ffdbec" }, ++ { GCRY_MD_SM3, 6, +64, ++ "f3277fa90c47afe5e4fc52374aadf8e96bc29c2b5a7a4ebf5d704245ada837ea" }, ++ ++ { GCRY_MD_BLAKE2S_256, 6, -64, ++ "0f3c17610777c34d40a0d11a93d5e5ed444ce16edefebabd0bc8e30392d5c2db" }, ++ { GCRY_MD_BLAKE2S_256, 6, -1, ++ "92cbcf142c45de9d64da9791c51dce4e32b58f74d9f3d201b1ea74deac765f51" }, ++ { GCRY_MD_BLAKE2S_256, 6, +0, ++ "b20702cb5a0bee2ab104f38eb513429589310a7edde81dd1f40043be7d16d0de" }, ++ { GCRY_MD_BLAKE2S_256, 6, +1, ++ "bfc17dc74930989841da05aac08402bf0dcb4a597b17c52402a516ea7e541cdf" }, ++ { GCRY_MD_BLAKE2S_256, 6, +64, ++ "d85588cdf5a00bec1327da02f22f1a10b68dd9d6b730f30a3aa65af3a51c1722" }, ++ ++ { GCRY_MD_BLAKE2B_512, 6, -64, ++ "30b6015f94524861b04b83f0455be10a993460e0f8f0fd755fc3d0270b0c7d00" ++ "039a6e01684ce0689ce4ef70932bd19a676acf4b4ea521c30337d2f445fc2055" }, ++ { GCRY_MD_BLAKE2B_512, 6, -1, ++ "49abef820ad7fc5e6ed9b63acddce639a69dcd749b0798b140216649bc3b927c" ++ "637dbe1cb39a41bbafe7f8b675401ccdcf69a7fba227ae4cda5cd28b9ff36776" }, ++ { GCRY_MD_BLAKE2B_512, 6, +0, ++ "4182a7307a89391b78af9dbc3ba1e8d643708abbed5919086aa6e2bc65ae9597" ++ "e40229450c86ac5d3117b006427dd0131f5ae4c1a1d64c81420d2731536c81d8" }, ++ { GCRY_MD_BLAKE2B_512, 6, +1, ++ "33c0d9e65b1b18e9556134a08c1e725c19155bbf6ed4349d7d6d678f1827fef3" ++ "74b6e3381471f3d3fff7ffbcb9474ce9038143b99e25cd5f8afbb336313d4648" }, ++ { GCRY_MD_BLAKE2B_512, 6, +64, ++ "d2d7f388611af78a2ea40b06f99993cff156afd25cbc47695bdb567d4d35b992" ++ "0ff8c325c359a2bdeddf54ececc671ac7b981031e90a7d63d6e0415ec4484282" }, ++ ++ { GCRY_MD_WHIRLPOOL, 6, -64, ++ "247707d1f9cf31b90ee68527144b1c20ad5ce96293bdccd1a81c8f40bc9df10c" ++ "e7441ac3b3097162d6fbf4d4b67b8fa09de451e2d920f16aad78c47ab00cb833" }, ++ { GCRY_MD_WHIRLPOOL, 6, -1, ++ "af49e4a553bdbec1fdafc41713029e0fb1666894753c0ab3ecb280fc5af6eff8" ++ "253120745a229d7a8b5831711e4fd16ed0741258504d8a47e2b42aa2f1886968" }, ++ { GCRY_MD_WHIRLPOOL, 6, +0, ++ "f269ffa424bc2aad2da654f01783fc9b2b431219f2b05784d718da0935e78792" ++ "9207b000ebbfb63dfdcc8adf8e5bd321d9616c1b8357430b9be6cb4640df8609" }, ++ { GCRY_MD_WHIRLPOOL, 6, +1, ++ "52b77eb13129151b69b63c09abb655dc9cb046cafd4cbf7d4a82ae04b61ef9e6" ++ "531dde04cae7c5ab400ed8ee8da2e3f490d177289b2b3aa29b12b292954b902c" }, ++ { GCRY_MD_WHIRLPOOL, 6, +64, ++ "60a950c92f3f08abbc81c41c86ce0463679ffd5ab420e988e15b210615b454ae" ++ "69607d14a1806fa44aacf8c926fbdcee998af46f56e0c642d3fb4ee54c8fb917" }, ++ ++ { GCRY_MD_CRC32, 6, -64, "20739052" }, ++ { GCRY_MD_CRC32, 6, -1, "971a5a74" }, ++ { GCRY_MD_CRC32, 6, +0, "bf48113c" }, ++ { GCRY_MD_CRC32, 6, +1, "c7678ad5" }, ++ { GCRY_MD_CRC32, 6, +64, "1efa7255" }, ++ ++ { GCRY_MD_CRC24_RFC2440, 6, -64, "747e81" }, ++ { GCRY_MD_CRC24_RFC2440, 6, -1, "deb97d" }, ++ { GCRY_MD_CRC24_RFC2440, 6, +0, "7d5bea" }, ++ { GCRY_MD_CRC24_RFC2440, 6, +1, "acc351" }, ++ { GCRY_MD_CRC24_RFC2440, 6, +64, "9d9032" }, ++ + { 0 } + }; + +@@ -251,12 +415,38 @@ run_longtest (int algo, int gigs) + gcry_md_hd_t hd_post = NULL; + gcry_md_hd_t hd_post2 = NULL; + char pattern[1024]; +- int i, g; ++ char *hugepattern = NULL; ++ size_t hugesize; ++ size_t hugegigs; ++ int i, g, gppos, gptot; + const unsigned char *digest; + unsigned int digestlen; + + memset (pattern, 'a', sizeof pattern); + ++ if (use_hugeblock) ++ { ++ hugegigs = 5; ++ if (sizeof(size_t) >= 8) ++ { ++ hugesize = hugegigs*1024*1024*1024; ++ hugepattern = malloc(hugesize); ++ if (hugepattern != NULL) ++ memset(hugepattern, 'a', hugesize); ++ else ++ show_note ("failed to allocate %d GiB huge pattern block: %s", ++ hugegigs, strerror(errno)); ++ } ++ else ++ show_note ("cannot allocate %d GiB huge pattern block on 32-bit system", ++ hugegigs); ++ } ++ if (hugepattern == NULL) ++ { ++ hugegigs = 0; ++ hugesize = 0; ++ } ++ + err = gcry_md_open (&hd, algo, 0); + if (err) + { +@@ -267,9 +457,17 @@ run_longtest (int algo, int gigs) + + digestlen = gcry_md_get_algo_dlen (algo); + +- +- for (g=0; g < gigs; g++) ++ gppos = 0; ++ gptot = 0; ++ for (g=0; g < gigs; ) + { ++ if (gppos >= 16) ++ { ++ gptot += 16; ++ gppos -= 16; ++ show_note ("%d GiB so far hashed with %s", gptot, ++ gcry_md_algo_name (algo)); ++ } + if (g == gigs - 1) + { + for (i = 0; i < 1024*1023; i++) +@@ -283,16 +481,24 @@ run_longtest (int algo, int gigs) + die ("gcry_md_copy failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + gcry_md_write (hd, pattern, sizeof pattern); ++ g++; ++ gppos++; ++ } ++ else if (hugepattern != NULL && gigs - g > hugegigs) ++ { ++ gcry_md_write (hd, hugepattern, hugesize); ++ g += hugegigs; ++ gppos += hugegigs; + } + else + { + for (i = 0; i < 1024*1024; i++) + gcry_md_write (hd, pattern, sizeof pattern); ++ g++; ++ gppos++; + } +- if (g && !(g % 16)) +- show_note ("%d GiB so far hashed with %s", g, gcry_md_algo_name (algo)); + } +- if (g >= 16) ++ if (g >= 16 && gppos) + show_note ("%d GiB hashed with %s", g, gcry_md_algo_name (algo)); + + err = gcry_md_copy (&hd_post, hd); +@@ -335,6 +541,8 @@ run_longtest (int algo, int gigs) + gcry_md_close (hd_pre2); + gcry_md_close (hd_post); + gcry_md_close (hd_post2); ++ ++ free(hugepattern); + } + + +@@ -361,9 +569,12 @@ main (int argc, char **argv) + { + fputs ("usage: " PGM " [options] [algos]\n" + "Options:\n" +- " --verbose print timings etc.\n" +- " --debug flyswatter\n" +- " --gigs N Run a test on N GiB\n", ++ " --verbose print timings etc.\n" ++ " --debug flyswatter\n" ++ " --hugeblock Use 5 GiB pattern block\n" ++ " --gigs N Run a test on N GiB\n" ++ " --disable-hwf Disable hardware acceleration feature(s)\n" ++ " for benchmarking.\n", + stdout); + exit (0); + } +@@ -378,6 +589,11 @@ main (int argc, char **argv) + debug++; + argc--; argv++; + } ++ else if (!strcmp (*argv, "--hugeblock")) ++ { ++ use_hugeblock = 1; ++ argc--; argv++; ++ } + else if (!strcmp (*argv, "--gigs")) + { + argc--; argv++; +@@ -387,6 +603,21 @@ main (int argc, char **argv) + argc--; argv++; + } + } ++ else if (!strcmp (*argv, "--disable-hwf")) ++ { ++ argc--; ++ argv++; ++ if (argc) ++ { ++ if (gcry_control (GCRYCTL_DISABLE_HWF, *argv, NULL)) ++ fprintf (stderr, ++ PGM ++ ": unknown hardware feature `%s' - option ignored\n", ++ *argv); ++ argc--; ++ argv++; ++ } ++ } + else if (!strncmp (*argv, "--", 2)) + die ("unknown option '%s'", *argv); + } +diff --git a/tests/testdrv.c b/tests/testdrv.c +index 0ccde326..bfca4c23 100644 +--- a/tests/testdrv.c ++++ b/tests/testdrv.c +@@ -78,7 +78,12 @@ static struct { + { "t-ed448" }, + { "benchmark" }, + { "bench-slope" }, +- { "hashtest-256g", "hashtest", "--gigs 256 SHA1 SHA256 SHA512 SM3", ++ { "hashtest-6g", "hashtest", "--hugeblock --gigs 6 SHA1 SHA256 SHA512 " ++ "SHA3-512 SM3 BLAKE2S_256 " ++ "BLAKE2B_512 CRC32 " ++ "CRC24RFC2440", ++ LONG_RUNNING }, ++ { "hashtest-256g", "hashtest", "--gigs 256 SHA1 SHA256 SHA512 SHA3-512 SM3", + LONG_RUNNING }, + { NULL } + }; +-- +2.34.1 + +From 567bc62e1c3046594088de7209fee7c545ece1e3 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Fri, 30 Sep 2022 14:54:14 +0200 +Subject: [PATCH] tests: Avoid memory leak + +* tests/hashtest.c (run_longtest): Avoid memory leak on error +-- + +Signed-off-by: Jakub Jelen +--- + tests/hashtest.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/hashtest.c b/tests/hashtest.c +index 9389e50c..379f7c40 100644 +--- a/tests/hashtest.c ++++ b/tests/hashtest.c +@@ -452,6 +452,7 @@ run_longtest (int algo, int gigs) + { + fail ("gcry_md_open failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); ++ free(hugepattern); + return; + } + +-- +2.37.3 + diff --git a/SPECS/libgcrypt.spec b/SPECS/libgcrypt.spec index da99e44..7949727 100644 --- a/SPECS/libgcrypt.spec +++ b/SPECS/libgcrypt.spec @@ -16,19 +16,41 @@ print(string.sub(hash, 0, 16)) Name: libgcrypt Version: 1.10.0 -Release: 5%{?dist} +Release: 9%{?dist} URL: https://www.gnupg.org/ Source0: https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2 Source1: https://www.gnupg.org/ftp/gcrypt/libgcrypt/libgcrypt-%{version}.tar.bz2.sig Source2: wk@g10code.com Patch1: libgcrypt-1.10.0-disable-brainpool.patch -Patch2: libgcrypt-1.10.0-fips-disable-pkcs1.5.patch Patch3: libgcrypt-1.10.0-ppc-hwf.patch Patch4: libgcrypt-1.10.0-allow-small-RSA-verify.patch Patch5: libgcrypt-1.10.0-allow-short-salt.patch Patch6: libgcrypt-1.10.0-fips-getrandom.patch +# https://dev.gnupg.org/T6127 +# https://lists.gnupg.org/pipermail/gcrypt-devel/2022-September/005379.html Patch7: libgcrypt-1.10.0-fips-selftest.patch -Patch8: libgcrypt-1.10.0-fips-disable-oaep.patch +# https://dev.gnupg.org/T6217 +Patch9: libgcrypt-1.10.0-sha3-large.patch +# https://dev.gnupg.org/T5919 +Patch10: libgcrypt-1.10.0-fips-keygen.patch +# https://dev.gnupg.org/T6219 +# f4a861f3e5ae82f278284061e4829c03edf9c3a7 +Patch11: libgcrypt-1.10.0-fips-kdf.patch +# c34c9e70055ee43e5ef257384fa15941f064e5a4 +# https://gitlab.com/redhat-crypto/libgcrypt/libgcrypt-mirror/-/merge_requests/13 +Patch12: libgcrypt-1.10.0-fips-indicator.patch +# beb5d6df5c5785db7c32a24a5d2a351cb964bfbc +# 521500624b4b11538d206137205e2a511dad7072 +# 9dcf9305962b90febdf2d7cc73b49feadbf6a01f +# a340e980388243ceae6df57d101036f3f2a955be +Patch13: libgcrypt-1.10.0-fips-integrity.patch +# 3c8b6c4a9cad59c5e1db5706f6774a3141b60210 +# 052c5ef4cea56772b7015e36f231fa0bcbf91410 +Patch14: libgcrypt-1.10.0-fips-integrity2.patch +# 06ea5b5332ffdb44a0a394d766be8989bcb6a95c +Patch15: libgcrypt-1.10.0-fips-x931.patch +# bf1e62e59200b2046680d1d3d1599facc88cfe63 +Patch16: libgcrypt-1.10.0-fips-rsa-pss.patch %global gcrylibdir %{_libdir} %global gcrysoname libgcrypt.so.20 @@ -65,13 +87,19 @@ applications using libgcrypt. %prep %setup -q %patch1 -p1 -%patch2 -p1 %patch3 -p1 %patch4 -p1 %patch5 -p1 %patch6 -p1 %patch7 -p1 -%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 %build # This package has a configure test which uses ASMs, but does not link the @@ -98,6 +126,7 @@ autoreconf -f --enable-noexecstack \ --enable-hmac-binary-check=%{hmackey} \ --disable-brainpool \ + --disable-jent-support \ --enable-digests="$DIGESTS" \ --enable-ciphers="$CIPHERS" \ --with-fips-module-version="$FIPS_MODULE_NAME %{version}-%{srpmhash}" @@ -115,12 +144,12 @@ LIBGCRYPT_FORCE_FIPS_MODE=1 make check %{?__debug_package:%{__debug_install_post}} \ %{__arch_install_post} \ %{__os_install_post} \ - dd if=/dev/zero of=%{libpath}.hmac bs=32 count=1 \ - objcopy --update-section .rodata1=%{libpath}.hmac %{libpath} %{libpath}.empty \ - src/hmac256 --binary %{hmackey} %{libpath}.empty > %{libpath}.hmac \ - objcopy --update-section .rodata1=%{libpath}.hmac %{libpath}.empty %{libpath}.new \ + cd src \ + sed -i -e 's|FILE=.*|FILE=\\\$1|' gen-note-integrity.sh \ + READELF=readelf AWK=awk ECHO_N="-n" bash gen-note-integrity.sh %{libpath} > %{libpath}.hmac \ + objcopy --update-section .note.fdo.integrity=%{libpath}.hmac %{libpath} %{libpath}.new \ mv -f %{libpath}.new %{libpath} \ - rm -f %{libpath}.hmac %{libpath}.empty + rm -f %{libpath}.hmac %{nil} %install @@ -190,6 +219,30 @@ mkdir -p -m 755 $RPM_BUILD_ROOT/etc/gcrypt %license COPYING %changelog +* Tue Jan 24 2023 Jakub Jelen - 1.10.0-9 +- Avoid usage of invalid arguments sizes for PBKDF2 in FIPS mode +- Do not allow large salt lengths with RSA-PSS padding +- Disable X9.31 key generation in FIPS mode +- Update the FIPS integrity checking code to upstream version +- Update cipher modes FIPS indicators for AES WRAP and GCM +- Disable jitter entropy generator + +* Thu Oct 20 2022 Jakub Jelen - 1.10.0-8 +- Fix unneeded PBKDF2 passphrase length limitation in FIPS mode +- Enforce HMAC key lengths in MD API in FIPS mode + +* Thu Oct 06 2022 Jakub Jelen - 1.10.0-7 +- Properly enforce KDF limits in FIPS mode (#2130275) +- Fix memory leak in large digest test (#2129150) +- Fix function name FIPS service indicator by disabling PK encryption and decryption (#2130275) +- Skip RSA encryption/decryption selftest in FIPS mode (#2130275) + +* Tue Sep 27 2022 Jakub Jelen - 1.10.0-6 +- Fix SHA3 digests with large inputs (#2129150) +- Fix FIPS RSA PCT (#2128455) +- Fix RSA FIPS Keygen that non-deterministically fails (#2130275) +- Get max 32B from getrandom in FIPS mode (#2130275) + * Wed Aug 17 2022 Jakub Jelen - 1.10.0-5 - Allow signature verification with smaller RSA keys (#2083846) - Allow short salt for KDF (#2114870)