ecc: Merge partly duplicated code.
authorWerner Koch <wk@gnupg.org>
Tue, 22 Oct 2013 12:26:53 +0000 (14:26 +0200)
committerWerner Koch <wk@gnupg.org>
Fri, 6 Dec 2013 19:59:24 +0000 (20:59 +0100)
* cipher/ecc-eddsa.c (_gcry_ecc_eddsa_sign): Factor A hashing out to ...
(_gcry_ecc_eddsa_compute_h_d): new function.
* cipher/ecc-misc.c (_gcry_ecc_compute_public): Use new function.
(reverse_buffer): Remove.

Signed-off-by: Werner Koch <wk@gnupg.org>
cipher/ecc-common.h
cipher/ecc-eddsa.c
cipher/ecc-misc.c

index dc4a9d0..c407c74 100644 (file)
@@ -115,6 +115,8 @@ gpg_err_code_t _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx,
                                             mpi_point_t result,
                                             unsigned char **r_encpk,
                                             unsigned int *r_encpklen);
+gpg_err_code_t _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
+                                            gcry_mpi_t d, mpi_ec_t ec);
 
 gpg_err_code_t _gcry_ecc_eddsa_genkey (ECC_secret_key *sk,
                                        elliptic_curve_t *E,
index 12cdea0..17c1f73 100644 (file)
@@ -368,6 +368,71 @@ _gcry_ecc_eddsa_decodepoint (gcry_mpi_t pk, mpi_ec_t ctx, mpi_point_t result,
 }
 
 
+/* Compute the A value as used by EdDSA.  The caller needs to provide
+   the context EC and the actual secret D as an MPI.  The function
+   returns a newly allocated 64 byte buffer at r_digest; the first 32
+   bytes represent the A value.  NULL is returned on error and NULL
+   stored at R_DIGEST.  */
+gpg_err_code_t
+_gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest,
+                             gcry_mpi_t d, mpi_ec_t ec)
+{
+  gpg_err_code_t rc;
+  unsigned char *rawmpi = NULL;
+  unsigned int rawmpilen;
+  unsigned char *digest;
+  gcry_buffer_t hvec[2];
+  int hashalgo, b;
+
+  *r_digest = NULL;
+
+  hashalgo = GCRY_MD_SHA512;
+  if (hashalgo != GCRY_MD_SHA512)
+    return GPG_ERR_DIGEST_ALGO;
+
+  b = (ec->nbits+7)/8;
+  if (b != 256/8)
+    return GPG_ERR_INTERNAL; /* We only support 256 bit. */
+
+  /* Note that we clear DIGEST so we can use it as input to left pad
+     the key with zeroes for hashing.  */
+  digest = gcry_calloc_secure (2, b);
+  if (!digest)
+    return gpg_err_code_from_syserror ();
+
+  memset (hvec, 0, sizeof hvec);
+
+  rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
+  if (!rawmpi)
+    {
+      gcry_free (digest);
+      return gpg_err_code_from_syserror ();
+    }
+
+  hvec[0].data = digest;
+  hvec[0].off = 0;
+  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
+  hvec[1].data = rawmpi;
+  hvec[1].off = 0;
+  hvec[1].len = rawmpilen;
+  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
+  gcry_free (rawmpi);
+  if (rc)
+    {
+      gcry_free (digest);
+      return rc;
+    }
+
+  /* Compute the A value.  */
+  reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
+  digest[0]   = (digest[0] & 0x7f) | 0x40;
+  digest[31] &= 0xf8;
+
+  *r_digest = digest;
+  return 0;
+}
+
+
 /* Ed25519 version of the key generation.  */
 gpg_err_code_t
 _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx,
@@ -480,8 +545,6 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
 
   if (!mpi_is_opaque (input))
     return GPG_ERR_INV_DATA;
-  if (hashalgo != GCRY_MD_SHA512)
-    return GPG_ERR_DIGEST_ALGO;
 
   /* Initialize some helpers.  */
   point_init (&I);
