You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

435 lines
12 KiB

  1. #include "test.h"
  2. #include <stdio.h>
  3. #include "ec_point.h"
  4. #include "scalarmul.h"
  5. #include "magic.h"
  6. #include "field.h"
  7. #include "crandom.h"
  8. static void
  9. failprint_ext (
  10. const struct extensible_t *a
  11. ) {
  12. field_a_t zi, scaled;
  13. field_print(" x", a->x);
  14. field_print(" y", a->y);
  15. field_print(" z", a->z);
  16. field_inverse(zi, a->z);
  17. field_mul(scaled, zi, a->x);
  18. field_print(" X", scaled);
  19. field_mul(scaled, zi, a->y);
  20. field_print(" Y", scaled);
  21. printf("\n");
  22. }
  23. static void
  24. failprint_tw_ext (
  25. const struct tw_extensible_t *a
  26. ) {
  27. failprint_ext((const struct extensible_t *)a);
  28. }
  29. static mask_t
  30. fail_if_different (
  31. const struct extensible_t *a,
  32. const struct extensible_t *b,
  33. const char *faildescr,
  34. const char *adescr,
  35. const char *bdescr
  36. ) {
  37. mask_t succ = eq_extensible(a, b);
  38. if (!succ) {
  39. youfail();
  40. printf(" %s\n", faildescr);
  41. printf("\n %s:\n", adescr);
  42. failprint_ext(a);
  43. printf("\n %s:\n", bdescr);
  44. failprint_ext(b);
  45. }
  46. return succ;
  47. }
  48. static mask_t
  49. validate_ext(
  50. const struct extensible_t *ext,
  51. int evenness,
  52. const char *description
  53. ) {
  54. mask_t succ = validate_extensible(ext), succ2;
  55. const char *error = "Point isn't on the curve.";
  56. if (evenness > 0) {
  57. succ2 = is_even_pt(ext);
  58. if (succ &~ succ2) error = "Point isn't even.";
  59. succ &= succ2;
  60. } else if (evenness < 0) {
  61. succ2 = is_even_pt(ext);
  62. if (succ &~ succ2) error = "Point is even but shouldn't be.";
  63. succ &= succ2;
  64. } /* FUTURE: quadness */
  65. if (~succ) {
  66. youfail();
  67. printf(" %s\n", error);
  68. printf(" %s\n", description);
  69. failprint_ext(ext);
  70. }
  71. return succ;
  72. }
  73. static mask_t
  74. validate_tw_ext(
  75. const struct tw_extensible_t *ext,
  76. int evenness,
  77. const char *description
  78. ) {
  79. mask_t succ = validate_tw_extensible(ext), succ2;
  80. const char *error = "Point isn't on the twisted curve.";
  81. if (evenness > 0) {
  82. succ2 = is_even_tw(ext);
  83. if (succ &~ succ2) error = "Point isn't even.";
  84. succ &= succ2;
  85. } else if (evenness < 0) {
  86. succ2 = is_even_tw(ext);
  87. if (succ &~ succ2) error = "Point is even but shouldn't be.";
  88. succ &= succ2;
  89. } /* FUTURE: quadness */
  90. if (~succ) {
  91. youfail();
  92. printf(" %s\n", error);
  93. printf(" %s\n", description);
  94. failprint_tw_ext(ext);
  95. }
  96. return succ;
  97. }
  98. static mask_t
  99. fail_if_different_tw (
  100. const struct tw_extensible_t *a,
  101. const struct tw_extensible_t *b,
  102. const char *faildescr,
  103. const char *adescr,
  104. const char *bdescr
  105. ) {
  106. return fail_if_different(
  107. (const struct extensible_t *)a, (const struct extensible_t *)b,
  108. faildescr,adescr,bdescr
  109. );
  110. }
  111. static int
  112. add_double_test (
  113. const struct affine_t *base1,
  114. const struct affine_t *base2
  115. ) {
  116. mask_t succ = MASK_SUCCESS;
  117. struct extensible_t exb;
  118. struct tw_extensible_t text1, text2, texta, textb;
  119. struct tw_pniels_t pn;
  120. /* Convert to ext */
  121. convert_affine_to_extensible(&exb, base1);
  122. succ &= validate_ext(&exb,0,"base1");
  123. twist_and_double(&text1, &exb);
  124. succ &= validate_tw_ext(&text1,2,"iso1");
  125. convert_affine_to_extensible(&exb, base2);
  126. succ &= validate_ext(&exb,0,"base2");
  127. twist_and_double(&text2, &exb);
  128. succ &= validate_tw_ext(&text2,2,"iso2");
  129. /* a + b == b + a? */
  130. convert_tw_extensible_to_tw_pniels(&pn, &text1);
  131. copy_tw_extensible(&texta, &text2);
  132. add_tw_pniels_to_tw_extensible(&texta, &pn);
  133. convert_tw_extensible_to_tw_pniels(&pn, &text2);
  134. copy_tw_extensible(&textb, &text1);
  135. add_tw_pniels_to_tw_extensible(&textb, &pn);
  136. succ &= fail_if_different_tw(&texta,&textb,"Addition commutativity","a+b","b+a");
  137. copy_tw_extensible(&textb, &text2);
  138. add_tw_pniels_to_tw_extensible(&textb, &pn);
  139. copy_tw_extensible(&texta, &text2);
  140. double_tw_extensible(&texta);
  141. succ &= fail_if_different_tw(&texta,&textb,"Doubling test","2b","b+b");
  142. if (~succ) {
  143. printf(" Bases were:\n");
  144. field_print(" x1", base1->x);
  145. field_print(" y1", base1->y);
  146. field_print(" x2", base2->x);
  147. field_print(" y2", base2->y);
  148. }
  149. return succ ? 0 : -1;
  150. }
  151. static int
  152. single_twisting_test (
  153. const struct affine_t *base
  154. ) {
  155. struct extensible_t exb, ext, tmpext;
  156. struct tw_extensible_t text, text2;
  157. mask_t succ = MASK_SUCCESS;
  158. convert_affine_to_extensible(&exb, base);
  159. succ &= validate_ext(&exb,0,"base");
  160. /* check: dual . iso = 4 */
  161. twist_and_double(&text, &exb);
  162. succ &= validate_tw_ext(&text,2,"iso");
  163. untwist_and_double(&ext, &text);
  164. succ &= validate_ext(&ext,2,"dual.iso");
  165. copy_extensible(&tmpext,&exb);
  166. double_extensible(&tmpext);
  167. succ &= validate_ext(&tmpext,1,"2*base");
  168. double_extensible(&tmpext);
  169. succ &= validate_ext(&tmpext,2,"4*base");
  170. succ &= fail_if_different(&ext,&tmpext,"Isogeny and dual","Dual . iso","4*base");
  171. /* check: twist and serialize */
  172. test_only_twist(&text, &exb);
  173. succ &= validate_tw_ext(&text,0,"tot");
  174. mask_t evt = is_even_tw(&text), evb = is_even_pt(&exb);
  175. if (evt != evb) {
  176. youfail();
  177. printf(" Different evenness from twist base: %d, twist: %d\n", (int)-evt, (int)-evb);
  178. succ = 0;
  179. } /* FUTURE: quadness */
  180. field_a_t sera,serb;
  181. untwist_and_double_and_serialize(sera,&text);
  182. copy_extensible(&tmpext,&exb);
  183. double_extensible(&tmpext);
  184. serialize_extensible(serb,&tmpext);
  185. /* check that their (doubled; FUTURE?) serializations are equal */
  186. if (~field_eq(sera,serb)) {
  187. youfail();
  188. printf(" Different serialization from twist + double ()\n");
  189. field_print(" t", sera);
  190. field_print(" b", serb);
  191. succ = 0;
  192. }
  193. untwist_and_double(&ext, &text);
  194. succ &= validate_ext(&tmpext,1,"dual.tot");
  195. twist_and_double(&text2, &ext);
  196. succ &= validate_tw_ext(&text2,2,"iso.dual.tot");
  197. double_tw_extensible(&text);
  198. succ &= validate_tw_ext(&text,1,"2*tot");
  199. double_tw_extensible(&text);
  200. succ &= validate_tw_ext(&text,2,"4*tot");
  201. succ &= fail_if_different_tw(&text,&text2,"Dual and isogeny","4*tot","iso.dual.tot");
  202. if (~succ) {
  203. printf(" Base was:\n");
  204. field_print(" x", base->x);
  205. field_print(" y", base->y);
  206. }
  207. return succ ? 0 : -1;
  208. }
  209. int test_decaf (void) {
  210. struct affine_t base;
  211. struct tw_affine_t tw_base;
  212. field_a_t serf;
  213. struct crandom_state_t crand;
  214. crandom_init_from_buffer(&crand, "my test_decaf random initializer");
  215. int i, hits = 0, fails = 0;
  216. for (i=0; i<1000; i++) {
  217. uint8_t ser[FIELD_BYTES];
  218. int j;
  219. mask_t succ = 0;
  220. for (j=0; j<128 && !succ; j++) {
  221. crandom_generate(&crand, ser, sizeof(ser));
  222. #if (FIELD_BITS % 8)
  223. ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  224. #endif
  225. ser[0] &= ~1;
  226. succ = field_deserialize(serf, ser);
  227. if (!succ) {
  228. youfail();
  229. printf(" Unlikely: fail at field_deserialize\n");
  230. return -1;
  231. }
  232. succ &= decaf_deserialize_affine(&base, serf, 0);
  233. }
  234. if (!succ) {
  235. youfail();
  236. printf("Unlikely: fail 128 desers\n");
  237. return -1;
  238. }
  239. hits++;
  240. field_a_t serf2;
  241. struct extensible_t ext;
  242. convert_affine_to_extensible(&ext, &base);
  243. decaf_serialize_extensible(serf2, &ext);
  244. if (~validate_affine(&base)) {
  245. youfail();
  246. printf("Invalid decaf deser:\n");
  247. field_print(" s", serf);
  248. field_print(" x", base.x);
  249. field_print(" y", base.y);
  250. fails ++;
  251. } else if (~field_eq(serf, serf2)) {
  252. youfail();
  253. printf("Fail round-trip through decaf ser:\n");
  254. field_print(" s", serf);
  255. field_print(" x", base.x);
  256. field_print(" y", base.y);
  257. printf(" deser is %s\n", validate_affine(&base) ? "valid" : "invalid");
  258. field_print(" S", serf2);
  259. fails ++;
  260. } else if (~is_even_pt(&ext)) {
  261. youfail();
  262. printf("Decaf deser isn't even:\n");
  263. field_print(" s", serf);
  264. field_print(" x", base.x);
  265. field_print(" y", base.y);
  266. fails ++;
  267. }
  268. succ = decaf_deserialize_tw_affine(&tw_base, serf, 0);
  269. struct tw_extensible_t tw_ext, tw_ext2;
  270. convert_tw_affine_to_tw_extensible(&tw_ext, &tw_base);
  271. decaf_serialize_tw_extensible(serf2, &tw_ext);
  272. twist_even(&tw_ext2, &ext);
  273. if (~succ | ~validate_tw_extensible(&tw_ext)) {
  274. youfail();
  275. printf("Invalid decaf tw deser:\n");
  276. field_print(" s", serf);
  277. field_print(" x", tw_base.x);
  278. field_print(" y", tw_base.y);
  279. fails ++;
  280. } else if (~field_eq(serf, serf2)) {
  281. youfail();
  282. printf("Fail round-trip through decaf ser:\n");
  283. field_print(" s", serf);
  284. field_print(" x", tw_base.x);
  285. field_print(" y", tw_base.y);
  286. printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid");
  287. field_print(" S", serf2);
  288. fails ++;
  289. } else if (~is_even_tw(&tw_ext)) {
  290. youfail();
  291. printf("Decaf tw deser isn't even:\n");
  292. field_print(" s", serf);
  293. field_print(" x", tw_base.x);
  294. field_print(" y", tw_base.y);
  295. fails ++;
  296. } else if (~decaf_eq_tw_extensible(&tw_ext,&tw_ext2)) {
  297. youfail();
  298. printf("Decaf tw doesn't equal ext:\n");
  299. field_print(" s", serf);
  300. field_print(" x1", base.x);
  301. field_print(" y1", base.y);
  302. field_print(" x2", tw_base.x);
  303. field_print(" y2", tw_base.y);
  304. field_print(" X2", tw_ext2.x);
  305. field_print(" Y2", tw_ext2.y);
  306. fails ++;
  307. }
  308. word_t scalar = i;
  309. mask_t res = montgomery_ladder_decaf(serf2,serf,&scalar,i,0);
  310. // youfail();
  311. // printf("Decaf Montgomery ladder i=%d res=%d\n", i, (int)res);
  312. // field_print(" s", serf);
  313. // field_print(" o", serf2);
  314. // printf("\n");
  315. (void)res;
  316. }
  317. if (hits < 1000) {
  318. youfail();
  319. printf(" Fail: only %d successes in decaf_deser\n", hits);
  320. return -1;
  321. } else if (fails) {
  322. return -1;
  323. } else {
  324. return 0;
  325. }
  326. }
  327. int test_pointops (void) {
  328. struct affine_t base, pbase;
  329. field_a_t serf;
  330. struct crandom_state_t crand;
  331. crandom_init_from_buffer(&crand, "test_pointops random initializer");
  332. struct extensible_t ext_base;
  333. if (!validate_affine(goldilocks_base_point)) {
  334. youfail();
  335. printf(" Base point isn't on the curve.\n");
  336. return -1;
  337. }
  338. convert_affine_to_extensible(&ext_base, goldilocks_base_point);
  339. if (!validate_ext(&ext_base, 2, "base")) return -1;
  340. int i, ret;
  341. for (i=0; i<1000; i++) {
  342. uint8_t ser[FIELD_BYTES];
  343. crandom_generate(&crand, ser, sizeof(ser));
  344. #if (FIELD_BITS % 8)
  345. ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  346. #endif
  347. /* TODO: we need a field generate, which can return random or pathological. */
  348. mask_t succ = field_deserialize(serf, ser);
  349. if (!succ) {
  350. youfail();
  351. printf(" Unlikely: fail at field_deserialize\n");
  352. return -1;
  353. }
  354. if (i) {
  355. copy_affine(&pbase, &base);
  356. }
  357. elligator_2s_inject(&base, serf);
  358. if (i) {
  359. ret = add_double_test(&base, &pbase);
  360. if (ret) return ret;
  361. }
  362. ret = single_twisting_test(&base);
  363. if (ret) return ret;
  364. }
  365. return 0;
  366. }