From 4b0bf31fc9d279560d275ab2a9c52bf8a27df42c Mon Sep 17 00:00:00 2001
From: Michael Hamburg <mike@shiftleft.org>
Date: Fri, 19 Jun 2015 15:20:48 -0700
Subject: [PATCH] progress checkin.  compiles.  working on point decode.  have
 switched some of the Ds over.  BTW, you can see that this is using
 PinkBikeShed instead of the real Curve25519; this is temporary

---
 aux/decaffeinate_curve25519.sage | 15 ++++---
 src/decaf_fast.c                 | 77 ++++++++++++++++++++------------
 src/p25519/f_arithmetic.c        |  2 +-
 3 files changed, 60 insertions(+), 34 deletions(-)

diff --git a/aux/decaffeinate_curve25519.sage b/aux/decaffeinate_curve25519.sage
index f206679..e16f93e 100644
--- a/aux/decaffeinate_curve25519.sage
+++ b/aux/decaffeinate_curve25519.sage
@@ -1,7 +1,12 @@
 # This is as sketch of how to decaffeinate Curve25519
 
 F = GF(2^255-19)
-d = -121665
+
+doPinkBikeShed = True
+
+if doPinkBikeShed: d = -89747 # PinkBikeShed
+else: d = -121665 # Curve25519
+
 M = EllipticCurve(F,[0,2-4*d,0,1,0])
     
 sqrtN1 = sqrt(F(-1))
@@ -28,7 +33,7 @@ def M_to_E(P):
 
 def decaf_encode_from_E(X,Y):
     assert X^2 + Y^2 == 1 + d*X^2*Y^2
-    if not qpositive(X*Y): X,Y = Y,-X
+    if not (qpositive(X*Y) or doPinkBikeShed): X,Y = Y,-X
     assert qpositive(X*Y)
     
     assert (1-X^2).is_square()
@@ -69,7 +74,7 @@ def decaf_encode_from_E_c(X,Y):
     osx = ooAll * TZ
     ooTZ = ooAll * zx * osx
     
-    floop = qpositive(T^2 * ooTZ)
+    floop = qpositive(T^2 * ooTZ) or doPinkBikeShed
     if floop:
         frob = zx * ooTZ
     else:
@@ -92,7 +97,7 @@ def decaf_decode_to_E(s):
     t = sqrt(s^4 + (2-4*d)*s^2 + 1)
     if not qpositive(t/s): t = -t
     X,Y = 2*s / (1+s^2), (1-s^2) / t
-    assert qpositive(X*Y)
+    assert qpositive(X*Y) or doPinkBikeShed
     return X,Y
     
 def decaf_decode_to_E_c(s):
@@ -111,7 +116,7 @@ def decaf_decode_to_E_c(s):
     Y = (1-s2) * oot
     
     if not qpositive(tos): Y = -Y
-    assert qpositive(X*Y)
+    assert qpositive(X*Y) or doPinkBikeShed
     
     return X,Y
 
diff --git a/src/decaf_fast.c b/src/decaf_fast.c
index c80a177..6fdb2f2 100644
--- a/src/decaf_fast.c
+++ b/src/decaf_fast.c
@@ -43,7 +43,7 @@ typedef int64_t decaf_sdword_t;
 #define sv static void
 #define snv static void __attribute__((noinline))
 #define siv static inline void __attribute__((always_inline))
-static const gf ZERO = {{{0}}}, ONE = {{{1}}}, TWO = {{{2}}};
+static const gf ZERO = {{{0}}}, ONE = {{{1}}};//, TWO = {{{2}}};
 
 static const int EDWARDS_D = -89747;
     // Gonna test with PinkBikeShed until the math works...
