From 4333b7c1f1a5ff82e24ccb48233afc69f1bfff92 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Fri, 23 Jan 2015 17:53:09 -0800 Subject: [PATCH] pass pathological decaf test cases! --- src/ec_point.c | 4 +- test/test.c | 3 ++ test/test.h | 1 + test/test_pointops.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) diff --git a/src/ec_point.c b/src/ec_point.c index dcb8751..29a60b4 100644 --- a/src/ec_point.c +++ b/src/ec_point.c @@ -451,7 +451,7 @@ decaf_serialize_montgomery ( field_mul(L1,den,a->s0); field_sqr(L2,L1); field_mul(L3,L2,xz_a); - constant_time_select(den,L3,L1,sizeof(den),swapped &~ zcase); + constant_time_select(den,L3,L1,sizeof(den),swapped | zcase); /* compute the output */ field_mul(L1,L0,den); @@ -459,7 +459,7 @@ decaf_serialize_montgomery ( constant_time_select(L2,a->s0,a->zs,sizeof(L2),zcase); /* zs, but s0 in zcase */ field_mul(L0,L1,L2); - constant_time_select(L3,a->xd,a->zd,sizeof(L3),za_zero); + constant_time_select(L3,a->zd,a->xd,sizeof(L3),za_zero); constant_time_select(L2,L3,a->xs,sizeof(L2),zcase); /* xs, but zq or qq in zcase */ field_mul(out,L0,L2); diff --git a/test/test.c b/test/test.c index 7ef3d8f..3b3ba5e 100644 --- a/test/test.c +++ b/test/test.c @@ -121,6 +121,9 @@ int main(int argc, char **argv) { begin_test("Decaf point encoding"); test_decaf(); + + begin_test("Decaf pathological cases"); + test_decaf_evil(); begin_test("Scalarmul compatibility"); test_scalarmul_compatibility(); diff --git a/test/test.h b/test/test.h index 03f2844..0e192e8 100644 --- a/test/test.h +++ b/test/test.h @@ -46,5 +46,6 @@ int test_goldilocks (void); int test_pointops (void); int test_decaf (void); +int test_decaf_evil (void); #endif // __GOLDILOCKS_TEST_H__ diff --git a/test/test_pointops.c b/test/test_pointops.c index f9b3c1d..fb6bc1e 100644 --- a/test/test_pointops.c +++ b/test/test_pointops.c @@ -251,6 +251,100 @@ single_twisting_test ( return succ ? 0 : -1; } +int test_decaf_evil (void) { + +#if FIELD_BITS != 448 || WORD_BITS != 64 + + printf(" [ UNIMP ] "); + return 0; +#else + + word_t evil_scalars[5][7] = { + {0}, + {0x2378c292ab5844f3,0x216cc2728dc58f55,0xc44edb49aed63690,0xffffffff7cca23e9, + 0xffffffffffffffff,0xffffffffffffffff,0x3fffffffffffffff}, /* q */ + {0xdc873d6d54a7bb0d,0xde933d8d723a70aa,0x3bb124b65129c96f, + 0x335dc16,0x0,0x0,0x4000000000000000}, /* qtwist */ + {0x46f1852556b089e6,0x42d984e51b8b1eaa,0x889db6935dac6d20,0xfffffffef99447d3, + 0xffffffffffffffff,0xffffffffffffffff,0x7fffffffffffffff}, /* 2q */ + {0xb90e7adaa94f761a,0xbd267b1ae474e155,0x7762496ca25392df,0x66bb82c, + 0x0,0x0,0x8000000000000000} /* 2*qtwist */ + }; + word_t random_scalar[7]; + + unsigned char evil_inputs[3][56]; + memset(evil_inputs[0],0,56); + memset(evil_inputs[1],0,56); + memset(evil_inputs[2],0xff,56); + evil_inputs[1][0] = 1; + evil_inputs[2][0] = evil_inputs[2][28] = 0xFE; + + unsigned char random_input[56]; + + + crandom_state_a_t crand; + crandom_init_from_buffer(crand, "my evil_decaf random initializer"); + + int i,j,fails=0; + int ret = 0; + for (i=0; i<100; i++) { + + crandom_generate(crand, (unsigned char *)random_scalar, sizeof(random_scalar)); + if (i<15) { + memcpy(random_scalar, evil_scalars[i%5], sizeof(random_scalar)); + if (i%3 == 1) random_scalar[0] ++; + if (i%3 == 2) random_scalar[0] --; + } + + for (j=0; j<100; j++) { + crandom_generate(crand, random_input, sizeof(random_input)); + mask_t should = 0, care_should = 0; + if (j<3) { + memcpy(random_input, evil_inputs[j], sizeof(random_input)); + care_should = -1; + should = (j==0) ? -1 : 0; + } else { + random_input[0] &= ~1; + } + + field_a_t base, out_m, out_e; + mask_t s_base = field_deserialize(base,random_input); + + affine_a_t pt_e; + tw_affine_a_t pt_te; + // 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_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); + + if ((care_should && should != s_m) + || ~s_base || s_e != s_te || s_m != s_te || (s_te && ~field_eq(out_e,out_m)) + ) { + youfail(); + field_print(" base", base); + scalar_print(" scal", random_scalar, (448+WORD_BITS-1)/WORD_BITS); + field_print(" oute", out_e); + 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 + ); + ret = -1; + fails++; + } + } + } + if (fails) { + printf(" Failed %d trials\n", fails); + } + return ret; +#endif +} + int test_decaf (void) { struct affine_t base; struct tw_affine_t tw_base;