summaryrefslogtreecommitdiff
path: root/mpi/ec.c
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2013-03-15 14:43:19 +0100
committerWerner Koch <wk@gnupg.org>2013-03-15 14:53:42 +0100
commit229f3219f80c9369ed9624242c0436ae6d293201 (patch)
tree1eaa99a11af69b72dc6c96d1222c4d1ffb0c4228 /mpi/ec.c
parente005629bd7bebb3e13945645c6e1230b44ab16a2 (diff)
downloadlibgcrypt-229f3219f80c9369ed9624242c0436ae6d293201.tar.gz
mpi: Add functions to manipulate an EC context.
* src/gcrypt.h.in (gcry_mpi_ec_p_new): Remove. (gcry_mpi_ec_new): New. (gcry_mpi_ec_get_mpi): New. (gcry_mpi_ec_get_point): New. (gcry_mpi_ec_set_mpi): New. (gcry_mpi_ec_set_point): New. * src/visibility.c (gcry_mpi_ec_p_new): Remove. * mpi/ec.c (_gcry_mpi_ec_p_new): Make it an internal function and change to return an error code. (_gcry_mpi_ec_get_mpi): New. (_gcry_mpi_ec_get_point): New. (_gcry_mpi_ec_set_mpi): New. (_gcry_mpi_ec_set_point): New. * src/mpi.h: Add new prototypes. * src/ec-context.h: New. * mpi/ec.c: Include that header. (mpi_ec_ctx_s): Move to ec-context.h, add new fields, and put some fields into an inner struct. (point_copy): New. * cipher/ecc.c (fill_in_curve): Allow passing NULL for R_NBITS. (mpi_from_keyparam, point_from_keyparam): New. (_gcry_mpi_ec_new): New. * tests/t-mpi-point.c (test-curve): New. (ec_p_new): New. Use it instead of the removed gcry_mpi_ec_p_new. (get_and_cmp_mpi, get_and_cmp_point): New. (context_param): New test. (basic_ec_math_simplified): New test. (main): Call new tests. * src/context.c (_gcry_ctx_get_pointer): Check for a NULL CTX. -- gcry_mpi_ec_p_new() was a specialized version of the more general new gcry_mpi_ec_new(). It was added to master only a few days ago, thus there should be no problem to remove it. A replacement can easily be written (cf. t-mpi-point.c). Note that gcry_mpi_ec_set_mpi and gcry_mpi_ec_set_point have not yet been tested.
Diffstat (limited to 'mpi/ec.c')
-rw-r--r--mpi/ec.c236
1 files changed, 167 insertions, 69 deletions
diff --git a/mpi/ec.c b/mpi/ec.c
index 7f310eac..9a6868b7 100644
--- a/mpi/ec.c
+++ b/mpi/ec.c
@@ -27,37 +27,13 @@
#include "longlong.h"
#include "g10lib.h"
#include "context.h"
+#include "ec-context.h"
#define point_init(a) _gcry_mpi_point_init ((a))
#define point_free(a) _gcry_mpi_point_free_parts ((a))
-/* Object to represent a point in projective coordinates. */
-/* Currently defined in mpi.h */
-
-/* This context is used with all our EC functions. */
-struct mpi_ec_ctx_s
-{
- /* Domain parameters. */
- gcry_mpi_t p; /* Prime specifying the field GF(p). */
- gcry_mpi_t a; /* First coefficient of the Weierstrass equation. */
-
- int a_is_pminus3; /* True if A = P - 3. */
-
- gcry_mpi_t two_inv_p;
-
- /* Scratch variables. */
- gcry_mpi_t scratch[11];
-
- /* Helper for fast reduction. */
-/* int nist_nbits; /\* If this is a NIST curve, the number of bits. *\/ */
-/* gcry_mpi_t s[10]; */
-/* gcry_mpi_t c; */
-
-};
-
-
/* Create a new point option. NBITS gives the size in bits of one
coordinate; it is only used to pre-allocate some resources and
might also be passed as 0 to use a default value. */
@@ -116,6 +92,24 @@ point_set (mpi_point_t d, mpi_point_t s)
mpi_set (d->z, s->z);
}
+
+/* Return a copy of POINT. */
+static gcry_mpi_point_t
+point_copy (gcry_mpi_point_t point)
+{
+ gcry_mpi_point_t newpoint;
+
+ if (point)
+ {
+ newpoint = gcry_mpi_point_new (0);
+ point_set (newpoint, point);
+ }
+ else
+ newpoint = NULL;
+ return newpoint;
+}
+
+
/* Set the projective coordinates from POINT into X, Y, and Z. If a
coordinate is not required, X, Y, or Z may be passed as NULL. */
void
@@ -353,27 +347,22 @@ ec_p_init (mpi_ec_t ctx, gcry_mpi_t p, gcry_mpi_t a)
int i;
gcry_mpi_t tmp;
- mpi_normalize (p);
- mpi_normalize (a);
-
- /* Fixme: Do we want to check some constraints? e.g.
- a < p
- */
+ /* 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->a_is_pminus3 = !mpi_cmp (ctx->a, tmp);
+ ctx->t.a_is_pminus3 = !mpi_cmp (ctx->a, tmp);
mpi_free (tmp);
- ctx->two_inv_p = mpi_alloc (0);
- ec_invm (ctx->two_inv_p, mpi_const (MPI_C_TWO), ctx);
+ 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->scratch); i++)
- ctx->scratch[i] = mpi_alloc_like (ctx->p);
+ for (i=0; i< DIM(ctx->t.scratch); i++)
+ ctx->t.scratch[i] = mpi_alloc_like (ctx->p);
/* Prepare for fast reduction. */
/* FIXME: need a test for NIST values. However it does not gain us
@@ -401,13 +390,22 @@ ec_deinit (void *opaque)
mpi_ec_t ctx = opaque;
int i;
+ /* Domain parameter. */
mpi_free (ctx->p);
mpi_free (ctx->a);
+ mpi_free (ctx->b);
+ gcry_mpi_point_release (ctx->G);
+ mpi_free (ctx->n);
+
+ /* The key. */
+ gcry_mpi_point_release (ctx->Q);
+ mpi_free (ctx->d);
- mpi_free (ctx->two_inv_p);
+ /* Private data of ec.c. */
+ mpi_free (ctx->t.two_inv_p);
- for (i=0; i< DIM(ctx->scratch); i++)
- mpi_free (ctx->scratch[i]);
+ for (i=0; i< DIM(ctx->t.scratch); i++)
+ mpi_free (ctx->t.scratch[i]);
/* if (ctx->nist_nbits == 192) */
/* { */
@@ -455,28 +453,128 @@ _gcry_mpi_ec_free (mpi_ec_t ctx)
/* This function returns a new context for elliptic curve operations
based on the field GF(p). P is the prime specifying this field, A
- is the first coefficient. This function is part of the public API.
- On error this function returns NULL and sets ERRNO.
- The context needs to be released using gcry_ctx_release. */
-gcry_ctx_t
-gcry_mpi_ec_p_new (gcry_mpi_t p, gcry_mpi_t a)
+ is the first coefficient. On success the new context is stored at
+ R_CTX and 0 is returned; on error NULL is stored at R_CTX and an
+ error code is returned. The context needs to be released using
+ gcry_ctx_release. This is an internal fucntions. */
+gpg_err_code_t
+_gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, gcry_mpi_t p, gcry_mpi_t a)
{
gcry_ctx_t ctx;
mpi_ec_t ec;
+ *r_ctx = NULL;
if (!p || !a || !mpi_cmp_ui (a, 0))
- {
- gpg_err_set_errno (EINVAL);
- return NULL;
- }
+ return GPG_ERR_EINVAL;
ctx = _gcry_ctx_alloc (CONTEXT_TYPE_EC, sizeof *ec, ec_deinit);
if (!ctx)
- return NULL;
+ return gpg_err_code_from_syserror ();
ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
ec_p_init (ec, p, a);
- return ctx;
+ *r_ctx = ctx;
+ return 0;
+}
+
+gcry_mpi_t
+_gcry_mpi_ec_get_mpi (const char *name, gcry_ctx_t ctx, int copy)
+{
+ mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+ 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)
+ return mpi_is_const (ec->a) && !copy? ec->a : mpi_copy (ec->a);
+ if (!strcmp (name, "b") && ec->b)
+ return mpi_is_const (ec->b) && !copy? ec->b : mpi_copy (ec->b);
+ if (!strcmp (name, "n") && ec->n)
+ 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);
+ 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);
+
+ return NULL;
+}
+
+
+gcry_mpi_point_t
+_gcry_mpi_ec_get_point (const char *name, gcry_ctx_t ctx, int copy)
+{
+ mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+ (void)copy; /* Not used. */
+
+ if (!strcmp (name, "g") && ec->G)
+ return point_copy (ec->G);
+ if (!strcmp (name, "q") && ec->Q)
+ return point_copy (ec->Q);
+
+ return NULL;
+}
+
+
+gpg_err_code_t
+_gcry_mpi_ec_set_mpi (const char *name, gcry_mpi_t newvalue,
+ gcry_ctx_t ctx)
+{
+ mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+ if (!strcmp (name, "p"))
+ {
+ mpi_free (ec->p);
+ ec->p = mpi_copy (newvalue);
+ }
+ else if (!strcmp (name, "a"))
+ {
+ mpi_free (ec->a);
+ ec->a = mpi_copy (newvalue);
+ }
+ else if (!strcmp (name, "b"))
+ {
+ mpi_free (ec->b);
+ ec->b = mpi_copy (newvalue);
+ }
+ else if (!strcmp (name, "n"))
+ {
+ mpi_free (ec->n);
+ ec->n = mpi_copy (newvalue);
+ }
+ else if (!strcmp (name, "d"))
+ {
+ mpi_free (ec->d);
+ ec->d = mpi_copy (newvalue);
+ }
+ else
+ return GPG_ERR_UNKNOWN_NAME;
+
+ return 0;
+}
+
+
+gpg_err_code_t
+_gcry_mpi_ec_set_point (const char *name, gcry_mpi_point_t newvalue,
+ gcry_ctx_t ctx)
+{
+ mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC);
+
+ if (!strcmp (name, "g"))
+ {
+ gcry_mpi_point_release (ec->G);
+ ec->G = point_copy (newvalue);
+ }
+ else if (!strcmp (name, "q"))
+ {
+ gcry_mpi_point_release (ec->Q);
+ ec->Q = point_copy (newvalue);
+ }
+ else
+ return GPG_ERR_UNKNOWN_NAME;
+
+ return 0;
}
@@ -523,12 +621,12 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
#define x3 (result->x)
#define y3 (result->y)
#define z3 (result->z)
-#define t1 (ctx->scratch[0])
-#define t2 (ctx->scratch[1])
-#define t3 (ctx->scratch[2])
-#define l1 (ctx->scratch[3])
-#define l2 (ctx->scratch[4])
-#define l3 (ctx->scratch[5])
+#define t1 (ctx->t.scratch[0])
+#define t2 (ctx->t.scratch[1])
+#define t3 (ctx->t.scratch[2])
+#define l1 (ctx->t.scratch[3])
+#define l2 (ctx->t.scratch[4])
+#define l3 (ctx->t.scratch[5])
if (!mpi_cmp_ui (point->y, 0) || !mpi_cmp_ui (point->z, 0))
{
@@ -539,7 +637,7 @@ _gcry_mpi_ec_dup_point (mpi_point_t result, mpi_point_t point, mpi_ec_t ctx)
}
else
{
- if (ctx->a_is_pminus3) /* Use the faster case. */
+ if (ctx->t.a_is_pminus3) /* Use the faster case. */
{
/* L1 = 3(X - Z^2)(X + Z^2) */
/* T1: used for Z^2. */
@@ -615,17 +713,17 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
#define x3 (result->x)
#define y3 (result->y)
#define z3 (result->z)
-#define l1 (ctx->scratch[0])
-#define l2 (ctx->scratch[1])
-#define l3 (ctx->scratch[2])
-#define l4 (ctx->scratch[3])
-#define l5 (ctx->scratch[4])
-#define l6 (ctx->scratch[5])
-#define l7 (ctx->scratch[6])
-#define l8 (ctx->scratch[7])
-#define l9 (ctx->scratch[8])
-#define t1 (ctx->scratch[9])
-#define t2 (ctx->scratch[10])
+#define l1 (ctx->t.scratch[0])
+#define l2 (ctx->t.scratch[1])
+#define l3 (ctx->t.scratch[2])
+#define l4 (ctx->t.scratch[3])
+#define l5 (ctx->t.scratch[4])
+#define l6 (ctx->t.scratch[5])
+#define l7 (ctx->t.scratch[6])
+#define l8 (ctx->t.scratch[7])
+#define l9 (ctx->t.scratch[8])
+#define t1 (ctx->t.scratch[9])
+#define t2 (ctx->t.scratch[10])
if ( (!mpi_cmp (x1, x2)) && (!mpi_cmp (y1, y2)) && (!mpi_cmp (z1, z2)) )
{
@@ -715,7 +813,7 @@ _gcry_mpi_ec_add_points (mpi_point_t result,
ec_powm (t1, l3, mpi_const (MPI_C_THREE), ctx); /* fixme: Use saved value*/
ec_mulm (t1, t1, l8, ctx);
ec_subm (y3, l9, t1, ctx);
- ec_mulm (y3, y3, ctx->two_inv_p, ctx);
+ ec_mulm (y3, y3, ctx->t.two_inv_p, ctx);
}
}