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.
 
 
 
 
 

530 lines
16 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_evil (void) {
  210. #if FIELD_BITS != 448 || WORD_BITS != 64
  211. printf(" [ UNIMP ] ");
  212. return 0;
  213. #else
  214. word_t evil_scalars[5][7] = {
  215. {0},
  216. {0x2378c292ab5844f3,0x216cc2728dc58f55,0xc44edb49aed63690,0xffffffff7cca23e9,
  217. 0xffffffffffffffff,0xffffffffffffffff,0x3fffffffffffffff}, /* q */
  218. {0xdc873d6d54a7bb0d,0xde933d8d723a70aa,0x3bb124b65129c96f,
  219. 0x335dc16,0x0,0x0,0x4000000000000000}, /* qtwist */
  220. {0x46f1852556b089e6,0x42d984e51b8b1eaa,0x889db6935dac6d20,0xfffffffef99447d3,
  221. 0xffffffffffffffff,0xffffffffffffffff,0x7fffffffffffffff}, /* 2q */
  222. {0xb90e7adaa94f761a,0xbd267b1ae474e155,0x7762496ca25392df,0x66bb82c,
  223. 0x0,0x0,0x8000000000000000} /* 2*qtwist */
  224. };
  225. word_t random_scalar[7];
  226. unsigned char evil_inputs[3][56];
  227. memset(evil_inputs[0],0,56);
  228. memset(evil_inputs[1],0,56);
  229. memset(evil_inputs[2],0xff,56);
  230. evil_inputs[1][0] = 1;
  231. evil_inputs[2][0] = evil_inputs[2][28] = 0xFE;
  232. unsigned char random_input[56];
  233. crandom_state_a_t crand;
  234. crandom_init_from_buffer(crand, "my evil_decaf random initializer");
  235. int i,j,fails=0;
  236. int ret = 0;
  237. for (i=0; i<100; i++) {
  238. crandom_generate(crand, (unsigned char *)random_scalar, sizeof(random_scalar));
  239. if (i<15) {
  240. memcpy(random_scalar, evil_scalars[i%5], sizeof(random_scalar));
  241. if (i%3 == 1) random_scalar[0] ++;
  242. if (i%3 == 2) random_scalar[0] --;
  243. }
  244. for (j=0; j<100; j++) {
  245. crandom_generate(crand, random_input, sizeof(random_input));
  246. mask_t should = 0, care_should = 0;
  247. if (j<3) {
  248. memcpy(random_input, evil_inputs[j], sizeof(random_input));
  249. care_should = -1;
  250. should = (j==0) ? -1 : 0;
  251. } else {
  252. random_input[0] &= ~1;
  253. }
  254. field_a_t base, out_m, out_e;
  255. mask_t s_base = field_deserialize(base,random_input);
  256. affine_a_t pt_e;
  257. tw_affine_a_t pt_te;
  258. // TODO: test don't allow identity
  259. mask_t s_e = decaf_deserialize_affine(pt_e,base,-1);
  260. mask_t s_te = decaf_deserialize_tw_affine(pt_te,base,-1);
  261. mask_t s_m = decaf_montgomery_ladder(out_m, base, random_scalar, 448);
  262. tw_extensible_a_t work;
  263. convert_tw_affine_to_tw_extensible(work,pt_te);
  264. scalarmul(work, random_scalar);
  265. decaf_serialize_tw_extensible(out_e, work);
  266. if ((care_should && should != s_m)
  267. || ~s_base || s_e != s_te || s_m != s_te || (s_te && ~field_eq(out_e,out_m))
  268. ) {
  269. youfail();
  270. field_print(" base", base);
  271. scalar_print(" scal", random_scalar, (448+WORD_BITS-1)/WORD_BITS);
  272. field_print(" oute", out_e);
  273. field_print(" outm", out_m);
  274. printf(" succ: m=%d, e=%d, t=%d, b=%d, should=%d[%d]\n",
  275. -(int)s_m,-(int)s_e,-(int)s_te,-(int)s_base,-(int)should,-(int)care_should
  276. );
  277. ret = -1;
  278. fails++;
  279. }
  280. }
  281. }
  282. if (fails) {
  283. printf(" Failed %d trials\n", fails);
  284. }
  285. return ret;
  286. #endif
  287. }
  288. int test_decaf (void) {
  289. struct affine_t base;
  290. struct tw_affine_t tw_base;
  291. field_a_t serf;
  292. struct crandom_state_t crand;
  293. crandom_init_from_buffer(&crand, "my test_decaf random initializer");
  294. int i, hits = 0, fails = 0;
  295. for (i=0; i<1000; i++) {
  296. uint8_t ser[FIELD_BYTES];
  297. int j;
  298. mask_t succ = 0;
  299. for (j=0; j<128 && !succ; j++) {
  300. crandom_generate(&crand, ser, sizeof(ser));
  301. #if (FIELD_BITS % 8)
  302. ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  303. #endif
  304. ser[0] &= ~1;
  305. succ = field_deserialize(serf, ser);
  306. if (!succ) {
  307. youfail();
  308. printf(" Unlikely: fail at field_deserialize\n");
  309. return -1;
  310. }
  311. succ &= decaf_deserialize_affine(&base, serf, 0);
  312. }
  313. if (!succ) {
  314. youfail();
  315. printf("Unlikely: fail 128 desers\n");
  316. return -1;
  317. }
  318. hits++;
  319. field_a_t serf2;
  320. struct extensible_t ext;
  321. convert_affine_to_extensible(&ext, &base);
  322. decaf_serialize_extensible(serf2, &ext);
  323. if (~validate_affine(&base)) {
  324. youfail();
  325. printf("Invalid decaf deser:\n");
  326. field_print(" s", serf);
  327. field_print(" x", base.x);
  328. field_print(" y", base.y);
  329. fails ++;
  330. } else if (~field_eq(serf, serf2)) {
  331. youfail();
  332. printf("Fail round-trip through decaf ser:\n");
  333. field_print(" s", serf);
  334. field_print(" x", base.x);
  335. field_print(" y", base.y);
  336. printf(" deser is %s\n", validate_affine(&base) ? "valid" : "invalid");
  337. field_print(" S", serf2);
  338. fails ++;
  339. } else if (~is_even_pt(&ext)) {
  340. youfail();
  341. printf("Decaf deser isn't even:\n");
  342. field_print(" s", serf);
  343. field_print(" x", base.x);
  344. field_print(" y", base.y);
  345. fails ++;
  346. }
  347. succ = decaf_deserialize_tw_affine(&tw_base, serf, 0);
  348. struct tw_extensible_t tw_ext, tw_ext2;
  349. convert_tw_affine_to_tw_extensible(&tw_ext, &tw_base);
  350. decaf_serialize_tw_extensible(serf2, &tw_ext);
  351. twist_even(&tw_ext2, &ext);
  352. if (~succ | ~validate_tw_extensible(&tw_ext)) {
  353. youfail();
  354. printf("Invalid decaf tw deser:\n");
  355. field_print(" s", serf);
  356. field_print(" x", tw_base.x);
  357. field_print(" y", tw_base.y);
  358. fails ++;
  359. } else if (~field_eq(serf, serf2)) {
  360. youfail();
  361. printf("Fail round-trip through decaf ser:\n");
  362. field_print(" s", serf);
  363. field_print(" x", tw_base.x);
  364. field_print(" y", tw_base.y);
  365. printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid");
  366. field_print(" S", serf2);
  367. fails ++;
  368. } else if (~is_even_tw(&tw_ext)) {
  369. youfail();
  370. printf("Decaf tw deser isn't even:\n");
  371. field_print(" s", serf);
  372. field_print(" x", tw_base.x);
  373. field_print(" y", tw_base.y);
  374. fails ++;
  375. } else if (~decaf_eq_tw_extensible(&tw_ext,&tw_ext2)) {
  376. youfail();
  377. printf("Decaf tw doesn't equal ext:\n");
  378. field_print(" s", serf);
  379. field_print(" x1", base.x);
  380. field_print(" y1", base.y);
  381. field_print(" x2", tw_base.x);
  382. field_print(" y2", tw_base.y);
  383. field_print(" X2", tw_ext2.x);
  384. field_print(" Y2", tw_ext2.y);
  385. fails ++;
  386. }
  387. word_t scalar = 1;
  388. mask_t res = decaf_montgomery_ladder(serf2,serf,&scalar,1+(i%31));
  389. if (~res | ~field_eq(serf2,serf)) {
  390. youfail();
  391. printf("Decaf Montgomery ladder i=%d res=%d\n", 1+(i%31), (int)res);
  392. field_print(" s", serf);
  393. field_print(" o", serf2);
  394. printf("\n");
  395. }
  396. }
  397. if (hits < 1000) {
  398. youfail();
  399. printf(" Fail: only %d successes in decaf_deser\n", hits);
  400. return -1;
  401. } else if (fails) {
  402. return -1;
  403. } else {
  404. return 0;
  405. }
  406. }
  407. int test_pointops (void) {
  408. struct affine_t base, pbase;
  409. field_a_t serf;
  410. struct crandom_state_t crand;
  411. crandom_init_from_buffer(&crand, "test_pointops random initializer");
  412. struct extensible_t ext_base;
  413. if (!validate_affine(goldilocks_base_point)) {
  414. youfail();
  415. printf(" Base point isn't on the curve.\n");
  416. return -1;
  417. }
  418. convert_affine_to_extensible(&ext_base, goldilocks_base_point);
  419. if (!validate_ext(&ext_base, 2, "base")) return -1;
  420. int i, ret;
  421. for (i=0; i<1000; i++) {
  422. uint8_t ser[FIELD_BYTES];
  423. crandom_generate(&crand, ser, sizeof(ser));
  424. #if (FIELD_BITS % 8)
  425. ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  426. #endif
  427. /* TODO: we need a field generate, which can return random or pathological. */
  428. mask_t succ = field_deserialize(serf, ser);
  429. if (!succ) {
  430. youfail();
  431. printf(" Unlikely: fail at field_deserialize\n");
  432. return -1;
  433. }
  434. if (i) {
  435. copy_affine(&pbase, &base);
  436. }
  437. elligator_2s_inject(&base, serf);
  438. if (i) {
  439. ret = add_double_test(&base, &pbase);
  440. if (ret) return ret;
  441. }
  442. ret = single_twisting_test(&base);
  443. if (ret) return ret;
  444. }
  445. return 0;
  446. }