From 21fe8b5f7138176ed66a55bbc631bb1d405201a9 Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 13 Jul 2021 22:56:49 +0200 Subject: [PATCH] Aggregate FIPS test patches for upstream submission and backport whats already in --- libgcrypt-1.7.3-ecc-test-fix.patch | 122 -- libgcrypt-1.8.3-fips-ctor.patch | 13 + libgcrypt-1.8.3-md-fips-enforce.patch | 19 + libgcrypt-1.8.4-tests-fipsmode.patch | 198 --- libgcrypt-1.9.3-fips-tests.patch | 1804 +++++++++++++++++++++++++ libgcrypt.spec | 5 +- 6 files changed, 1837 insertions(+), 324 deletions(-) delete mode 100644 libgcrypt-1.7.3-ecc-test-fix.patch delete mode 100644 libgcrypt-1.8.4-tests-fipsmode.patch create mode 100644 libgcrypt-1.9.3-fips-tests.patch diff --git a/libgcrypt-1.7.3-ecc-test-fix.patch b/libgcrypt-1.7.3-ecc-test-fix.patch deleted file mode 100644 index 8ce7aa9..0000000 --- a/libgcrypt-1.7.3-ecc-test-fix.patch +++ /dev/null @@ -1,122 +0,0 @@ -diff -up libgcrypt-1.7.3/tests/benchmark.c.eccfix libgcrypt-1.7.3/tests/benchmark.c ---- libgcrypt-1.7.3/tests/benchmark.c.eccfix 2016-07-14 11:19:17.000000000 +0200 -+++ libgcrypt-1.7.3/tests/benchmark.c 2016-11-22 16:21:00.109004197 +0100 -@@ -1412,7 +1412,7 @@ ecc_bench (int iterations, int print_hea - { - #if USE_ECC - gpg_error_t err; -- const char *p_sizes[] = { "192", "224", "256", "384", "521", "Ed25519", -+ const char *p_sizes[] = { "224", "256", "384", "521", "Ed25519", - "gost256", "gost512" }; - int testno; - -diff -up libgcrypt-1.7.3/tests/dsa-rfc6979.c.eccfix libgcrypt-1.7.3/tests/dsa-rfc6979.c ---- libgcrypt-1.7.3/tests/dsa-rfc6979.c.eccfix 2016-02-18 09:38:03.000000000 +0100 -+++ libgcrypt-1.7.3/tests/dsa-rfc6979.c 2016-11-22 16:22:11.804674008 +0100 -@@ -210,16 +210,6 @@ check_dsa_rfc6979 (void) - " ))" - }, - { -- "ECDSA, 192 bits (prime field)", -- "(private-key" -- " (ecdsa" -- " (curve \"NIST P-192\")" -- " (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56" -- " 3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)" -- " (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)" -- " ))" -- }, -- { - "ECDSA, 224 bits (prime field)", - "(private-key" - " (ecdsa" -@@ -443,89 +433,6 @@ check_dsa_rfc6979 (void) - "C9F0BDABCC0D880BB137A994CC7F3980CE91CC10FAF529FC46565B15CEA854E1" - }, - { -- "ECDSA, 192 bits (prime field)", -- "With SHA-1, message = \"sample\"", -- "sha1", "sample", -- "37D7CA00D2C7B0E5E412AC03BD44BA837FDD5B28CD3B0021", -- "98C6BD12B23EAF5E2A2045132086BE3EB8EBD62ABF6698FF", -- "57A22B07DEA9530F8DE9471B1DC6624472E8E2844BC25B64" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-224, message = \"sample\"", -- "sha224", "sample", -- "4381526B3FC1E7128F202E194505592F01D5FF4C5AF015D8", -- "A1F00DAD97AEEC91C95585F36200C65F3C01812AA60378F5", -- "E07EC1304C7C6C9DEBBE980B9692668F81D4DE7922A0F97A" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-256, message = \"sample\"", -- "sha256", "sample", -- "32B1B6D7D42A05CB449065727A84804FB1A3E34D8F261496", -- "4B0B8CE98A92866A2820E20AA6B75B56382E0F9BFD5ECB55", -- "CCDB006926EA9565CBADC840829D8C384E06DE1F1E381B85" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-384, message = \"sample\"", -- "sha384", "sample", -- "4730005C4FCB01834C063A7B6760096DBE284B8252EF4311", -- "DA63BF0B9ABCF948FBB1E9167F136145F7A20426DCC287D5", -- "C3AA2C960972BD7A2003A57E1C4C77F0578F8AE95E31EC5E" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-512, message = \"sample\"", -- "sha512", "sample", -- "A2AC7AB055E4F20692D49209544C203A7D1F2C0BFBC75DB1", -- "4D60C5AB1996BD848343B31C00850205E2EA6922DAC2E4B8", -- "3F6E837448F027A1BF4B34E796E32A811CBB4050908D8F67" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-1, message = \"test\"", -- "sha1", "test", -- "D9CF9C3D3297D3260773A1DA7418DB5537AB8DD93DE7FA25", -- "0F2141A0EBBC44D2E1AF90A50EBCFCE5E197B3B7D4DE036D", -- "EB18BC9E1F3D7387500CB99CF5F7C157070A8961E38700B7" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-224, message = \"test\"", -- "sha224", "test", -- "F5DC805F76EF851800700CCE82E7B98D8911B7D510059FBE", -- "6945A1C1D1B2206B8145548F633BB61CEF04891BAF26ED34", -- "B7FB7FDFC339C0B9BD61A9F5A8EAF9BE58FC5CBA2CB15293" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-256, message = \"test\"", -- "sha256", "test", -- "5C4CE89CF56D9E7C77C8585339B006B97B5F0680B4306C6C", -- "3A718BD8B4926C3B52EE6BBE67EF79B18CB6EB62B1AD97AE", -- "5662E6848A4A19B1F1AE2F72ACD4B8BBE50F1EAC65D9124F" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-384, message = \"test\"", -- "sha384", "test", -- "5AFEFB5D3393261B828DB6C91FBC68C230727B030C975693", -- "B234B60B4DB75A733E19280A7A6034BD6B1EE88AF5332367", -- "7994090B2D59BB782BE57E74A44C9A1C700413F8ABEFE77A" -- }, -- { -- "ECDSA, 192 bits (prime field)", -- "With SHA-512, message = \"test\"", -- "sha512", "test", -- "0758753A5254759C7CFBAD2E2D9B0792EEE44136C9480527", -- "FE4F4AE86A58B6507946715934FE2D8FF9D95B6B098FE739", -- "74CF5605C98FBA0E1EF34D4B5A1577A7DCF59457CAE52290" -- }, -- -- -- -- { - "ECDSA, 224 bits (prime field)", - "With SHA-1, message = \"sample\"", - "sha1", "sample", diff --git a/libgcrypt-1.8.3-fips-ctor.patch b/libgcrypt-1.8.3-fips-ctor.patch index adecbe4..a5d3467 100644 --- a/libgcrypt-1.8.3-fips-ctor.patch +++ b/libgcrypt-1.8.3-fips-ctor.patch @@ -58,3 +58,16 @@ diff -up libgcrypt-1.8.3/src/global.c.fips-ctor libgcrypt-1.8.3/src/global.c _gcry_set_preferred_rng_type (0); _gcry_set_enforced_fips_mode (); } +diff --git a/tests/t-secmem.c b/tests/t-secmem.c +index 2b769134..1d33bbfd 100644 +--- a/tests/t-secmem.c ++++ b/tests/t-secmem.c +@@ -54,7 +54,7 @@ test_secmem (void) + + /* Allocating another 2k should fail for the default 16k pool. */ + b = gcry_malloc_secure (chunk_size*4); +- if (b) ++ if (b && !gcry_fips_mode_active ()) + fail ("allocation did not fail as expected\n"); + + for (i=0; i < DIM(a); i++) diff --git a/libgcrypt-1.8.3-md-fips-enforce.patch b/libgcrypt-1.8.3-md-fips-enforce.patch index eed7fa5..3b730a1 100644 --- a/libgcrypt-1.8.3-md-fips-enforce.patch +++ b/libgcrypt-1.8.3-md-fips-enforce.patch @@ -16,3 +16,22 @@ diff -up libgcrypt-1.8.3/cipher/md.c.fips-enforce libgcrypt-1.8.3/cipher/md.c err = GPG_ERR_DIGEST_ALGO; } } +diff --git a/tests/t-kdf.c b/tests/t-kdf.c +index 7a48e98a..48309b9a 100644 +--- a/tests/t-kdf.c ++++ b/tests/t-kdf.c +@@ -1104,6 +1104,13 @@ check_pbkdf2 (void) + GCRY_KDF_PBKDF2, tv[tvidx].hashalgo, + tv[tvidx].salt, tv[tvidx].saltlen, + tv[tvidx].c, tv[tvidx].dklen, outbuf); ++ if (gcry_fips_mode_active() && tvidx > 6) ++ { ++ if (!err) ++ fail ("pbkdf2 test %d unexpectedly passed in FIPS mode: %s\n", ++ tvidx, gpg_strerror (err)); ++ continue; ++ } + if (err) + fail ("pbkdf2 test %d failed: %s\n", tvidx, gpg_strerror (err)); + else if (memcmp (outbuf, tv[tvidx].dk, tv[tvidx].dklen)) + diff --git a/libgcrypt-1.8.4-tests-fipsmode.patch b/libgcrypt-1.8.4-tests-fipsmode.patch deleted file mode 100644 index fa235f8..0000000 --- a/libgcrypt-1.8.4-tests-fipsmode.patch +++ /dev/null @@ -1,198 +0,0 @@ -diff -up libgcrypt-1.8.4/tests/basic.c.tests-fipsmode libgcrypt-1.8.4/tests/basic.c ---- libgcrypt-1.8.4/tests/basic.c.tests-fipsmode 2018-04-17 17:29:40.000000000 +0200 -+++ libgcrypt-1.8.4/tests/basic.c 2019-02-12 13:30:48.935791024 +0100 -@@ -6964,7 +6964,7 @@ check_ciphers (void) - check_one_cipher (algos[i], GCRY_CIPHER_MODE_EAX, 0); - if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_CCM_BLOCK_LEN) - check_one_cipher (algos[i], GCRY_CIPHER_MODE_CCM, 0); -- if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_GCM_BLOCK_LEN) -+ if (!in_fips_mode && gcry_cipher_get_algo_blklen (algos[i]) == GCRY_GCM_BLOCK_LEN) - check_one_cipher (algos[i], GCRY_CIPHER_MODE_GCM, 0); - if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_OCB_BLOCK_LEN) - check_one_cipher (algos[i], GCRY_CIPHER_MODE_OCB, 0); -@@ -7010,12 +7010,18 @@ check_cipher_modes(void) - check_cfb_cipher (); - check_ofb_cipher (); - check_ccm_cipher (); -- check_gcm_cipher (); -- check_poly1305_cipher (); -- check_ocb_cipher (); -+ if (!in_fips_mode) -+ { -+ check_gcm_cipher (); -+ check_poly1305_cipher (); -+ check_ocb_cipher (); -+ } - check_xts_cipher (); - check_eax_cipher (); -- check_gost28147_cipher (); -+ if (!in_fips_mode) -+ { -+ check_gost28147_cipher (); -+ } - check_stream_cipher (); - check_stream_cipher_large_block (); - -@@ -10001,7 +10007,7 @@ check_mac (void) - show_mac_not_available (algos[i].algo); - continue; - } -- if (gcry_mac_test_algo (algos[i].algo) && in_fips_mode) -+ if ((algos[i].algo == GCRY_MAC_GMAC_AES || gcry_mac_test_algo (algos[i].algo)) && in_fips_mode) - { - if (verbose) - fprintf (stderr, " algorithm %d not available in fips mode\n", -@@ -11095,8 +11101,6 @@ main (int argc, char **argv) - /* If we are in fips mode do some more tests. */ - gcry_md_hd_t md; - -- /* First trigger a self-test. */ -- xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); - if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) - fail ("not in operational state after self-test\n"); - -@@ -11121,15 +11125,6 @@ main (int argc, char **argv) - gcry_md_close (md); - if (gcry_control (GCRYCTL_OPERATIONAL_P, 0)) - fail ("expected error state but still in operational state\n"); -- else -- { -- /* Now run a self-test and to get back into -- operational state. */ -- xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); -- if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) -- fail ("did not reach operational after error " -- "and self-test\n"); -- } - } - } - -diff -up libgcrypt-1.8.4/tests/benchmark.c.tests-fipsmode libgcrypt-1.8.4/tests/benchmark.c ---- libgcrypt-1.8.4/tests/benchmark.c.tests-fipsmode 2019-02-12 11:31:44.859603883 +0100 -+++ libgcrypt-1.8.4/tests/benchmark.c 2019-02-12 14:10:40.271999352 +0100 -@@ -872,8 +872,10 @@ cipher_bench ( const char *algoname ) - && algo != GCRY_CIPHER_CHACHA20) - continue; - -- if (modes[modeidx].req_blocksize > 0 -- && blklen != modes[modeidx].req_blocksize) -+ if ((modes[modeidx].req_blocksize > 0 -+ && blklen != modes[modeidx].req_blocksize) -+ || (in_fips_mode -+ && modes[modeidx].mode == GCRY_CIPHER_MODE_GCM)) - { - printf (" %7s %7s", "-", "-" ); - continue; -diff -up libgcrypt-1.8.4/tests/bench-slope.c.tests-fipsmode libgcrypt-1.8.4/tests/bench-slope.c ---- libgcrypt-1.8.4/tests/bench-slope.c.tests-fipsmode 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.4/tests/bench-slope.c 2019-02-12 14:14:33.618763325 +0100 -@@ -1338,7 +1338,7 @@ cipher_bench_one (int algo, struct bench - return; - - /* GCM has restrictions for block-size */ -- if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN) -+ if (mode.mode == GCRY_CIPHER_MODE_GCM && (gcry_fips_mode_active () || blklen != GCRY_GCM_BLOCK_LEN)) - return; - - /* XTS has restrictions for block-size */ -diff -up libgcrypt-1.8.4/tests/pubkey.c.tests-fipsmode libgcrypt-1.8.4/tests/pubkey.c ---- libgcrypt-1.8.4/tests/pubkey.c.tests-fipsmode 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.4/tests/pubkey.c 2019-02-12 13:52:25.658746415 +0100 -@@ -504,15 +504,30 @@ get_dsa_key_with_domain_new (gcry_sexp_t - rc = gcry_sexp_new - (&key_spec, - "(genkey (dsa (transient-key)(domain" -- "(p #d3aed1876054db831d0c1348fbb1ada72507e5fbf9a62cbd47a63aeb7859d6921" -- "4adeb9146a6ec3f43520f0fd8e3125dd8bbc5d87405d1ac5f82073cd762a3f8d7" -- "74322657c9da88a7d2f0e1a9ceb84a39cb40876179e6a76e400498de4bb9379b0" -- "5f5feb7b91eb8fea97ee17a955a0a8a37587a272c4719d6feb6b54ba4ab69#)" -- "(q #9c916d121de9a03f71fb21bc2e1c0d116f065a4f#)" -- "(g #8157c5f68ca40b3ded11c353327ab9b8af3e186dd2e8dade98761a0996dda99ab" -- "0250d3409063ad99efae48b10c6ab2bba3ea9a67b12b911a372a2bba260176fad" -- "b4b93247d9712aad13aa70216c55da9858f7a298deb670a403eb1e7c91b847f1e" -- "ccfbd14bd806fd42cf45dbb69cd6d6b43add2a78f7d16928eaa04458dea44#)" -+ " (p #a85378d8fd3f8d72ec7418080da21317e43ec4b62ba8c862" -+ " 3b7e4d04441dd1a0658662596493ca8e9e8fbb7e34aaddb6" -+ " 2e5d67b6d09a6e61b769e7c352aa2b10e20ca0636963b552" -+ " 3e86470decbbeda027e797e7b67635d4d49c30700e74af8a" -+ " 0ff156a801af57a26e7078f1d82f74908ecb6d07e70b3503" -+ " eed94fa32cf17a7fc3d6cf40dc7b00830e6a2566dc073e34" -+ " 3312517c6aa5152b4bfecd2e551fee346318a153423c996b" -+ " 0d5dcb9102aedd38798616f1f1e0d6c403525b1f9b3d4dc7" -+ " 66de2dfc4a56d7b8ba5963d60f3e16318870ad436952e557" -+ " 65374eab85e8ec17d6b9a4547b9b5f2752f3105be809b23a" -+ " 2c8d7469db02e24d592394a7dba069e9#)" -+ " (q #d277044e50f5a4e3f510a50a0b84fdffbca047ed27602056" -+ " 7441a0a5#)" -+ " (g #13d754e21fd241655da891c522a65a72a89bdc64ec9b54a8" -+ " 21ed4a898b490e0c4fcb72192a4a20f541f3f2925399f0ba" -+ " ecf929aafbf79dfe4332393b32cd2e2fcf272f32a627434a" -+ " 0df242b75b414df372121e53a553f222f836b000f016485b" -+ " 6bd0898451801dcd8de64cd5365696ffc532d528c506620a" -+ " 942a0305046d8f1876341f1e570bc3974ba6b9a438e97023" -+ " 02a2e6e67bfd06d32bc679962271d7b40cd72f386e64e0d7" -+ " ef86ca8ca5d14228dc2a4f16e3189886b5990674f4200f3a" -+ " 4cf65a3f0ddba1fa672dff2f5e143d10e4e97ae84f6da095" -+ " 35d5b9df259181a79b63b069e949972b02ba36b3586aab7e" -+ " 45f322f82e4e85ca3ab85591b3c2a966#)" - ")))", 0, 1); - if (rc) - die ("error creating S-expression: %s\n", gcry_strerror (rc)); -@@ -595,7 +610,7 @@ get_dsa_key_fips186_with_seed_new (gcry_ - " (use-fips186)" - " (transient-key)" - " (derive-parms" -- " (seed #f770a4598ff756931fc529764513b103ce57d85f4ad8c5cf297c9b4d48241c5b#))))", -+ " (seed #8b4c4d671fff82e8ed932260206d0571e3a1c2cee8cd94cb73fe58f9b67488fa#))))", - 0, 1); - if (rc) - die ("error creating S-expression: %s\n", gcry_strerror (rc)); -diff -up libgcrypt-1.8.4/tests/t-cv25519.c.tests-fipsmode libgcrypt-1.8.4/tests/t-cv25519.c ---- libgcrypt-1.8.4/tests/t-cv25519.c.tests-fipsmode 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.4/tests/t-cv25519.c 2019-02-12 14:02:35.935705390 +0100 -@@ -560,6 +560,9 @@ main (int argc, char **argv) - xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); - xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); - xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); -+ /* Curve25519 isn't supported in fips mode */ -+ if (gcry_fips_mode_active()) -+ return 77; - - start_timer (); - check_cv25519 (); -diff -up libgcrypt-1.8.4/tests/t-x448.c.tests-fipsmode libgcrypt-1.8.4/tests/t-x448.c ---- libgcrypt-1.8.4/tests/t-x448.c.tests-fipsmode 2017-11-23 19:16:58.000000000 +0100 -+++ libgcrypt-1.8.4/tests/t-x448.c 2019-02-12 14:02:35.935705390 +0100 -@@ -560,6 +560,9 @@ main (int argc, char **argv) - xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); - xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); - xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); -+ /* x448 isn't supported in fips mode */ -+ if (gcry_fips_mode_active()) -+ return 77; - - start_timer (); - check_x448 (); -diff -up libgcrypt-1.8.4/tests/t-secmem.c.tests-fipsmode libgcrypt-1.8.4/tests/t-secmem.c ---- libgcrypt-1.8.4/tests/t-secmem.c.tests-fipsmode 2017-11-23 19:19:54.000000000 +0100 -+++ libgcrypt-1.8.4/tests/t-secmem.c 2019-02-12 11:51:02.462190538 +0100 -@@ -174,7 +174,8 @@ main (int argc, char **argv) - xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); - xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); - xgcry_control ((GCRYCTL_INIT_SECMEM, pool_size, 0)); -- gcry_set_outofcore_handler (outofcore_handler, NULL); -+ if (!gcry_fips_mode_active ()) -+ gcry_set_outofcore_handler (outofcore_handler, NULL); - xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); - - /* Libgcrypt prints a warning when the first overflow is allocated; -@@ -184,7 +185,8 @@ main (int argc, char **argv) - - - test_secmem (); -- test_secmem_overflow (); -+ if (!gcry_fips_mode_active ()) -+ test_secmem_overflow (); - /* FIXME: We need to improve the tests, for example by registering - * our own log handler and comparing the output of - * PRIV_CTL_DUMP_SECMEM_STATS to expected pattern. */ diff --git a/libgcrypt-1.9.3-fips-tests.patch b/libgcrypt-1.9.3-fips-tests.patch new file mode 100644 index 0000000..1ddc64f --- /dev/null +++ b/libgcrypt-1.9.3-fips-tests.patch @@ -0,0 +1,1804 @@ +commit 57cf83834bc00a7431378aabda692bf700e4876c +Author: Jussi Kivilinna +Date: Sat Apr 17 17:06:40 2021 +0300 + + tests/bench-slope: add ECC benchmarking + + * tests/bench-slope.c (bench_print_result_nsec_per_iteration): New. + (bench_print_header_nsec_per_iteration): New. + (kdf_bench_one, kdf_bench): Use new print helper functions. + [USE_ECC]: New ECC benchmarks. + (ecc_bench): New. + (print_help): Add 'ecc' option. + (main): Add ECC benchmarks. + -- + + Signed-off-by: Jussi Kivilinna + +diff --git a/tests/bench-slope.c b/tests/bench-slope.c +index c8647b6b..9b4a139a 100644 +--- a/tests/bench-slope.c ++++ b/tests/bench-slope.c +@@ -783,6 +783,54 @@ bench_print_result (double nsecs_per_byte) + bench_print_result_std (nsecs_per_byte); + } + ++static void ++bench_print_result_nsec_per_iteration (double nsecs_per_iteration) ++{ ++ double cycles_per_iteration; ++ char nsecpiter_buf[16]; ++ char cpiter_buf[16]; ++ char mhz_buf[16]; ++ ++ strcpy(cpiter_buf, csv_mode ? "" : "-"); ++ strcpy(mhz_buf, csv_mode ? "" : "-"); ++ ++ double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration); ++ ++ /* If user didn't provide CPU speed, we cannot show cycles/iter results. */ ++ if (bench_ghz > 0.0) ++ { ++ cycles_per_iteration = nsecs_per_iteration * bench_ghz; ++ double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration); ++ double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); ++ } ++ ++ if (csv_mode) ++ { ++ if (auto_ghz) ++ printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n", ++ current_section_name, ++ current_algo_name ? current_algo_name : "", ++ current_mode_name ? current_mode_name : "", ++ nsecpiter_buf, ++ cpiter_buf, ++ mhz_buf); ++ else ++ printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n", ++ current_section_name, ++ current_algo_name ? current_algo_name : "", ++ current_mode_name ? current_mode_name : "", ++ nsecpiter_buf, ++ cpiter_buf); ++ } ++ else ++ { ++ if (auto_ghz) ++ printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf); ++ else ++ printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf); ++ } ++} ++ + static void + bench_print_section (const char *section_name, const char *print_name) + { +@@ -819,6 +867,28 @@ bench_print_header (int algo_width, const char *algo_name) + } + } + ++static void ++bench_print_header_nsec_per_iteration (int algo_width, const char *algo_name) ++{ ++ if (csv_mode) ++ { ++ gcry_free (current_algo_name); ++ current_algo_name = gcry_xstrdup (algo_name); ++ } ++ else ++ { ++ if (algo_width < 0) ++ printf (" %-*s | ", -algo_width, algo_name); ++ else ++ printf (" %-*s | ", algo_width, algo_name); ++ ++ if (auto_ghz) ++ printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz"); ++ else ++ printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter"); ++ } ++} ++ + static void + bench_print_algo (int algo_width, const char *algo_name) + { +@@ -1991,11 +2061,7 @@ kdf_bench_one (int algo, int subalgo) + struct bench_kdf_mode mode = { &kdf_ops }; + struct bench_obj obj = { 0 }; + double nsecs_per_iteration; +- double cycles_per_iteration; + char algo_name[32]; +- char nsecpiter_buf[16]; +- char cpiter_buf[16]; +- char mhz_buf[16]; + + mode.algo = algo; + mode.subalgo = subalgo; +@@ -2030,45 +2096,7 @@ kdf_bench_one (int algo, int subalgo) + obj.priv = &mode; + + nsecs_per_iteration = do_slope_benchmark (&obj); +- +- strcpy(cpiter_buf, csv_mode ? "" : "-"); +- strcpy(mhz_buf, csv_mode ? "" : "-"); +- +- double_to_str (nsecpiter_buf, sizeof (nsecpiter_buf), nsecs_per_iteration); +- +- /* If user didn't provide CPU speed, we cannot show cycles/iter results. */ +- if (bench_ghz > 0.0) +- { +- cycles_per_iteration = nsecs_per_iteration * bench_ghz; +- double_to_str (cpiter_buf, sizeof (cpiter_buf), cycles_per_iteration); +- double_to_str (mhz_buf, sizeof (mhz_buf), bench_ghz * 1000); +- } +- +- if (csv_mode) +- { +- if (auto_ghz) +- printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter,%s,Mhz\n", +- current_section_name, +- current_algo_name ? current_algo_name : "", +- current_mode_name ? current_mode_name : "", +- nsecpiter_buf, +- cpiter_buf, +- mhz_buf); +- else +- printf ("%s,%s,%s,,,,,,,,,%s,ns/iter,%s,c/iter\n", +- current_section_name, +- current_algo_name ? current_algo_name : "", +- current_mode_name ? current_mode_name : "", +- nsecpiter_buf, +- cpiter_buf); +- } +- else +- { +- if (auto_ghz) +- printf ("%14s %13s %9s\n", nsecpiter_buf, cpiter_buf, mhz_buf); +- else +- printf ("%14s %13s\n", nsecpiter_buf, cpiter_buf); +- } ++ bench_print_result_nsec_per_iteration (nsecs_per_iteration); + } + + void +@@ -2079,14 +2107,7 @@ kdf_bench (char **argv, int argc) + + bench_print_section ("kdf", "KDF"); + +- if (!csv_mode) +- { +- printf (" %-*s | ", 24, ""); +- if (auto_ghz) +- printf ("%14s %13s %9s\n", "nanosecs/iter", "cycles/iter", "auto Mhz"); +- else +- printf ("%14s %13s\n", "nanosecs/iter", "cycles/iter"); +- } ++ bench_print_header_nsec_per_iteration (24, ""); + + if (argv && argc) + { +@@ -2116,13 +2137,571 @@ kdf_bench (char **argv, int argc) + } + + ++/************************************************************ ECC benchmarks. */ ++ ++#if USE_ECC ++enum bench_ecc_algo ++{ ++ ECC_ALGO_ED25519 = 0, ++ ECC_ALGO_ED448, ++ ECC_ALGO_NIST_P192, ++ ECC_ALGO_NIST_P224, ++ ECC_ALGO_NIST_P256, ++ ECC_ALGO_NIST_P384, ++ ECC_ALGO_NIST_P521, ++ ECC_ALGO_SECP256K1, ++ __MAX_ECC_ALGO ++}; ++ ++enum bench_ecc_operation ++{ ++ ECC_OPER_MULT = 0, ++ ECC_OPER_KEYGEN, ++ ECC_OPER_SIGN, ++ ECC_OPER_VERIFY, ++ __MAX_ECC_OPER ++}; ++ ++struct bench_ecc_oper ++{ ++ enum bench_ecc_operation oper; ++ const char *name; ++ struct bench_ops *ops; ++ ++ enum bench_ecc_algo algo; ++}; ++ ++struct bench_ecc_mult_hd ++{ ++ gcry_ctx_t ec; ++ gcry_mpi_t k, x, y; ++ gcry_mpi_point_t G, Q; ++}; ++ ++struct bench_ecc_hd ++{ ++ gcry_sexp_t key_spec; ++ gcry_sexp_t data; ++ gcry_sexp_t pub_key; ++ gcry_sexp_t sec_key; ++ gcry_sexp_t sig; ++}; ++ ++ ++static const char * ++ecc_algo_name (int algo) ++{ ++ switch (algo) ++ { ++ case ECC_ALGO_ED25519: ++ return "Ed25519"; ++ case ECC_ALGO_ED448: ++ return "Ed448"; ++ case ECC_ALGO_NIST_P192: ++ return "NIST-P192"; ++ case ECC_ALGO_NIST_P224: ++ return "NIST-P224"; ++ case ECC_ALGO_NIST_P256: ++ return "NIST-P256"; ++ case ECC_ALGO_NIST_P384: ++ return "NIST-P384"; ++ case ECC_ALGO_NIST_P521: ++ return "NIST-P521"; ++ case ECC_ALGO_SECP256K1: ++ return "secp256k1"; ++ default: ++ return NULL; ++ } ++} ++ ++static const char * ++ecc_algo_curve (int algo) ++{ ++ switch (algo) ++ { ++ case ECC_ALGO_ED25519: ++ return "Ed25519"; ++ case ECC_ALGO_ED448: ++ return "Ed448"; ++ case ECC_ALGO_NIST_P192: ++ return "NIST P-192"; ++ case ECC_ALGO_NIST_P224: ++ return "NIST P-224"; ++ case ECC_ALGO_NIST_P256: ++ return "NIST P-256"; ++ case ECC_ALGO_NIST_P384: ++ return "NIST P-384"; ++ case ECC_ALGO_NIST_P521: ++ return "NIST P-521"; ++ case ECC_ALGO_SECP256K1: ++ return "secp256k1"; ++ default: ++ return NULL; ++ } ++} ++ ++static int ++ecc_nbits (int algo) ++{ ++ switch (algo) ++ { ++ case ECC_ALGO_ED25519: ++ return 255; ++ case ECC_ALGO_ED448: ++ return 448; ++ case ECC_ALGO_NIST_P192: ++ return 192; ++ case ECC_ALGO_NIST_P224: ++ return 224; ++ case ECC_ALGO_NIST_P256: ++ return 256; ++ case ECC_ALGO_NIST_P384: ++ return 384; ++ case ECC_ALGO_NIST_P521: ++ return 521; ++ case ECC_ALGO_SECP256K1: ++ return 256; ++ default: ++ return 0; ++ } ++} ++ ++static int ++ecc_map_name (const char *name) ++{ ++ int i; ++ ++ for (i = 0; i < __MAX_ECC_ALGO; i++) ++ { ++ if (strcmp(ecc_algo_name(i), name) == 0) ++ { ++ return i; ++ } ++ } ++ ++ return -1; ++} ++ ++ ++static int ++bench_ecc_mult_init (struct bench_obj *obj) ++{ ++ struct bench_ecc_oper *oper = obj->priv; ++ struct bench_ecc_mult_hd *hd; ++ int p_size = ecc_nbits (oper->algo); ++ gpg_error_t err; ++ gcry_mpi_t p; ++ ++ obj->min_bufsize = 1; ++ obj->max_bufsize = 4; ++ obj->step_size = 1; ++ obj->num_measure_repetitions = ++ num_measurement_repetitions / obj->max_bufsize; ++ ++ while (obj->num_measure_repetitions == 0) ++ { ++ if (obj->max_bufsize == 2) ++ { ++ obj->num_measure_repetitions = 2; ++ } ++ else ++ { ++ obj->max_bufsize--; ++ obj->num_measure_repetitions = ++ num_measurement_repetitions / obj->max_bufsize; ++ } ++ } ++ ++ hd = calloc (1, sizeof(*hd)); ++ if (!hd) ++ return -1; ++ ++ err = gcry_mpi_ec_new (&hd->ec, NULL, ecc_algo_curve(oper->algo)); ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_mpi_ec_new failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ hd->G = gcry_mpi_ec_get_point ("g", hd->ec, 1); ++ hd->Q = gcry_mpi_point_new (0); ++ hd->x = gcry_mpi_new (0); ++ hd->y = gcry_mpi_new (0); ++ hd->k = gcry_mpi_new (p_size); ++ gcry_mpi_randomize (hd->k, p_size, GCRY_WEAK_RANDOM); ++ p = gcry_mpi_ec_get_mpi ("p", hd->ec, 1); ++ gcry_mpi_mod (hd->k, hd->k, p); ++ gcry_mpi_release (p); ++ ++ obj->hd = hd; ++ return 0; ++} ++ ++static void ++bench_ecc_mult_free (struct bench_obj *obj) ++{ ++ struct bench_ecc_mult_hd *hd = obj->hd; ++ ++ gcry_mpi_release (hd->k); ++ gcry_mpi_release (hd->y); ++ gcry_mpi_release (hd->x); ++ gcry_mpi_point_release (hd->Q); ++ gcry_mpi_point_release (hd->G); ++ gcry_ctx_release (hd->ec); ++ free (hd); ++ obj->hd = NULL; ++} ++ ++static void ++bench_ecc_mult_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) ++{ ++ struct bench_ecc_mult_hd *hd = obj->hd; ++ size_t i; ++ ++ (void)buf; ++ ++ for (i = 0; i < num_iter; i++) ++ { ++ gcry_mpi_ec_mul (hd->Q, hd->k, hd->G, hd->ec); ++ if (gcry_mpi_ec_get_affine (hd->x, hd->y, hd->Q, hd->ec)) ++ { ++ fprintf (stderr, PGM ": gcry_mpi_ec_get_affine failed\n"); ++ exit (1); ++ } ++ } ++} ++ ++ ++static int ++bench_ecc_init (struct bench_obj *obj) ++{ ++ struct bench_ecc_oper *oper = obj->priv; ++ struct bench_ecc_hd *hd; ++ int p_size = ecc_nbits (oper->algo); ++ gpg_error_t err; ++ gcry_mpi_t x; ++ ++ obj->min_bufsize = 1; ++ obj->max_bufsize = 4; ++ obj->step_size = 1; ++ obj->num_measure_repetitions = ++ num_measurement_repetitions / obj->max_bufsize; ++ ++ while (obj->num_measure_repetitions == 0) ++ { ++ if (obj->max_bufsize == 2) ++ { ++ obj->num_measure_repetitions = 2; ++ } ++ else ++ { ++ obj->max_bufsize--; ++ obj->num_measure_repetitions = ++ num_measurement_repetitions / obj->max_bufsize; ++ } ++ } ++ ++ hd = calloc (1, sizeof(*hd)); ++ if (!hd) ++ return -1; ++ ++ x = gcry_mpi_new (p_size); ++ gcry_mpi_randomize (x, p_size, GCRY_WEAK_RANDOM); ++ ++ switch (oper->algo) ++ { ++ default: ++ return -1; ++ ++ case ECC_ALGO_ED25519: ++ err = gcry_sexp_build (&hd->key_spec, NULL, ++ "(genkey (ecdsa (curve \"Ed25519\")" ++ "(flags eddsa)))"); ++ if (err) ++ break; ++ err = gcry_sexp_build (&hd->data, NULL, ++ "(data (flags eddsa)(hash-algo sha512)" ++ " (value %m))", x); ++ break; ++ ++ case ECC_ALGO_ED448: ++ err = gcry_sexp_build (&hd->key_spec, NULL, ++ "(genkey (ecdsa (curve \"Ed448\")" ++ "(flags eddsa)))"); ++ if (err) ++ break; ++ err = gcry_sexp_build (&hd->data, NULL, ++ "(data (flags eddsa)(hash-algo shake256)" ++ " (value %m))", x); ++ break; ++ ++ case ECC_ALGO_NIST_P192: ++ case ECC_ALGO_NIST_P224: ++ case ECC_ALGO_NIST_P256: ++ case ECC_ALGO_NIST_P384: ++ case ECC_ALGO_NIST_P521: ++ err = gcry_sexp_build (&hd->key_spec, NULL, ++ "(genkey (ECDSA (nbits %d)))", p_size); ++ if (err) ++ break; ++ err = gcry_sexp_build (&hd->data, NULL, ++ "(data (flags raw) (value %m))", x); ++ break; ++ } ++ ++ gcry_mpi_release (x); ++ ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_sexp_build failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ ++ obj->hd = hd; ++ return 0; ++} ++ ++static void ++bench_ecc_free (struct bench_obj *obj) ++{ ++ struct bench_ecc_hd *hd = obj->hd; ++ ++ gcry_sexp_release (hd->sig); ++ gcry_sexp_release (hd->pub_key); ++ gcry_sexp_release (hd->sec_key); ++ gcry_sexp_release (hd->data); ++ gcry_sexp_release (hd->key_spec); ++ free (hd); ++ obj->hd = NULL; ++} ++ ++static void ++bench_ecc_keygen (struct bench_ecc_hd *hd) ++{ ++ gcry_sexp_t key_pair; ++ gpg_error_t err; ++ ++ err = gcry_pk_genkey (&key_pair, hd->key_spec); ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_pk_genkey failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ ++ hd->pub_key = gcry_sexp_find_token (key_pair, "public-key", 0); ++ if (!hd->pub_key) ++ { ++ fprintf (stderr, PGM ": public part missing in key\n"); ++ exit (1); ++ } ++ hd->sec_key = gcry_sexp_find_token (key_pair, "private-key", 0); ++ if (!hd->sec_key) ++ { ++ fprintf (stderr, PGM ": private part missing in key\n"); ++ exit (1); ++ } ++ ++ gcry_sexp_release (key_pair); ++} ++ ++static void ++bench_ecc_keygen_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) ++{ ++ struct bench_ecc_hd *hd = obj->hd; ++ size_t i; ++ ++ (void)buf; ++ ++ for (i = 0; i < num_iter; i++) ++ { ++ bench_ecc_keygen (hd); ++ gcry_sexp_release (hd->pub_key); ++ gcry_sexp_release (hd->sec_key); ++ } ++ ++ hd->pub_key = NULL; ++ hd->sec_key = NULL; ++} ++ ++static void ++bench_ecc_sign_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) ++{ ++ struct bench_ecc_hd *hd = obj->hd; ++ gpg_error_t err; ++ size_t i; ++ ++ (void)buf; ++ ++ bench_ecc_keygen (hd); ++ ++ for (i = 0; i < num_iter; i++) ++ { ++ err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ gcry_sexp_release (hd->sig); ++ } ++ ++ gcry_sexp_release (hd->pub_key); ++ gcry_sexp_release (hd->sec_key); ++ hd->sig = NULL; ++ hd->pub_key = NULL; ++ hd->sec_key = NULL; ++} ++ ++static void ++bench_ecc_verify_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) ++{ ++ struct bench_ecc_hd *hd = obj->hd; ++ gpg_error_t err; ++ int i; ++ ++ (void)buf; ++ ++ bench_ecc_keygen (hd); ++ err = gcry_pk_sign (&hd->sig, hd->data, hd->sec_key); ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_pk_sign failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ ++ for (i = 0; i < num_iter; i++) ++ { ++ err = gcry_pk_verify (hd->sig, hd->data, hd->pub_key); ++ if (err) ++ { ++ fprintf (stderr, PGM ": gcry_pk_verify failed: %s\n", ++ gpg_strerror (err)); ++ exit (1); ++ } ++ } ++ ++ gcry_sexp_release (hd->sig); ++ gcry_sexp_release (hd->pub_key); ++ gcry_sexp_release (hd->sec_key); ++ hd->sig = NULL; ++ hd->pub_key = NULL; ++ hd->sec_key = NULL; ++} ++ ++ ++static struct bench_ops ecc_mult_ops = { ++ &bench_ecc_mult_init, ++ &bench_ecc_mult_free, ++ &bench_ecc_mult_do_bench ++}; ++ ++static struct bench_ops ecc_keygen_ops = { ++ &bench_ecc_init, ++ &bench_ecc_free, ++ &bench_ecc_keygen_do_bench ++}; ++ ++static struct bench_ops ecc_sign_ops = { ++ &bench_ecc_init, ++ &bench_ecc_free, ++ &bench_ecc_sign_do_bench ++}; ++ ++static struct bench_ops ecc_verify_ops = { ++ &bench_ecc_init, ++ &bench_ecc_free, ++ &bench_ecc_verify_do_bench ++}; ++ ++ ++static struct bench_ecc_oper ecc_operations[] = { ++ { ECC_OPER_MULT, "mult", &ecc_mult_ops }, ++ { ECC_OPER_KEYGEN, "keygen", &ecc_keygen_ops }, ++ { ECC_OPER_SIGN, "sign", &ecc_sign_ops }, ++ { ECC_OPER_VERIFY, "verify", &ecc_verify_ops }, ++ { 0, NULL, NULL } ++}; ++ ++ ++static void ++cipher_ecc_one (enum bench_ecc_algo algo, struct bench_ecc_oper *poper) ++{ ++ struct bench_ecc_oper oper = *poper; ++ struct bench_obj obj = { 0 }; ++ double result; ++ ++ if (algo == ECC_ALGO_SECP256K1 && oper.oper != ECC_OPER_MULT) ++ return; ++ ++ oper.algo = algo; ++ ++ bench_print_mode (14, oper.name); ++ ++ obj.ops = oper.ops; ++ obj.priv = &oper; ++ ++ result = do_slope_benchmark (&obj); ++ bench_print_result_nsec_per_iteration (result); ++} ++ ++ ++static void ++_ecc_bench (int algo) ++{ ++ const char *algo_name; ++ int i; ++ ++ algo_name = ecc_algo_name (algo); ++ ++ bench_print_header_nsec_per_iteration (14, algo_name); ++ ++ for (i = 0; ecc_operations[i].name; i++) ++ cipher_ecc_one (algo, &ecc_operations[i]); ++ ++ bench_print_footer (14); ++} ++#endif ++ ++ ++void ++ecc_bench (char **argv, int argc) ++{ ++#if USE_ECC ++ int i, algo; ++ ++ bench_print_section ("ecc", "ECC"); ++ ++ if (argv && argc) ++ { ++ for (i = 0; i < argc; i++) ++ { ++ algo = ecc_map_name (argv[i]); ++ if (algo >= 0) ++ _ecc_bench (algo); ++ } ++ } ++ else ++ { ++ for (i = 0; i < __MAX_ECC_ALGO; i++) ++ _ecc_bench (i); ++ } ++#else ++ (void)argv; ++ (void)argc; ++#endif ++} ++ + /************************************************************** Main program. */ + + void + print_help (void) + { + static const char *help_lines[] = { +- "usage: bench-slope [options] [hash|mac|cipher|kdf [algonames]]", ++ "usage: bench-slope [options] [hash|mac|cipher|kdf|ecc [algonames]]", + "", + " options:", + " --cpu-mhz Set CPU speed for calculating cycles", +@@ -2304,6 +2883,7 @@ main (int argc, char **argv) + mac_bench (NULL, 0); + cipher_bench (NULL, 0); + kdf_bench (NULL, 0); ++ ecc_bench (NULL, 0); + } + else if (!strcmp (*argv, "hash")) + { +@@ -2337,6 +2917,14 @@ main (int argc, char **argv) + warm_up_cpu (); + kdf_bench ((argc == 0) ? NULL : argv, argc); + } ++ else if (!strcmp (*argv, "ecc")) ++ { ++ argc--; ++ argv++; ++ ++ warm_up_cpu (); ++ ecc_bench ((argc == 0) ? NULL : argv, argc); ++ } + else + { + fprintf (stderr, PGM ": unknown argument: %s\n", *argv); + +commit 9911069388e762d2a85bc2a11ca6cfcc4c895e4f +Author: Jussi Kivilinna +Date: Wed Jun 16 20:27:01 2021 +0300 + + bench-slope: add X25519 and X448 scalar multiplication + + * tests/bench-slope.c (ECC_ALGO_X25519, ECC_ALGO_X448): New. + (ecc_algo_name, ecc_algo_curve, ecc_nbits): Add X25519 and X448. + (bench_ecc_mult_do_bench): Pass Y as NULL to ec_get_affine with + X25519 and X448. + (cipher_ecc_one): Run only multiplication bench for X25519 and X448. + -- + + Signed-off-by: Jussi Kivilinna + +diff --git a/tests/bench-slope.c b/tests/bench-slope.c +index 9b4a139a..35272094 100644 +--- a/tests/bench-slope.c ++++ b/tests/bench-slope.c +@@ -2144,6 +2144,8 @@ enum bench_ecc_algo + { + ECC_ALGO_ED25519 = 0, + ECC_ALGO_ED448, ++ ECC_ALGO_X25519, ++ ECC_ALGO_X448, + ECC_ALGO_NIST_P192, + ECC_ALGO_NIST_P224, + ECC_ALGO_NIST_P256, +@@ -2197,6 +2199,10 @@ ecc_algo_name (int algo) + return "Ed25519"; + case ECC_ALGO_ED448: + return "Ed448"; ++ case ECC_ALGO_X25519: ++ return "X25519"; ++ case ECC_ALGO_X448: ++ return "X448"; + case ECC_ALGO_NIST_P192: + return "NIST-P192"; + case ECC_ALGO_NIST_P224: +@@ -2223,6 +2229,10 @@ ecc_algo_curve (int algo) + return "Ed25519"; + case ECC_ALGO_ED448: + return "Ed448"; ++ case ECC_ALGO_X25519: ++ return "Curve25519"; ++ case ECC_ALGO_X448: ++ return "X448"; + case ECC_ALGO_NIST_P192: + return "NIST P-192"; + case ECC_ALGO_NIST_P224: +@@ -2249,6 +2259,10 @@ ecc_nbits (int algo) + return 255; + case ECC_ALGO_ED448: + return 448; ++ case ECC_ALGO_X25519: ++ return 255; ++ case ECC_ALGO_X448: ++ return 448; + case ECC_ALGO_NIST_P192: + return 192; + case ECC_ALGO_NIST_P224: +@@ -2355,15 +2369,26 @@ bench_ecc_mult_free (struct bench_obj *obj) + static void + bench_ecc_mult_do_bench (struct bench_obj *obj, void *buf, size_t num_iter) + { ++ struct bench_ecc_oper *oper = obj->priv; + struct bench_ecc_mult_hd *hd = obj->hd; ++ gcry_mpi_t y; + size_t i; + + (void)buf; + ++ if (oper->algo == ECC_ALGO_X25519 || oper->algo == ECC_ALGO_X448) ++ { ++ y = NULL; ++ } ++ else ++ { ++ y = hd->y; ++ } ++ + for (i = 0; i < num_iter; i++) + { + gcry_mpi_ec_mul (hd->Q, hd->k, hd->G, hd->ec); +- if (gcry_mpi_ec_get_affine (hd->x, hd->y, hd->Q, hd->ec)) ++ if (gcry_mpi_ec_get_affine (hd->x, y, hd->Q, hd->ec)) + { + fprintf (stderr, PGM ": gcry_mpi_ec_get_affine failed\n"); + exit (1); +@@ -2634,7 +2659,8 @@ cipher_ecc_one (enum bench_ecc_algo algo, struct bench_ecc_oper *poper) + struct bench_obj obj = { 0 }; + double result; + +- if (algo == ECC_ALGO_SECP256K1 && oper.oper != ECC_OPER_MULT) ++ if ((algo == ECC_ALGO_X25519 || algo == ECC_ALGO_X448 || ++ algo == ECC_ALGO_SECP256K1) && oper.oper != ECC_OPER_MULT) + return; + + oper.algo = algo; + + +From bd49a4fa915b8a078c341b35f5a51fcb2a004c35 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 12 Jul 2021 21:35:18 +0200 +Subject: [PATCH 1/8] mac: Disable AES GMAC in FIPS mode + +* cipher/mac-gmac.c (_gcry_mac_type_spec_gmac_aes): Remove FIPS flag +-- +The GMAC does not work in FIPS mode until libgcrypt will have internal +IV generator. + +Signed-off-by: Jakub Jelen +--- + cipher/mac-gmac.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c +index e04c6d1e..1d59d085 100644 +--- a/cipher/mac-gmac.c ++++ b/cipher/mac-gmac.c +@@ -157,7 +157,7 @@ static gcry_mac_spec_ops_t gmac_ops = { + + #if USE_AES + gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = { +- GCRY_MAC_GMAC_AES, {0, 1}, "GMAC_AES", ++ GCRY_MAC_GMAC_AES, {0, 0}, "GMAC_AES", + &gmac_ops + }; + #endif +-- +2.31.1 + + +From fd0e1c3e7f6062579869d345875d6ef823706e56 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Mon, 12 Jul 2021 21:36:34 +0200 +Subject: [PATCH 2/8] tests: Do not expect GCM work in FIPS + +* tests/basic.c (check_one_cipher_core): Expect GCM ciphers to fail in + FIPS mode + (check_cipher_modes): Skip GCM ciphers tests as they fail quite late + in gcry_cipher_gettag(). +-- + +Signed-off-by: Jakub Jelen +--- + tests/basic.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +diff --git a/tests/basic.c b/tests/basic.c +index 0572c46e..d7b7f496 100644 +--- a/tests/basic.c ++++ b/tests/basic.c +@@ -9510,6 +9510,13 @@ check_one_cipher_core (int algo, int mode, int flags, + + clutter_vector_registers(); + err = gcry_cipher_encrypt (hd, out, nplain, plain, nplain); ++ if (in_fips_mode && mode == GCRY_CIPHER_MODE_GCM) ++ { ++ if (!err) ++ fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt is expected to " ++ "fail in FIPS mode: %s\n", pass, algo, mode, gpg_strerror (err)); ++ goto err_out_free; ++ } + if (err) + { + fail ("pass %d, algo %d, mode %d, gcry_cipher_encrypt failed: %s\n", +@@ -10257,7 +10264,12 @@ check_cipher_modes(void) + check_cfb_cipher (); + check_ofb_cipher (); + check_ccm_cipher (); +- check_gcm_cipher (); ++ if (!in_fips_mode) ++ { ++ /* This will have to go through modifications as the GCM fails in fips ++ * as late as in gcry_cipher_gettag, but we want to allow it in the end */ ++ check_gcm_cipher (); ++ } + check_poly1305_cipher (); + check_ocb_cipher (); + check_xts_cipher (); +-- +2.31.1 + + +From ccbb1694693080822858e2065cf88ab43ec03fbc Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 09:18:52 +0200 +Subject: [PATCH 3/8] tests: Skip unsupported mechanisms in FIPS mode + +* tests/bench-slope.c (cipher_bench_one): Skip GCM mode in FIPS mode + (ecc_algo_fips_allowed): New function + (_ecc_bench): Skip algorithms disabled in FIPS mode + (main): Check for FIPS mode +* tests/benchmark.c (cipher_bench): Skip GCM in FIPS mode +-- +In FIPS mode, not all the curves are allowed. This is already checked in +other parts of the code base, but not in the benchmark test. + +Signed-off-by: Jakub Jelen +--- + tests/bench-slope.c | 33 +++++++++++++++++++++++++++++++-- + tests/benchmark.c | 4 ++++ + 2 files changed, 35 insertions(+), 2 deletions(-) + +diff --git a/tests/bench-slope.c b/tests/bench-slope.c +index 35272094..5bdb391e 100644 +--- a/tests/bench-slope.c ++++ b/tests/bench-slope.c +@@ -70,6 +70,7 @@ static double bench_ghz; + /* Current accuracy of auto-detected CPU Ghz. */ + static double bench_ghz_diff; + ++static int in_fips_mode = 0; + + /*************************************** Default parameters for measurements. */ + +@@ -1642,8 +1643,8 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode) + if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN) + return; + +- /* GCM has restrictions for block-size */ +- if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN) ++ /* GCM has restrictions for block-size; not allowed in FIPS mode */ ++ if (mode.mode == GCRY_CIPHER_MODE_GCM && (in_fips_mode || blklen != GCRY_GCM_BLOCK_LEN)) + return; + + /* XTS has restrictions for block-size */ +@@ -2190,6 +2191,27 @@ struct bench_ecc_hd + }; + + ++static int ++ecc_algo_fips_allowed (int algo) ++{ ++ switch (algo) ++ { ++ case ECC_ALGO_NIST_P224: ++ case ECC_ALGO_NIST_P256: ++ case ECC_ALGO_NIST_P384: ++ case ECC_ALGO_NIST_P521: ++ return 1; ++ case ECC_ALGO_SECP256K1: ++ case ECC_ALGO_ED25519: ++ case ECC_ALGO_ED448: ++ case ECC_ALGO_X25519: ++ case ECC_ALGO_X448: ++ case ECC_ALGO_NIST_P192: ++ default: ++ return 0; ++ } ++} ++ + static const char * + ecc_algo_name (int algo) + { +@@ -2681,6 +2703,10 @@ _ecc_bench (int algo) + const char *algo_name; + int i; + ++ /* Skip not allowed mechanisms */ ++ if (!ecc_algo_fips_allowed(algo)) ++ return; ++ + algo_name = ecc_algo_name (algo); + + bench_print_header_nsec_per_iteration (14, algo_name); +@@ -2899,6 +2925,9 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + if (in_regression_test) + fputs ("Note: " PGM " running in quick regression test mode.\n", stdout); + +diff --git a/tests/benchmark.c b/tests/benchmark.c +index 605b50c6..24141371 100644 +--- a/tests/benchmark.c ++++ b/tests/benchmark.c +@@ -943,6 +943,10 @@ cipher_bench ( const char *algoname ) + && algo != GCRY_CIPHER_CHACHA20) + continue; + ++ /* GCM is not available in FIPS mode */ ++ if (in_fips_mode && modes[modeidx].mode == GCRY_CIPHER_MODE_GCM) ++ continue; ++ + if (modes[modeidx].req_blocksize > 0 + && blklen != modes[modeidx].req_blocksize) + { +-- +2.31.1 + + +From 744baa85722da10d7374c6eca6b08b8197819ab6 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 09:20:18 +0200 +Subject: [PATCH 4/8] tests: Expect curves 25519/448 to fail in FIPS mode + +* tests/t-cv25519.c (test_cv_hl): Expect the operation to fail in FIPS + mode. + (test_cv_x25519, test_it): Ditto. + (main) Detect FIPS mode. +* tests/t-ed25519.c (one_test): Expect the operation to fail in FIPS + mode. + (main) Detect FIPS mode. +* tests/t-ed448.c (one_test): Expect the operation to fail in FIPS + mode. + (main) Detect FIPS mode. +* tests/t-x448.c (test_cv_hl): Expect the operation to fail in FIPS + mode. + (test_cv_x448, test_cv): Ditto. + (main) Detect FIPS mode. +-- +The ed25519, ed448, cv25519 and cv448 curves are not available in FIPS +mode. Some of the tests already skipped these, but it is always better +to make sure thy are failing, rather than just skipping these. + +Signed-off-by: Jakub Jelen +--- + tests/t-cv25519.c | 37 +++++++++++++++++++++++++++++++++++-- + tests/t-ed25519.c | 18 ++++++++++++++---- + tests/t-ed448.c | 18 ++++++++++++++---- + tests/t-x448.c | 41 +++++++++++++++++++++++++++++++++++++---- + 4 files changed, 100 insertions(+), 14 deletions(-) + +diff --git a/tests/t-cv25519.c b/tests/t-cv25519.c +index 0de50a02..b4126f4c 100644 +--- a/tests/t-cv25519.c ++++ b/tests/t-cv25519.c +@@ -33,6 +33,7 @@ + #include "t-common.h" + #define N_TESTS 18 + ++static int in_fips_mode = 0; + + static void + print_mpi (const char *text, gcry_mpi_t a) +@@ -188,7 +189,17 @@ test_cv_hl (int testno, const char *k_str, const char *u_str, + xfree (buffer); + buffer = NULL; + +- if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) ++ err = gcry_pk_encrypt (&s_result, s_data, s_pk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_encrypt failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -281,7 +292,17 @@ test_cv_x25519 (int testno, const char *k_str, const char *u_str, + goto leave; + } + +- if ((err = gcry_ecc_mul_point (algo, result, scalar, point))) ++ err = gcry_ecc_mul_point (algo, result, scalar, point); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_ecc_mul_point failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -335,6 +356,15 @@ test_it (int testno, const char *k_str, int iter, const char *result_str) + info ("Running test %d: iteration=%d\n", testno, iter); + + gcry_mpi_ec_new (&ctx, NULL, "Curve25519"); ++ if (in_fips_mode) ++ { ++ if (ctx) ++ fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ return; ++ } + Q = gcry_mpi_point_new (0); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 32) +@@ -640,6 +670,9 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + start_timer (); + check_cv25519 (); + stop_timer (); +diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c +index a5271c25..567bc797 100644 +--- a/tests/t-ed25519.c ++++ b/tests/t-ed25519.c +@@ -36,6 +36,7 @@ + static int sign_with_pk; + static int no_verify; + static int custom_data_file; ++static int in_fips_mode = 0; + + + static void +@@ -271,7 +272,17 @@ one_test (int testno, const char *sk, const char *pk, + goto leave; + } + +- if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) ++ err = gcry_pk_sign (&s_sig, s_msg, s_sk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); + if (debug) + show_sexp ("sig=", s_sig); +@@ -481,9 +492,8 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + +- /* Ed25519 isn't supported in fips mode */ +- if (gcry_fips_mode_active()) +- return 77; ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + + start_timer (); + check_ed25519 (fname); +diff --git a/tests/t-ed448.c b/tests/t-ed448.c +index 1f445ffc..f38cd10c 100644 +--- a/tests/t-ed448.c ++++ b/tests/t-ed448.c +@@ -36,6 +36,7 @@ + static int sign_with_pk; + static int no_verify; + static int custom_data_file; ++static int in_fips_mode = 0; + + + static void +@@ -302,7 +303,17 @@ one_test (int testno, int ph, const char *sk, const char *pk, + } + } + +- if ((err = gcry_pk_sign (&s_sig, s_msg, s_sk))) ++ err = gcry_pk_sign (&s_sig, s_msg, s_sk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_sign is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_pk_sign failed for test %d: %s", testno, gpg_strerror (err)); + if (debug) + show_sexp ("sig=", s_sig); +@@ -521,9 +532,8 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + +- /* Ed448 isn't supported in fips mode */ +- if (gcry_fips_mode_active()) +- return 77; ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + + start_timer (); + check_ed448 (fname); +diff --git a/tests/t-x448.c b/tests/t-x448.c +index 5c3cbeb9..cc4b10fc 100644 +--- a/tests/t-x448.c ++++ b/tests/t-x448.c +@@ -34,6 +34,7 @@ + #include "t-common.h" + #define N_TESTS 9 + ++static int in_fips_mode = 0; + + static void + print_mpi (const char *text, gcry_mpi_t a) +@@ -179,8 +180,18 @@ test_cv_hl (int testno, const char *k_str, const char *u_str, + xfree (buffer); + buffer = NULL; + +- if ((err = gcry_pk_encrypt (&s_result, s_data, s_pk))) +- fail ("gcry_pk_encrypt failed for test %d: %s", testno, ++ err = gcry_pk_encrypt (&s_result, s_data, s_pk); ++ if (in_fips_mode) ++ { ++ if (!err) ++ fail ("gcry_pk_encrypt is not expected to work in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) ++ fail ("gcry_pk_encrypt goto leavefailed for test %d: %s", testno, + gpg_strerror (err)); + + s_tmp = gcry_sexp_find_token (s_result, "s", 0); +@@ -257,7 +268,17 @@ test_cv_x448 (int testno, const char *k_str, const char *u_str, + goto leave; + } + +- if ((err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point))) ++ err = gcry_ecc_mul_point (GCRY_ECC_CURVE448, result, scalar, point); ++ if (in_fips_mode) ++ { ++ if (err != GPG_ERR_NOT_SUPPORTED) ++ fail ("gcry_ecc_mul_point is not expected to work in FIPS mode for test %d: %s", ++ testno, gpg_strerror (err)); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ goto leave; ++ } ++ if (err) + fail ("gcry_ecc_mul_point failed for test %d: %s", testno, + gpg_strerror (err)); + +@@ -296,7 +317,7 @@ test_cv (int testno, const char *k_str, const char *u_str, + static void + test_it (int testno, const char *k_str, int iter, const char *result_str) + { +- gcry_ctx_t ctx; ++ gcry_ctx_t ctx = NULL; + gpg_error_t err; + void *buffer = NULL; + size_t buflen; +@@ -311,6 +332,15 @@ test_it (int testno, const char *k_str, int iter, const char *result_str) + info ("Running test %d: iteration=%d\n", testno, iter); + + gcry_mpi_ec_new (&ctx, NULL, "X448"); ++ if (in_fips_mode) ++ { ++ if (ctx) ++ fail ("gcry_mpi_ec_new should fail in FIPS mode for test %d", ++ testno); ++ if (verbose > 1) ++ info ("not executed in FIPS mode\n"); ++ return; ++ } + Q = gcry_mpi_point_new (0); + + if (!(buffer = hex2buffer (k_str, &buflen)) || buflen != 56) +@@ -583,6 +613,9 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + start_timer (); + check_x448 (); + stop_timer (); +-- +2.31.1 + + +From d3a603cd4a0ff2a8df35f5bb39efd64c52b2b2c5 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 10:11:42 +0200 +Subject: [PATCH 5/8] tests: Expect the 192b ECDSA tests to fail in fips mode + +* tests/dsa-rfc6979.c (check_dsa_rfc6979): Expect ECDSA 192b keys to + fail in FIPS mode. + (main): Detect FIPS mode. +-- +The 192b ECDSA curve is not FIPS approved so it does not work. This adds +a flag to the list of the keys to mark if it is expected to work in FIPS +mode. + +Signed-off-by: Jakub Jelen +--- + tests/dsa-rfc6979.c | 24 +++++++++++++++++------- + 1 file changed, 17 insertions(+), 7 deletions(-) + +diff --git a/tests/dsa-rfc6979.c b/tests/dsa-rfc6979.c +index 7d3d2080..0f124575 100644 +--- a/tests/dsa-rfc6979.c ++++ b/tests/dsa-rfc6979.c +@@ -33,6 +33,7 @@ + #define PGM "dsa-rfc6979" + #include "t-common.h" + ++static int in_fips_mode = 0; + + static void + show_sexp (const char *prefix, gcry_sexp_t a) +@@ -111,6 +112,7 @@ check_dsa_rfc6979 (void) + static struct { + const char *name; + const char *key; ++ int fips; + } keys[] = { + { + "DSA, 1024 bits", +@@ -130,7 +132,7 @@ check_dsa_rfc6979 (void) + " 92195A38B90523E2542EE61871C0440CB87C322FC4B4D2EC5E1E7EC766E1BE8D" + " 4CE935437DC11C3C8FD426338933EBFE739CB3465F4D3668C5E473508253B1E6" + " 82F65CBDC4FAE93C2EA212390E54905A86E2223170B44EAA7DA5DD9FFCFB7F3B#)" +- " ))" ++ " ))", 1 + }, + { + "DSA, 2048 bits", +@@ -162,7 +164,7 @@ check_dsa_rfc6979 (void) + " 687972A2D382599C9BAC4E0ED7998193078913032558134976410B89D2C171D1" + " 23AC35FD977219597AA7D15C1A9A428E59194F75C721EBCBCFAE44696A499AFA" + " 74E04299F132026601638CB87AB79190D4A0986315DA8EEC6561C938996BEADF#)" +- " ))" ++ " ))", 1 + }, + { + "ECDSA, 192 bits (prime field)", +@@ -172,7 +174,7 @@ check_dsa_rfc6979 (void) + " (q #04AC2C77F529F91689FEA0EA5EFEC7F210D8EEA0B9E047ED56" + " 3BC723E57670BD4887EBC732C523063D0A7C957BC97C1C43#)" + " (d #6FAB034934E4C0FC9AE67F5B5659A9D7D1FEFD187EE09FD4#)" +- " ))" ++ " ))", 0 + }, + { + "ECDSA, 224 bits (prime field)", +@@ -183,7 +185,7 @@ check_dsa_rfc6979 (void) + " 00CF08DA5AD719E42707FA431292DEA11244D64FC51610D94B130D6C" + " EEAB6F3DEBE455E3DBF85416F7030CBD94F34F2D6F232C69F3C1385A#)" + " (d #F220266E1105BFE3083E03EC7A3A654651F45E37167E88600BF257C1#)" +- " ))" ++ " ))", 1 + }, + { + "ECDSA, 256 bits (prime field)", +@@ -194,7 +196,7 @@ check_dsa_rfc6979 (void) + " 60FED4BA255A9D31C961EB74C6356D68C049B8923B61FA6CE669622E60F29FB6" + " 7903FE1008B8BC99A41AE9E95628BC64F2F1B20C2D7E9F5177A3C294D4462299#)" + " (d #C9AFA9D845BA75166B5C215767B1D6934E50C3DB36E89B127B8A622B120F6721#)" +- " ))" ++ " ))", 1 + }, + { + "ECDSA, 384 bits (prime field)", +@@ -208,7 +210,7 @@ check_dsa_rfc6979 (void) + " 288B231C3AE0D4FE7344FD2533264720#)" + " (d #6B9D3DAD2E1B8C1C05B19875B6659F4DE23C3B667BF297BA9AA47740787137D8" + " 96D5724E4C70A825F872C9EA60D2EDF5#)" +- " ))" ++ " ))", 1 + }, + { + "ECDSA, 521 bits (prime field)", +@@ -225,7 +227,7 @@ check_dsa_rfc6979 (void) + " (d #FAD06DAA62BA3B25D2FB40133DA757205DE67F5BB0018FEE8C86E1B68C7E75" + " CAA896EB32F1F47C70855836A6D16FCC1466F6D8FBEC67DB89EC0C08B0E996B8" + " 3538#)" +- " ))" ++ " ))", 1 + }, + { NULL } + }; +@@ -937,6 +939,12 @@ check_dsa_rfc6979 (void) + die ("building data sexp failed: %s\n", gpg_strerror (err)); + + err = gcry_pk_sign (&sig, data, seckey); ++ if (in_fips_mode && !keys[i].fips) ++ { ++ if (!err) ++ fail ("signing should not work in FIPS mode: %s\n", gpg_strerror (err)); ++ continue; ++ } + if (err) + fail ("signing failed: %s\n", gpg_strerror (err)); + +@@ -972,6 +980,8 @@ main (int argc, char **argv) + die ("version mismatch; pgm=%s, library=%s\n", + GCRYPT_VERSION,gcry_check_version (NULL)); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + if (debug) + xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u, 0)); + /* No valuable keys are create, so we can speed up our RNG. */ +-- +2.31.1 + + +From d4a52861e7d0d1871f4c1d32bc0815f0824eb9ab Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 10:32:33 +0200 +Subject: [PATCH 6/8] tests: Skip secmem overflow test in FIPS mode + +* tests/t-secmem.c (main): Skip overflow tests in FIPS mode because they + are fatal and there is no way to override the outofcore handler. +-- + +Signed-off-by: Jakub Jelen +--- + tests/t-secmem.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/tests/t-secmem.c b/tests/t-secmem.c +index 2b769134..692c0f1a 100644 +--- a/tests/t-secmem.c ++++ b/tests/t-secmem.c +@@ -37,6 +37,7 @@ + #define MINIMUM_POOL_SIZE 16384 + static size_t pool_size; + static size_t chunk_size; ++static int in_fips_mode = 0; + + static void + test_secmem (void) +@@ -182,8 +183,11 @@ main (int argc, char **argv) + xgcry_control ((GCRYCTL_SET_DEBUG_FLAGS, 1u , 0)); + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + xgcry_control ((GCRYCTL_INIT_SECMEM, pool_size, 0)); ++ /* This is ignored in FIPS Mode */ + gcry_set_outofcore_handler (outofcore_handler, NULL); + xgcry_control ((GCRYCTL_INITIALIZATION_FINISHED, 0)); ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; + + /* Libgcrypt prints a warning when the first overflow is allocated; + * we do not want to see that. */ +@@ -192,7 +196,8 @@ main (int argc, char **argv) + + + test_secmem (); +- test_secmem_overflow (); ++ if (!in_fips_mode) ++ test_secmem_overflow (); + /* FIXME: We need to improve the tests, for example by registering + * our own log handler and comparing the output of + * PRIV_CTL_DUMP_SECMEM_STATS to expected pattern. */ +-- +2.31.1 + + +From fc6de9c7b48ab45deb8ea84d1c768e4f056edb08 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 10:52:00 +0200 +Subject: [PATCH 7/8] tests: Transient DSA keys work in FIPS mode + +* tests/pubkey.c (check_run): Enable tests with DSA transient keys which + work in FIPS. +-- + +Signed-off-by: Jakub Jelen +--- + tests/pubkey.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +diff --git a/tests/pubkey.c b/tests/pubkey.c +index 754952ee..cd51e0a2 100644 +--- a/tests/pubkey.c ++++ b/tests/pubkey.c +@@ -680,15 +680,12 @@ check_run (void) + gcry_sexp_release (pkey); + gcry_sexp_release (skey); + +- if (!gcry_fips_mode_active ()) +- { +- if (verbose) +- fprintf (stderr, "Generating transient DSA key.\n"); +- get_dsa_key_new (&pkey, &skey, 1); +- /* Fixme: Add a check function for DSA keys. */ +- gcry_sexp_release (pkey); +- gcry_sexp_release (skey); +- } ++ if (verbose) ++ fprintf (stderr, "Generating transient DSA key.\n"); ++ get_dsa_key_new (&pkey, &skey, 1); ++ /* Fixme: Add a check function for DSA keys. */ ++ gcry_sexp_release (pkey); ++ gcry_sexp_release (skey); + + if (verbose) + fprintf (stderr, "Generating DSA key (FIPS 186).\n"); +-- +2.31.1 + + +From e68b538008063938b9b054f18e56e9f27bb3a720 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 13 Jul 2021 10:53:13 +0200 +Subject: [PATCH 8/8] tests: Generating DSA from domain should fail in FIPS + mode + +* tests/pubkey.c (get_dsa_key_with_domain_new): Expect failure in FIPS + mode + (check_x931_derived_key): Simplify testing for FIPS mode. + (main): Check for fips mode. +-- + +Signed-off-by: Jakub Jelen +--- + tests/pubkey.c | 16 ++++++++++++++-- + 1 file changed, 14 insertions(+), 2 deletions(-) + +diff --git a/tests/pubkey.c b/tests/pubkey.c +index cd51e0a2..7209f44e 100644 +--- a/tests/pubkey.c ++++ b/tests/pubkey.c +@@ -29,6 +29,7 @@ + #define PGM "pubkey" + #include "t-common.h" + ++static int in_fips_mode; + + /* Sample RSA keys, taken from basic.c. */ + +@@ -518,6 +519,14 @@ get_dsa_key_with_domain_new (gcry_sexp_t *pkey, gcry_sexp_t *skey) + die ("error creating S-expression: %s\n", gcry_strerror (rc)); + rc = gcry_pk_genkey (&key, key_spec); + gcry_sexp_release (key_spec); ++ if (in_fips_mode) ++ { ++ if (!rc) ++ die ("generating DSA key should fail in FIPS mode: %s\n", gcry_strerror (rc)); ++ *pkey = NULL; ++ *skey = NULL; ++ return; ++ } + if (rc) + die ("error generating DSA key: %s\n", gcry_strerror (rc)); + +@@ -899,7 +908,7 @@ check_x931_derived_key (int what) + err = _gcry_pk_util_get_nbits(key_spec, &nbits); + if (err) + die ("nbits not found\n"); +- if (gcry_fips_mode_active() && nbits < 2048) ++ if (in_fips_mode && nbits < 2048) + { + info("RSA key test with %d bits skipped in fips mode\n", nbits); + goto leave; +@@ -1186,6 +1195,9 @@ main (int argc, char **argv) + /* No valuable keys are create, so we can speed up our RNG. */ + xgcry_control ((GCRYCTL_ENABLE_QUICK_RANDOM, 0)); + ++ if (gcry_fips_mode_active ()) ++ in_fips_mode = 1; ++ + for (i=0; i < 2; i++) + check_run (); + +@@ -1193,7 +1205,7 @@ main (int argc, char **argv) + check_x931_derived_key (i); + + check_ecc_sample_key (); +- if (!gcry_fips_mode_active ()) ++ if (!in_fips_mode) + check_ed25519ecdsa_sample_key (); + + return !!error_count; +-- +2.31.1 + +commit 61c87070abc4baeb9d847db015e6a3031f349483 +Author: NIIBE Yutaka +Date: Wed Jul 7 15:52:06 2021 +0900 + + tests: Skip unavailable ciphers in FIPS mode. + + * tests/basic.c (_check_poly1305_cipher): + (check_ocb_cipher_largebuf_split): Skip unavailable ciphers when + IN_FIPS_MODE. + (check_ocb_cipher_checksum, check_gost28147_cipher_basic): Likewise. + + -- + + GnuPG-bug-id: 5520 + Signed-off-by: NIIBE Yutaka + +diff --git a/tests/basic.c b/tests/basic.c +index 0a1e8293..43ef122e 100644 +--- a/tests/basic.c ++++ b/tests/basic.c +@@ -5026,6 +5026,14 @@ _check_poly1305_cipher (unsigned int step) + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { ++ if (gcry_cipher_test_algo (tv[i].algo) && in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, " algorithm %d not available in fips mode\n", ++ tv[i].algo); ++ continue; ++ } ++ + if (verbose) + fprintf (stderr, " checking POLY1305 mode for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), +@@ -6643,6 +6651,14 @@ check_ocb_cipher_largebuf_split (int algo, int keylen, const char *tagexpect, + memcpy(inbuf + i, hash, 16); + } + ++ if (gcry_cipher_test_algo (algo) && in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, " algorithm %d not available in fips mode\n", ++ algo); ++ goto out_free; ++ } ++ + err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) + err = gcry_cipher_open (&hdd, algo, GCRY_CIPHER_MODE_OCB, 0); +@@ -6841,6 +6857,14 @@ check_ocb_cipher_checksum (int algo, int keylen) + blk[byteidx] |= 1 << bitpos; + } + ++ if (gcry_cipher_test_algo (algo) && in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, " algorithm %d not available in fips mode\n", ++ algo); ++ goto out_free; ++ } ++ + err = gcry_cipher_open (&hde, algo, GCRY_CIPHER_MODE_OCB, 0); + if (!err) + err = gcry_cipher_open (&hde2, algo, GCRY_CIPHER_MODE_OCB, 0); +@@ -7651,6 +7675,15 @@ check_gost28147_cipher_basic (enum gcry_cipher_algos algo) + + if (verbose) + fprintf (stderr, " Starting GOST28147 cipher checks.\n"); ++ ++ if (gcry_cipher_test_algo (algo) && in_fips_mode) ++ { ++ if (verbose) ++ fprintf (stderr, " algorithm %d not available in fips mode\n", ++ algo); ++ return; ++ } ++ + keylen = gcry_cipher_get_algo_keylen(algo); + if (!keylen) + { +commit b98ca3f798abd17696f52163665204c4e83d9092 +Author: Jussi Kivilinna +Date: Wed Jul 7 18:21:27 2021 +0300 + + tests/basic: use SHA256 instead of RMD160 for SHAKE extract testing + + * tests/basic.c (check_one_md): Use GCRY_MD_SHA256 as 'crcalgo' for + SHAKE128/SHAKE256 testing. + -- + + RMD160 was used to calculate output checksum from two SHAKE extract + streams, which are run with different extract buffer size but for + same total length and with same input. Patch switches to use SHA256 + for checksumming for FIPS support. + + GnuPG-bug-id: 5520 + Signed-off-by: Jussi Kivilinna + +diff --git a/tests/basic.c b/tests/basic.c +index bc34bb99..eb6d1514 100644 +--- a/tests/basic.c ++++ b/tests/basic.c +@@ -10395,7 +10395,7 @@ check_one_md (int algo, const char *data, int len, const char *expect, int elen, + + if (*data == '!' && !data[1]) + { +- int crcalgo = GCRY_MD_RMD160; ++ int crcalgo = GCRY_MD_SHA256; + gcry_md_hd_t crc1, crc2; + size_t startlen; + size_t piecelen; +commit ccb076e8aabb9c49e7026258b3a36a8422f6bbe4 +Author: NIIBE Yutaka +Date: Wed Jul 7 16:29:48 2021 +0900 + + tests: Fix tests/basic.c for FIPS mode. + + * tests/basic.c (main): Use bare gcry_control for + GCRYCTL_FORCE_FIPS_MODE. + + -- + + GnuPG-bug-id: 5520 + Signed-off-by: NIIBE Yutaka + +diff --git a/tests/basic.c b/tests/basic.c +index 43ef122e..bc34bb99 100644 +--- a/tests/basic.c ++++ b/tests/basic.c +@@ -14610,7 +14610,7 @@ main (int argc, char **argv) + gcry_md_hd_t md; + + /* First trigger a self-test. */ +- xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); ++ gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) + fail ("not in operational state after self-test\n"); + +@@ -14639,7 +14639,7 @@ main (int argc, char **argv) + { + /* Now run a self-test and to get back into + operational state. */ +- xgcry_control ((GCRYCTL_FORCE_FIPS_MODE, 0)); ++ gcry_control (GCRYCTL_FORCE_FIPS_MODE, 0); + if (!gcry_control (GCRYCTL_OPERATIONAL_P, 0)) + fail ("did not reach operational after error " + "and self-test\n"); diff --git a/libgcrypt.spec b/libgcrypt.spec index 5b0e0aa..5b355fa 100644 --- a/libgcrypt.spec +++ b/libgcrypt.spec @@ -27,15 +27,13 @@ Patch2: libgcrypt-1.8.5-use-fipscheck.patch # modify FIPS RSA and DSA keygen to comply with requirements Patch5: libgcrypt-1.8.4-fips-keygen.patch # fix the tests to work correctly in the FIPS mode -Patch6: libgcrypt-1.8.4-tests-fipsmode.patch +Patch6: libgcrypt-1.9.3-fips-tests.patch # update the CAVS tests Patch7: libgcrypt-1.7.3-fips-cavs.patch # use poll instead of select when gathering randomness Patch11: libgcrypt-1.8.4-use-poll.patch # slight optimalization of mpicoder.c to silence Valgrind (#968288) Patch13: libgcrypt-1.6.1-mpicoder-gccopt.patch -# fix tests to work with approved ECC -Patch14: libgcrypt-1.7.3-ecc-test-fix.patch # Run the FIPS mode initialization in the shared library constructor Patch18: libgcrypt-1.8.3-fips-ctor.patch # Do not try to open /dev/urandom if getrandom() works @@ -92,7 +90,6 @@ applications using libgcrypt. %patch7 -p1 -b .cavs %patch11 -p1 -b .use-poll %patch13 -p1 -b .gccopt -%patch14 -p1 -b .eccfix %patch18 -p1 -b .fips-ctor %patch24 -p1 -b .getrandom %patch26 -p1 -b .fips-enttest