summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cipher/ecc-curves.c128
-rw-r--r--cipher/ecc-ecdsa.c4
-rw-r--r--cipher/ecc-eddsa.c4
-rw-r--r--cipher/ecc-gost.c4
-rw-r--r--cipher/ecc-misc.c112
-rw-r--r--cipher/ecc.c10
-rw-r--r--doc/gcrypt.texi2
-rw-r--r--mpi/ec.c8
-rw-r--r--src/ec-context.h2
-rw-r--r--src/mpi.h2
10 files changed, 159 insertions, 117 deletions
diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c
index fb0db3b6..1bd3679f 100644
--- a/cipher/ecc-curves.c
+++ b/cipher/ecc-curves.c
@@ -545,28 +545,36 @@ mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name)
/* Helper to extract a point from key parameters. If no parameter
with NAME is found, the functions tries to find a non-encoded point
by appending ".x", ".y" and ".z" to NAME. ".z" is in this case
- optional and defaults to 1. */
+ optional and defaults to 1. EC is the context which at this point
+ may not be fully initialized. */
static gpg_err_code_t
point_from_keyparam (gcry_mpi_point_t *r_a,
- gcry_sexp_t keyparam, const char *name)
+ gcry_sexp_t keyparam, const char *name, mpi_ec_t ec)
{
- gcry_err_code_t ec;
- gcry_mpi_t a = NULL;
+ gcry_err_code_t rc;
+ gcry_sexp_t l1;
gcry_mpi_point_t point;
- ec = mpi_from_keyparam (&a, keyparam, name);
- if (ec)
- return ec;
-
- if (a)
+ l1 = gcry_sexp_find_token (keyparam, name, 0);
+ if (l1)
{
+ gcry_mpi_t a;
+
+ a = _gcry_sexp_nth_opaque_mpi (l1, 1);
+ gcry_sexp_release (l1);
+ if (!a)
+ return GPG_ERR_INV_OBJ;
+
point = gcry_mpi_point_new (0);
- ec = _gcry_ecc_os2ec (point, a);
+ if (ec && ec->dialect == ECC_DIALECT_ED25519)
+ rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL);
+ else
+ rc = _gcry_ecc_os2ec (point, a);
mpi_free (a);
- if (ec)
+ if (rc)
{
gcry_mpi_point_release (point);
- return ec;
+ return rc;
}
}
else
@@ -580,28 +588,28 @@ point_from_keyparam (gcry_mpi_point_t *r_a,
if (!tmpname)
return gpg_err_code_from_syserror ();
strcpy (stpcpy (tmpname, name), ".x");
- ec = mpi_from_keyparam (&x, keyparam, tmpname);
- if (ec)
+ rc = mpi_from_keyparam (&x, keyparam, tmpname);
+ if (rc)
{
gcry_free (tmpname);
- return ec;
+ return rc;
}
strcpy (stpcpy (tmpname, name), ".y");
- ec = mpi_from_keyparam (&y, keyparam, tmpname);
- if (ec)
+ rc = mpi_from_keyparam (&y, keyparam, tmpname);
+ if (rc)
{
mpi_free (x);
gcry_free (tmpname);
- return ec;
+ return rc;
}
strcpy (stpcpy (tmpname, name), ".z");
- ec = mpi_from_keyparam (&z, keyparam, tmpname);
- if (ec)
+ rc = mpi_from_keyparam (&z, keyparam, tmpname);
+ if (rc)
{
mpi_free (y);
mpi_free (x);
gcry_free (tmpname);
- return ec;
+ return rc;
}
if (!z)
z = mpi_set_ui (NULL, 1);
@@ -645,35 +653,43 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
gcry_mpi_t n = NULL;
gcry_mpi_point_t Q = NULL;
gcry_mpi_t d = NULL;
+ int flags = 0;
gcry_sexp_t l1;
*r_ctx = NULL;
if (keyparam)
{
- errc = mpi_from_keyparam (&p, keyparam, "p");
- if (errc)
- goto leave;
- errc = mpi_from_keyparam (&a, keyparam, "a");
- if (errc)
- goto leave;
- errc = mpi_from_keyparam (&b, keyparam, "b");
- if (errc)
- goto leave;
- errc = point_from_keyparam (&G, keyparam, "g");
- if (errc)
- goto leave;
- errc = mpi_from_keyparam (&n, keyparam, "n");
- if (errc)
- goto leave;
- errc = point_from_keyparam (&Q, keyparam, "q");
- if (errc)
- goto leave;
- errc = mpi_from_keyparam (&d, keyparam, "d");
- if (errc)
- goto leave;
- }
+ /* Parse an optional flags list. */
+ l1 = gcry_sexp_find_token (keyparam, "flags", 0);
+ if (l1)
+ {
+ errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL);
+ gcry_sexp_release (l1);
+ l1 = NULL;
+ if (errc)
+ goto leave;
+ }
+ if (!(flags & PUBKEY_FLAG_NOPARAM))
+ {
+ errc = mpi_from_keyparam (&p, keyparam, "p");
+ if (errc)
+ goto leave;
+ errc = mpi_from_keyparam (&a, keyparam, "a");
+ if (errc)
+ goto leave;
+ errc = mpi_from_keyparam (&b, keyparam, "b");
+ if (errc)
+ goto leave;
+ errc = point_from_keyparam (&G, keyparam, "g", NULL);
+ if (errc)
+ goto leave;
+ errc = mpi_from_keyparam (&n, keyparam, "n");
+ if (errc)
+ goto leave;
+ }
+ }
/* Check whether a curve parameter is available and use that to fill
in missing values. If no curve parameter is available try an
@@ -751,7 +767,8 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
gcry_free (E);
}
- errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, p, a, b);
+
+ errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b);
if (!errc)
{
mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
@@ -771,6 +788,22 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
ec->n = n;
n = NULL;
}
+
+ /* Now that we now the curve name we can look for the public key
+ Q. point_from_keyparam needs to know the curve parameters so
+ that it is able to use the correct decompression. Parsing
+ the private key D could have been done earlier but it is less
+ surprising if we do it here as well. */
+ if (keyparam)
+ {
+ errc = point_from_keyparam (&Q, keyparam, "q", ec);
+ if (errc)
+ goto leave;
+ errc = mpi_from_keyparam (&d, keyparam, "d");
+ if (errc)
+ goto leave;
+ }
+
if (Q)
{
ec->Q = Q;
@@ -783,9 +816,11 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx,
}
*r_ctx = ctx;
+ ctx = NULL;
}
leave:
+ gcry_ctx_release (ctx);
mpi_free (p);
mpi_free (a);
mpi_free (b);
@@ -814,7 +849,10 @@ _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey)
g_x = mpi_new (0);
g_y = mpi_new (0);
- ctx = _gcry_mpi_ec_p_internal_new (0, ECC_DIALECT_STANDARD, E.p, E.a, NULL);
+ ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS,
+ ECC_DIALECT_STANDARD,
+ 0,
+ E.p, E.a, NULL);
if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx))
log_fatal ("ecc get param: Failed to get affine coordinates\n");
_gcry_mpi_ec_free (ctx);
diff --git a/cipher/ecc-ecdsa.c b/cipher/ecc-ecdsa.c
index 70dfe38d..7663623d 100644
--- a/cipher/ecc-ecdsa.c
+++ b/cipher/ecc-ecdsa.c
@@ -78,7 +78,7 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
x = mpi_alloc (0);
point_init (&I);
- ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
skey->E.p, skey->E.a, skey->E.b);
/* Two loops to avoid R or S are zero. This is more of a joke than
@@ -179,7 +179,7 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
point_init (&Q1);
point_init (&Q2);
- ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
pkey->E.p, pkey->E.a, pkey->E.b);
/* h = s^(-1) (mod n) */
diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c
index 22f27023..d83b7c69 100644
--- a/cipher/ecc-eddsa.c
+++ b/cipher/ecc-eddsa.c
@@ -441,7 +441,7 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey,
x = mpi_new (0);
y = mpi_new (0);
r = mpi_new (0);
- ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
skey->E.p, skey->E.a, skey->E.b);
b = (ctx->nbits+7)/8;
if (b != 256/8)
@@ -618,7 +618,7 @@ _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey,
h = mpi_new (0);
s = mpi_new (0);
- ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
pkey->E.p, pkey->E.a, pkey->E.b);
b = ctx->nbits/8;
if (b != 256/8)
diff --git a/cipher/ecc-gost.c b/cipher/ecc-gost.c
index a40459c0..ce3e921a 100644
--- a/cipher/ecc-gost.c
+++ b/cipher/ecc-gost.c
@@ -77,7 +77,7 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey,
x = mpi_alloc (0);
point_init (&I);
- ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0,
skey->E.p, skey->E.a, skey->E.b);
mpi_mod (e, input, skey->E.n); /* e = hash mod n */
@@ -164,7 +164,7 @@ _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey,
point_init (&Q1);
point_init (&Q2);
- ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0,
pkey->E.p, pkey->E.a, pkey->E.b);
mpi_mod (e, input, pkey->E.n); /* e = hash mod n */
diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c
index fa0bded5..6c75e75d 100644
--- a/cipher/ecc-misc.c
+++ b/cipher/ecc-misc.c
@@ -26,6 +26,7 @@
#include "g10lib.h"
#include "mpi.h"
+#include "cipher.h"
#include "context.h"
#include "ec-context.h"
#include "ecc-common.h"
@@ -263,67 +264,62 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec)
if (ec->model == MPI_EC_TWISTEDEDWARDS && !ec->b)
return NULL;
- switch (ec->dialect)
+ if (ec->dialect == ECC_DIALECT_ED25519
+ && !(ec->flags & PUBKEY_FLAG_ECDSA))
{
- case ECC_DIALECT_ED25519:
- {
- 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)
+ 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 (ec->d, 0, &rawmpilen, NULL);
+ if (!rawmpi)
+ 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;
- memset (hvec, 0, sizeof hvec);
+ }
- rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL);
- if (!rawmpi)
- 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);
-
- /* And finally the public key. */
- if (!Q)
- Q = gcry_mpi_point_new (0);
- if (Q)
- _gcry_mpi_ec_mul_point (Q, a, ec->G, ec);
- mpi_free (a);
- }
- break;
-
- default:
- {
- if (!Q)
- Q = gcry_mpi_point_new (0);
- if (Q)
- _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec);
- }
- break;
+ /* 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);
+
+ /* And finally the public key. */
+ if (!Q)
+ Q = gcry_mpi_point_new (0);
+ if (Q)
+ _gcry_mpi_ec_mul_point (Q, a, ec->G, ec);
+ mpi_free (a);
+ }
+ else
+ {
+ if (!Q)
+ Q = gcry_mpi_point_new (0);
+ if (Q)
+ _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec);
}
return Q;
diff --git a/cipher/ecc.c b/cipher/ecc.c
index 752dfc10..8bc8ea6c 100644
--- a/cipher/ecc.c
+++ b/cipher/ecc.c
@@ -312,7 +312,7 @@ check_secret_key (ECC_secret_key * sk)
goto leave;
}
- ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect,
+ ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, 0,
sk->E.p, sk->E.a, sk->E.b);
_gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx);
@@ -469,7 +469,7 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey)
else
random_level = GCRY_VERY_STRONG_RANDOM;
- ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, E.p, E.a, E.b);
+ ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, 0, E.p, E.a, E.b);
x = mpi_new (0);
y = mpi_new (0);
@@ -984,7 +984,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms)
/* Fixme: Factor the curve context setup out of eddsa_verify
and ecdsa_verify. So that we don't do it twice. */
- ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect,
+ ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
pk.E.p, pk.E.a, pk.E.b);
rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &pk.Q, NULL, NULL);
@@ -1169,7 +1169,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms)
}
/* Compute the encrypted value. */
- ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect,
+ ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0,
pk.E.p, pk.E.a, pk.E.b);
/* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */
@@ -1338,7 +1338,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms)
return rc;
}
- ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect,
+ ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, 0,
sk.E.p, sk.E.a, sk.E.b);
/* R = dkG */
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index 76cf0bdb..9c695e02 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -2278,7 +2278,7 @@ For ECC key generation do not return the domain parameters but only
the name of the curve. For ECC signing and verification ignore any
provided domain parameters of the public or private key and use only
the curve name. It is more secure to rely on the curve name and thus
-use the curve parameters as known by Libgcrypt. This option shouild
+use the curve parameters as known by Libgcrypt. This option should
have been the default but for backward compatibility reasons this is
not possible. It is best to always use this flag with ECC keys.
diff --git a/mpi/ec.c b/mpi/ec.c
index 39ab5ebe..57396ce0 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -350,6 +350,7 @@ ec_get_two_inv_p (mpi_ec_t ec)
static void
ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
+ int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
int i;
@@ -367,6 +368,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model,
ctx->model = model;
ctx->dialect = dialect;
+ ctx->flags = flags;
if (dialect == ECC_DIALECT_ED25519)
ctx->nbits = 256;
else
@@ -454,12 +456,13 @@ ec_deinit (void *opaque)
mpi_ec_t
_gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
+ int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
mpi_ec_t ctx;
ctx = gcry_xcalloc (1, sizeof *ctx);
- ec_p_init (ctx, model, dialect, p, a, b);
+ ec_p_init (ctx, model, dialect, flags, p, a, b);
return ctx;
}
@@ -476,6 +479,7 @@ gpg_err_code_t
_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
+ int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b)
{
gcry_ctx_t ctx;
@@ -489,7 +493,7 @@ _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
if (!ctx)
return gpg_err_code_from_syserror ();
ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
- ec_p_init (ec, model, dialect, p, a, b);
+ ec_p_init (ec, model, dialect, flags, p, a, b);
*r_ctx = ctx;
return 0;
diff --git a/src/ec-context.h b/src/ec-context.h
index a118608e..60ca7590 100644
--- a/src/ec-context.h
+++ b/src/ec-context.h
@@ -27,6 +27,8 @@ struct mpi_ec_ctx_s
enum ecc_dialects dialect; /* The ECC dialect used with the curve. */
+ int flags; /* Public key flags (not always used). */
+
unsigned int nbits; /* Number of bits. */
/* Domain parameters. Note that they may not all be set and if set
diff --git a/src/mpi.h b/src/mpi.h
index 15fb5423..a5d805e3 100644
--- a/src/mpi.h
+++ b/src/mpi.h
@@ -312,10 +312,12 @@ void _gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx);
mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
+ int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx,
enum gcry_mpi_ec_models model,
enum ecc_dialects dialect,
+ int flags,
gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b);
void _gcry_mpi_ec_free (mpi_ec_t ctx);