@@ -496,36 +559,9 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
   if (b != 256/8)
     return GPG_ERR_INTERNAL; /* We only support 256 bit. */
 
-  digest = gcry_calloc_secure (2, b);
-  if (!digest)
-    {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
-    }
-
-  /* Hash the secret key.  We clear DIGEST so we can use it as input
-     to left pad the key with zeroes for hashing.  */
-  rawmpi = _gcry_mpi_get_buffer (skey->d, 0, &rawmpilen, NULL);
-  if (!rawmpi)
-    {
-      rc = gpg_err_code_from_syserror ();
-      goto leave;
-    }
-  hvec[0].data = digest;
-  hvec[0].off = 0;
-  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
-  hvec[1].data = rawmpi;
-  hvec[1].off = 0;
-  hvec[1].len = rawmpilen;
-  rc = _gcry_md_hash_buffers (hashalgo, 0, digest, hvec, 2);
-  gcry_free (rawmpi); rawmpi = NULL;
+  rc = _gcry_ecc_eddsa_compute_h_d (&digest, skey->d, ctx);
   if (rc)
     goto leave;
-
-  /* Compute the A value (this modifies DIGEST).  */
-  reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
-  digest[0] = (digest[0] & 0x7f) | 0x40;
-  digest[31] &= 0xf8;
   _gcry_mpi_set_buffer (a, digest, 32, 0);
 
   /* Compute the public key if it has not been supplied as optional
index 26c9e8d..ae3e4f0 100644 (file)
@@ -236,20 +236,6 @@ _gcry_ecc_os2ec (mpi_point_t result, gcry_mpi_t value)
 }
 
 
-static void
-reverse_buffer (unsigned char *buffer, unsigned int length)
-{
-  unsigned int tmp, i;
-
-  for (i=0; i < length/2; i++)
-    {
-      tmp = buffer[i];
-      buffer[i] = buffer[length-1-i];
-      buffer[length-1-i] = tmp;
-    }
-}
-
-
 /* Compute the public key from the the context EC.  Obviously a
    requirement is that the secret key is available in EC.  On success
    Q is returned; on error NULL.  If Q is NULL a newly allocated point
@@ -259,8 +245,6 @@ mpi_point_t
 _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
                           mpi_point_t G, gcry_mpi_t d)
 {
-  int rc;
-
   if (!G)
     G = ec->G;
   if (!d)
@@ -275,41 +259,11 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec,
       && (ec->flags & PUBKEY_FLAG_EDDSA))
     {
       gcry_mpi_t a;
-      unsigned char *rawmpi = NULL;
-      unsigned int rawmpilen;
       unsigned char *digest;
-      gcry_buffer_t hvec[2];
-      int b = (ec->nbits+7)/8;
-
-      gcry_assert (b >= 32);
-      digest = gcry_calloc_secure (2, b);
-      if (!digest)
-        return NULL;
-      memset (hvec, 0, sizeof hvec);
 
-      rawmpi = _gcry_mpi_get_buffer (d, 0, &rawmpilen, NULL);
-      if (!rawmpi)
+      if (_gcry_ecc_eddsa_compute_h_d (&digest, d, ec))
         return NULL;
-      memset (digest, 0, b);
-      hvec[0].data = digest;
-      hvec[0].off = 0;
-      hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
-      hvec[1].data = rawmpi;
-      hvec[1].off = 0;
-      hvec[1].len = rawmpilen;
-      /* FIXME: Put and take the hash algo from the context.  */
-      rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, digest, hvec, 2);
-      gcry_free (rawmpi);
-      if (rc)
-        {
-          gcry_free (digest);
-          return NULL;
-        }
 
-      /* Compute the A value.  */
-      reverse_buffer (digest, 32);  /* Only the first half of the hash.  */
-      digest[0] = (digest[0] & 0x7f) | 0x40;
-      digest[31] &= 0xf8;
       a = mpi_snew (0);
       _gcry_mpi_set_buffer (a, digest, 32, 0);
       gcry_free (digest);