summaryrefslogtreecommitdiff
path: root/mpi
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-03-19 15:12:07 +0100
committerWerner Koch <wk@gnupg.org>2013-03-19 15:12:07 +0100
commit931e409e877d1e444edd53dead327ec8e64daf9a (patch)
tree841c4f30324273512effe06d32af6f36d8da26c8 /mpi
parent229f3219f80c9369ed9624242c0436ae6d293201 (diff)
downloadlibgcrypt-931e409e877d1e444edd53dead327ec8e64daf9a.tar.gz
Extend the new EC interface and fix two bugs.
* src/ec-context.h (mpi_ec_ctx_s): Add field NEED_SYNC. * mpi/ec.c (ec_p_sync): New. (ec_p_init): Only set NEED_SYNC. (_gcry_mpi_ec_set_mpi): Set NEED_SYNC for 'p' and 'a'. (_gcry_mpi_ec_dup_point, _gcry_mpi_ec_add_points) (_gcry_mpi_ec_mul_point): Call ec_p_sync. (_gcry_mpi_ec_get_point): Recompute 'q' is needed. (_gcry_mpi_ec_get_mpi): Ditto. Also allow for names 'q', 'q.x', 'q.y', and 'g'. * cipher/ecc.c (_gcry_mpi_ec_ec2os): New. * cipher/ecc.c (_gcry_mpi_ec_new): Fix init from parameters 'Q'->'q', 'G'->'q'. -- Note that the parameter names are all lowercase. This patch fixes an inconsistency. The other bug was that changing the parameters D or A may have resulted in wrong computations because helper variables were not updated. Now we delay the computation of those helper variables until we need them.
Diffstat (limited to 'mpi')
-rw-r--r--mpi/ec.c67
1 files changed, 58 insertions, 9 deletions
diff --git a/mpi/ec.c b/mpi/ec.c
index 9a6868b7..0a348d2e 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -337,6 +337,25 @@ ec_invm (gcry_mpi_t x, gcry_mpi_t a, mpi_ec_t ctx)
}
+/* Sync changed data in the context. */
+static void
+ec_p_sync (mpi_ec_t ec)
+{
+ gcry_mpi_t tmp;
+
+ if (!ec->t.need_sync)
+ return;
+
+ tmp = mpi_alloc_like (ec->p);
+ mpi_sub_ui (tmp, ec->p, 3);
+ ec->t.a_is_pminus3 = !mpi_cmp (ec->a, tmp);
+ mpi_free (tmp);
+
+ ec_invm (ec->t.two_inv_p, mpi_const (MPI_C_TWO), ec);
+ ec->t.need_sync = 0;
+}
+
+
/* This function initialized a context for elliptic curve based on the
field GF(p). P is the prime specifying this field, A is the first
@@ -345,20 +364,14 @@ static void
ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a)
{
int i;
- gcry_mpi_t tmp;
/* Fixme: Do we want to check some constraints? e.g. a < p */
ctx->p = mpi_copy (p);
ctx->a = mpi_copy (a);
- tmp = mpi_alloc_like (ctx->p);
- mpi_sub_ui (tmp, ctx->p, 3);
- ctx->t.a_is_pminus3 = !mpi_cmp (ctx->a, tmp);
- mpi_free (tmp);
-
+ ctx->t.need_sync = 1;
ctx->t.two_inv_p = mpi_alloc (0);
- ec_invm (ctx->t.two_inv_p, mpi_const (MPI_C_TWO), ctx);
/* Allocate scratch variables. */
for (i=0; i< DIM(ctx->t.scratch); i++)
@@ -492,10 +505,29 @@ _gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
return mpi_is_const (ec->n) && !copy? ec->n : mpi_copy (ec->n);
if (!strcmp (name, "d") && ec->d)
return mpi_is_const (ec->d) && !copy? ec->d : mpi_copy (ec->d);
+
+ /* Return a requested point coordinate. */
if (!strcmp (name, "g.x") && ec->G && ec->G->x)
return mpi_is_const (ec->G->x) && !copy? ec->G->x : mpi_copy (ec->G->x);
if (!strcmp (name, "g.y") && ec->G && ec->G->y)
return mpi_is_const (ec->G->y) && !copy? ec->G->y : mpi_copy (ec->G->y);
+ if (!strcmp (name, "q.x") && ec->Q && ec->Q->x)
+ return mpi_is_const (ec->Q->x) && !copy? ec->Q->x : mpi_copy (ec->Q->x);
+ 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 (!strcmp (name, "g") && ec->G)
+ return _gcry_mpi_ec_ec2os (ec->G, ec);
+ if (!strcmp (name, "q"))
+ {
+ /* If only the private key is given, compute the public key. */
+ if (!ec->Q && ec->d && ec->G && ec->p && ec->a)
+ _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+
+ if (ec->Q)
+ return _gcry_mpi_ec_ec2os (ec->Q, ec);
+ }
return NULL;
}
@@ -510,8 +542,15 @@ _gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
if (!strcmp (name, "g") && ec->G)
return point_copy (ec->G);
- if (!strcmp (name, "q") && ec->Q)
- return point_copy (ec->Q);
+ if (!strcmp (name, "q"))
+ {
+ /* If only the private key is given, compute the public key. */
+ if (!ec->Q && ec->d && ec->G && ec->p && ec->a)
+ _gcry_mpi_ec_mul_point (ec->Q, ec->d, ec->G, ec);
+
+ if (ec->Q)
+ return point_copy (ec->Q);
+ }
return NULL;
}
@@ -527,11 +566,13 @@ _gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
{
mpi_free (ec->p);
ec->p = mpi_copy (newvalue);
+ ec->t.need_sync = 1;
}
else if (!strcmp (name, "a"))
{
mpi_free (ec->a);
ec->a = mpi_copy (newvalue);
+ ec->t.need_sync = 1;
}
else if (!strcmp (name, "b"))
{
@@ -628,6 +669,8 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
#define l2 (ctx->t.scratch[4])
#define l3 (ctx->t.scratch[5])
+ ec_p_sync (ctx);
+
if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0))
{
/* P_y == 0 || P_z == 0 => [1:1:0] */
@@ -725,6 +768,8 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
#define t1 (ctx->t.scratch[9])
#define t2 (ctx->t.scratch[10])
+ ec_p_sync (ctx);
+
if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) )
{
/* Same point; need to call the duplicate function. */
@@ -854,6 +899,8 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
unsigned int nbits;
int i;
+ ec_p_sync (ctx);
+
nbits = mpi_get_nbits (scalar);
mpi_set_ui (result->x, 1);
mpi_set_ui (result->y, 1);
@@ -871,6 +918,8 @@ _gcry_mpi_ec_mul_point (mpi_point_t result,
unsigned int i, loops;
mpi_point_struct p1, p2, p1inv;
+ ec_p_sync (ctx);
+
x1 = mpi_alloc_like (ctx->p);
y1 = mpi_alloc_like (ctx->p);
h = mpi_alloc_like (ctx->p);