File libgcrypt-PCT-ECC.patch of Package libgcrypt.14348

Index: libgcrypt-1.8.2/cipher/ecc.c
===================================================================
--- libgcrypt-1.8.2.orig/cipher/ecc.c
+++ libgcrypt-1.8.2/cipher/ecc.c
@@ -190,6 +190,9 @@ 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)
+    sk->E.name = strdup(E->name);
+
   point_init (&sk->Q);
 
   x = mpi_new (pbits);
@@ -297,17 +300,102 @@ 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_md_hd_t hd = NULL;
+  unsigned char *buf = NULL;
+  size_t buflen;
+  if (_gcry_md_open(&hd, GCRY_MD_SHA256, 0))
+    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);
+
+  mpi_ec_t ctx;
+  int flags = 0;
+  gcry_sexp_t r_sig = NULL;
+  gcry_sexp_t s_hash = NULL;
+  gcry_sexp_t s_pkey = NULL;
+  gcry_sexp_t s_skey = NULL;
+  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 ("ecdh: Failed to get affine coordinates for Q\n");
+
+  unsigned char *rawqx, *rawqy;
+  int rawqxlen, rawqylen;
+  rawqx = _gcry_mpi_get_buffer (Qx, 0, &rawqxlen, NULL);
+  rawqy = _gcry_mpi_get_buffer (Qy, 0, &rawqylen, NULL);
+
+  unsigned char q[1024];
+  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;
+
+  /* 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))
+        log_fatal ("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))
+        log_fatal ("ecc: Failed to build sexp for private key.\n");
+    }
+
+  if (_gcry_pk_sign_md(&r_sig, hd, s_hash, s_skey))
+    {
+      log_debug("ecc: gcry_pk_sign failed\n");
+      goto leave;
+    }
+
+  /* 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))
+        log_fatal ("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))
+        log_fatal ("ecc: Failed to build sexp for private key.\n");
+    }
+
+  if (_gcry_md_open(&hd, GCRY_MD_SHA256, 0))
+    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);
 
-  if (_gcry_ecc_ecdsa_verify (test, &pk, r, s))
+  /* verify the signature */
+  if (_gcry_pk_verify_md(r_sig, hd, s_hash, s_pkey))
     {
-      log_fatal ("ECDSA operation: sign, verify failed\n");
+      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");
 
+leave:
   point_free (&pk.Q);
   _gcry_ecc_curve_free (&pk.E);
 
@@ -317,6 +405,11 @@ test_keys (ECC_secret_key *sk, unsigned
   mpi_free (out);
   mpi_free (c);
   mpi_free (test);
+  _gcry_sexp_release(s_skey);
+  _gcry_sexp_release(s_pkey);
+  _gcry_sexp_release(s_hash);
+  _gcry_sexp_release(r_sig);
+  xfree(buf);
 }
 
 
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(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,42 @@ _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;
+  size_t n;
+  int lalgo;
+
+  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)
openSUSE Build Service is sponsored by