summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-10-22 14:26:53 +0200
committerWerner Koch <wk@gnupg.org>2013-12-06 20:59:24 +0100
commit405021cb6d4e470337302c65dec5bc91491a89c1 (patch)
treefa9b5b6b98c2f37aac1d80ac8e0c035030513ac7
parent4cf2c65fe15173c8d68a141a01b34fc1fb9080b7 (diff)
downloadlibgcrypt-405021cb6d4e470337302c65dec5bc91491a89c1.tar.gz
ecc: Merge partly duplicated code.
* 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>
-rw-r--r--cipher/ecc-common.h2
-rw-r--r--cipher/ecc-eddsa.c96
-rw-r--r--cipher/ecc-misc.c48
3 files changed, 69 insertions, 77 deletions
diff --git a/cipher/ecc-common.h b/cipher/ecc-common.h
index dc4a9d03..c407c744 100644
--- a/cipher/ecc-common.h
+++ b/cipher/ecc-common.h
@@ -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,
diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 12cdea0c..17c1f731 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
@@ -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
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index 26c9e8d9..ae3e4f04 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -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);