Further progress.
[u/mdw/catacomb] / ec-prime.c
index 5a806da..09733ce 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: ec-prime.c,v 1.1 2001/04/29 18:12:33 mdw Exp $
+ * $Id: ec-prime.c,v 1.2 2002/01/13 13:48:44 mdw Exp $
  *
  * Elliptic curves over prime fields
  *
@@ -30,6 +30,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: ec-prime.c,v $
+ * Revision 1.2  2002/01/13 13:48:44  mdw
+ * Further progress.
+ *
  * Revision 1.1  2001/04/29 18:12:33  mdw
  * Prototype version.
  *
@@ -48,25 +51,93 @@ typedef struct ecctx {
 
 /*----- Main code ---------------------------------------------------------*/
 
-static void ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+static ec *ecneg(ec_cuvrve *c, ec *d, const ec *p)
+{
+  EC_COPY(d, p);
+  d->y = F_NEG(c->f, d->y, d->y);
+  return (d);
+}
+
+static ec *ecdbl(ec_curve *c, ec *d, const ec *a)
 {
-  /* --- Deal with the simple cases --- */
+  if (EC_ATINF(a))
+    EC_SETINF(d);
+  else if (!MP_LEN(a->y))
+    EC_COPY(d, a);
+  else {
+    field *f = c->f;
+    ecctx *cc = (ecctx *)c;
+    mp *lambda;
+    mp *dy, *dx;
+
+    dx = F_SQR(f, MP_NEW, a->x);
+    dy = F_DBL(f, MP_NEW, a->y);
+    dx = F_TPL(f, dx, dx);
+    dx = F_ADD(f, dx, dx, cc->a);
+    dy = F_INV(f, dy, dy);
+    lambda = F_MUL(d, MP_NEW, dx, dy);
+
+    dx = F_SQR(f, dx, lambda);
+    dy = F_DBL(d, dy, a->x);
+    dx = F_SUB(f, dx, dx, dy);
+    dy = F_SUB(f, dy, a->x, dx);
+    dy = F_MUL(f, dy, lambda, dy);
+    dy = F_SUB(f, dy, dy, a->y);
 
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
+  }
+  return (d);
+}
+
+static ec *ecadd(ec_curve *c, ec *d, const ec *a, const ec *b)
+{
   if (a == b)
     ecdbl(c, d, a);
   else if (EC_ATINF(a))
     EC_COPY(d, b);
   else if (EC_ATINF(b))
     EC_COPY(d, a);
-  else if (MP_EQ(a->x, b->x) && MP_EQ(a->z, b->z)) {
-    if ((a->y->f ^ b->y->f) & MP_NEG)
+  else {
+    field *f = c->f;
+    mp *lambda;
+    mp *dy, *dx;
+
+    if (!MP_EQ(a->x, b->x)) {
+      dy = F_SUB(f, MP_NEW, a->y, b->y);
+      dx = F_SUB(f, MP_NEW, a->x, b->x);
+      dx = F_INV(f, dx, dx);
+      lambda = F_MUL(f, MP_NEW, dy, dx);
+    } else if (!MP_LEN(a->y) || !MP_EQ(a->y, b->y)) {
       EC_SETINF(d);
-    else
-      ecdbl(c, d, a);
-  } else {
+      return (d);
+    } else {
+      ecctx *cc = (ecctx *)c;
+      dx = F_SQR(f, MP_NEW, a->x);
+      dx = F_TPL(f, dx, dx);
+      dx = F_ADD(f, dx, dx, cc->a);
+      dy = F_DBL(f, MP_NEW, a->y);
+      dy = F_INV(f, dy, dy);
+      lambda = F_MUL(d, MP_NEW, dx, dy);
+    }
+
+    dx = F_SQR(f, dx, lambda);
+    dx = F_SUB(f, dx, dx, a->x);
+    dx = F_SUB(f, dx, dx, b->x);
+    dy = F_SUB(f, dy, b->x, dx);
+    dy = F_MUL(f, dy, lambda, dy);
+    dy = F_SUB(f, dy, dy, b->y);
 
-    /* --- 
+    EC_DESTROY(d);
+    d->x = dx;
+    d->y = dy;
+    d->z = 0;
+    MP_DROP(lambda);
   }
+  return (d);
 }
 
 /*----- That's all, folks -------------------------------------------------*/