#include "test.h" #include #include "ec_point.h" #include "magic.h" #include "field.h" #include "crandom.h" static void failprint_ext ( const struct extensible_t *a ) { field_a_t zi, scaled; field_print(" x", a->x); field_print(" y", a->y); field_print(" z", a->z); field_inverse(zi, a->z); field_mul(scaled, zi, a->x); field_print(" X", scaled); field_mul(scaled, zi, a->y); field_print(" Y", scaled); printf("\n"); } static void failprint_tw_ext ( const struct tw_extensible_t *a ) { failprint_ext((const struct extensible_t *)a); } static mask_t fail_if_different ( const struct extensible_t *a, const struct extensible_t *b, const char *faildescr, const char *adescr, const char *bdescr ) { mask_t succ = eq_extensible(a, b); if (!succ) { youfail(); printf(" %s\n", faildescr); printf("\n %s:\n", adescr); failprint_ext(a); printf("\n %s:\n", bdescr); failprint_ext(b); } return succ; } static mask_t validate_ext( const struct extensible_t *ext, int evenness, const char *description ) { mask_t succ = validate_extensible(ext), succ2; const char *error = "Point isn't on the curve."; if (evenness > 0) { succ2 = is_even_pt(ext); if (succ &~ succ2) error = "Point isn't even."; succ &= succ2; } else if (evenness < 0) { succ2 = is_even_pt(ext); if (succ &~ succ2) error = "Point is even but shouldn't be."; succ &= succ2; } /* FUTURE: quadness */ if (~succ) { youfail(); printf(" %s\n", error); printf(" %s\n", description); failprint_ext(ext); } return succ; } static mask_t validate_tw_ext( const struct tw_extensible_t *ext, int evenness, const char *description ) { mask_t succ = validate_tw_extensible(ext), succ2; const char *error = "Point isn't on the twisted curve."; if (evenness > 0) { succ2 = is_even_tw(ext); if (succ &~ succ2) error = "Point isn't even."; succ &= succ2; } else if (evenness < 0) { succ2 = is_even_tw(ext); if (succ &~ succ2) error = "Point is even but shouldn't be."; succ &= succ2; } /* FUTURE: quadness */ if (~succ) { youfail(); printf(" %s\n", error); printf(" %s\n", description); failprint_tw_ext(ext); } return succ; } static mask_t fail_if_different_tw ( const struct tw_extensible_t *a, const struct tw_extensible_t *b, const char *faildescr, const char *adescr, const char *bdescr ) { return fail_if_different( (const struct extensible_t *)a, (const struct extensible_t *)b, faildescr,adescr,bdescr ); } static int add_double_test ( const struct affine_t *base1, const struct affine_t *base2 ) { mask_t succ = MASK_SUCCESS; struct extensible_t exb; struct tw_extensible_t text1, text2, texta, textb; struct tw_pniels_t pn; /* Convert to ext */ convert_affine_to_extensible(&exb, base1); succ &= validate_ext(&exb,0,"base1"); twist_and_double(&text1, &exb); succ &= validate_tw_ext(&text1,2,"iso1"); convert_affine_to_extensible(&exb, base2); succ &= validate_ext(&exb,0,"base2"); twist_and_double(&text2, &exb); succ &= validate_tw_ext(&text2,2,"iso2"); /* a + b == b + a? */ convert_tw_extensible_to_tw_pniels(&pn, &text1); copy_tw_extensible(&texta, &text2); add_tw_pniels_to_tw_extensible(&texta, &pn); convert_tw_extensible_to_tw_pniels(&pn, &text2); copy_tw_extensible(&textb, &text1); add_tw_pniels_to_tw_extensible(&textb, &pn); succ &= fail_if_different_tw(&texta,&textb,"Addition commutativity","a+b","b+a"); copy_tw_extensible(&textb, &text2); 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) { printf(" Bases were:\n"); field_print(" x1", base1->x); field_print(" y1", base1->y); field_print(" x2", base2->x); field_print(" y2", base2->y); } return succ ? 0 : -1; } static int single_twisting_test ( const struct affine_t *base ) { struct extensible_t exb, ext, tmpext; struct tw_extensible_t text, text2; mask_t succ = MASK_SUCCESS; convert_affine_to_extensible(&exb, base); succ &= validate_ext(&exb,0,"base"); /* check: dual . iso = 4 */ twist_and_double(&text, &exb); succ &= validate_tw_ext(&text,2,"iso"); untwist_and_double(&ext, &text); succ &= validate_ext(&ext,2,"dual.iso"); copy_extensible(&tmpext,&exb); double_extensible(&tmpext); succ &= validate_ext(&tmpext,1,"2*base"); double_extensible(&tmpext); succ &= validate_ext(&tmpext,2,"4*base"); succ &= fail_if_different(&ext,&tmpext,"Isogeny and dual","Dual . iso","4*base"); /* check: twist and serialize */ test_only_twist(&text, &exb); succ &= validate_tw_ext(&text,0,"tot"); mask_t evt = is_even_tw(&text), evb = is_even_pt(&exb); if (evt != evb) { youfail(); printf(" Different evenness from twist base: %d, twist: %d\n", (int)-evt, (int)-evb); succ = 0; } /* FUTURE: quadness */ field_a_t sera,serb; untwist_and_double_and_serialize(sera,&text); copy_extensible(&tmpext,&exb); double_extensible(&tmpext); serialize_extensible(serb,&tmpext); /* check that their (doubled; FUTURE?) serializations are equal */ if (~field_eq(sera,serb)) { youfail(); printf(" Different serialization from twist + double ()\n"); field_print(" t", sera); field_print(" b", serb); succ = 0; } untwist_and_double(&ext, &text); succ &= validate_ext(&tmpext,1,"dual.tot"); twist_and_double(&text2, &ext); succ &= validate_tw_ext(&text2,2,"iso.dual.tot"); double_tw_extensible(&text); succ &= validate_tw_ext(&text,1,"2*tot"); double_tw_extensible(&text); succ &= validate_tw_ext(&text,2,"4*tot"); succ &= fail_if_different_tw(&text,&text2,"Dual and isogeny","4*tot","iso.dual.tot"); if (~succ) { printf(" Base was:\n"); field_print(" x", base->x); field_print(" y", base->y); } return succ ? 0 : -1; } int test_pointops (void) { struct affine_t base, pbase; field_a_t serf; struct crandom_state_t crand; crandom_init_from_buffer(&crand, "test_pointops random initializer"); struct extensible_t ext_base; if (!validate_affine(goldilocks_base_point)) { youfail(); printf(" Base point isn't on the curve.\n"); return -1; } convert_affine_to_extensible(&ext_base, goldilocks_base_point); if (!validate_ext(&ext_base, 2, "base")) return -1; int i, ret; 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 /* TODO: we need a field generate, which can return random or pathological. */ mask_t succ = field_deserialize(serf, ser); if (!succ) { youfail(); printf(" Unlikely: fail at field_deserialize\n"); return -1; } if (i) { copy_affine(&pbase, &base); } elligator_2s_inject(&base, serf); if (i) { ret = add_double_test(&base, &pbase); if (ret) return ret; } ret = single_twisting_test(&base); if (ret) return ret; } return 0; }