summaryrefslogtreecommitdiff
path: root/cipher/ecc-eddsa.c
diff options
context:
space:
mode:
authorNIIBE Yutaka <gniibe@fsij.org>2020-06-11 17:19:00 +0900
committerNIIBE Yutaka <gniibe@fsij.org>2020-06-16 10:30:52 +0900
commite25446ecc04442b399302ce72db6d5ea2e9e85e8 (patch)
tree823df49ea56d4c0d8619083eef75e7ccf47d4a31 /cipher/ecc-eddsa.c
parentbd22b029bbf50737f90535c506fba4f812bcf040 (diff)
downloadlibgcrypt-e25446ecc04442b399302ce72db6d5ea2e9e85e8.tar.gz
ecc: Support Ed448 for key generation.
* cipher/ecc-eddsa.c (_gcry_ecc_eddsa_compute_h_d): Support Ed448. (_gcry_ecc_eddsa_genkey): Support Ed448, using _gcry_ecc_eddsa_compute_h_d. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
Diffstat (limited to 'cipher/ecc-eddsa.c')
-rw-r--r--cipher/ecc-eddsa.c77
1 files changed, 45 insertions, 32 deletions
diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 0054aad6..1b49840a 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
@@ -505,13 +505,21 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest, mpi_ec_t ec)
*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. */
+
+ /*
+ * Choice of hashalgo is curve specific.
+ * For now, it's determine by the bit size of the field.
+ */
+ if (ec->nbits == 255)
+ hashalgo = GCRY_MD_SHA512;
+ else if (ec->nbits == 448)
+ {
+ b++;
+ hashalgo = GCRY_MD_SHAKE256;
+ }
+ else
+ return GPG_ERR_NOT_IMPLEMENTED;
/* Note that we clear DIGEST so we can use it as input to left pad
the key with zeroes for hashing. */
@@ -543,9 +551,20 @@ _gcry_ecc_eddsa_compute_h_d (unsigned char **r_digest, mpi_ec_t ec)
}
/* Compute the A value. */
- reverse_buffer (digest, 32); /* Only the first half of the hash. */
- digest[0] = (digest[0] & 0x7f) | 0x40;
- digest[31] &= 0xf8;
+ reverse_buffer (digest, b); /* Only the first half of the hash. */
+
+ /* Field specific handling of clearing/setting bits. */
+ if (ec->nbits == 255)
+ {
+ digest[0] = (digest[0] & 0x7f) | 0x40;
+ digest[31] &= 0xf8;
+ }
+ else
+ {
+ digest[0] = 0;
+ digest[1] |= 0x80;
+ digest[56] &= 0xfc;
+ }
*r_digest = digest;
return 0;
@@ -567,50 +586,45 @@ gpg_err_code_t
_gcry_ecc_eddsa_genkey (mpi_ec_t ec, int flags)
{
gpg_err_code_t rc;
- int b = 256/8; /* The only size we currently support. */
+ int b;
gcry_mpi_t a, x, y;
mpi_point_struct Q;
gcry_random_level_t random_level;
char *dbuf;
size_t dlen;
- gcry_buffer_t hvec[1];
unsigned char *hash_d = NULL;
point_init (&Q);
- memset (hvec, 0, sizeof hvec);
if ((flags & PUBKEY_FLAG_TRANSIENT_KEY))
random_level = GCRY_STRONG_RANDOM;
else
random_level = GCRY_VERY_STRONG_RANDOM;
+ b = (ec->nbits+7)/8;
+
+ if (ec->nbits == 255)
+ ;
+ else if (ec->nbits == 448)
+ b++;
+ else
+ return GPG_ERR_NOT_IMPLEMENTED;
+
+ dlen = b;
+
a = mpi_snew (0);
x = mpi_new (0);
y = mpi_new (0);
/* Generate a secret. */
- hash_d = xtrymalloc_secure (2*b);
- if (!hash_d)
- {
- rc = gpg_err_code_from_syserror ();
- goto leave;
- }
- dlen = b;
dbuf = _gcry_random_bytes_secure (dlen, random_level);
-
- /* Compute the A value. */
- hvec[0].data = dbuf;
- hvec[0].len = dlen;
- rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, hash_d, hvec, 1);
+ ec->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
+ rc = _gcry_ecc_eddsa_compute_h_d (&hash_d, ec);
if (rc)
goto leave;
- ec->d = _gcry_mpi_set_opaque (NULL, dbuf, dlen*8);
- dbuf = NULL;
- reverse_buffer (hash_d, 32); /* Only the first half of the hash. */
- hash_d[0] = (hash_d[0] & 0x7f) | 0x40;
- hash_d[31] &= 0xf8;
- _gcry_mpi_set_buffer (a, hash_d, 32, 0);
- xfree (hash_d); hash_d = NULL;
+
+ _gcry_mpi_set_buffer (a, hash_d, b, 0);
+ xfree (hash_d);
/* log_printmpi ("ecgen a", a); */
/* Compute Q. */
@@ -627,7 +641,6 @@ _gcry_ecc_eddsa_genkey (mpi_ec_t ec, int flags)
_gcry_mpi_release (a);
_gcry_mpi_release (x);
_gcry_mpi_release (y);
- xfree (hash_d);
return rc;
}