@@ -504,33 +504,47 @@ void API_NS(point_encode)( unsigned char ser[SER_BYTES], const point_t p ) {
 static decaf_bool_t gf_deser(gf s, const unsigned char ser[SER_BYTES]) {
     return field_deserialize((field_t *)s, ser);
 }
-    
+ 
+extern const gf SQRT_MINUS_ONE; /* Intern this? */
+   
 decaf_bool_t API_NS(point_decode) (
     point_t p,
     const unsigned char ser[SER_BYTES],
     decaf_bool_t allow_identity
 ) {
-    gf s, a, b, c, d;
+    gf s, a, b, c, d, e, f, g;
     decaf_bool_t succ = gf_deser(s, ser), zero = gf_eq(s, ZERO);
     succ &= allow_identity | ~zero;
     succ &= ~hibit(s);
     gf_sqr ( a, s );
-    gf_sub ( p->z, ONE, a ); /* 1-s^2 = 1+as^2 since a=-1 */
-    gf_sqr ( b, p->z ); 
-    gf_mlw ( c, a, 4-4*EDWARDS_D ); 
-    gf_add ( c, c, b ); /* u = Z^2 - 4ds^2 with d = EDWARDS_D-1 */
-    gf_mul ( b, c, a );
-    succ &= gf_isqrt_chk ( d, b, DECAF_TRUE ); /* v <- 1/sqrt(us^2) */
-    gf_mul ( b, c, d );
-    cond_neg ( d, hibit(b) ); /* v <- -v if uv negative */
-    gf_add ( p->x, s, s ); /* X = 2s */
-    gf_mul ( c, d, s );
-    gf_sub ( b, TWO, p->z ); 
-    gf_mul ( a, b, c ); /* vs(2-Z) */
-    gf_mul ( p->y,a,p->z ); /* Y = wZ */
-    gf_mul ( p->t,a,p->x ); /* T = wX */
+    gf_add ( g, ONE, a ); /* 1+s^2 = 1+as^2 since a=1 */
+    succ &= ~ gf_eq( g, ZERO );
+    gf_sqr ( b, g ); 
+    gf_mlw ( c, a, -4*EDWARDS_D ); 
+    gf_add ( c, c, b ); /* t^2 */
+    gf_mul ( d, g, s ); /* s(1+s^2) for denoms */
+    gf_sqr ( e, d );
+    gf_mul ( b, c, e );
+    
+    succ &= gf_isqrt_chk ( e, b, DECAF_TRUE ); /* e = "the" */
+    gf_mul ( f, e, d ); /* 1/t */
+    gf_mul ( d, e, c ); /* d = later "the" */
+    gf_mul ( e, d, g ); /* t/s */
+    gf_sub ( a, ONE, a); /* 1-s^2 */
+    
+    gf_mul ( p->y, a, f );
+    gf_cpy ( p->z, ONE );
+    gf_sub ( d, e, d );
+    gf_mul ( c, d, f );
+    gf_mul ( b, c, SQRT_MINUS_ONE );
+    gf_add ( p->x, b, b );
+    cond_neg ( p->x, hibit(e) );
+    gf_mul ( p->t, p->x, p->y );
+    
     p->y->limb[0] -= zero;
-    /* TODO: do something safe-ish if ~succ? */
+    
+    /* Curve25519: succ &= ~hibit(p->t); */
+    
     return succ;
 }
 
@@ -547,13 +561,13 @@ void API_NS(point_sub) (
     gf_add_nr ( b, q->y, q->x );
     gf_mul ( p->y, d, b );
     gf_mul ( b, r->t, q->t );
-    gf_mlw ( p->x, b, 2-2*EDWARDS_D );
+    gf_mlw ( p->x, b, -2*EDWARDS_D );
     gf_add_nr ( b, a, p->y );
     gf_sub_nr ( c, p->y, a );
     gf_mul ( a, q->z, r->z );
     gf_add_nr ( a, a, a );
-    gf_sub_nr ( p->y, a, p->x );
-    gf_add_nr ( a, a, p->x );
+    gf_add_nr ( p->y, a, p->x );
+    gf_sub_nr ( a, a, p->x );
     gf_mul ( p->z, a, p->y );
     gf_mul ( p->x, p->y, c );
     gf_mul ( p->y, a, b );
@@ -573,13 +587,13 @@ void API_NS(point_add) (
     gf_add_nr ( b, q->y, q->x );
     gf_mul ( p->y, d, b );
     gf_mul ( b, r->t, q->t );
-    gf_mlw ( p->x, b, 2-2*EDWARDS_D );
+    gf_mlw ( p->x, b, -2*EDWARDS_D );
     gf_add_nr ( b, a, p->y );
     gf_sub_nr ( c, p->y, a );
     gf_mul ( a, q->z, r->z );
     gf_add_nr ( a, a, a );
-    gf_add_nr ( p->y, a, p->x );
-    gf_sub_nr ( a, a, p->x );
+    gf_sub_nr ( p->y, a, p->x );
+    gf_add_nr ( a, a, p->x );
     gf_mul ( p->z, a, p->y );
     gf_mul ( p->x, p->y, c );
     gf_mul ( p->y, a, b );
@@ -747,7 +761,7 @@ static void pt_to_pniels (
 ) {
     gf_sub ( b->n->a, a->y, a->x );
     gf_add ( b->n->b, a->x, a->y );
-    gf_mlw ( b->n->c, a->t, 2*EDWARDS_D-2 );
+    gf_mlw ( b->n->c, a->t, -2*EDWARDS_D );
     gf_add ( b->z, a->z, a->z );
 }
 
@@ -1012,7 +1026,14 @@ decaf_bool_t API_NS(point_eq) ( const point_t p, const point_t q ) {
     gf a, b;
     gf_mul ( a, p->y, q->x );
     gf_mul ( b, q->y, p->x );
-    return gf_eq(a,b);
+    decaf_bool_t succ = gf_eq(a,b);
+    
+    gf_mul ( a, p->y, q->y );
+    gf_mul ( b, q->x, p->x );
+    gf_add ( a, a, b);
+    succ |= gf_eq(a,ZERO);
+    
+    return succ;
 }
 
 unsigned char API_NS(point_from_hash_nonuniform) (
@@ -1190,9 +1211,9 @@ decaf_bool_t API_NS(point_valid) (
     gf_sqr(b,p->y);
     gf_sub(a,b,a);
     gf_sqr(b,p->t);
-    gf_mlw(c,b,1-EDWARDS_D);
+    gf_mlw(c,b,-EDWARDS_D);
     gf_sqr(b,p->z);
-    gf_sub(b,b,c);
+    gf_add(b,b,c);
     out &= gf_eq(a,b);
     out &= ~gf_eq(p->z,ZERO);
     return out;
diff --git a/src/p25519/f_arithmetic.c b/src/p25519/f_arithmetic.c
index eab2640..ed6f833 100644
--- a/src/p25519/f_arithmetic.c
+++ b/src/p25519/f_arithmetic.c
@@ -10,7 +10,7 @@
 
 #include "field.h"
 
-static const field_a_t SQRT_MINUS_ONE = {FIELD_LITERAL( // FIXME goes elsewhere?
+const field_a_t SQRT_MINUS_ONE = {FIELD_LITERAL( // FIXME goes elsewhere?
     0x61b274a0ea0b0,
     0x0d5a5fc8f189d,
     0x7ef5e9cbd0c60,