2020-05-14 17:39:34 +02:00
|
|
|
|
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_;
|
2020-05-19 14:29:20 +02:00
|
|
|
|
@@ -297,17 +310,190 @@ test_keys (ECC_secret_key *sk, unsigned
|
2020-05-14 17:39:34 +02:00
|
|
|
|
|
|
|
|
|
_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))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("gcry_pk_sign failed: _gcry_md_open\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+
|
|
|
|
|
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
|
|
|
|
|
+ _gcry_md_write (hd, buf, buflen);
|
|
|
|
|
+
|
|
|
|
|
+ xfree (buf);
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ buf = NULL;
|
|
|
|
|
|
|
|
|
|
- if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ 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))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
{
|
|
|
|
|
- log_fatal ("ECDSA operation: sign, verify failed\n");
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecdh: Failed to get affine coordinates for Q\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+
|
|
|
|
|
+ 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);
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ /* build ECC private key sexp in s_skey */
|
|
|
|
|
+ if (sk->E.name)
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ if (sexp_build (&s_skey, NULL,
|
|
|
|
|
+ "(private-key (ecc (curve %s)(d %m)(q %b)))",
|
|
|
|
|
+ sk->E.name, sk->d, qlen, q))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: Failed to build sexp for private key.\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ }
|
|
|
|
|
+ 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))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: Failed to build sexp for private key.\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (_gcry_pk_sign_md (&r_sig, hd, s_hash, s_skey))
|
|
|
|
|
+ {
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: gcry_pk_sign failed\n");
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ goto leave;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Check that the signature and the original test differ. */
|
|
|
|
|
+ if (_gcry_sexp_extract_param (r_sig, NULL, "s", &s_sig_mpi, NULL))
|
|
|
|
|
+ {
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("extracting signature data failed\n");
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ goto leave;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!mpi_cmp (s_sig_mpi, test))
|
|
|
|
|
+ {
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("Signature failed\n");
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ 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))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: Failed to build sexp for public key.\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ }
|
|
|
|
|
+ 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))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: Failed to build sexp for private key.\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ _gcry_md_close (hd);
|
|
|
|
|
+
|
|
|
|
|
+ if (_gcry_md_open (&hd, GCRY_MD_SHA256, 0))
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("gcry_pk_verify failed: _gcry_md_open\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+
|
|
|
|
|
+ _gcry_mpi_aprint (GCRYMPI_FMT_STD, &buf, &buflen, test);
|
|
|
|
|
+ _gcry_md_write (hd, buf, buflen);
|
|
|
|
|
+
|
|
|
|
|
+ xfree (buf);
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ buf = NULL;
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+
|
|
|
|
|
+ /* verify the signature */
|
|
|
|
|
+ if (_gcry_pk_verify_md (r_sig, hd, s_hash, s_pkey))
|
|
|
|
|
+ {
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ecc: gcry_pk_verify failed\n");
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ goto leave; /* Signature does not match. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DBG_CIPHER)
|
2020-05-19 14:29:20 +02:00
|
|
|
|
- log_debug ("ECDSA operation: sign, verify ok.\n");
|
|
|
|
|
+ {
|
|
|
|
|
+ if (DBG_CIPHER)
|
|
|
|
|
+ log_debug ("ECDSA operation: sign, verify ok.\n");
|
|
|
|
|
+ }
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+
|
2020-05-19 14:29:20 +02:00
|
|
|
|
+ result = 0; /* The test succeeded. */
|
|
|
|
|
|
2020-05-14 17:39:34 +02:00
|
|
|
|
+ leave:
|
|
|
|
|
point_free (&pk.Q);
|
|
|
|
|
_gcry_ecc_curve_free (&pk.E);
|
|
|
|
|
|
2020-05-19 14:29:20 +02:00
|
|
|
|
@@ -317,6 +503,16 @@ test_keys (ECC_secret_key *sk, unsigned
|
2020-05-14 17:39:34 +02:00
|
|
|
|
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)
|