From a9e16440a230c67f2ad0ac4a8587d2a8ed40dd41 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Thu, 15 Jan 2015 13:09:39 -0800 Subject: [PATCH] decaf in and working for untwisted curve --- src/ec_point.c | 50 +++++++++++++++++-------------- src/include/ec_point.h | 15 ++++++++++ test/test.c | 3 ++ test/test.h | 2 ++ test/test_pointops.c | 68 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 115 insertions(+), 23 deletions(-) diff --git a/src/ec_point.c b/src/ec_point.c index 1ae28c1..dbdfeef 100644 --- a/src/ec_point.c +++ b/src/ec_point.c @@ -457,26 +457,30 @@ decaf_serialize_extensible ( ) { /* FIXME: IF32...? */ struct field_t L0, L1, L2, L3; - field_mulw_scc ( &L2, &a->y, EDWARDS_D ); - field_mul ( &L3, &L2, &a->t ); - field_mul ( &L2, &L3, &a->u ); - field_mul ( &L0, &a->x, &a->z ); - field_sub ( &L3, &L2, &L0 ); - field_add ( &L0, &a->y, &a->z ); + field_mulw_scc ( &L2, &a->y, EDWARDS_D ); // L2 = d*y + field_mul ( &L3, &L2, &a->t ); // L3 = d*y*t_ + field_mul ( &L2, &L3, &a->u ); // L2 = d*y*t + field_mul ( &L0, &a->x, &a->z ); // L0 = x*z + field_sub ( &L3, &L2, &L0 ); + field_bias ( &L3, 2 ); + IF32( field_weak_reduce( &L3 ) ); // L3 = d*y*t - x*z + field_add ( &L0, &a->y, &a->z ); // L0 = y+z field_sub ( &L1, &a->y, &a->z ); field_bias ( &L1, 2 ); - field_mul ( &L2, &L1, &L0 ); - field_isr ( &L2, &L2 ); - field_sqr ( &L1, &L2 ); - field_mul ( &L0, &L1, &L3 ); - field_mul ( &L1, &L2, &sqrt_d_minus_1 ); - field_add ( &L3, &L1, &L1 ); - field_neg ( &L3, &L3 ); + IF32( field_weak_reduce( &L1 ) ); // L1 = y-z + field_mul ( &L2, &L1, &L0 ); // L2 = y^2-z^2 + field_isr ( &L2, &L2 ); // L2 = 1/sqrt(y^2-z^2) + field_sqr ( &L1, &L2 ); // L1 = 1/(y^2-z^2) + field_mul ( &L0, &L1, &L3 ); // L0 = (d*y*t - z*x)/(y^2-z^2) = 1/x + field_mul ( &L1, &L2, &sqrt_d_minus_1 ); // L1 = sy + field_add ( &L3, &L1, &L1 ); // L3 = 2*sy + field_neg ( &L3, &L3 ); field_bias ( &L3, 2 ); - field_mul ( &L3, &L0, &a->z ); - field_cond_neg ( &L1, field_low_bit(&L3) ); - field_mul ( &L2, &L1, &a->y ); - field_add ( b, &L2, &L3 ); + IF32( field_weak_reduce( &L3 ) ); // L3 = -2*sy + field_mul ( &L2, &L3, &a->z ); // L2 = -2*sy*z + field_cond_neg ( &L1, field_low_bit(&L2) ); // cond-neg sy + field_mul ( &L2, &L1, &a->y ); // L2 = 2*sy*y + field_add ( b, &L0, &L2 ); decaf_make_even ( b ); } @@ -492,7 +496,7 @@ decaf_deserialize_affine ( succ = allow_identity | ~zero; succ &= ~field_low_bit(s); field_sqr ( &L0, s ); - field_copy ( &L1, &L1 ); + field_copy ( &L1, &L0 ); field_addw ( &L1, 1 ); field_make_nonzero ( &L1 ); field_sqr ( &L2, &L1 ); @@ -502,19 +506,19 @@ decaf_deserialize_affine ( field_mul ( &L2, &L4, &L0 ); field_isr ( &L4, &L2 ); field_sqr ( &L5, &L4 ); - field_mul ( &L4, &L5, &L2 ); - field_addw( &L4, 1 ); - succ &= ~field_is_zero( &L4 ); + field_mul ( &L0, &L5, &L2 ); + field_addw( &L0, 1 ); + succ &= ~field_is_zero( &L0 ); field_mul ( &L2, &L3, &L1 ); field_mul ( &L3, &L2, &L4 ); field_cond_neg ( &L4, field_low_bit(&L3) ); field_mul ( &L3, &L4, s ); field_sqr ( &L4, &L3 ); - field_mul ( &L0, &L1, &L4 ); + field_mul ( &L0, &L2, &L4 ); field_add ( &L0, &L0, &L0 ); field_mul ( &a->x, &L0, s ); field_mul ( &L2, &L1, &L3 ); - field_neg ( &L1, &L1 ); + field_neg ( &L1, &L1 ); field_bias ( &L1, 2 ); field_addw ( &L1, 2 ); field_mul ( &a->y, &L1, &L2 ); diff --git a/src/include/ec_point.h b/src/include/ec_point.h index 74bbe91..1a01c03 100644 --- a/src/include/ec_point.h +++ b/src/include/ec_point.h @@ -379,6 +379,21 @@ deserialize_and_twist_approx ( struct tw_extensible_t* a, const struct field_t* sdm1, const struct field_t* sz +) +__attribute__((warn_unused_result)); + +mask_t +decaf_deserialize_affine ( + struct affine_t *a, + const struct field_t *s, + mask_t allow_identity +) +__attribute__((warn_unused_result)); + +void +decaf_serialize_extensible ( + struct field_t* b, + const struct extensible_t* a ); void diff --git a/test/test.c b/test/test.c index d3c41b4..3111a74 100644 --- a/test/test.c +++ b/test/test.c @@ -118,6 +118,9 @@ int main(int argc, char **argv) { begin_test("EC point operations"); test_pointops(); + + begin_test("Decaf point encoding"); + test_decaf(); begin_test("Scalarmul compatibility"); test_scalarmul_compatibility(); diff --git a/test/test.h b/test/test.h index b491f0e..4776b79 100644 --- a/test/test.h +++ b/test/test.h @@ -45,4 +45,6 @@ int test_goldilocks (void); int test_pointops (void); +int test_decaf (void); + #endif // __GOLDILOCKS_TEST_H__ diff --git a/test/test_pointops.c b/test/test_pointops.c index 05b13e5..9632aed 100644 --- a/test/test_pointops.c +++ b/test/test_pointops.c @@ -250,6 +250,74 @@ single_twisting_test ( return succ ? 0 : -1; } +int test_decaf (void) { + struct affine_t base; + struct field_t serf; + + struct crandom_state_t crand; + crandom_init_from_buffer(&crand, "my test_decaf random initializer"); + + int i, hits = 0, fails = 0; + for (i=0; i<1000; i++) { + uint8_t ser[FIELD_BYTES]; + crandom_generate(&crand, ser, sizeof(ser)); + #if (FIELD_BITS % 8) + ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1; + #endif + ser[0] &= ~1; + + mask_t succ = field_deserialize(&serf, ser); + if (!succ) { + youfail(); + printf(" Unlikely: fail at field_deserialize\n"); + return -1; + } + + succ &= decaf_deserialize_affine(&base, &serf, 0); + if (!succ) continue; + + hits++; + struct field_t serf2; + struct extensible_t ext; + convert_affine_to_extensible(&ext, &base); + decaf_serialize_extensible(&serf2, &ext); + + if (~validate_affine(&base)) { + youfail(); + printf("Invalid decaf deser:\n"); + field_print(" s", &serf); + field_print(" x", &base.x); + field_print(" y", &base.y); + fails ++; + } else if (~field_eq(&serf, &serf2)) { + youfail(); + printf("Fail round-trip through decaf ser:\n"); + field_print(" s", &serf); + field_print(" x", &base.x); + field_print(" y", &base.y); + printf(" deser is %s\n", validate_affine(&base) ? "valid" : "invalid"); + field_print(" S", &serf2); + fails ++; + } else if (~is_even_pt(&ext)) { + youfail(); + printf("Decaf deser isn't even:\n"); + field_print(" s", &serf); + field_print(" x", &base.x); + field_print(" y", &base.y); + fails ++; + } + } + if (hits < 350) { + youfail(); + printf(" Unlikely: only %d successes in decaf_deser\n", hits); + return -1; + } else if (fails) { + return -1; + } else { + return 0; + } +} + int test_pointops (void) { struct affine_t base, pbase; struct field_t serf;