diff options
author | Werner Koch <wk@gnupg.org> | 2013-10-22 14:26:53 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2013-12-06 20:59:24 +0100 |
commit | 405021cb6d4e470337302c65dec5bc91491a89c1 (patch) | |
tree | fa9b5b6b98c2f37aac1d80ac8e0c035030513ac7 | |
parent | 4cf2c65fe15173c8d68a141a01b34fc1fb9080b7 (diff) | |
download | libgcrypt-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.h | 2 | ||||
-rw-r--r-- | cipher/ecc-eddsa.c | 96 | ||||
-rw-r--r-- | cipher/ecc-misc.c | 48 |
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); |