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.
 
 
 
 
 

649 lines
20 KiB

  1. #include "test.h"
  2. #include <stdio.h>
  3. #include "ec_point.h"
  4. #include "decaf.h"
  5. #include "scalarmul.h"
  6. #include "magic.h"
  7. #include "field.h"
  8. #include "crandom.h"
  9. static void
  10. failprint_ext (
  11. const struct extensible_t *a
  12. ) {
  13. field_a_t zi, scaled;
  14. field_print(" x", a->x);
  15. field_print(" y", a->y);
  16. field_print(" z", a->z);
  17. field_inverse(zi, a->z);
  18. field_mul(scaled, zi, a->x);
  19. field_print(" X", scaled);
  20. field_mul(scaled, zi, a->y);
  21. field_print(" Y", scaled);
  22. printf("\n");
  23. }
  24. static void
  25. failprint_tw_ext (
  26. const struct tw_extensible_t *a
  27. ) {
  28. failprint_ext((const struct extensible_t *)a);
  29. }
  30. static mask_t
  31. fail_if_different (
  32. const struct extensible_t *a,
  33. const struct extensible_t *b,
  34. const char *faildescr,
  35. const char *adescr,
  36. const char *bdescr
  37. ) {
  38. mask_t succ = eq_extensible(a, b);
  39. if (!succ) {
  40. youfail();
  41. printf(" %s\n", faildescr);
  42. printf("\n %s:\n", adescr);
  43. failprint_ext(a);
  44. printf("\n %s:\n", bdescr);
  45. failprint_ext(b);
  46. }
  47. return succ;
  48. }
  49. static mask_t
  50. validate_ext(
  51. const struct extensible_t *ext,
  52. int evenness,
  53. const char *description
  54. ) {
  55. mask_t succ = validate_extensible(ext), succ2;
  56. const char *error = "Point isn't on the curve.";
  57. if (evenness > 0) {
  58. succ2 = is_even_pt(ext);
  59. if (succ &~ succ2) error = "Point isn't even.";
  60. succ &= succ2;
  61. } else if (evenness < 0) {
  62. succ2 = is_even_pt(ext);
  63. if (succ &~ succ2) error = "Point is even but shouldn't be.";
  64. succ &= succ2;
  65. } /* FUTURE: quadness */
  66. if (~succ) {
  67. youfail();
  68. printf(" %s\n", error);
  69. printf(" %s\n", description);
  70. failprint_ext(ext);
  71. }
  72. return succ;
  73. }
  74. static mask_t
  75. validate_tw_ext(
  76. const struct tw_extensible_t *ext,
  77. int evenness,
  78. const char *description
  79. ) {
  80. mask_t succ = validate_tw_extensible(ext), succ2;
  81. const char *error = "Point isn't on the twisted curve.";
  82. if (evenness > 0) {
  83. succ2 = is_even_tw(ext);
  84. if (succ &~ succ2) error = "Point isn't even.";
  85. succ &= succ2;
  86. } else if (evenness < 0) {
  87. succ2 = is_even_tw(ext);
  88. if (succ &~ succ2) error = "Point is even but shouldn't be.";
  89. succ &= succ2;
  90. } /* FUTURE: quadness */
  91. if (~succ) {
  92. youfail();
  93. printf(" %s\n", error);
  94. printf(" %s\n", description);
  95. failprint_tw_ext(ext);
  96. }
  97. return succ;
  98. }
  99. static mask_t
  100. fail_if_different_tw (
  101. const struct tw_extensible_t *a,
  102. const struct tw_extensible_t *b,
  103. const char *faildescr,
  104. const char *adescr,
  105. const char *bdescr
  106. ) {
  107. return fail_if_different(
  108. (const struct extensible_t *)a, (const struct extensible_t *)b,
  109. faildescr,adescr,bdescr
  110. );
  111. }
  112. static int
  113. add_double_test (
  114. const struct affine_t *base1,
  115. const struct affine_t *base2
  116. ) {
  117. mask_t succ = MASK_SUCCESS;
  118. struct extensible_t exb;
  119. struct tw_extensible_t text1, text2, texta, textb;
  120. struct tw_extended_t ted1, ted2;
  121. struct tw_pniels_t pn;
  122. /* Convert to ext */
  123. convert_affine_to_extensible(&exb, base1);
  124. succ &= validate_ext(&exb,0,"base1");
  125. twist_and_double(&text1, &exb);
  126. succ &= validate_tw_ext(&text1,2,"iso1");
  127. convert_affine_to_extensible(&exb, base2);
  128. succ &= validate_ext(&exb,0,"base2");
  129. twist_and_double(&text2, &exb);
  130. succ &= validate_tw_ext(&text2,2,"iso2");
  131. /* a + b == b + a? */
  132. convert_tw_extensible_to_tw_pniels(&pn, &text1);
  133. copy_tw_extensible(&texta, &text2);
  134. add_tw_pniels_to_tw_extensible(&texta, &pn);
  135. convert_tw_extensible_to_tw_pniels(&pn, &text2);
  136. copy_tw_extensible(&textb, &text1);
  137. add_tw_pniels_to_tw_extensible(&textb, &pn);
  138. decaf_448_point_t ted3;
  139. convert_tw_extensible_to_tw_extended(&ted1, &text1);
  140. convert_tw_extensible_to_tw_extended(&ted2, &text2);
  141. decaf_448_point_add(ted3, (struct decaf_448_point_s*)&ted1, (struct decaf_448_point_s*)&ted2);
  142. add_tw_extended(&ted1, &ted2);
  143. convert_tw_extensible_to_tw_extended(&ted2, &textb);
  144. if (~decaf_eq_tw_extended(&ted1, &ted2) | ~decaf_448_point_eq((struct decaf_448_point_s*)&ted1, ted3)) {
  145. youfail();
  146. succ = 0;
  147. printf(" Tw extended simple compat:\n");
  148. field_print(" x1",ted1.x);
  149. field_print(" y1",ted1.y);
  150. field_print(" z1",ted1.z);
  151. field_print(" t1",ted1.t);
  152. field_print(" x2",ted2.x);
  153. field_print(" y2",ted2.y);
  154. field_print(" z2",ted2.z);
  155. field_print(" t2",ted2.t);
  156. struct tw_extended_t *t3 = (struct tw_extended_t *)&ted3;
  157. field_print(" x3",t3->x);
  158. field_print(" y3",t3->y);
  159. field_print(" z3",t3->z);
  160. field_print(" t3",t3->t);
  161. }
  162. succ &= fail_if_different_tw(&texta,&textb,"Addition commutativity","a+b","b+a");
  163. copy_tw_extensible(&textb, &text2);
  164. add_tw_pniels_to_tw_extensible(&textb, &pn);
  165. copy_tw_extensible(&texta, &text2);
  166. double_tw_extensible(&texta);
  167. succ &= fail_if_different_tw(&texta,&textb,"Doubling test","2b","b+b");
  168. if (~succ) {
  169. printf(" Bases were:\n");
  170. field_print(" x1", base1->x);
  171. field_print(" y1", base1->y);
  172. field_print(" x2", base2->x);
  173. field_print(" y2", base2->y);
  174. }
  175. return succ ? 0 : -1;
  176. }
  177. static int
  178. single_twisting_test (
  179. const struct affine_t *base
  180. ) {
  181. struct extensible_t exb, ext, tmpext;
  182. struct tw_extensible_t text, text2;
  183. mask_t succ = MASK_SUCCESS;
  184. convert_affine_to_extensible(&exb, base);
  185. succ &= validate_ext(&exb,0,"base");
  186. /* check: dual . iso = 4 */
  187. twist_and_double(&text, &exb);
  188. succ &= validate_tw_ext(&text,2,"iso");
  189. untwist_and_double(&ext, &text);
  190. succ &= validate_ext(&ext,2,"dual.iso");
  191. copy_extensible(&tmpext,&exb);
  192. double_extensible(&tmpext);
  193. succ &= validate_ext(&tmpext,1,"2*base");
  194. double_extensible(&tmpext);
  195. succ &= validate_ext(&tmpext,2,"4*base");
  196. succ &= fail_if_different(&ext,&tmpext,"Isogeny and dual","Dual . iso","4*base");
  197. /* check: twist and serialize */
  198. test_only_twist(&text, &exb);
  199. succ &= validate_tw_ext(&text,0,"tot");
  200. mask_t evt = is_even_tw(&text), evb = is_even_pt(&exb);
  201. if (evt != evb) {
  202. youfail();
  203. printf(" Different evenness from twist base: %d, twist: %d\n", (int)-evt, (int)-evb);
  204. succ = 0;
  205. } /* FUTURE: quadness */
  206. field_a_t sera,serb;
  207. untwist_and_double_and_serialize(sera,&text);
  208. copy_extensible(&tmpext,&exb);
  209. double_extensible(&tmpext);
  210. serialize_extensible(serb,&tmpext);
  211. /* check that their (doubled; FUTURE?) serializations are equal */
  212. if (~field_eq(sera,serb)) {
  213. youfail();
  214. printf(" Different serialization from twist + double ()\n");
  215. field_print(" t", sera);
  216. field_print(" b", serb);
  217. succ = 0;
  218. }
  219. untwist_and_double(&ext, &text);
  220. succ &= validate_ext(&tmpext,1,"dual.tot");
  221. twist_and_double(&text2, &ext);
  222. succ &= validate_tw_ext(&text2,2,"iso.dual.tot");
  223. double_tw_extensible(&text);
  224. succ &= validate_tw_ext(&text,1,"2*tot");
  225. double_tw_extensible(&text);
  226. succ &= validate_tw_ext(&text,2,"4*tot");
  227. succ &= fail_if_different_tw(&text,&text2,"Dual and isogeny","4*tot","iso.dual.tot");
  228. if (~succ) {
  229. printf(" Base was:\n");
  230. field_print(" x", base->x);
  231. field_print(" y", base->y);
  232. }
  233. return succ ? 0 : -1;
  234. }
  235. int test_decaf_evil (void) {
  236. #if FIELD_BITS != 448
  237. printf(" [ UNIMP ] ");
  238. return 0;
  239. #else
  240. #if WORD_BITS==64
  241. #define SC_WORD(x) x##ull
  242. #elif WORD_BITS==32
  243. #define SC_WORD(x) (uint32_t)(x##ull), (x##ull)>>32
  244. #endif
  245. word_t evil_scalars[5][448/WORD_BITS] = {
  246. {0},
  247. {SC_WORD(0x2378c292ab5844f3),SC_WORD(0x216cc2728dc58f55),SC_WORD(0xc44edb49aed63690),SC_WORD(0xffffffff7cca23e9),
  248. SC_WORD(0xffffffffffffffff),SC_WORD(0xffffffffffffffff),SC_WORD(0x3fffffffffffffff)}, /* q */
  249. {SC_WORD(0xdc873d6d54a7bb0d),SC_WORD(0xde933d8d723a70aa),SC_WORD(0x3bb124b65129c96f),
  250. SC_WORD(0x335dc16),SC_WORD(0x0),SC_WORD(0x0),SC_WORD(0x4000000000000000)}, /* qtwist */
  251. {SC_WORD(0x46f1852556b089e6),SC_WORD(0x42d984e51b8b1eaa),SC_WORD(0x889db6935dac6d20),SC_WORD(0xfffffffef99447d3),
  252. SC_WORD(0xffffffffffffffff),SC_WORD(0xffffffffffffffff),SC_WORD(0x7fffffffffffffff)}, /* 2q */
  253. {SC_WORD(0xb90e7adaa94f761a),SC_WORD(0xbd267b1ae474e155),SC_WORD(0x7762496ca25392df),SC_WORD(0x66bb82c),
  254. SC_WORD(0x0),SC_WORD(0x0),SC_WORD(0x8000000000000000)} /* 2*qtwist */
  255. };
  256. word_t random_scalar[448/WORD_BITS];
  257. unsigned char evil_inputs[3][56];
  258. memset(evil_inputs[0],0,56);
  259. memset(evil_inputs[1],0,56);
  260. memset(evil_inputs[2],0xff,56);
  261. evil_inputs[1][0] = 1;
  262. evil_inputs[2][0] = evil_inputs[2][28] = 0xFE;
  263. unsigned char random_input[56];
  264. crandom_state_a_t crand;
  265. crandom_init_from_buffer(crand, "my evil_decaf random initializer");
  266. int i,j,fails=0;
  267. int ret = 0;
  268. for (i=0; i<100; i++) {
  269. crandom_generate(crand, (unsigned char *)random_scalar, sizeof(random_scalar));
  270. if (i<15) {
  271. memcpy(random_scalar, evil_scalars[i%5], sizeof(random_scalar));
  272. if (i%3 == 1) random_scalar[0] ++;
  273. if (i%3 == 2) random_scalar[0] --;
  274. }
  275. for (j=0; j<100; j++) {
  276. crandom_generate(crand, random_input, sizeof(random_input));
  277. mask_t should = 0, care_should = 0;
  278. if (j<3) {
  279. memcpy(random_input, evil_inputs[j], sizeof(random_input));
  280. care_should = -1;
  281. should = (j==0) ? -1 : 0;
  282. } else {
  283. random_input[55] &= 0x7F;
  284. }
  285. field_a_t base, out_m, out_e, out_ed;
  286. mask_t s_base = field_deserialize(base,random_input);
  287. affine_a_t pt_e;
  288. tw_affine_a_t pt_te;
  289. tw_extended_a_t pt_ed;
  290. // TODO: test don't allow identity
  291. mask_t s_e = decaf_deserialize_affine(pt_e,base,-1);
  292. mask_t s_te = decaf_deserialize_tw_affine(pt_te,base,-1);
  293. mask_t s_ed = decaf_deserialize_tw_extended(pt_ed,base,-1);
  294. mask_t s_m = decaf_montgomery_ladder(out_m, base, random_scalar, 448);
  295. uint8_t ser_di[56];
  296. mask_t s_di = decaf_448_direct_scalarmul(ser_di,random_input,(struct decaf_448_scalar_s *)random_scalar,-1,-1);
  297. tw_extensible_a_t work;
  298. convert_tw_affine_to_tw_extensible(work,pt_te);
  299. scalarmul(work, random_scalar);
  300. decaf_serialize_tw_extensible(out_e, work);
  301. scalarmul_ed(pt_ed, random_scalar);
  302. decaf_serialize_tw_extended(out_ed, pt_ed);
  303. uint8_t ser_de[56], ser_ed[56];
  304. decaf_448_point_t pt_dec, pt_dec2;
  305. memcpy(pt_dec, pt_ed, sizeof(pt_dec));
  306. decaf_448_point_encode(ser_de, pt_dec);
  307. mask_t succ_dec = decaf_448_point_decode(pt_dec2, ser_de, -1);
  308. field_serialize(ser_ed, out_ed);
  309. decaf_448_point_t p,q,m;
  310. uint8_t oo_base_ser[56], n_base_ser[56];
  311. field_a_t oo_base,tmp,tmp2;
  312. field_isr(tmp,base);
  313. field_sqr(tmp2,tmp); // 1/+-s_base
  314. field_sqr(tmp,tmp2); // = 1/s_base^2
  315. field_mul(oo_base,tmp,base); // = 1/s_base
  316. field_serialize(oo_base_ser,oo_base);
  317. field_neg(tmp,base);
  318. field_serialize(n_base_ser,tmp); // = -base
  319. decaf_448_point_from_hash_nonuniform (p,random_input);
  320. decaf_448_point_from_hash_nonuniform (q,oo_base_ser);
  321. decaf_448_point_from_hash_nonuniform (m,n_base_ser);
  322. mask_t succ_nur = decaf_448_point_valid(p);
  323. succ_nur &= decaf_448_point_valid(q);
  324. succ_nur &= decaf_448_point_valid(m);
  325. mask_t eq_neg, eq_pos;
  326. eq_neg = decaf_448_point_eq(m,p);
  327. decaf_448_point_add(m,p,q);
  328. eq_pos = decaf_448_point_eq(m,decaf_448_point_identity);
  329. if ((care_should && should != s_m)
  330. || ~s_base || s_e != s_te || s_m != s_te || s_ed != s_te || s_di != s_te
  331. || (s_te && ~field_eq(out_e,out_m))
  332. || (s_ed && ~field_eq(out_e,out_ed))
  333. || memcmp(ser_de, ser_ed, 56)
  334. || (s_te && memcmp(ser_di, ser_ed, 56))
  335. || (s_e & ~succ_dec)
  336. || (s_e & ~decaf_448_point_eq(pt_dec, pt_dec2)
  337. || (s_e & ~decaf_448_point_valid(pt_dec))
  338. || (succ_dec & ~decaf_448_point_valid(pt_dec2))
  339. || ~succ_nur
  340. || ~eq_neg
  341. || ~eq_pos)
  342. ) {
  343. youfail();
  344. field_print(" base", base);
  345. scalar_print(" scal", random_scalar, (448+WORD_BITS-1)/WORD_BITS);
  346. field_print(" oute", out_e);
  347. field_print(" outE", out_ed);
  348. field_print(" outm", out_m);
  349. printf(" succ: m=%d, e=%d, t=%d, di=%d, b=%d, T=%d, D=%d, nur=%d, e+=%d, e-=%d, should=%d[%d]\n",
  350. -(int)s_m,-(int)s_e,-(int)s_te,-(int)s_di,-(int)s_base,-(int)s_ed,-(int)succ_dec,
  351. -(int)succ_nur, -(int)eq_neg, -(int)eq_pos,
  352. -(int)should,-(int)care_should
  353. );
  354. ret = -1;
  355. fails++;
  356. }
  357. }
  358. }
  359. if (fails) {
  360. printf(" Failed %d trials\n", fails);
  361. }
  362. return ret;
  363. #endif
  364. }
  365. int test_decaf (void) {
  366. struct affine_t base;
  367. struct tw_affine_t tw_base;
  368. field_a_t serf;
  369. struct crandom_state_t crand;
  370. crandom_init_from_buffer(&crand, "my test_decaf random initializer");
  371. int i, hits = 0, fails = 0;
  372. if (~decaf_448_point_valid(decaf_448_point_base)) {
  373. youfail();
  374. printf(" Decaf base point invalid\n");
  375. fails++;
  376. }
  377. if (~decaf_448_point_valid(decaf_448_point_identity)) {
  378. youfail();
  379. printf(" Decaf identity point invalid\n");
  380. fails++;
  381. }
  382. for (i=0; i<1000; i++) {
  383. uint8_t ser[FIELD_BYTES];
  384. int j;
  385. mask_t succ = 0;
  386. for (j=0; j<128 && !succ; j++) {
  387. crandom_generate(&crand, ser, sizeof(ser));
  388. ser[FIELD_BYTES-1] &= (1<<((FIELD_BITS-1)%8)) - 1;
  389. succ = field_deserialize(serf, ser);
  390. if (!succ) {
  391. youfail();
  392. printf(" Unlikely: fail at field_deserialize\n");
  393. return -1;
  394. }
  395. succ &= decaf_deserialize_affine(&base, serf, 0);
  396. }
  397. if (!succ) {
  398. youfail();
  399. printf("Unlikely: fail 128 desers\n");
  400. return -1;
  401. }
  402. hits++;
  403. field_a_t serf2;
  404. struct extensible_t ext;
  405. convert_affine_to_extensible(&ext, &base);
  406. decaf_serialize_extensible(serf2, &ext);
  407. if (~validate_affine(&base)) {
  408. youfail();
  409. printf("Invalid decaf deser:\n");
  410. field_print(" s", serf);
  411. field_print(" x", base.x);
  412. field_print(" y", base.y);
  413. fails ++;
  414. } else if (~field_eq(serf, serf2)) {
  415. youfail();
  416. printf("Fail round-trip through decaf ser:\n");
  417. field_print(" s", serf);
  418. field_print(" x", base.x);
  419. field_print(" y", base.y);
  420. printf(" deser is %s\n", validate_affine(&base) ? "valid" : "invalid");
  421. field_print(" S", serf2);
  422. fails ++;
  423. } else if (~is_even_pt(&ext)) {
  424. youfail();
  425. printf("Decaf deser isn't even:\n");
  426. field_print(" s", serf);
  427. field_print(" x", base.x);
  428. field_print(" y", base.y);
  429. fails ++;
  430. }
  431. succ = decaf_deserialize_tw_affine(&tw_base, serf, 0);
  432. struct tw_extensible_t tw_ext, tw_ext2;
  433. convert_tw_affine_to_tw_extensible(&tw_ext, &tw_base);
  434. decaf_serialize_tw_extensible(serf2, &tw_ext);
  435. twist_even(&tw_ext2, &ext);
  436. if (~succ | ~validate_tw_extensible(&tw_ext)) {
  437. youfail();
  438. printf("Invalid decaf tw deser:\n");
  439. field_print(" s", serf);
  440. field_print(" x", tw_base.x);
  441. field_print(" y", tw_base.y);
  442. fails ++;
  443. } else if (~field_eq(serf, serf2)) {
  444. youfail();
  445. printf("Fail round-trip through decaf ser:\n");
  446. field_print(" s", serf);
  447. field_print(" x", tw_base.x);
  448. field_print(" y", tw_base.y);
  449. printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid");
  450. field_print(" S", serf2);
  451. fails ++;
  452. } else if (~is_even_tw(&tw_ext)) {
  453. youfail();
  454. printf("Decaf tw deser isn't even:\n");
  455. field_print(" s", serf);
  456. field_print(" x", tw_base.x);
  457. field_print(" y", tw_base.y);
  458. fails ++;
  459. } else if (~decaf_eq_tw_extensible(&tw_ext,&tw_ext2)) {
  460. youfail();
  461. printf("Decaf tw doesn't equal ext:\n");
  462. field_print(" s", serf);
  463. field_print(" x1", base.x);
  464. field_print(" y1", base.y);
  465. field_print(" x2", tw_base.x);
  466. field_print(" y2", tw_base.y);
  467. field_print(" X2", tw_ext2.x);
  468. field_print(" Y2", tw_ext2.y);
  469. fails ++;
  470. }
  471. tw_extended_a_t ed;
  472. succ = decaf_deserialize_tw_extended(ed, serf, 0);
  473. decaf_serialize_tw_extended(serf2, ed);
  474. if (~succ) {
  475. youfail();
  476. printf("Invalid decaf ed deser:\n");
  477. field_print(" s", serf);
  478. fails ++;
  479. } else if (~field_eq(serf, serf2)) {
  480. youfail();
  481. printf("Fail round-trip through decaf ser:\n");
  482. field_print(" s", serf);
  483. field_print(" x", ed->x);
  484. field_print(" y", ed->y);
  485. field_print(" z", ed->z);
  486. field_print(" t", ed->t);
  487. printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid");
  488. field_print(" S", serf2);
  489. fails ++;
  490. }
  491. word_t scalar = 1;
  492. mask_t res = decaf_montgomery_ladder(serf2,serf,&scalar,1+(i%31));
  493. if (~res | ~field_eq(serf2,serf)) {
  494. youfail();
  495. printf("Decaf Montgomery ladder i=%d res=%d\n", 1+(i%31), (int)res);
  496. field_print(" s", serf);
  497. field_print(" o", serf2);
  498. printf("\n");
  499. }
  500. }
  501. if (hits < 1000) {
  502. youfail();
  503. printf(" Fail: only %d successes in decaf_deser\n", hits);
  504. return -1;
  505. } else if (fails) {
  506. printf(" %d fails\n", fails);
  507. return -1;
  508. } else {
  509. return 0;
  510. }
  511. }
  512. int test_pointops (void) {
  513. struct affine_t base, pbase;
  514. field_a_t serf;
  515. struct crandom_state_t crand;
  516. crandom_init_from_buffer(&crand, "test_pointops random initializer");
  517. struct extensible_t ext_base;
  518. if (!validate_affine(goldilocks_base_point)) {
  519. youfail();
  520. printf(" Base point isn't on the curve.\n");
  521. return -1;
  522. }
  523. convert_affine_to_extensible(&ext_base, goldilocks_base_point);
  524. if (!validate_ext(&ext_base, 2, "base")) return -1;
  525. int i, ret;
  526. for (i=0; i<1000; i++) {
  527. uint8_t ser[FIELD_BYTES];
  528. crandom_generate(&crand, ser, sizeof(ser));
  529. #if (FIELD_BITS % 8)
  530. ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  531. #endif
  532. /* TODO: we need a field generate, which can return random or pathological. */
  533. mask_t succ = field_deserialize(serf, ser);
  534. if (!succ) {
  535. youfail();
  536. printf(" Unlikely: fail at field_deserialize\n");
  537. return -1;
  538. }
  539. if (i) {
  540. copy_affine(&pbase, &base);
  541. }
  542. elligator_2s_inject(&base, serf);
  543. if (i) {
  544. ret = add_double_test(&base, &pbase);
  545. if (ret) return ret;
  546. }
  547. ret = single_twisting_test(&base);
  548. if (ret) return ret;
  549. }
  550. return 0;
  551. }