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.
 
 
 
 
 

481 lines
15 KiB

  1. #include "test.h"
  2. #include <stdio.h>
  3. #include "scalarmul.h"
  4. #include "decaf.h"
  5. #include "ec_point.h"
  6. #include "field.h"
  7. #include "crandom.h"
  8. #define STRIDE 7
  9. /* 0 = succeed, 1 = inval, -1 = fail */
  10. static int
  11. single_scalarmul_compatibility_test (
  12. const field_a_t base,
  13. const word_t *scalar,
  14. int nbits
  15. ) {
  16. struct tw_extensible_t text, work;
  17. field_a_t mont, ct, vl, vt, sced, decaf_s, decaf_m, decaf_te;
  18. int ret = 0, i;
  19. mask_t succ, succm;
  20. succ = deserialize_and_twist_approx(&text, base);
  21. succm = montgomery_ladder(mont,base,scalar,nbits,1);
  22. if (succ != succm) {
  23. youfail();
  24. printf(" Deserialize_and_twist_approx succ=%d, montgomery_ladder succ=%d\n",
  25. (int)-succ, (int)-succm);
  26. printf(" nbits = %d\n", nbits);
  27. field_print(" base", base);
  28. scalar_print(" scal", scalar, (nbits+WORD_BITS-1)/WORD_BITS);
  29. return -1;
  30. }
  31. if (!succ) {
  32. return 1;
  33. }
  34. #if FIELD_BITS == 448
  35. struct { int n,t,s; } params[] = {{5,5,18},{3,5,30},{4,4,28},{1,2,224}};
  36. #elif FIELD_BITS == 480
  37. struct { int n,t,s; } params[] = {{5,6,16},{6,5,16},{4,5,24},{4,4,30},{1,2,240}};
  38. #elif FIELD_BITS == 521
  39. struct { int n,t,s; } params[] = {{5,8,13},{4,5,26},{1,2,(SCALAR_BITS+1)/2}};
  40. #else
  41. struct { int n,t,s; } params[] = {{5,5,(SCALAR_BITS+24)/25},{1,2,(SCALAR_BITS+1)/2}};
  42. #endif
  43. const int nparams = sizeof(params)/sizeof(params[0]);
  44. struct fixed_base_table_t fbt;
  45. const int nsizes = 6;
  46. field_a_t fbout[nparams], wout[nsizes];
  47. memset(&fbt, 0, sizeof(fbt));
  48. memset(&fbout, 0, sizeof(fbout));
  49. memset(&wout, 0, sizeof(wout));
  50. /* compute using combs */
  51. for (i=0; i<nparams; i++) {
  52. int n=params[i].n, t=params[i].t, s=params[i].s;
  53. succ = precompute_fixed_base(&fbt, &text, n, t, s, NULL);
  54. if (!succ) {
  55. youfail();
  56. printf(" Failed to precompute_fixed_base(%d,%d,%d)\n", n, t, s);
  57. continue;
  58. }
  59. succ = scalarmul_fixed_base(&work, scalar, nbits, &fbt);
  60. destroy_fixed_base(&fbt);
  61. if (!succ) {
  62. youfail();
  63. printf(" Failed to scalarmul_fixed_base(%d,%d,%d)\n", n, t, s);
  64. continue;
  65. }
  66. untwist_and_double_and_serialize(fbout[i], &work);
  67. }
  68. /* compute using precomp wNAF */
  69. for (i=0; i<nsizes; i++) {
  70. tw_niels_a_t pre[1<<i];
  71. succ = precompute_fixed_base_wnaf(pre, &text, i);
  72. if (!succ) {
  73. youfail();
  74. printf(" Failed to precompute_fixed_base_wnaf(%d)\n", i);
  75. continue;
  76. }
  77. scalarmul_fixed_base_wnaf_vt(&work, scalar, nbits, (const tw_niels_a_t*)pre, i);
  78. untwist_and_double_and_serialize(wout[i], &work);
  79. }
  80. mask_t consistent = MASK_SUCCESS;
  81. if (nbits == FIELD_BITS) {
  82. /* window methods currently only work on FIELD_BITS bits. */
  83. copy_tw_extensible(&work, &text);
  84. scalarmul(&work, scalar);
  85. untwist_and_double_and_serialize(ct, &work);
  86. copy_tw_extensible(&work, &text);
  87. scalarmul_vlook(&work, scalar);
  88. untwist_and_double_and_serialize(vl, &work);
  89. copy_tw_extensible(&work, &text);
  90. scalarmul_vt(&work, scalar, nbits);
  91. untwist_and_double_and_serialize(vt, &work);
  92. decaf_448_point_t ed2, ed3;
  93. struct decaf_448_precomputed_s *dpre;
  94. int pmret = posix_memalign(
  95. (void**)&dpre,
  96. alignof_decaf_448_precomputed_s,
  97. sizeof_decaf_448_precomputed_s
  98. );
  99. if (pmret) return 1;
  100. tw_extended_a_t ed;
  101. convert_tw_extensible_to_tw_extended(ed, &text);
  102. uint8_t ser4[DECAF_448_SER_BYTES];
  103. decaf_448_point_encode(ser4, (struct decaf_448_point_s *)ed);
  104. decaf_448_point_scalarmul(
  105. ed2,
  106. (struct decaf_448_point_s *)ed,
  107. (struct decaf_448_scalar_s *)scalar
  108. );
  109. decaf_448_precompute(dpre, (struct decaf_448_point_s *)ed);
  110. decaf_448_precomputed_scalarmul(
  111. ed3,
  112. dpre,
  113. (struct decaf_448_scalar_s *)scalar
  114. );
  115. free(dpre);
  116. scalarmul_ed(ed, scalar);
  117. field_copy(work.x, ed->x);
  118. field_copy(work.y, ed->y);
  119. field_copy(work.z, ed->z);
  120. field_copy(work.t, ed->t);
  121. field_set_ui(work.u, 1);
  122. untwist_and_double_and_serialize(sced, &work);
  123. uint8_t ser1[DECAF_448_SER_BYTES], ser2[DECAF_448_SER_BYTES],
  124. ser3[DECAF_448_SER_BYTES];
  125. decaf_448_point_encode(ser1, (struct decaf_448_point_s *)ed);
  126. decaf_448_point_encode(ser2, ed2);
  127. decaf_448_point_encode(ser3, ed3);
  128. consistent &= decaf_448_direct_scalarmul(ser4, ser4, (struct decaf_448_scalar_s *)scalar, -1, -1);
  129. /* check consistency mont vs window */
  130. consistent &= field_eq(mont, ct);
  131. consistent &= field_eq(mont, vl);
  132. consistent &= field_eq(mont, vt);
  133. consistent &= field_eq(mont, sced);
  134. consistent &= memcmp(ser1,ser2,sizeof(ser1)) ? 0 : -1;
  135. consistent &= memcmp(ser1,ser3,sizeof(ser1)) ? 0 : -1;
  136. consistent &= memcmp(ser1,ser4,sizeof(ser1)) ? 0 : -1;
  137. }
  138. /* check consistency mont vs combs */
  139. for (i=0; i<nparams; i++) {
  140. consistent &= field_eq(mont,fbout[i]);
  141. }
  142. /* check consistency mont vs wNAF */
  143. for (i=0; i<nsizes; i++) {
  144. consistent &= field_eq(mont,wout[i]);
  145. }
  146. /* Do decaf */
  147. copy_tw_extensible(&work,&text);
  148. double_tw_extensible(&work);
  149. decaf_serialize_tw_extensible(decaf_s, &work);
  150. mask_t succ_dm, succ_dta;
  151. succ_dm = decaf_montgomery_ladder(decaf_m, decaf_s, scalar, nbits);
  152. succ_dta = deserialize_and_twist_approx(&work, mont);
  153. decaf_serialize_tw_extensible(decaf_te, &work);
  154. consistent &= field_eq(decaf_m, decaf_te);
  155. consistent &= succ_dm & succ_dta;
  156. /* If inconsistent, complain. */
  157. if (!consistent) {
  158. youfail();
  159. printf(" Failed scalarmul consistency test with nbits=%d.\n",nbits);
  160. field_print(" base", base);
  161. scalar_print(" scal", scalar, (nbits+WORD_BITS-1)/WORD_BITS);
  162. field_print(" mont", mont);
  163. for (i=0; i<nparams; i++) {
  164. printf(" With n=%d, t=%d, s=%d:\n", params[i].n, params[i].t, params[i].s);
  165. field_print(" out ", fbout[i]);
  166. }
  167. for (i=0; i<nsizes; i++) {
  168. printf(" With w=%d:\n",i);
  169. field_print(" wNAF", wout[i]);
  170. }
  171. if (nbits == FIELD_BITS) {
  172. field_print(" ct ", ct);
  173. field_print(" vl ", vl);
  174. field_print(" vt ", vt);
  175. field_print(" ed ", sced);
  176. }
  177. printf("decaf: succ = %d, %d\n", (int)succ_dm, (int)succ_dta);
  178. field_print(" s0", decaf_s);
  179. field_print(" dm", decaf_m);
  180. field_print(" dt", decaf_te);
  181. ret = -1;
  182. }
  183. return ret;
  184. }
  185. static int
  186. single_linear_combo_test (
  187. const field_a_t base1,
  188. const word_t *scalar1,
  189. int nbits1,
  190. const field_a_t base2,
  191. const word_t *scalar2,
  192. int nbits2
  193. ) {
  194. struct tw_extensible_t text1, text2, working;
  195. struct tw_pniels_t pn;
  196. field_a_t result_comb, result_combo, result_wnaf;
  197. mask_t succ =
  198. deserialize_and_twist_approx(&text1, base1)
  199. & deserialize_and_twist_approx(&text2, base2);
  200. if (!succ) return 1;
  201. struct fixed_base_table_t t1, t2;
  202. tw_niels_a_t wnaf[32];
  203. memset(&t1,0,sizeof(t1));
  204. memset(&t2,0,sizeof(t2));
  205. succ = precompute_fixed_base(&t1, &text1, 5, 5, 18, NULL); // FIELD_MAGIC
  206. succ &= precompute_fixed_base(&t2, &text2, 6, 3, 25, NULL); // FIELD_MAGIC
  207. succ &= precompute_fixed_base_wnaf(wnaf, &text2, 5);
  208. if (!succ) {
  209. destroy_fixed_base(&t1);
  210. destroy_fixed_base(&t2);
  211. return -1;
  212. }
  213. /* use the dedicated wNAF linear combo algorithm */
  214. copy_tw_extensible(&working, &text1);
  215. linear_combo_var_fixed_vt(&working, scalar1, nbits1, scalar2, nbits2, (const tw_niels_a_t*)wnaf, 5);
  216. untwist_and_double_and_serialize(result_wnaf, &working);
  217. /* use the dedicated combs algorithm */
  218. succ &= linear_combo_combs_vt(&working, scalar1, nbits1, &t1, scalar2, nbits2, &t2);
  219. untwist_and_double_and_serialize(result_combo, &working);
  220. /* use two combs */
  221. succ &= scalarmul_fixed_base(&working, scalar1, nbits1, &t1);
  222. convert_tw_extensible_to_tw_pniels(&pn, &working);
  223. succ &= scalarmul_fixed_base(&working, scalar2, nbits2, &t2);
  224. add_tw_pniels_to_tw_extensible(&working, &pn);
  225. untwist_and_double_and_serialize(result_comb, &working);
  226. mask_t consistent = MASK_SUCCESS;
  227. consistent &= field_eq(result_combo, result_wnaf);
  228. consistent &= field_eq(result_comb, result_wnaf);
  229. if (!succ || !consistent) {
  230. youfail();
  231. printf(" Failed linear combo consistency test with nbits=%d,%d.\n",nbits1,nbits2);
  232. field_print(" base1", base1);
  233. scalar_print(" scal1", scalar1, (nbits1+WORD_BITS-1)/WORD_BITS);
  234. field_print(" base2", base2);
  235. scalar_print(" scal2", scalar2, (nbits1+WORD_BITS-1)/WORD_BITS);
  236. field_print(" combs", result_comb);
  237. field_print(" combo", result_combo);
  238. field_print(" wNAFs", result_wnaf);
  239. return -1;
  240. }
  241. destroy_fixed_base(&t1);
  242. destroy_fixed_base(&t2);
  243. return 0;
  244. }
  245. /* 0 = succeed, 1 = inval, -1 = fail */
  246. static int
  247. single_scalarmul_commutativity_test (
  248. const field_a_t base,
  249. const word_t *scalar1,
  250. int nbits1,
  251. int ned1,
  252. const word_t *scalar2,
  253. int nbits2,
  254. int ned2
  255. ) {
  256. field_a_t m12, m21, tmp1, tmp2;
  257. mask_t succ12a = montgomery_ladder(tmp1,base,scalar1,nbits1,ned1);
  258. mask_t succ12b = montgomery_ladder(m12,tmp1,scalar2,nbits2,ned2);
  259. mask_t succ21a = montgomery_ladder(tmp2,base,scalar2,nbits2,ned2);
  260. mask_t succ21b = montgomery_ladder(m21,tmp2,scalar1,nbits1,ned1);
  261. mask_t succ12 = succ12a & succ12b, succ21 = succ21a & succ21b;
  262. if (succ12 != succ21) {
  263. youfail();
  264. printf(" Failed scalarmul commutativity test with (nbits,ned) = (%d,%d), (%d,%d).\n",
  265. nbits1,ned1,nbits2,ned2);
  266. field_print(" base", base);
  267. field_print(" tmp1", tmp1);
  268. field_print(" tmp2", tmp2);
  269. scalar_print(" sca1", scalar1, (nbits1+WORD_BITS-1)/WORD_BITS);
  270. scalar_print(" sca2", scalar2, (nbits1+WORD_BITS-1)/WORD_BITS);
  271. printf(" good = ((%d,%d),(%d,%d))\n", (int)-succ12a,
  272. (int)-succ12b, (int)-succ21a, (int)-succ21b);
  273. return -1;
  274. } else if (!succ12) {
  275. // printf(" (nbits,ned) = (%d,%d), (%d,%d).\n", nbits1,ned1,nbits2,ned2);
  276. // printf(" succ = (%d,%d), (%d,%d).\n", (int)-succ12a, (int)-succ12b, (int)-succ21a, (int)-succ21b);
  277. return 1;
  278. }
  279. mask_t consistent = field_eq(m12,m21);
  280. if (consistent) {
  281. return 0;
  282. } else {
  283. youfail();
  284. printf(" Failed scalarmul commutativity test with (nbits,ned) = (%d,%d), (%d,%d).\n",
  285. nbits1,ned1,nbits2,ned2);
  286. field_print(" base", base);
  287. scalar_print(" sca1", scalar1, (nbits1+WORD_BITS-1)/WORD_BITS);
  288. scalar_print(" sca2", scalar2, (nbits1+WORD_BITS-1)/WORD_BITS);
  289. field_print(" m12 ", m12);
  290. field_print(" m21 ", m21);
  291. return -1;
  292. }
  293. }
  294. static void crandom_generate_f(struct crandom_state_t *crand, uint8_t *scalar, int n) {
  295. crandom_generate(crand, scalar, n);
  296. int i;
  297. for (i = FIELD_BYTES; i<n; i++) {
  298. scalar[i] = 0;
  299. }
  300. #if (FIELD_BITS % 8)
  301. if (n >= FIELD_BYTES) {
  302. scalar[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
  303. }
  304. #endif
  305. }
  306. int test_scalarmul_commutativity (void) {
  307. int i,j,k,got;
  308. struct crandom_state_t crand;
  309. crandom_init_from_buffer(&crand, "scalarmul_commutativity_test RNG");
  310. for (i=0; i<=FIELD_BITS; i+=STRIDE) {
  311. for (j=0; j<=FIELD_BITS; j+=STRIDE) {
  312. got = 0;
  313. for (k=0; k<128 && !got; k++) {
  314. uint8_t ser[FIELD_BYTES];
  315. word_t scalar1[SCALAR_WORDS], scalar2[SCALAR_WORDS];
  316. crandom_generate_f(&crand, ser, sizeof(ser));
  317. crandom_generate(&crand, (uint8_t *)scalar1, sizeof(scalar1));
  318. crandom_generate(&crand, (uint8_t *)scalar2, sizeof(scalar2));
  319. field_t base;
  320. mask_t succ = field_deserialize(&base, ser);
  321. if (!succ) continue;
  322. int ret = single_scalarmul_commutativity_test (&base, scalar1, i, i%3, scalar2, j, j%3);
  323. got = !ret;
  324. if (ret == -1) return -1;
  325. }
  326. if (!got) {
  327. youfail();
  328. printf(" Unlikely: rejected 128 scalars in a row.\n");
  329. return -1;
  330. }
  331. }
  332. }
  333. return 0;
  334. }
  335. int test_linear_combo (void) {
  336. int i,j,k,got;
  337. struct crandom_state_t crand;
  338. crandom_init_from_buffer(&crand, "scalarmul_linear_combos_test RNG");
  339. for (i=0; i<=FIELD_BITS; i+=STRIDE) {
  340. for (j=0; j<=FIELD_BITS; j+=STRIDE) {
  341. got = 0;
  342. for (k=0; k<128 && !got; k++) {
  343. uint8_t ser[FIELD_BYTES];
  344. word_t scalar1[SCALAR_WORDS], scalar2[SCALAR_WORDS];
  345. crandom_generate(&crand, (uint8_t *)scalar1, sizeof(scalar1));
  346. crandom_generate(&crand, (uint8_t *)scalar2, sizeof(scalar2));
  347. field_t base1;
  348. crandom_generate_f(&crand, ser, sizeof(ser));
  349. mask_t succ = field_deserialize(&base1, ser);
  350. if (!succ) continue;
  351. field_t base2;
  352. crandom_generate(&crand, ser, sizeof(ser));
  353. succ = field_deserialize(&base2, ser);
  354. if (!succ) continue;
  355. int ret = single_linear_combo_test (&base1, scalar1, i, &base2, scalar2, j);
  356. got = !ret;
  357. if (ret == -1) return -1;
  358. }
  359. if (!got) {
  360. youfail();
  361. printf(" Unlikely: rejected 128 scalars in a row.\n");
  362. return -1;
  363. }
  364. }
  365. }
  366. return 0;
  367. }
  368. int test_scalarmul_compatibility (void) {
  369. int i,j,k,got;
  370. struct crandom_state_t crand;
  371. crandom_init_from_buffer(&crand, "scalarmul_compatibility_test RNG");
  372. for (i=0; i<=FIELD_BITS; i+=STRIDE) {
  373. for (j=0; j<=20; j++) {
  374. got = 0;
  375. for (k=0; k<128 && !got; k++) {
  376. uint8_t ser[FIELD_BYTES];
  377. word_t scalar[SCALAR_WORDS];
  378. crandom_generate_f(&crand, ser, sizeof(ser));
  379. crandom_generate(&crand, (uint8_t *)scalar, sizeof(scalar));
  380. field_t base;
  381. mask_t succ = field_deserialize(&base, ser);
  382. if (!succ) continue;
  383. int ret = single_scalarmul_compatibility_test (&base, scalar, i);
  384. got = !ret;
  385. if (ret == -1) return -1;
  386. }
  387. if (!got) {
  388. youfail();
  389. printf(" Unlikely: rejected 128 scalars in a row.\n");
  390. return -1;
  391. }
  392. }
  393. }
  394. return 0;
  395. }