From 53c97483b17fee280e24f595bc0d82d9b362ffde Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 26 Dec 2024 11:12:48 +0900 Subject: [PATCH 18/19] fips,ecc: Check DATA in gcry_pk_sign/verify in FIPS mode. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * src/gcrypt.h.in (GCRY_FIPS_FLAG_REJECT_PK_MD): New. (GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2): New. * cipher/ecc.c (ecc_sign): Check if GOST or SM2. Check if hash is compliant. (ecc_verify): Likewise. * tests/t-fips-service-ind.c (check_pk_s_v): Modify tests including hash compliance. -- GnuPG-bug-id: 7338 Signed-off-by: NIIBE Yutaka Signed-off-by: Lucas Mülling --- cipher/ecc.c | 70 +++++++++++++++++++++++++++++++++++--- src/gcrypt.h.in | 4 ++- tests/t-fips-service-ind.c | 52 ++++++++++++++++++++-------- 3 files changed, 107 insertions(+), 19 deletions(-) diff --git a/cipher/ecc.c b/cipher/ecc.c index 8896afd0..525523ed 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -941,6 +941,18 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) if (rc) goto leave; + if (fips_mode () + && ((ctx.flags & PUBKEY_FLAG_GOST) || (ctx.flags & PUBKEY_FLAG_SM2))) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + /* Hash algo is determined by curve in EdDSA. */ if ((ctx.flags & PUBKEY_FLAG_EDDSA)) { @@ -953,10 +965,12 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) && ctx.hash_algo != GCRY_MD_SHAKE256))) { if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) - rc = GPG_ERR_DIGEST_ALGO; + { + rc = GPG_ERR_DIGEST_ALGO; + goto leave; + } else fips_service_indicator_mark_non_compliant (); - goto leave; } } else @@ -967,6 +981,23 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) ctx.hash_algo = GCRY_MD_SHAKE256; } } + else + { + if (fips_mode ()) + { + if (_gcry_md_algo_info (ctx.hash_algo, GCRYCTL_TEST_ALGO, NULL, NULL) + || ctx.hash_algo == GCRY_MD_SHA1) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_MD)) + { + rc = GPG_ERR_DIGEST_ALGO; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + } + } sig_r = mpi_new (0); sig_s = mpi_new (0); @@ -1066,6 +1097,18 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) if (DBG_CIPHER) log_mpidump ("ecc_verify data", data); + if (fips_mode () + && ((ctx.flags & PUBKEY_FLAG_GOST) || (ctx.flags & PUBKEY_FLAG_SM2))) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2)) + { + rc = GPG_ERR_INV_DATA; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + /* Hash algo is determined by curve in EdDSA. */ if ((ctx.flags & PUBKEY_FLAG_EDDSA)) { @@ -1078,10 +1121,12 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) && ctx.hash_algo != GCRY_MD_SHAKE256))) { if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK)) - rc = GPG_ERR_DIGEST_ALGO; + { + rc = GPG_ERR_DIGEST_ALGO; + goto leave; + } else fips_service_indicator_mark_non_compliant (); - goto leave; } } else @@ -1092,6 +1137,23 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) ctx.hash_algo = GCRY_MD_SHAKE256; } } + else + { + if (fips_mode ()) + { + if (_gcry_md_algo_info (ctx.hash_algo, GCRYCTL_TEST_ALGO, NULL, NULL) + || ctx.hash_algo == GCRY_MD_SHA1) + { + if (fips_check_rejection (GCRY_FIPS_FLAG_REJECT_PK_MD)) + { + rc = GPG_ERR_DIGEST_ALGO; + goto leave; + } + else + fips_service_indicator_mark_non_compliant (); + } + } + } /* * Extract the signature value. diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 7bee45e9..fcb6a327 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1986,11 +1986,13 @@ char *gcry_get_config (int mode, const char *what); #define GCRY_FIPS_FLAG_REJECT_MAC (1 << 3) #define GCRY_FIPS_FLAG_REJECT_CIPHER (1 << 4) #define GCRY_FIPS_FLAG_REJECT_PK (1 << 5) +#define GCRY_FIPS_FLAG_REJECT_PK_MD (1 << 6) +#define GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2 (1 << 7) #define GCRY_FIPS_FLAG_REJECT_MD \ (GCRY_FIPS_FLAG_REJECT_MD_MD5 | GCRY_FIPS_FLAG_REJECT_MD_OTHERS) -/* Note: Don't reject MD5 */ +/* Note: Don't reject MD5, PK MD, PK GOST and PK SM2 */ #define GCRY_FIPS_FLAG_REJECT_COMPAT110 \ (GCRY_FIPS_FLAG_REJECT_MD_OTHERS \ | GCRY_FIPS_FLAG_REJECT_MAC \ diff --git a/tests/t-fips-service-ind.c b/tests/t-fips-service-ind.c index 90d92c70..fe963fa5 100644 --- a/tests/t-fips-service-ind.c +++ b/tests/t-fips-service-ind.c @@ -228,6 +228,7 @@ check_pk_s_v (int reject) static struct { const char *prvkey; const char *pubkey; + const char *data; int expect_failure; } tv[] = { { @@ -236,6 +237,8 @@ check_pk_s_v (int reject) "(public-key (ecc (curve nistp256)" " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", + "(data (flags raw)(hash sha256 " + "#00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))", 0 }, { /* non-compliant curve */ @@ -244,28 +247,40 @@ check_pk_s_v (int reject) "(public-key (ecc (curve secp256k1)" " (q #046fcc37ea5e9e09fec6c83e5fbd7a745e3eee81d16ebd861c9e66f55518c19798" "4e9f113c07f875691df8afc1029496fc4cb9509b39dcd38f251a83359cc8b4f7#)))", + "(data (flags raw)(hash sha256 " + "#00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))", 1 - } + }, + { /* non-compliant hash */ + "(private-key (ecc (curve nistp256)" + " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))", + "(public-key (ecc (curve nistp256)" + " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" + "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", + "(data (flags raw)(hash ripemd160 " + "#00112233445566778899AABBCCDDEEFF00010203#))", + 1 + }, + { /* non-compliant hash for signing */ + "(private-key (ecc (curve nistp256)" + " (d #519b423d715f8b581f4fa8ee59f4771a5b44c8130b4e3eacca54a56dda72b464#)))", + "(public-key (ecc (curve nistp256)" + " (q #041ccbe91c075fc7f4f033bfa248db8fccd3565de94bbfb12f3c59ff46c271bf83" + "ce4014c68811f9a21a1fdb2c0e6113e06db7ca93b7404e78dc7ccd5ca89a4ca9#)))", + "(data (flags raw)(hash sha1 " + "#00112233445566778899AABBCCDDEEFF00010203#))", + 1 + }, }; int tvidx; gpg_error_t err; gpg_err_code_t ec; - const char *data = "(data (flags raw)" - "(hash sha256 #00112233445566778899AABBCCDDEEFF000102030405060708090A0B0C0D0E0F#))"; - gcry_sexp_t s_data = NULL; - - err = gcry_sexp_build (&s_data, NULL, data); - if (err) - { - fail ("error building SEXP for test, %s: %s", - "data", gpg_strerror (err)); - return; - } for (tvidx=0; tvidx < DIM(tv); tvidx++) { gcry_sexp_t s_pk = NULL; gcry_sexp_t s_sk = NULL; + gcry_sexp_t s_data = NULL; gcry_sexp_t s_sig= NULL; if (verbose) @@ -287,6 +302,14 @@ check_pk_s_v (int reject) goto next; } + err = gcry_sexp_build (&s_data, NULL, tv[tvidx].data); + if (err) + { + fail ("error building SEXP for test, %s: %s", + "data", gpg_strerror (err)); + goto next; + } + err = gcry_pk_sign (&s_sig, s_data, s_sk); if (err) { @@ -363,11 +386,10 @@ check_pk_s_v (int reject) next: gcry_sexp_release (s_sig); + gcry_sexp_release (s_data); gcry_sexp_release (s_pk); gcry_sexp_release (s_sk); } - - gcry_sexp_release (s_data); } /* Check gcry_pk_hash_sign, gcry_pk_hash_verify API. */ @@ -1461,6 +1483,8 @@ main (int argc, char **argv) xgcry_control ((GCRYCTL_FIPS_REJECT_NON_FIPS, (GCRY_FIPS_FLAG_REJECT_MD_MD5 + | GCRY_FIPS_FLAG_REJECT_PK_MD + | GCRY_FIPS_FLAG_REJECT_PK_GOST_SM2 | GCRY_FIPS_FLAG_REJECT_COMPAT110))); check_md_o_w_r_c (1); -- 2.49.0