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.
 
 
 
 
 

726 lines
20 KiB

  1. /* Copyright (c) 2014 Cryptography Research, Inc.
  2. * Released under the MIT License. See LICENSE.txt for license information.
  3. */
  4. #include "word.h"
  5. #include <sys/time.h>
  6. #include <sys/types.h>
  7. #include <stdio.h>
  8. #include <memory.h>
  9. #include "p448.h"
  10. #include "ec_point.h"
  11. #include "scalarmul.h"
  12. #include "barrett_field.h"
  13. #include "crandom.h"
  14. #include "goldilocks.h"
  15. #include "sha512.h"
  16. static __inline__ void
  17. ignore_result ( int result ) {
  18. (void)result;
  19. }
  20. static double now() {
  21. struct timeval tv;
  22. gettimeofday(&tv, NULL);
  23. return tv.tv_sec + tv.tv_usec/1000000.0;
  24. }
  25. static void p448_randomize( struct crandom_state_t *crand, struct p448_t *a ) {
  26. crandom_generate(crand, (unsigned char *)a, sizeof(*a));
  27. p448_strong_reduce(a);
  28. }
  29. static void q448_randomize( struct crandom_state_t *crand, word_t sk[448/WORD_BITS] ) {
  30. crandom_generate(crand, (unsigned char *)sk, 448/8);
  31. }
  32. static void p448_print( const char *descr, const struct p448_t *a ) {
  33. p448_t b;
  34. p448_copy(&b, a);
  35. p448_strong_reduce(&b);
  36. int j;
  37. printf("%s = 0x", descr);
  38. for (j=sizeof(*a)/sizeof(a->limb[0])-1; j>=0; j--) {
  39. printf(PRIxWORD58, b.limb[j]);
  40. }
  41. printf("\n");
  42. }
  43. static void __attribute__((unused))
  44. p448_print_full (
  45. const char *descr,
  46. const struct p448_t *a
  47. ) {
  48. int j;
  49. printf("%s = 0x", descr);
  50. for (j=15; j>=0; j--) {
  51. printf("%02" PRIxWORD "_" PRIxWORD58 " ",
  52. a->limb[j]>>28, a->limb[j]&((1<<28)-1));
  53. }
  54. printf("\n");
  55. }
  56. static void q448_print( const char *descr, const word_t secret[448/WORD_BITS] ) {
  57. int j;
  58. printf("%s = 0x", descr);
  59. for (j=448/WORD_BITS-1; j>=0; j--) {
  60. printf(PRIxWORDfull, secret[j]);
  61. }
  62. printf("\n");
  63. }
  64. #ifndef N_TESTS_BASE
  65. #define N_TESTS_BASE 10000
  66. #endif
  67. int main(int argc, char **argv) {
  68. (void)argc;
  69. (void)argv;
  70. struct tw_extensible_t ext;
  71. struct extensible_t exta;
  72. struct tw_niels_t niels;
  73. struct tw_pniels_t pniels;
  74. struct affine_t affine;
  75. struct montgomery_t mb;
  76. struct p448_t a,b,c,d;
  77. double when;
  78. int i;
  79. int nbase = N_TESTS_BASE;
  80. /* Bad randomness so we can debug. */
  81. char initial_seed[32];
  82. for (i=0; i<32; i++) initial_seed[i] = i;
  83. struct crandom_state_t crand;
  84. crandom_init_from_buffer(&crand, initial_seed);
  85. word_t sk[448/WORD_BITS],tk[448/WORD_BITS];
  86. q448_randomize(&crand, sk);
  87. when = now();
  88. for (i=0; i<nbase*1000; i++) {
  89. p448_mul(&c, &b, &a);
  90. }
  91. when = now() - when;
  92. printf("mul: %5.1fns\n", when * 1e9 / i);
  93. when = now();
  94. for (i=0; i<nbase*1000; i++) {
  95. p448_sqr(&c, &a);
  96. }
  97. when = now() - when;
  98. printf("sqr: %5.1fns\n", when * 1e9 / i);
  99. when = now();
  100. for (i=0; i<nbase*500; i++) {
  101. p448_mul(&c, &b, &a);
  102. p448_mul(&a, &b, &c);
  103. }
  104. when = now() - when;
  105. printf("mul dep: %5.1fns\n", when * 1e9 / i / 2);
  106. when = now();
  107. for (i=0; i<nbase*1000; i++) {
  108. p448_mulw(&c, &b, 1234562);
  109. }
  110. when = now() - when;
  111. printf("mulw: %5.1fns\n", when * 1e9 / i);
  112. when = now();
  113. for (i=0; i<nbase*10; i++) {
  114. p448_randomize(&crand, &a);
  115. }
  116. when = now() - when;
  117. printf("rand448: %5.1fns\n", when * 1e9 / i);
  118. struct sha512_ctx_t sha;
  119. uint8_t hashout[128];
  120. when = now();
  121. for (i=0; i<nbase; i++) {
  122. sha512_init(&sha);
  123. sha512_final(&sha, hashout);
  124. }
  125. when = now() - when;
  126. printf("sha512 1blk: %5.1fns\n", when * 1e9 / i);
  127. when = now();
  128. for (i=0; i<nbase; i++) {
  129. sha512_update(&sha, hashout, 128);
  130. }
  131. when = now() - when;
  132. printf("sha512 blk: %5.1fns (%0.2f MB/s)\n", when * 1e9 / i, 128*i/when/1e6);
  133. when = now();
  134. for (i=0; i<nbase; i++) {
  135. p448_isr(&c, &a);
  136. }
  137. when = now() - when;
  138. printf("isr auto: %5.1fµs\n", when * 1e6 / i);
  139. for (i=0; i<100; i++) {
  140. p448_randomize(&crand, &a);
  141. p448_isr(&d,&a);
  142. p448_sqr(&b,&d);
  143. p448_mul(&c,&b,&a);
  144. p448_sqr(&b,&c);
  145. p448_subw(&b,1);
  146. p448_bias(&b,1);
  147. if (!p448_is_zero(&b)) {
  148. printf("ISR validation failure!\n");
  149. p448_print("a", &a);
  150. p448_print("s", &d);
  151. }
  152. }
  153. when = now();
  154. for (i=0; i<nbase; i++) {
  155. elligator_2s_inject(&affine, &a);
  156. }
  157. when = now() - when;
  158. printf("elligator: %5.1fµs\n", when * 1e6 / i);
  159. for (i=0; i<100; i++) {
  160. p448_randomize(&crand, &a);
  161. elligator_2s_inject(&affine, &a);
  162. if (!validate_affine(&affine)) {
  163. printf("Elligator validation failure!\n");
  164. p448_print("a", &a);
  165. p448_print("x", &affine.x);
  166. p448_print("y", &affine.y);
  167. }
  168. }
  169. when = now();
  170. for (i=0; i<nbase; i++) {
  171. deserialize_affine(&affine, &a);
  172. }
  173. when = now() - when;
  174. printf("decompress: %5.1fµs\n", when * 1e6 / i);
  175. when = now();
  176. for (i=0; i<nbase; i++) {
  177. serialize_extensible(&a, &exta);
  178. }
  179. when = now() - when;
  180. printf("compress: %5.1fµs\n", when * 1e6 / i);
  181. int goods = 0;
  182. for (i=0; i<100; i++) {
  183. p448_randomize(&crand, &a);
  184. mask_t good = deserialize_affine(&affine, &a);
  185. if (good & !validate_affine(&affine)) {
  186. printf("Deserialize validation failure!\n");
  187. p448_print("a", &a);
  188. p448_print("x", &affine.x);
  189. p448_print("y", &affine.y);
  190. } else if (good) {
  191. goods++;
  192. convert_affine_to_extensible(&exta,&affine);
  193. serialize_extensible(&b, &exta);
  194. p448_sub(&c,&b,&a);
  195. p448_bias(&c,2);
  196. if (!p448_is_zero(&c)) {
  197. printf("Reserialize validation failure!\n");
  198. p448_print("a", &a);
  199. p448_print("x", &affine.x);
  200. p448_print("y", &affine.y);
  201. deserialize_affine(&affine, &b);
  202. p448_print("b", &b);
  203. p448_print("x", &affine.x);
  204. p448_print("y", &affine.y);
  205. printf("\n");
  206. }
  207. }
  208. }
  209. if (goods<i/3) {
  210. printf("Deserialization validation failure! Deserialized %d/%d points\n", goods, i);
  211. }
  212. word_t lsk[768/WORD_BITS];
  213. crandom_generate(&crand, (unsigned char *)lsk, sizeof(lsk));
  214. when = now();
  215. for (i=0; i<nbase*100; i++) {
  216. barrett_reduce(lsk,sizeof(lsk)/sizeof(word_t),0,&goldi_q448);
  217. }
  218. when = now() - when;
  219. printf("barrett red: %5.1fns\n", when * 1e9 / i);
  220. when = now();
  221. for (i=0; i<nbase*10; i++) {
  222. barrett_mac(lsk,448/WORD_BITS,lsk,448/WORD_BITS,lsk,448/WORD_BITS,&goldi_q448);
  223. }
  224. when = now() - when;
  225. printf("barrett mac: %5.1fns\n", when * 1e9 / i);
  226. when = now();
  227. for (i=0; i<nbase*100; i++) {
  228. add_tw_niels_to_tw_extensible(&ext, &niels);
  229. }
  230. when = now() - when;
  231. printf("exti+niels: %5.1fns\n", when * 1e9 / i);
  232. when = now();
  233. for (i=0; i<nbase*100; i++) {
  234. add_tw_pniels_to_tw_extensible(&ext, &pniels);
  235. }
  236. when = now() - when;
  237. printf("exti+pniels: %5.1fns\n", when * 1e9 / i);
  238. when = now();
  239. for (i=0; i<nbase*100; i++) {
  240. double_tw_extensible(&ext);
  241. }
  242. when = now() - when;
  243. printf("exti dbl: %5.1fns\n", when * 1e9 / i);
  244. when = now();
  245. for (i=0; i<nbase*100; i++) {
  246. untwist_and_double(&exta, &ext);
  247. }
  248. when = now() - when;
  249. printf("i->a isog: %5.1fns\n", when * 1e9 / i);
  250. when = now();
  251. for (i=0; i<nbase*100; i++) {
  252. twist_and_double(&ext, &exta);
  253. }
  254. when = now() - when;
  255. printf("a->i isog: %5.1fns\n", when * 1e9 / i);
  256. when = now();
  257. for (i=0; i<nbase*100; i++) {
  258. montgomery_step(&mb);
  259. }
  260. when = now() - when;
  261. printf("monty step: %5.1fns\n", when * 1e9 / i);
  262. when = now();
  263. for (i=0; i<nbase/10; i++) {
  264. ignore_result(montgomery_ladder(&a,&b,sk,448,0));
  265. }
  266. when = now() - when;
  267. printf("full ladder: %5.1fµs\n", when * 1e6 / i);
  268. when = now();
  269. for (i=0; i<nbase/10; i++) {
  270. scalarmul(&ext,sk);
  271. }
  272. when = now() - when;
  273. printf("edwards smz: %5.1fµs\n", when * 1e6 / i);
  274. when = now();
  275. for (i=0; i<nbase/10; i++) {
  276. scalarmul_vlook(&ext,sk);
  277. }
  278. when = now() - when;
  279. printf("edwards svl: %5.1fµs\n", when * 1e6 / i);
  280. when = now();
  281. for (i=0; i<nbase/10; i++) {
  282. scalarmul(&ext,sk);
  283. untwist_and_double_and_serialize(&a,&ext);
  284. }
  285. when = now() - when;
  286. printf("edwards smc: %5.1fµs\n", when * 1e6 / i);
  287. when = now();
  288. for (i=0; i<nbase/10; i++) {
  289. q448_randomize(&crand, sk);
  290. scalarmul_vt(&ext,sk);
  291. }
  292. when = now() - when;
  293. printf("edwards vtm: %5.1fµs\n", when * 1e6 / i);
  294. struct tw_niels_t wnaft[1<<6];
  295. when = now();
  296. for (i=0; i<nbase/10; i++) {
  297. ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,6));
  298. }
  299. when = now() - when;
  300. printf("wnaf6 pre: %5.1fµs\n", when * 1e6 / i);
  301. when = now();
  302. for (i=0; i<nbase/10; i++) {
  303. q448_randomize(&crand, sk);
  304. scalarmul_fixed_base_wnaf_vt(&ext,sk,446,wnaft,6);
  305. }
  306. when = now() - when;
  307. printf("edwards vt6: %5.1fµs\n", when * 1e6 / i);
  308. when = now();
  309. for (i=0; i<nbase/10; i++) {
  310. ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,4));
  311. }
  312. when = now() - when;
  313. printf("wnaf4 pre: %5.1fµs\n", when * 1e6 / i);
  314. when = now();
  315. for (i=0; i<nbase/10; i++) {
  316. q448_randomize(&crand, sk);
  317. scalarmul_fixed_base_wnaf_vt(&ext,sk,446,wnaft,4);
  318. }
  319. when = now() - when;
  320. printf("edwards vt4: %5.1fµs\n", when * 1e6 / i);
  321. when = now();
  322. for (i=0; i<nbase/10; i++) {
  323. ignore_result(precompute_fixed_base_wnaf(wnaft,&ext,5));
  324. }
  325. when = now() - when;
  326. printf("wnaf5 pre: %5.1fµs\n", when * 1e6 / i);
  327. when = now();
  328. for (i=0; i<nbase/10; i++) {
  329. q448_randomize(&crand, sk);
  330. scalarmul_fixed_base_wnaf_vt(&ext,sk,446,wnaft,5);
  331. }
  332. when = now() - when;
  333. printf("edwards vt5: %5.1fµs\n", when * 1e6 / i);
  334. when = now();
  335. for (i=0; i<nbase/10; i++) {
  336. q448_randomize(&crand, sk);
  337. q448_randomize(&crand, tk);
  338. linear_combo_var_fixed_vt(&ext,sk,448,tk,448,wnaft,5);
  339. }
  340. when = now() - when;
  341. printf("vt vf combo: %5.1fµs\n", when * 1e6 / i);
  342. when = now();
  343. for (i=0; i<nbase/10; i++) {
  344. deserialize_affine(&affine, &a);
  345. convert_affine_to_extensible(&exta,&affine);
  346. twist_and_double(&ext,&exta);
  347. scalarmul(&ext,sk);
  348. untwist_and_double(&exta,&ext);
  349. serialize_extensible(&b, &exta);
  350. }
  351. when = now() - when;
  352. printf("edwards sm: %5.1fµs\n", when * 1e6 / i);
  353. struct fixed_base_table_t t_5_5_18, t_3_5_30, t_8_4_14, t_5_3_30, t_15_3_10;
  354. while (1) {
  355. p448_randomize(&crand, &a);
  356. if (deserialize_affine(&affine, &a)) break;
  357. }
  358. convert_affine_to_extensible(&exta,&affine);
  359. twist_and_double(&ext,&exta);
  360. when = now();
  361. for (i=0; i<nbase/10; i++) {
  362. if (i) destroy_fixed_base(&t_5_5_18);
  363. ignore_result(precompute_fixed_base(&t_5_5_18, &ext, 5, 5, 18, NULL));
  364. }
  365. when = now() - when;
  366. printf("pre(5,5,18): %5.1fµs\n", when * 1e6 / i);
  367. when = now();
  368. for (i=0; i<nbase/10; i++) {
  369. if (i) destroy_fixed_base(&t_3_5_30);
  370. ignore_result(precompute_fixed_base(&t_3_5_30, &ext, 3, 5, 30, NULL));
  371. }
  372. when = now() - when;
  373. printf("pre(3,5,30): %5.1fµs\n", when * 1e6 / i);
  374. when = now();
  375. for (i=0; i<nbase/10; i++) {
  376. if (i) destroy_fixed_base(&t_5_3_30);
  377. ignore_result(precompute_fixed_base(&t_5_3_30, &ext, 5, 3, 30, NULL));
  378. }
  379. when = now() - when;
  380. printf("pre(5,3,30): %5.1fµs\n", when * 1e6 / i);
  381. when = now();
  382. for (i=0; i<nbase/10; i++) {
  383. if (i) destroy_fixed_base(&t_15_3_10);
  384. ignore_result(precompute_fixed_base(&t_15_3_10, &ext, 15, 3, 10, NULL));
  385. }
  386. when = now() - when;
  387. printf("pre(15,3,10):%5.1fµs\n", when * 1e6 / i);
  388. when = now();
  389. for (i=0; i<nbase/10; i++) {
  390. if (i) destroy_fixed_base(&t_8_4_14);
  391. ignore_result(precompute_fixed_base(&t_8_4_14, &ext, 8, 4, 14, NULL));
  392. }
  393. when = now() - when;
  394. printf("pre(8,4,14): %5.1fµs\n", when * 1e6 / i);
  395. when = now();
  396. for (i=0; i<nbase; i++) {
  397. scalarmul_fixed_base(&ext, sk, 448, &t_5_5_18);
  398. }
  399. when = now() - when;
  400. printf("com(5,5,18): %5.1fµs\n", when * 1e6 / i);
  401. when = now();
  402. for (i=0; i<nbase; i++) {
  403. scalarmul_fixed_base(&ext, sk, 448, &t_3_5_30);
  404. }
  405. when = now() - when;
  406. printf("com(3,5,30): %5.1fµs\n", when * 1e6 / i);
  407. when = now();
  408. for (i=0; i<nbase; i++) {
  409. scalarmul_fixed_base(&ext, sk, 448, &t_8_4_14);
  410. }
  411. when = now() - when;
  412. printf("com(8,4,14): %5.1fµs\n", when * 1e6 / i);
  413. when = now();
  414. for (i=0; i<nbase; i++) {
  415. scalarmul_fixed_base(&ext, sk, 448, &t_5_3_30);
  416. }
  417. when = now() - when;
  418. printf("com(5,3,30): %5.1fµs\n", when * 1e6 / i);
  419. when = now();
  420. for (i=0; i<nbase; i++) {
  421. scalarmul_fixed_base(&ext, sk, 448, &t_15_3_10);
  422. }
  423. when = now() - when;
  424. printf("com(15,3,10):%5.1fµs\n", when * 1e6 / i);
  425. printf("\nGoldilocks:\n");
  426. int res = goldilocks_init();
  427. assert(!res);
  428. struct goldilocks_public_key_t gpk,hpk;
  429. struct goldilocks_private_key_t gsk,hsk;
  430. when = now();
  431. for (i=0; i<nbase; i++) {
  432. if (i&1) {
  433. res = goldilocks_keygen(&gsk,&gpk);
  434. } else {
  435. res = goldilocks_keygen(&hsk,&hpk);
  436. }
  437. assert(!res);
  438. }
  439. when = now() - when;
  440. printf("keygen: %5.1fµs\n", when * 1e6 / i);
  441. uint8_t ss1[64],ss2[64];
  442. int gres1=0,gres2=0;
  443. when = now();
  444. for (i=0; i<nbase; i++) {
  445. if (i&1) {
  446. gres1 = goldilocks_shared_secret(ss1,&gsk,&hpk);
  447. } else {
  448. gres2 = goldilocks_shared_secret(ss2,&hsk,&gpk);
  449. }
  450. }
  451. when = now() - when;
  452. printf("ecdh: %5.1fµs\n", when * 1e6 / i);
  453. if (gres1 || gres2 || memcmp(ss1,ss2,64)) {
  454. printf("[FAIL] %d %d\n",gres1,gres2);
  455. printf("sk1 = ");
  456. for (i=0; i<56; i++) {
  457. printf("%02x", gsk.opaque[i]);
  458. }
  459. printf("\nsk2 = ");
  460. for (i=0; i<56; i++) {
  461. printf("%02x", hsk.opaque[i]);
  462. }
  463. printf("\nss1 = ");
  464. for (i=0; i<56; i++) {
  465. printf("%02x", ss1[i]);
  466. }
  467. printf("\nss2 = ");
  468. for (i=0; i<56; i++) {
  469. printf("%02x", ss2[i]);
  470. }
  471. printf("\n");
  472. }
  473. uint8_t sout[56*2];
  474. const char *message = "hello world";
  475. size_t message_len = strlen(message);
  476. when = now();
  477. for (i=0; i<nbase; i++) {
  478. res = goldilocks_sign(sout,(const unsigned char *)message,message_len,&gsk);
  479. assert(!res);
  480. }
  481. when = now() - when;
  482. printf("sign: %5.1fµs\n", when * 1e6 / i);
  483. when = now();
  484. for (i=0; i<nbase; i++) {
  485. int ver = goldilocks_verify(sout,(const unsigned char *)message,message_len,&gpk);
  486. assert(!ver);
  487. }
  488. when = now() - when;
  489. printf("verify: %5.1fµs\n", when * 1e6 / i);
  490. struct goldilocks_precomputed_public_key_t *pre = NULL;
  491. when = now();
  492. for (i=0; i<nbase; i++) {
  493. goldilocks_destroy_precomputed_public_key(pre);
  494. pre = goldilocks_precompute_public_key(&gpk);
  495. }
  496. when = now() - when;
  497. printf("precompute: %5.1fµs\n", when * 1e6 / i);
  498. when = now();
  499. for (i=0; i<nbase; i++) {
  500. int ver = goldilocks_verify_precomputed(sout,(const unsigned char *)message,message_len,pre);
  501. assert(!ver);
  502. }
  503. when = now() - when;
  504. printf("verify pre: %5.1fµs\n", when * 1e6 / i);
  505. when = now();
  506. for (i=0; i<nbase; i++) {
  507. int ret = goldilocks_shared_secret_precomputed(ss1,&gsk,pre);
  508. assert(!ret);
  509. }
  510. when = now() - when;
  511. printf("ecdh pre: %5.1fµs\n", when * 1e6 / i);
  512. printf("\nTesting...\n");
  513. int failures=0, successes = 0;
  514. for (i=0; i<nbase/10; i++) {
  515. ignore_result(goldilocks_keygen(&gsk,&gpk));
  516. goldilocks_sign(sout,(const unsigned char *)message,message_len,&gsk);
  517. res = goldilocks_verify(sout,(const unsigned char *)message,message_len,&gpk);
  518. if (res) failures++;
  519. }
  520. if (failures) {
  521. printf("FAIL %d/%d signature checks!\n", failures, i);
  522. }
  523. failures=0; successes = 0;
  524. for (i=0; i<nbase/10; i++) {
  525. p448_randomize(&crand, &a);
  526. word_t two = 2;
  527. mask_t good = montgomery_ladder(&b,&a,&two,2,0);
  528. if (!good) continue;
  529. word_t x,y;
  530. crandom_generate(&crand, (unsigned char *)&x, sizeof(x));
  531. crandom_generate(&crand, (unsigned char *)&y, sizeof(y));
  532. x = (hword_t)x;
  533. y = (hword_t)y;
  534. word_t z=x*y;
  535. ignore_result(montgomery_ladder(&b,&a,&x,WORD_BITS,0));
  536. ignore_result(montgomery_ladder(&c,&b,&y,WORD_BITS,0));
  537. ignore_result(montgomery_ladder(&b,&a,&z,WORD_BITS,0));
  538. p448_sub(&d,&b,&c);
  539. p448_bias(&d,2);
  540. if (!p448_is_zero(&d)) {
  541. printf("Odd ladder validation failure %d!\n", ++failures);
  542. p448_print("a", &a);
  543. printf("x=%"PRIxWORD", y=%"PRIxWORD", z=%"PRIxWORD"\n", x,y,z);
  544. p448_print("c", &c);
  545. p448_print("b", &b);
  546. printf("\n");
  547. }
  548. }
  549. failures = 0;
  550. for (i=0; i<nbase/10; i++) {
  551. mask_t good;
  552. do {
  553. p448_randomize(&crand, &a);
  554. good = deserialize_affine(&affine, &a);
  555. } while (!good);
  556. convert_affine_to_extensible(&exta,&affine);
  557. twist_and_double(&ext,&exta);
  558. untwist_and_double(&exta,&ext);
  559. serialize_extensible(&b, &exta);
  560. untwist_and_double_and_serialize(&c, &ext);
  561. p448_sub(&d,&b,&c);
  562. p448_bias(&d,2);
  563. if (good && !p448_is_zero(&d)){
  564. printf("Iso+serial validation failure %d!\n", ++failures);
  565. p448_print("a", &a);
  566. p448_print("b", &b);
  567. p448_print("c", &c);
  568. printf("\n");
  569. } else if (good) {
  570. successes ++;
  571. }
  572. }
  573. if (successes < i/3) {
  574. printf("Iso+serial variation: only %d/%d successful.\n", successes, i);
  575. }
  576. successes = failures = 0;
  577. for (i=0; i<nbase/10; i++) {
  578. struct p448_t aa;
  579. struct tw_extensible_t exu,exv,exw;
  580. mask_t good;
  581. do {
  582. p448_randomize(&crand, &a);
  583. good = deserialize_affine(&affine, &a);
  584. convert_affine_to_extensible(&exta,&affine);
  585. twist_and_double(&ext,&exta);
  586. } while (!good);
  587. do {
  588. p448_randomize(&crand, &aa);
  589. good = deserialize_affine(&affine, &aa);
  590. convert_affine_to_extensible(&exta,&affine);
  591. twist_and_double(&exu,&exta);
  592. } while (!good);
  593. p448_randomize(&crand, &aa);
  594. q448_randomize(&crand, sk);
  595. if (i==0 || i==2) memset(&sk, 0, sizeof(sk));
  596. q448_randomize(&crand, tk);
  597. if (i==0 || i==1) memset(&tk, 0, sizeof(tk));
  598. copy_tw_extensible(&exv, &ext);
  599. copy_tw_extensible(&exw, &exu);
  600. scalarmul(&exv,sk);
  601. scalarmul(&exw,tk);
  602. convert_tw_extensible_to_tw_pniels(&pniels, &exw);
  603. add_tw_pniels_to_tw_extensible(&exv,&pniels);
  604. untwist_and_double(&exta,&exv);
  605. serialize_extensible(&b, &exta);
  606. ignore_result(precompute_fixed_base_wnaf(wnaft,&exu,5));
  607. linear_combo_var_fixed_vt(&ext,sk,448,tk,448,wnaft,5);
  608. untwist_and_double(&exta,&exv);
  609. serialize_extensible(&c, &exta);
  610. p448_sub(&d,&b,&c);
  611. p448_bias(&d,2);
  612. if (!p448_is_zero(&d)){
  613. printf("PreWNAF combo validation failure %d!\n", ++failures);
  614. p448_print("a", &a);
  615. p448_print("A", &aa);
  616. q448_print("s", sk);
  617. q448_print("t", tk);
  618. p448_print("c", &c);
  619. p448_print("b", &b);
  620. printf("\n\n");
  621. } else if (good) {
  622. successes ++;
  623. }
  624. }
  625. if (successes < i) {
  626. printf("PreWNAF combo variation: only %d/%d successful.\n", successes, i);
  627. }
  628. return 0;
  629. }