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.
 
 
 
 
 

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