summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelen <jjelen@redhat.com>2022-08-15 19:55:33 +0200
committerNIIBE Yutaka <gniibe@fsij.org>2022-08-30 11:01:08 +0900
commit076a8adaf314d593ca25c245d2a74207710a4fe7 (patch)
treead07824c909b536af08661e3d13b0d0bd2486e45
parent78151e6d6bbbbf1248b7c32cbab0b9b638ad6c11 (diff)
downloadlibgcrypt-076a8adaf314d593ca25c245d2a74207710a4fe7.tar.gz
ecc: Run PCT also with the digest step
* cipher/ecc.c (test_keys_fips): New function (nist_generate_key): In FIPS mode, execute new PCT test --- Cherry-picked from master commit: 505f048cac8e5af92d3431bd97ade492d1a30bc2 Signed-off-by: Jakub Jelen <jjelen@redhat.com>
-rw-r--r--cipher/ecc.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 63b0d05e..783e249d 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -101,6 +101,7 @@ static void *progress_cb_data;
/* Local prototypes. */
static void test_keys (mpi_ec_t ec, unsigned int nbits);
+static void test_keys_fips (mpi_ec_t ec, gcry_mpi_t x, gcry_mpi_t y);
static void test_ecdh_only_keys (mpi_ec_t ec, unsigned int nbits, int flags);
static unsigned int ecc_get_nbits (gcry_sexp_t parms);
@@ -255,6 +256,8 @@ nist_generate_key (mpi_ec_t ec, int flags,
; /* User requested to skip the test. */
else if (ec->model == MPI_EC_MONTGOMERY)
test_ecdh_only_keys (ec, ec->nbits - 63, flags);
+ else if (fips_mode ())
+ test_keys_fips (ec, x, y);
else
test_keys (ec, ec->nbits - 64);
@@ -304,6 +307,84 @@ test_keys (mpi_ec_t ec, unsigned int nbits)
mpi_free (test);
}
+/* We should get here only with the NIST curves as they are the only ones
+ * having the fips bit set in ecc_domain_parms_t struct so this is slightly
+ * simpler than the whole ecc_generate function */
+static void
+test_keys_fips (mpi_ec_t ec, gcry_mpi_t Qx, gcry_mpi_t Qy)
+{
+ gcry_md_hd_t hd = NULL;
+ const char *data_tmpl = "(data (flags rfc6979) (hash %s %b))";
+ gcry_sexp_t skey = NULL, pkey = NULL;
+ gcry_sexp_t curve_info = NULL;
+ gcry_sexp_t sig = NULL;
+ gcry_mpi_t public = NULL;
+ char plaintext[128];
+ int rc;
+
+ /* Build keys structures */
+ if (ec->name)
+ {
+ rc = sexp_build (&curve_info, NULL, "(curve %s)", ec->name);
+ if (rc)
+ log_fatal ("ECDSA operation: failed to build curve_info\n");
+ }
+
+ public = _gcry_ecc_ec2os (Qx, Qy, ec->p);
+ rc = sexp_build (&pkey, NULL,
+ "(key-data"
+ " (public-key"
+ " (ecc%S(q%m)))"
+ " )",
+ curve_info,
+ public);
+ if (rc)
+ log_fatal ("ECDSA operation: failed to build public key: %s\n", gpg_strerror (rc));
+ rc = sexp_build (&skey, NULL,
+ "(key-data"
+ " (private-key"
+ " (ecc%S(q%m)(d%m)))"
+ " )",
+ curve_info,
+ public, ec->d);
+ if (rc)
+ log_fatal ("ECDSA operation: failed to build private key: %s\n", gpg_strerror (rc));
+
+ /* Create a random plaintext. */
+ _gcry_randomize (plaintext, sizeof plaintext, GCRY_WEAK_RANDOM);
+
+ /* Open MD context and feed the random data in */
+ rc = _gcry_md_open (&hd, GCRY_MD_SHA256, 0);
+ if (rc)
+ log_fatal ("ECDSA operation: failed to initialize MD context: %s\n", gpg_strerror (rc));
+ _gcry_md_write (hd, plaintext, sizeof(plaintext));
+
+ /* Sign the data */
+ rc = _gcry_pk_sign_md (&sig, data_tmpl, hd, skey, NULL);
+ if (rc)
+ log_fatal ("ECDSA operation: signing failed: %s\n", gpg_strerror (rc));
+
+ /* Verify this signature. */
+ rc = _gcry_pk_verify_md (sig, data_tmpl, hd, pkey, NULL);
+ if (rc)
+ log_fatal ("ECDSA operation: verification failed: %s\n", gpg_strerror (rc));
+
+ /* Modify the data and check that the signing fails. */
+ _gcry_md_reset(hd);
+ plaintext[sizeof plaintext / 2] ^= 1;
+ _gcry_md_write (hd, plaintext, sizeof(plaintext));
+ rc = _gcry_pk_verify_md (sig, data_tmpl, hd, pkey, NULL);
+ if (rc != GPG_ERR_BAD_SIGNATURE)
+ log_fatal ("ECDSA operation: signature verification worked on modified data\n");
+
+ mpi_free (public);
+ sexp_release (curve_info);
+ _gcry_md_close (hd);
+ sexp_release (pkey);
+ sexp_release (skey);
+ sexp_release (sig);
+}
+
static void
test_ecdh_only_keys (mpi_ec_t ec, unsigned int nbits, int flags)