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.
 
 
 
 
 

436 lines
14 KiB

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