summaryrefslogtreecommitdiff
path: root/cipher/ecc-curves.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-09-07 10:06:46 +0200
committerWerner Koch <wk@gnupg.org>2013-09-25 17:06:05 +0200
commitd6683d2a6065986a9198d2d2eaa02c005b68cea4 (patch)
tree20d4f5b0c7512ba955a5e6f9c97d962c989b0a49 /cipher/ecc-curves.c
parent9a4447ccd1b90bcd701941e80a7f484a1825fcea (diff)
downloadlibgcrypt-d6683d2a6065986a9198d2d2eaa02c005b68cea4.tar.gz
ecc: Allow the name "q@eddsa" to get/set the public key.
* cipher/ecc-curves.c (_gcry_ecc_get_mpi): Support "q@eddsa". (_gcry_ecc_set_mpi): Support "q". * cipher/ecc.c (eddsa_encodepoint): Rename to ... (_gcry_ecc_eddsa_encodepoint): this and make global. Remove arg MINLEN and take from context. (eddsa_decodepoint): Rename to (_gcry_ecc_eddsa_decodepoint): this and make global. Remove arg LEN and take from context. (sign_eddsa, verify_eddsa): Take B from context. (ecc_sign, ecc_verify): Add hack to set DIALECT. (_gcry_pk_ecc_get_sexp): Use _gcry_ecc_compute_public. Handle EdDSA. * src/ec-context.h (mpi_ec_ctx_s): Add field NBITS. * mpi/ec.c (ec_p_init): Init NBITS. * tests/t-mpi-point.c (test_curve): Add Ed25519. (sample_ed25519_q): New. (context_param): Check new sample key. (hex2buffer, hex2mpiopa): New. (cmp_mpihex): Take care of opaque MPIs. Signed-off-by: Werner Koch <wk@gnupg.org>
Diffstat (limited to 'cipher/ecc-curves.c')
-rw-r--r--cipher/ecc-curves.c62
1 files changed, 56 insertions, 6 deletions
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index e6a993f2..74473407 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -812,6 +812,9 @@ _gcry_ecc_get_param_sexp (const char *name)
gcry_mpi_t
_gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
{
+ if (!*name)
+ return NULL;
+
if (!strcmp (name, "p") && ec->p)
return mpi_is_const (ec->p) && !copy? ec->p : mpi_copy (ec->p);
if (!strcmp (name, "a") && ec->a)
@@ -833,17 +836,35 @@ _gcry_ecc_get_mpi (const char *name, mpi_ec_t ec, int copy)
if (!strcmp (name, "q.y") && ec->Q && ec->Q->y)
return mpi_is_const (ec->G->y) && !copy? ec->Q->y : mpi_copy (ec->Q->y);
- /* If a point has been requested, return it in standard encoding. */
+ /* If the base point has been requested, return it in standard
+ encoding. */
if (!strcmp (name, "g") && ec->G)
return _gcry_mpi_ec_ec2os (ec->G, ec);
- if (!strcmp (name, "q"))
+
+ /* If the public key has been requested, return it by default in
+ standard uncompressed encoding or if requested in other
+ encodings. */
+ if (*name == 'q' && (!name[1] || name[1] == '@'))
{
/* If only the private key is given, compute the public key. */
if (!ec->Q)
ec->Q = _gcry_ecc_compute_public (NULL, ec);
- if (ec->Q)
+ if (!ec->Q)
+ return NULL;
+
+ if (name[1] != '@')
return _gcry_mpi_ec_ec2os (ec->Q, ec);
+
+ if (!strcmp (name+2, "eddsa") && ec->model == MPI_EC_TWISTEDEDWARDS)
+ {
+ unsigned char *encpk;
+ unsigned int encpklen;
+
+ if (!_gcry_ecc_eddsa_encodepoint (ec->Q, ec, NULL, NULL,
+ &encpk, &encpklen))
+ return gcry_mpi_set_opaque (NULL, encpk, encpklen*8);
+ }
}
return NULL;
@@ -874,7 +895,11 @@ _gcry_ecc_get_point (const char *name, mpi_ec_t ec)
gpg_err_code_t
_gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
{
- if (!strcmp (name, "p"))
+ gpg_err_code_t rc = 0;
+
+ if (!*name)
+ ;
+ else if (!strcmp (name, "p"))
{
mpi_free (ec->p);
ec->p = mpi_copy (newvalue);
@@ -896,15 +921,40 @@ _gcry_ecc_set_mpi (const char *name, gcry_mpi_t newvalue, mpi_ec_t ec)
mpi_free (ec->n);
ec->n = mpi_copy (newvalue);
}
+ else if (*name == 'q' && (!name[1] || name[1] == '@'))
+ {
+ if (newvalue)
+ {
+ if (!ec->Q)
+ ec->Q = gcry_mpi_point_new (0);
+ if (ec->dialect == ECC_DIALECT_ED25519)
+ rc = _gcry_ecc_eddsa_decodepoint (newvalue, ec, ec->Q, NULL, NULL);
+ else
+ rc = _gcry_ecc_os2ec (ec->Q, newvalue);
+ }
+ if (rc || !newvalue)
+ {
+ gcry_mpi_point_release (ec->Q);
+ ec->Q = NULL;
+ }
+ /* Note: We assume that Q matches d and thus do not reset d. */
+ }
else if (!strcmp (name, "d"))
{
mpi_free (ec->d);
ec->d = mpi_copy (newvalue);
+ if (ec->d)
+ {
+ /* We need to reset the public key because it may not
+ anymore match. */
+ gcry_mpi_point_release (ec->Q);
+ ec->Q = NULL;
+ }
}
else
- return GPG_ERR_UNKNOWN_NAME;
+ rc = GPG_ERR_UNKNOWN_NAME;
- return 0;
+ return rc;
}