SHA256
8
0
forked from pool/libgcrypt
Files
libgcrypt/libgcrypt-fips-cipher-Implement-FIPS-service-indicator-for-gcry_pk_hash_-API.patch

361 lines
12 KiB
Diff
Raw Permalink Normal View History

From edb43bc290046bd22548bf69ae2fbeb453112e44 Mon Sep 17 00:00:00 2001
From: NIIBE Yutaka <gniibe@fsij.org>
Date: Wed, 18 Dec 2024 14:18:26 +0900
Subject: [PATCH 11/19] fips,cipher: Implement FIPS service indicator for
gcry_pk_hash_ API.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* src/visibility.c (gcry_pk_hash_sign): Initialize the indicator.
(gcry_pk_hash_verify): Likewise.
* tests/t-fips-service-ind.c (check_pk_hash_sign_verify): New.
(main): Call check_pk_hash_sign_verify.
* cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Don't reject, but
mark non-compliance.
* cipher/pubkey.c (prepare_datasexp_to_be_signed): Likewise.
(_gcry_pk_sign_md, _gcry_pk_verify_md): Likewise.
--
GnuPG-bug-id: 7338
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Signed-off-by: Lucas Mülling <lucas.mulling@suse.com>
---
cipher/ecc-curves.c | 2 +-
cipher/pubkey.c | 20 ++--
src/visibility.c | 2 +
tests/t-fips-service-ind.c | 209 +++++++++++++++++++++++++++++++++++++
4 files changed, 222 insertions(+), 11 deletions(-)
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index 17fa5505..ddf9cbe1 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -645,7 +645,7 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name,
possible to bypass this check by specifying the curve parameters
directly. */
if (fips_mode () && !domain_parms[idx].fips )
- return GPG_ERR_NOT_SUPPORTED;
+ fips_service_indicator_mark_non_compliant ();
switch (domain_parms[idx].model)
{
diff --git a/cipher/pubkey.c b/cipher/pubkey.c
index 214bd611..e2e54199 100644
--- a/cipher/pubkey.c
+++ b/cipher/pubkey.c
@@ -510,10 +510,7 @@ prepare_datasexp_to_be_signed (const char *tmpl, gcry_md_hd_t hd,
algo = _gcry_md_get_algo (hd);
if (fips_mode () && algo == GCRY_MD_SHA1)
- {
- _gcry_md_close (hd);
- return GPG_ERR_DIGEST_ALGO;
- }
+ fips_service_indicator_mark_non_compliant ();
digest_name = _gcry_md_algo_name (algo);
digest_size = (int)_gcry_md_get_algo_dlen (algo);
@@ -535,12 +532,13 @@ prepare_datasexp_to_be_signed (const char *tmpl, gcry_md_hd_t hd,
algo = _gcry_md_map_name (digest_name_supplied);
xfree (digest_name_supplied);
- if (algo == 0
- || (fips_mode () && algo == GCRY_MD_SHA1))
+ if (algo == 0)
{
_gcry_md_close (hd);
return GPG_ERR_DIGEST_ALGO;
}
+ else if (fips_mode () && algo == GCRY_MD_SHA1)
+ fips_service_indicator_mark_non_compliant ();
digest_size = (int)_gcry_md_get_algo_dlen (algo);
digest = _gcry_md_read (hd, algo);
@@ -613,10 +611,11 @@ _gcry_pk_sign_md (gcry_sexp_t *r_sig, const char *tmpl, gcry_md_hd_t hd_orig,
if (rc)
goto leave;
+ if (!spec->flags.fips && fips_mode ())
+ fips_service_indicator_mark_non_compliant ();
+
if (spec->flags.disabled)
rc = GPG_ERR_PUBKEY_ALGO;
- else if (!spec->flags.fips && fips_mode ())
- rc = GPG_ERR_PUBKEY_ALGO;
else if (spec->sign)
rc = spec->sign (r_sig, s_data, keyparms);
else
@@ -690,10 +689,11 @@ _gcry_pk_verify_md (gcry_sexp_t s_sig, const char *tmpl, gcry_md_hd_t hd_orig,
if (rc)
goto leave;
+ if (!spec->flags.fips && fips_mode ())
+ fips_service_indicator_mark_non_compliant ();
+
if (spec->flags.disabled)
rc = GPG_ERR_PUBKEY_ALGO;
- else if (!spec->flags.fips && fips_mode ())
- rc = GPG_ERR_PUBKEY_ALGO;
else if (spec->verify)
rc = spec->verify (s_sig, s_data, keyparms);
else
diff --git a/src/visibility.c b/src/visibility.c
index c9d07f0b..d22c8b59 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1056,6 +1056,7 @@ gcry_pk_hash_sign (gcry_sexp_t *result, const char *data_tmpl, gcry_sexp_t skey,
*result = NULL;
return gpg_error (fips_not_operational ());
}
+ fips_service_indicator_init ();
return gpg_error (_gcry_pk_sign_md (result, data_tmpl, hd, skey, ctx));
}
@@ -1073,6 +1074,7 @@ gcry_pk_hash_verify (gcry_sexp_t sigval, const char *data_tmpl, gcry_sexp_t pkey
{
if (!fips_is_operational ())
return gpg_error (fips_not_operational ());
+ fips_service_indicator_init ();
return gpg_error (_gcry_pk_verify_md (sigval, data_tmpl, hd, pkey, ctx));
}
diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c
index 4b13436f..9a22d696 100644
--- a/tests/t-fips-service-ind.c
+++ b/tests/t-fips-service-ind.c
@@ -29,6 +29,7 @@
#define PGM "t-fips-service-ind"
+#define NEED_HEX2BUFFER
#include "t-common.h"
static int in_fips_mode;
#define MAX_DATA_LEN 1040
@@ -39,6 +40,213 @@ static int in_fips_mode;
# include <windows.h>
#endif
+/* Check gcry_pk_hash_sign, gcry_pk_hash_verify API. */
+static void
+check_pk_hash_sign_verify (void)
+{
+ static struct {
+ int md_algo;
+ const char *prvkey;
+ const char *pubkey;
+ const char *data_tmpl;
+ const char *k;
+ int expect_failure;
+ int expect_failure_hash;
+ } tv[] = {
+ { /* non-compliant hash */
+ GCRY_MD_BLAKE2B_512,
+ "(private-key (ecc (curve nistp256)"
+ " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))",
+ "(public-key (ecc (curve nistp256)"
+ " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"
+ "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))",
+ "(data(flags raw)(hash %s %b)(label %b))",
+ "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de",
+ 1, 1
+ },
+ { /* non-compliant curve */
+ GCRY_MD_SHA256,
+ "(private-key (ecc (curve secp256k1)"
+ " (d #c2cdf0a8b0a83b35ace53f097b5e6e6a0a1f2d40535eff1cf434f52a43d59d8f#)))",
+
+ "(public-key (ecc (curve secp256k1)"
+ " (q #046fcc37ea5e9e09fec6c83e5fbd7a745e3eee81d16ebd861c9e66f55518c19798"
+ "4e9f113c07f875691df8afc1029496fc4cb9509b39dcd38f251a83359cc8b4f7#)))",
+ "(data(flags raw)(hash %s %b)(label %b))",
+ "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de",
+ 1, 0
+ },
+ {
+ GCRY_MD_SHA256,
+ "(private-key (ecc (curve nistp256)"
+ " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))",
+ "(public-key (ecc (curve nistp256)"
+ " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83"
+ "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))",
+ "(data(flags raw)(hash %s %b)(label %b))",
+ "94a1bbb14b906a61a280f245f9e93c7f3b4a6247824f5d33b9670787642a68de",
+ 0, 0
+ }
+ };
+ int tvidx;
+ gpg_error_t err;
+ gpg_err_code_t ec;
+ const char *msg = "Takerufuji Mikiya, who won the championship in March 2024";
+ int msglen;
+
+ msglen = strlen (msg);
+ for (tvidx=0; tvidx < DIM(tv); tvidx++)
+ {
+ gcry_md_hd_t hd = NULL;
+ gcry_sexp_t s_sk = NULL;
+ gcry_sexp_t s_pk = NULL;
+ void *buffer = NULL;
+ size_t buflen;
+ gcry_ctx_t ctx = NULL;
+ gcry_sexp_t s_sig= NULL;
+
+ if (verbose)
+ info ("checking gcry_pk_hash_ test %d\n", tvidx);
+
+ err = gcry_md_open (&hd, tv[tvidx].md_algo, 0);
+ if (err)
+ {
+ fail ("algo %d, gcry_md_open failed: %s\n", tv[tvidx].md_algo,
+ gpg_strerror (err));
+ goto next;
+ }
+
+ ec = gcry_get_fips_service_indicator ();
+ if (ec == GPG_ERR_INV_OP)
+ {
+ /* libgcrypt is old, no support of the FIPS service indicator. */
+ fail ("gcry_pk_hash test %d unexpectedly failed to check the FIPS service indicator.\n",
+ tvidx);
+ goto next;
+ }
+
+ if (in_fips_mode && !tv[tvidx].expect_failure_hash && ec)
+ {
+ /* Success with the FIPS service indicator == 0 expected, but != 0. */
+ fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+ else if (in_fips_mode && tv[tvidx].expect_failure_hash && !ec)
+ {
+ /* Success with the FIPS service indicator != 0 expected, but == 0. */
+ fail ("gcry_pk_hash test %d unexpectedly cleared the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+
+ err = gcry_sexp_build (&s_sk, NULL, tv[tvidx].prvkey);
+ if (err)
+ {
+ fail ("error building SEXP for test, %s: %s",
+ "sk", gpg_strerror (err));
+ goto next;
+ }
+
+ err = gcry_sexp_build (&s_pk, NULL, tv[tvidx].pubkey);
+ if (err)
+ {
+ fail ("error building SEXP for test, %s: %s",
+ "pk", gpg_strerror (err));
+ goto next;
+ }
+
+ if (!(buffer = hex2buffer (tv[tvidx].k, &buflen)))
+ {
+ fail ("error parsing for test, %s: %s",
+ "msg", "invalid hex string");
+ goto next;
+ }
+
+ err = gcry_pk_random_override_new (&ctx, buffer, buflen);
+ if (err)
+ {
+ fail ("error setting 'k' for test: %s",
+ gpg_strerror (err));
+ goto next;
+ }
+
+ gcry_md_write (hd, msg, msglen);
+
+ err = gcry_pk_hash_sign (&s_sig, tv[tvidx].data_tmpl, s_sk, hd, ctx);
+ if (err)
+ {
+ fail ("gcry_pk_hash_sign failed: %s", gpg_strerror (err));
+ goto next;
+ }
+
+ ec = gcry_get_fips_service_indicator ();
+ if (ec == GPG_ERR_INV_OP)
+ {
+ /* libgcrypt is old, no support of the FIPS service indicator. */
+ fail ("gcry_pk_hash test %d unexpectedly failed to check the FIPS service indicator.\n",
+ tvidx);
+ goto next;
+ }
+
+ if (in_fips_mode && !tv[tvidx].expect_failure && ec)
+ {
+ /* Success with the FIPS service indicator == 0 expected, but != 0. */
+ fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+ else if (in_fips_mode && tv[tvidx].expect_failure && !ec)
+ {
+ /* Success with the FIPS service indicator != 0 expected, but == 0. */
+ fail ("gcry_pk_hash_sign test %d unexpectedly cleared the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+
+ err = gcry_pk_hash_verify (s_sig, tv[tvidx].data_tmpl, s_pk, hd, ctx);
+ if (err)
+ {
+ fail ("gcry_pk_hash_verify failed for test: %s",
+ gpg_strerror (err));
+ goto next;
+ }
+
+ ec = gcry_get_fips_service_indicator ();
+ if (ec == GPG_ERR_INV_OP)
+ {
+ /* libgcrypt is old, no support of the FIPS service indicator. */
+ fail ("gcry_pk_hash test %d unexpectedly failed to check the FIPS service indicator.\n",
+ tvidx);
+ goto next;
+ }
+
+ if (in_fips_mode && !tv[tvidx].expect_failure && ec)
+ {
+ /* Success with the FIPS service indicator == 0 expected, but != 0. */
+ fail ("gcry_pk_hash test %d unexpectedly set the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+ else if (in_fips_mode && tv[tvidx].expect_failure && !ec)
+ {
+ /* Success with the FIPS service indicator != 0 expected, but == 0. */
+ fail ("gcry_pk_hash_verify test %d unexpectedly cleared the indicator in FIPS mode.\n",
+ tvidx);
+ goto next;
+ }
+
+ next:
+ gcry_sexp_release (s_sig);
+ xfree (buffer);
+ gcry_ctx_release (ctx);
+ gcry_sexp_release (s_pk);
+ gcry_sexp_release (s_sk);
+ if (hd)
+ gcry_md_close (hd);
+ }
+}
+
/* Check gcry_cipher_open, gcry_cipher_setkey, gcry_cipher_encrypt,
gcry_cipher_decrypt, gcry_cipher_close API. */
static void
@@ -936,6 +1144,7 @@ main (int argc, char **argv)
check_md_o_w_r_c ();
check_mac_o_w_r_c ();
check_cipher_o_s_e_d_c ();
+ check_pk_hash_sign_verify ();
return !!error_count;
}
--
2.49.0