Commit e251453d authored by Mike Hamburg's avatar Mike Hamburg

simple extended form is in. Probably simplify it more...

parent 812163ff
......@@ -7,6 +7,11 @@
* @author Mike Hamburg
* @warning This file was automatically generated.
* Then it was edited by hand. Good luck, have fun.
*
* This file contains a huge number of different options for EC point arithmetic,
* but only a few of them will be used by any given library. They are here for
* reference and for consistency checks. The Goldilocks library link step strips
* out unused functions.
*/
#include "ec_point.h"
......@@ -19,7 +24,7 @@ add_tw_niels_to_tw_extensible (
) {
ANALYZE_THIS_ROUTINE_CAREFULLY;
field_a_t L0, L1;
field_sub ( L1, d->y, d->x );
field_subx_nr ( L1, d->y, d->x );
field_mul ( L0, e->a, L1 );
field_add_nr ( L1, d->x, d->y );
field_mul ( d->y, e->b, L1 );
......@@ -34,6 +39,62 @@ add_tw_niels_to_tw_extensible (
field_mul ( d->y, L0, d->u );
}
void
add_tw_extended (
tw_extended_a_t d,
const tw_extended_a_t e
) {
ANALYZE_THIS_ROUTINE_CAREFULLY;
field_a_t L0, L1, L2;
field_subx_nr ( L1, d->y, d->x );
field_subx_nr ( L2, e->y, e->x );
field_mul ( L0, L2, L1 );
field_add_nr ( L1, d->y, d->x );
field_add_nr ( L2, e->y, e->x );
field_mul ( d->y, L2, L1 );
field_mul ( L1, e->t, d->t );
field_mulw_scc_wr ( d->x, L1, 2-2*EDWARDS_D );
field_add_nr ( L1, L0, d->y );
field_subx_nr ( L2, d->y, L0 );
field_mul ( L0, d->z, e->z );
field_add_nr ( L0, L0, L0 );
field_add_nr ( d->y, L0, d->x );
field_subx_nr ( L0, L0, d->x );
field_mul ( d->z, L0, d->y );
field_mul ( d->x, d->y, L2 );
field_mul ( d->y, L0, L1 );
field_mul ( d->t, L1, L2 );
}
void
add_sub_tw_extended (
tw_extended_a_t d,
const tw_extended_a_t e,
mask_t sub
) {
field_a_t L0, L1, L2, L3;
field_sub ( L1, d->y, d->x );
field_sub ( L2, e->y, e->x );
field_add ( L3, e->y, e->x );
constant_time_cond_swap(L2,L3,sizeof(L2),sub);
field_mul ( L0, L2, L1 );
field_add ( L1, d->y, d->x );
field_mul ( d->y, L3, L1 );
field_mul ( L1, e->t, d->t );
field_mulw_scc_wr ( d->x, L1, 2-2*EDWARDS_D );
field_add ( L1, L0, d->y );
field_sub ( L2, d->y, L0 );
field_mul ( L0, d->z, e->z );
field_add ( L0, L0, L0 );
field_add ( d->y, L0, d->x );
field_sub ( L0, L0, d->x );
constant_time_cond_swap(L0,d->y,sizeof(L0),sub);
field_mul ( d->z, L0, d->y );
field_mul ( d->x, d->y, L2 );
field_mul ( d->y, L0, L1 );
field_mul ( d->t, L1, L2 );
}
void
sub_tw_niels_from_tw_extensible (
tw_extensible_a_t d,
......@@ -194,6 +255,17 @@ convert_tw_affine_to_tw_extensible (
field_copy ( b->u, a->y );
}
void
convert_tw_extensible_to_tw_extended (
tw_extended_a_t b,
const tw_extensible_a_t a
) {
field_copy ( b->x, a->x );
field_copy ( b->y, a->y );
field_copy ( b->z, a->z );
field_mul ( b->t, a->t, a->u );
}
void
convert_affine_to_extensible (
extensible_a_t b,
......@@ -523,6 +595,90 @@ decaf_serialize_tw_extensible (
decaf_abs ( b );
}
void
decaf_serialize_tw_extended (
field_a_t b,
const tw_extended_a_t a
) {
field_a_t L0, L1, L2, L3;
field_mulw_scc ( L0, a->y, 1-EDWARDS_D );
field_mul ( L2, L0, a->t );
field_mul ( L0, a->x, a->z );
field_sub ( L3, L2, L0 );
field_add ( L0, a->z, a->y );
field_sub ( L1, a->z, a->y );
field_mul ( L2, L1, L0 );
field_mulw_scc ( L1, L2, -EDWARDS_D );
field_isr ( L0, L1 );
field_mulw_scc ( L1, L0, -EDWARDS_D );
field_mul ( L2, L1, L0 );
field_mul ( L0, L2, L3 );
field_add ( L3, L1, L1 );
field_mul ( L2, L3, a->z );
field_cond_neg ( L1, ~field_high_bit(L2) );
field_mul ( L2, L1, a->y );
field_add ( b, L0, L2 );
decaf_abs ( b );
}
/*
static void
tw_extended_efgh (
tw_extended_a_t a,
field_a_t x,
field_a_t xz,
field_a_t y,
field_a_t yz
) {
field_mul(a->x,x,yz);
field_mul(a->y,y,xz);
field_mul(a->z,xz,yz);
field_mul(a->t,x,y);
}
*/
mask_t
decaf_deserialize_tw_extended (
tw_extended_a_t a,
const field_a_t s,
mask_t allow_identity
) {
field_a_t L0, L1, L2, L3, L4;
mask_t succ, zero;
zero = field_is_zero(s);
succ = allow_identity | ~zero;
succ &= ~field_high_bit(s);
field_sqr ( L0, s ); // L0 = s^2
field_neg ( a->z, L0 );
field_addw ( a->z, 1 );
field_sqr ( L1, a->z );
field_mulw_scc_wr ( L2, L0, 4-4*EDWARDS_D );
field_add ( L2, L2, L1 ); // L2 = [t^2]
field_mul ( L1, L2, L0 ); // L1 = [t^2] s^2
field_isr ( L3, L1 ); // L3 =? 1/ts; check it
field_sqr ( L4, L3 );
field_mul ( L0, L4, L1 );
field_addw( L0, 1 );
succ &= ~field_is_zero( L0 );
field_mul ( L1, L2, L3 ); // L1 = t^2 * 1/ts = t/s
field_cond_neg ( L3, field_high_bit(L1) ); // negate 1/ts?
field_add( a->x, s, s );
field_mul ( L2, L3, s );
field_neg ( L1, a->z );
field_addw ( L1, 2 );
field_mul ( L0, L1, L2 );
field_mul(a->y,L0,a->z);
field_mul(a->t,a->x,L0);
field_addw ( a->y, -zero );
return succ;
}
mask_t
decaf_deserialize_affine (
affine_a_t a,
......@@ -803,6 +959,16 @@ set_identity_extensible (
field_set_ui( a->u, 0 );
}
void
set_identity_tw_extended (
tw_extended_a_t a
) {
field_set_ui( a->x, 0 );
field_set_ui( a->y, 1 );
field_set_ui( a->z, 1 );
field_set_ui( a->t, 0 );
}
void
set_identity_tw_extensible (
tw_extensible_a_t a
......@@ -827,12 +993,21 @@ decaf_eq_extensible (
const struct extensible_t* a,
const struct extensible_t* b
) {
field_a_t L0, L1, L2;
field_mul ( L2, b->y, a->x );
field_a_t L0, L1;
field_mul ( L0, b->y, a->x );
field_mul ( L1, a->y, b->x );
field_sub ( L0, L2, L1 );
field_bias ( L0, 2 );
return field_is_zero ( L0 );
return field_eq(L0,L1);
}
mask_t
decaf_eq_tw_extended (
const tw_extended_a_t a,
const tw_extended_a_t b
) {
field_a_t L0, L1;
field_mul ( L0, b->y, a->x );
field_mul ( L1, a->y, b->x );
return field_eq(L0,L1);
}
mask_t
......
......@@ -4,7 +4,11 @@
* Copyright (c) 2014 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @warning This file was automatically generated.
*
* This file contains a huge number of different options for EC point arithmetic,
* but only a few of them will be used by any given library. They are here for
* reference and for consistency checks. The Goldilocks library link step strips
* out unused functions.
*/
#ifndef __CC_INCLUDED_EC_POINT_H__
......@@ -75,6 +79,14 @@ typedef struct tw_extensible_t {
field_a_t x, y, z, t, u;
} tw_extensible_a_t[1];
/**
* Extended coordinates for twisted Edwards curves.
* Jack of all trades, master of none.
*/
typedef struct tw_extended_t {
field_a_t x, y, z, t;
} tw_extended_a_t[1];
/**
* Niels coordinates for twisted Edwards curves.
*
......@@ -140,6 +152,15 @@ copy_tw_extensible (
const tw_extensible_a_t ds
) __attribute__((unused,always_inline));
/**
* Auto-generated copy method.
*/
static __inline__ void
copy_tw_extended (
tw_extended_a_t a,
const tw_extended_a_t ds
) __attribute__((unused,always_inline));
/**
* Auto-generated copy method.
*/
......@@ -272,6 +293,25 @@ convert_tw_niels_to_tw_extensible (
const tw_niels_a_t d
);
void
convert_tw_extensible_to_tw_extended (
tw_extended_a_t b,
const tw_extensible_a_t a
);
void
add_tw_extended (
tw_extended_a_t d,
const tw_extended_a_t e
);
void
add_sub_tw_extended (
tw_extended_a_t d,
const tw_extended_a_t e,
mask_t sub
);
void
montgomery_step (
montgomery_a_t a
......@@ -435,6 +475,21 @@ decaf_serialize_tw_extensible (
const tw_extensible_a_t a
);
mask_t
decaf_deserialize_tw_extended (
tw_extended_a_t a,
const field_a_t s,
mask_t allow_identity
)
__attribute__((warn_unused_result));
void
decaf_serialize_tw_extended (
field_a_t b,
const tw_extended_a_t a
);
void
set_identity_extensible (
extensible_a_t a
......@@ -445,6 +500,11 @@ set_identity_tw_extensible (
tw_extensible_a_t a
);
void
set_identity_tw_extended (
tw_extended_a_t a
);
void
set_identity_affine (
affine_a_t a
......@@ -486,6 +546,13 @@ decaf_eq_tw_extensible (
)
__attribute__((warn_unused_result));
mask_t
decaf_eq_tw_extended (
const tw_extended_a_t a,
const tw_extended_a_t b
)
__attribute__((warn_unused_result));
mask_t
decaf_eq_extensible (
const extensible_a_t a,
......@@ -592,6 +659,17 @@ copy_tw_extensible (
field_copy ( a->u, ds->u );
}
void
copy_tw_extended (
tw_extended_a_t a,
const tw_extended_a_t ds
) {
field_copy ( a->x, ds->x );
field_copy ( a->y, ds->y );
field_copy ( a->z, ds->z );
field_copy ( a->t, ds->t );
}
void
copy_tw_niels (
tw_niels_a_t a,
......
......@@ -145,6 +145,23 @@ scalarmul (
/* TODO? int nbits */
);
/**
* Scalar multiply a twisted Edwards-form point, simply, in extended coordinates.
*
* This function takes constant time.
*
* Currently the scalar is always exactly 448 bits long.
*
* @param [inout] working The point to multply.
* @param [in] scalar The scalar, in little-endian form.
*/
void
scalarmul_ed (
tw_extended_a_t working,
const word_t scalar[SCALAR_WORDS]
/* TODO? int nbits */
);
/**
* Scalar multiply a twisted Edwards-form point. Use the same
* algorithm as scalarmul(), but uses variable array indices.
......
......@@ -88,6 +88,17 @@ constant_time_lookup_tw_pniels (
constant_time_lookup(out,in,sizeof(*out),nin,idx);
}
static __inline__ void
__attribute__((unused,always_inline))
constant_time_lookup_tw_extended (
tw_extended_a_t out,
const tw_extended_a_t *in,
int nin,
int idx
) {
constant_time_lookup(out,in,sizeof(*out),nin,idx);
}
static __inline__ void
__attribute__((unused,always_inline))
constant_time_lookup_tw_niels (
......@@ -189,6 +200,65 @@ scalarmul (
}
}
void
scalarmul_ed (
tw_extended_a_t working,
const word_t scalar[SCALAR_WORDS]
) {
const int WINDOW = SCALARMUL_FIXED_WINDOW_SIZE,
WINDOW_MASK = (1<<WINDOW)-1, WINDOW_T_MASK = WINDOW_MASK >> 1,
NTABLE = 1<<(WINDOW-1),
nbits = ROUND_UP(SCALAR_BITS,WINDOW);
word_t scalar2[SCALAR_WORDS];
convert_to_signed_window_form (
scalar2, scalar, SCALAR_WORDS,
SCALARMUL_FIXED_WINDOW_ADJUSTMENT, SCALAR_WORDS
);
tw_extended_a_t
tmp VECTOR_ALIGNED,
multiples[NTABLE] VECTOR_ALIGNED;
copy_tw_extended(tmp, working);
add_tw_extended(tmp, tmp);
copy_tw_extended(multiples[0], working);
int i,j;
for (i=1; i<NTABLE; i++) {
add_tw_extended(working, tmp);
copy_tw_extended(multiples[i], working);
}
i = nbits - WINDOW;
int bits = scalar2[i/WORD_BITS] >> (i%WORD_BITS) & WINDOW_MASK,
inv = (bits>>(WINDOW-1))-1;
bits ^= inv;
set_identity_tw_extended(working);
for (; i>=0; i-=WINDOW) {
if (i != nbits-WINDOW) {
for (j=0; j<WINDOW; j++) {
add_tw_extended(working,working);
}
}
bits = scalar2[i/WORD_BITS] >> (i%WORD_BITS);
if (i/WORD_BITS < SCALAR_WORDS-1 && i%WORD_BITS >= WORD_BITS-WINDOW) {
bits ^= scalar2[i/WORD_BITS+1] << (WORD_BITS - (i%WORD_BITS));
}
bits &= WINDOW_MASK;
inv = (bits>>(WINDOW-1))-1;
bits ^= inv;
constant_time_lookup_tw_extended(tmp, (const tw_extended_a_t*)multiples, NTABLE, bits & WINDOW_T_MASK);
add_sub_tw_extended(working, tmp, inv);
}
}
void
scalarmul_vlook (
tw_extensible_a_t working,
......
......@@ -267,12 +267,23 @@ int main(int argc, char **argv) {
memset(&ext,0,sizeof(ext));
memset(&niels,0,sizeof(niels)); /* avoid assertions in p521 even though this isn't a valid ext or niels */
tw_extended_a_t ed;
convert_tw_extensible_to_tw_extended(ed,&ext);
when = now();
for (i=0; i<nbase*100; i++) {
add_tw_niels_to_tw_extensible(&ext, &niels);
}
when = now() - when;
printf("exti+niels: %5.1fns\n", when * 1e9 / i);
when = now();
for (i=0; i<nbase*100; i++) {
add_tw_extended(ed,ed);
}
when = now() - when;
printf("txt + txt : %5.1fns\n", when * 1e9 / i);
convert_tw_extensible_to_tw_pniels(&pniels, &ext);
when = now();
......@@ -347,6 +358,23 @@ int main(int argc, char **argv) {
when = now() - when;
printf("edwards svl: %5.1fµs\n", when * 1e6 / i);
when = now();
for (i=0; i<nbase/10; i++) {
scalarmul_ed(ed,sk);
}
when = now() - when;
printf("edwards txt: %5.1fµs\n", when * 1e6 / i);
field_set_ui(a,0);
when = now();
for (i=0; i<nbase/10; i++) {
ignore_result(decaf_deserialize_tw_extended(ed,a,-1));
scalarmul_ed(ed,sk);
decaf_serialize_tw_extended(a,ed);
}
when = now() - when;
printf("simple ECDH: %5.1fµs\n", when * 1e6 / i);
when = now();
for (i=0; i<nbase/10; i++) {
scalarmul(&ext,sk);
......
......@@ -134,6 +134,7 @@ add_double_test (
mask_t succ = MASK_SUCCESS;
struct extensible_t exb;
struct tw_extensible_t text1, text2, texta, textb;
struct tw_extended_t ted1, ted2;
struct tw_pniels_t pn;
/* Convert to ext */
......@@ -154,6 +155,25 @@ add_double_test (
convert_tw_extensible_to_tw_pniels(&pn, &text2);
copy_tw_extensible(&textb, &text1);
add_tw_pniels_to_tw_extensible(&textb, &pn);
convert_tw_extensible_to_tw_extended(&ted1, &text1);
convert_tw_extensible_to_tw_extended(&ted2, &text2);
add_tw_extended(&ted1, &ted2);
convert_tw_extensible_to_tw_extended(&ted2, &textb);
if (~decaf_eq_tw_extended(&ted1, &ted2)) {
youfail();
succ = 0;
printf(" Tw extended simple compat:\n");
field_print(" x1",ted1.x);
field_print(" y1",ted1.y);
field_print(" z1",ted1.z);
field_print(" t1",ted1.t);
field_print(" x2",ted2.x);
field_print(" y2",ted2.y);
field_print(" z2",ted2.z);
field_print(" t2",ted2.t);
}
succ &= fail_if_different_tw(&texta,&textb,"Addition commutativity","a+b","b+a");
......@@ -161,7 +181,7 @@ add_double_test (
add_tw_pniels_to_tw_extensible(&textb, &pn);
copy_tw_extensible(&texta, &text2);
double_tw_extensible(&texta);
succ &= fail_if_different_tw(&texta,&textb,"Doubling test","2b","b+b");
if (~succ) {
......@@ -307,31 +327,39 @@ int test_decaf_evil (void) {
random_input[55] &= 0x7F;
}
field_a_t base, out_m, out_e;
field_a_t base, out_m, out_e, out_ed;
mask_t s_base = field_deserialize(base,random_input);
affine_a_t pt_e;
tw_affine_a_t pt_te;
tw_extended_a_t pt_ed;
// TODO: test don't allow identity
mask_t s_e = decaf_deserialize_affine(pt_e,base,-1);
mask_t s_te = decaf_deserialize_tw_affine(pt_te,base,-1);
mask_t s_ed = decaf_deserialize_tw_extended(pt_ed,base,-1);
mask_t s_m = decaf_montgomery_ladder(out_m, base, random_scalar, 448);
tw_extensible_a_t work;
convert_tw_affine_to_tw_extensible(work,pt_te);
scalarmul(work, random_scalar);
decaf_serialize_tw_extensible(out_e, work);
scalarmul_ed(pt_ed, random_scalar);
decaf_serialize_tw_extended(out_ed, pt_ed);
if ((care_should && should != s_m)
|| ~s_base || s_e != s_te || s_m != s_te || (s_te && ~field_eq(out_e,out_m))
|| ~s_base || s_e != s_te || s_m != s_te || s_ed != s_te
|| (s_te && ~field_eq(out_e,out_m))
|| (s_ed && ~field_eq(out_e,out_ed))
) {
youfail();
field_print(" base", base);
scalar_print(" scal", random_scalar, (448+WORD_BITS-1)/WORD_BITS);
field_print(" oute", out_e);
field_print(" outE", out_ed);
field_print(" outm", out_m);
printf(" succ: m=%d, e=%d, t=%d, b=%d, should=%d[%d]\n",
-(int)s_m,-(int)s_e,-(int)s_te,-(int)s_base,-(int)should,-(int)care_should
printf(" succ: m=%d, e=%d, t=%d, b=%d, T=%d, should=%d[%d]\n",
-(int)s_m,-(int)s_e,-(int)s_te,-(int)s_base,-(int)s_ed,-(int)should,-(int)care_should
);
ret = -1;
fails++;
......@@ -452,7 +480,29 @@ int test_decaf (void) {
field_print(" Y2", tw_ext2.y);
fails ++;
}
tw_extended_a_t ed;
succ = decaf_deserialize_tw_extended(ed, serf, 0);
decaf_serialize_tw_extended(serf2, ed);
if (~succ) {
youfail();
printf("Invalid decaf ed deser:\n");
field_print(" s", serf);
fails ++;
} else if (~field_eq(serf, serf2)) {
youfail();
printf("Fail round-trip through decaf ser:\n");
field_print(" s", serf);
field_print(" x", ed->x);
field_print(" y", ed->y);
field_print(" z", ed->z);
field_print(" t", ed->t);
printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid");
field_print(" S", serf2);
fails ++;
}
word_t scalar = 1;
mask_t res = decaf_montgomery_ladder(serf2,serf,&scalar,1+(i%31));
if (~res | ~field_eq(serf2,serf)) {
......
......@@ -17,7 +17,7 @@ single_scalarmul_compatibility_test (
int nbits
) {
struct tw_extensible_t text, work;
field_a_t mont, ct, vl, vt, decaf_s, decaf_m, decaf_te;
field_a_t mont, ct, vl, vt, sced, decaf_s, decaf_m, decaf_te;
int ret = 0, i;
mask_t succ, succm;
......@@ -110,11 +110,21 @@ single_scalarmul_compatibility_test (
scalarmul_vt(&work, scalar, nbits);
untwist_and_double_and_serialize(vt, &work);
tw_extended_a_t ed;
convert_tw_extensible_to_tw_extended(ed, &text);
scalarmul_ed(ed, scalar);
field_copy(work.x, ed->x);
field_copy(work.y, ed->y);
field_copy(work.z, ed->z);
field_copy(work.t, ed->t);
field_set_ui(work.u, 1);
untwist_and_double_and_serialize(sced, &work);
/* check consistency mont vs window */
consistent &= field_eq(mont, ct);
consistent &= field_eq(mont, vl);
consistent &= field_eq(mont, vt);
consistent &= field_eq(mont, sced);
}
/* check consistency mont vs combs */
......@@ -163,6 +173,7 @@ single_scalarmul_compatibility_test (
field_print(" ct ", ct);
field_print(" vl ", vl);
field_print(" vt ", vt);
field_print(" ed ", sced);
}
printf("decaf: succ = %d, %d\n", (int)succ_dm, (int)succ_dta);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment