libgcrypt/libgcrypt-PCT-ECC.patch
Vítězslav Čížek b626ac7062 Accepting request 807298 from home:pmonrealgonzalez:branches:devel:libraries:c_c++
- FIPS: RSA/DSA/ECC test_keys() print out debug messages [bsc#1171872]
  * Print the debug messages in test_keys() only in debug mode.
- Update patches: libgcrypt-PCT-RSA.patch libgcrypt-PCT-DSA.patch
  libgcrypt-PCT-ECC.patch

OBS-URL: https://build.opensuse.org/request/show/807298
OBS-URL: https://build.opensuse.org/package/show/devel:libraries:c_c++/libgcrypt?expand=0&rev=135
2020-05-19 12:29:20 +00:00

379 lines
10 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Index: libgcrypt-1.8.2/cipher/ecc.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/ecc.c
+++ libgcrypt-1.8.2/cipher/ecc.c
@@ -99,7 +99,7 @@ static void *progress_cb_data;
/* Local prototypes. */
-static void test_keys (ECC_secret_key * sk, unsigned int nbits);
+static int test_keys (ECC_secret_key * sk, unsigned int nbits);
static void test_ecdh_only_keys (ECC_secret_key * sk, unsigned int nbits, int flags);
static unsigned int ecc_get_nbits (gcry_sexp_t parms);
@@ -152,6 +152,7 @@ nist_generate_key (ECC_secret_key *sk, e
gcry_random_level_t random_level;
gcry_mpi_t x, y;
const unsigned int pbits = mpi_get_nbits (E->p);
+ int free_skEname = 0;
point_init (&Q);
@@ -176,7 +177,6 @@ nist_generate_key (ECC_secret_key *sk, e
else
sk->d = _gcry_dsa_gen_k (E->n, random_level);
-
/* Compute Q. */
_gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx);
@@ -190,6 +190,12 @@ nist_generate_key (ECC_secret_key *sk, e
point_set (&sk->E.G, &E->G);
sk->E.n = mpi_copy (E->n);
sk->E.h = mpi_copy (E->h);
+ if (E->name)
+ {
+ free_skEname = 1;
+ sk->E.name = _gcry_xstrdup(E->name);
+ }
+
point_init (&sk->Q);
x = mpi_new (pbits);
@@ -261,10 +267,16 @@ nist_generate_key (ECC_secret_key *sk, e
if ((flags & PUBKEY_FLAG_NO_KEYTEST))
; /* User requested to skip the test. */
else if (sk->E.model != MPI_EC_MONTGOMERY)
- test_keys (sk, nbits - 64);
+ {
+ if (test_keys (sk, nbits - 64))
+ return GPG_ERR_BAD_SIGNATURE;
+ }
else
test_ecdh_only_keys (sk, nbits - 64, flags);
+ if (free_skEname)
+ xfree ((void*)sk->E.name);
+
return 0;
}
@@ -275,9 +287,10 @@ nist_generate_key (ECC_secret_key *sk, e
* test if the information is recuperated.
* Second, test with the sign and verify functions.
*/
-static void
+static int
test_keys (ECC_secret_key *sk, unsigned int nbits)
{
+ int result = -1; /* Default to failure. */
ECC_public_key pk;
gcry_mpi_t test = mpi_new (nbits);
mpi_point_struct R_;
@@ -297,17 +310,190 @@ test_keys (ECC_secret_key *sk, unsigned
_gcry_mpi_randomize (test, nbits, GCRY_WEAK_RANDOM);
- if (_gcry_ecc_ecdsa_sign (test, sk, r, s, 0, 0) )
- log_fatal ("ECDSA operation: sign failed\n");
+ /* Use the gcry_pk_sign_md API in order to comply with FIPS 140-2,
+ * which requires full signature operation for PCT (hashing +
+ * asymmetric operation). */
+ gcry_sexp_t r_sig = NULL;
+ gcry_sexp_t s_skey = NULL;
+ gcry_sexp_t s_pkey = NULL;
+ gcry_sexp_t s_hash = NULL;
+ gcry_mpi_t s_sig_mpi = NULL;
+ gcry_md_hd_t hd = NULL;
+ unsigned char *buf = NULL;
+ size_t buflen;
+ mpi_ec_t ctx;
+ int flags = 0;
+
+ if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+ {
+ if (DBG_CIPHER)
+ log_debug ("gcry_pk_sign failed: _gcry_md_open\n");
+ }
+
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+ _gcry_md_write (hd, buf, buflen);
+
+ xfree (buf);
+ buf = NULL;
- if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+ sexp_build (&s_hash, NULL, "(data (flags rfc6979)(hash-algo sha256))");
+
+ /* Assemble the point Q from affine coordinates by simple
+ * concatenation. */
+ gcry_mpi_t Qx = NULL;
+ gcry_mpi_t Qy = NULL;
+ Qx = mpi_new (0);
+ Qy = mpi_new (0);
+ ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, flags,
+ sk->E.p, sk->E.a, sk->E.b);
+ if (_gcry_mpi_ec_get_affine (Qx, Qy, &(sk->Q), ctx))
{
- log_fatal ("ECDSA operation: sign, verify failed\n");
+ if (DBG_CIPHER)
+ log_debug ("ecdh: Failed to get affine coordinates for Q\n");
+ }
+
+ unsigned char *rawqx, *rawqy;
+ unsigned int rawqxlen, rawqylen;
+ rawqx = _gcry_mpi_get_buffer (Qx, 0, &rawqxlen, NULL);
+ rawqy = _gcry_mpi_get_buffer (Qy, 0, &rawqylen, NULL);
+
+ if (rawqxlen != rawqylen)
+ {
+ if (rawqxlen < rawqylen)
+ {
+ size_t diff = rawqylen - rawqxlen;
+ unsigned char *zeros = xmalloc (rawqxlen + diff);
+ memset (zeros, 0, rawqxlen + diff);
+ memmove (zeros + diff, rawqx, rawqxlen);
+ xfree (rawqx);
+ rawqx = zeros;
+ rawqxlen += diff;
+ }
+ if (rawqylen < rawqxlen)
+ {
+ size_t diff = rawqxlen - rawqylen;
+ unsigned char *zeros = xmalloc (rawqylen + diff);
+ memset (zeros, 0, rawqylen + diff);
+ memmove (zeros + diff, rawqy, rawqylen);
+ xfree (rawqy);
+ rawqy = zeros;
+ rawqylen += diff;
+ }
+ }
+
+ unsigned char q[1 + rawqxlen + rawqxlen];
+ size_t qlen;
+ memset (&q, 0, sizeof(q));
+ *q = 4;
+ memcpy (q + 1, rawqx, rawqxlen);
+ memcpy (q + 1 + rawqxlen, rawqy, rawqylen);
+ qlen = 1 + rawqxlen + rawqylen;
+
+ _gcry_mpi_release (Qx);
+ _gcry_mpi_release (Qy);
+ xfree (rawqx);
+ xfree (rawqy);
+
+ /* build ECC private key sexp in s_skey */
+ if (sk->E.name)
+ {
+ if (sexp_build (&s_skey, NULL,
+ "(private-key (ecc (curve %s)(d %m)(q %b)))",
+ sk->E.name, sk->d, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+ else
+ {
+ if (sexp_build (&s_skey, NULL,
+ "(private-key"
+ " (ecc (curve %s)(d %m)(p %m)(a %m)(b %m)(n %m)(h %m)(q %b)))",
+ "NIST P-512", sk->d, sk->E.p, sk->E.a, sk->E.b, sk->E.n, sk->E.h,
+ qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+
+ if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: gcry_pk_sign failed\n");
+ goto leave;
+ }
+
+ /* Check that the signature and the original test differ. */
+ if (_gcry_sexp_extract_param (r_sig, NULL, "s", &s_sig_mpi, NULL))
+ {
+ if (DBG_CIPHER)
+ log_debug ("extracting signature data failed\n");
+ goto leave;
+ }
+
+ if (!mpi_cmp (s_sig_mpi, test))
+ {
+ if (DBG_CIPHER)
+ log_debug ("Signature failed\n");
+ goto leave; /* Signature and test match but should not. */
+ }
+
+ /* verify */
+ /* build public key sexp in s_pkey */
+ if (pk.E.name)
+ {
+ if (sexp_build (&s_pkey, NULL,
+ "(public-key (ecc (curve %s)(q %b)))", pk.E.name, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for public key.\n");
+ }
+ }
+ else
+ {
+ if (sexp_build (&s_pkey, NULL,
+ "(public-key"
+ " (ecc (curve %s)(p %m)(a %m)(b %m)(n %m)(h %m)(q %b)))",
+ "NIST P-512", pk.E.p, pk.E.a, pk.E.b, pk.E.n, pk.E.h, qlen, q))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: Failed to build sexp for private key.\n");
+ }
+ }
+
+ _gcry_md_close (hd);
+
+ if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
+ {
+ if (DBG_CIPHER)
+ log_debug ("gcry_pk_verify failed: _gcry_md_open\n");
+ }
+
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
+ _gcry_md_write (hd, buf, buflen);
+
+ xfree (buf);
+ buf = NULL;
+
+ /* verify the signature */
+ if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey))
+ {
+ if (DBG_CIPHER)
+ log_debug ("ecc: gcry_pk_verify failed\n");
+ goto leave; /* Signature does not match. */
}
if (DBG_CIPHER)
- log_debug ("ECDSA operation: sign, verify ok.\n");
+ {
+ if (DBG_CIPHER)
+ log_debug ("ECDSA operation: sign, verify ok.\n");
+ }
+
+ result = 0; /* The test succeeded. */
+ leave:
point_free (&pk.Q);
_gcry_ecc_curve_free (&pk.E);
@@ -317,6 +503,16 @@ test_keys (ECC_secret_key *sk, unsigned
mpi_free (out);
mpi_free (c);
mpi_free (test);
+
+ _gcry_sexp_release (r_sig);
+ _gcry_sexp_release (s_skey);
+ _gcry_sexp_release (s_pkey);
+ _gcry_sexp_release (s_hash);
+ _gcry_mpi_release (s_sig_mpi);
+ _gcry_md_close (hd);
+ xfree (ctx);
+
+ return result;
}
Index: libgcrypt-1.8.2/cipher/pubkey.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey.c
+++ libgcrypt-1.8.2/cipher/pubkey.c
@@ -390,6 +390,7 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
gcry_err_code_t rc;
const unsigned char *digest;
int algo;
+ const char *flags;
if (!hd)
return 0;
@@ -398,16 +399,21 @@ calculate_hash (gcry_md_hd_t hd, gcry_se
if (rc)
return rc;
+ rc = _gcry_pk_util_get_flags (*s_hash, &flags);
+ if (rc)
+ return rc;
+
digest = _gcry_md_read(hd, algo);
if (!digest)
return GPG_ERR_DIGEST_ALGO;
rc = _gcry_sexp_build (s_hash, NULL,
- "(data (flags pkcs1)(hash %s %b))",
+ "(data (flags %s)(hash %s %b))", flags,
_gcry_md_algo_name(algo),
(int) _gcry_md_get_algo_dlen(algo),
digest);
+ xfree ((void *)flags);
return rc;
}
Index: libgcrypt-1.8.2/cipher/pubkey-internal.h
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey-internal.h
+++ libgcrypt-1.8.2/cipher/pubkey-internal.h
@@ -45,6 +45,8 @@ gcry_err_code_t _gcry_pk_util_data_to_mp
struct pk_encoding_ctx *ctx);
gcry_err_code_t _gcry_pk_util_get_algo (gcry_sexp_t input,
int *algo);
+gcry_err_code_t _gcry_pk_util_get_flags (gcry_sexp_t input,
+ const char **flags);
Index: libgcrypt-1.8.2/cipher/pubkey-util.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/pubkey-util.c
+++ libgcrypt-1.8.2/cipher/pubkey-util.c
@@ -1120,6 +1120,40 @@ _gcry_pk_util_data_to_mpi (gcry_sexp_t i
return rc;
}
+gcry_err_code_t
+_gcry_pk_util_get_flags (gcry_sexp_t input, const char **flags)
+{
+ gcry_err_code_t rc = 0;
+ gcry_sexp_t ldata, list = NULL;
+
+ ldata = sexp_find_token (input, "data", 0);
+ if (!ldata)
+ {
+ rc = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+
+ list = sexp_find_token (ldata, "flags", 0);
+ if (!list)
+ {
+ rc = GPG_ERR_INV_OBJ;
+ goto leave;
+ }
+
+ /* FIXME: gets only the first flag */
+ *flags = sexp_nth_string (list, 1);
+ if (!*flags)
+ {
+ rc = GPG_ERR_NO_OBJ;
+ goto leave;
+ }
+
+ leave:
+ sexp_release (ldata);
+ sexp_release (list);
+
+ return rc;
+}
gcry_err_code_t
_gcry_pk_util_get_algo (gcry_sexp_t input, int *algo)