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.
 
 
 
 
 

777 lines
21 KiB

  1. /* Copyright (c) 2014 Cryptography Research, Inc.
  2. * Released under the MIT License. See LICENSE.txt for license information.
  3. */
  4. #include <stdlib.h>
  5. #include "scalarmul.h"
  6. #include "string.h"
  7. #include "barrett_field.h"
  8. mask_t
  9. p448_montgomery_ladder(
  10. struct p448_t *out,
  11. const struct p448_t *in,
  12. const uint64_t *scalar,
  13. int nbits,
  14. int n_extra_doubles
  15. ) {
  16. struct montgomery_t mont;
  17. p448_sqr(&mont.z0,in);
  18. p448_copy(&mont.za,&mont.z0);
  19. p448_set_ui(&mont.xa,1);
  20. p448_set_ui(&mont.zd,0);
  21. p448_set_ui(&mont.xd,1);
  22. int i,j,n=(nbits-1)&63;
  23. mask_t pflip = 0;
  24. for (j=(nbits+63)/64-1; j>=0; j--) {
  25. uint64_t w = scalar[j];
  26. for (i=n; i>=0; i--) {
  27. mask_t flip = -((w>>i)&1);
  28. p448_cond_swap(&mont.xa,&mont.xd,flip^pflip);
  29. p448_cond_swap(&mont.za,&mont.zd,flip^pflip);
  30. montgomery_step(&mont);
  31. pflip = flip;
  32. }
  33. n = 63;
  34. }
  35. p448_cond_swap(&mont.xa,&mont.xd,pflip);
  36. p448_cond_swap(&mont.za,&mont.zd,pflip);
  37. for (j=0; j<n_extra_doubles; j++) {
  38. montgomery_step(&mont);
  39. }
  40. struct p448_t sign;
  41. serialize_montgomery(&sign, out, &mont, in);
  42. p448_addw(&sign,1);
  43. return ~p448_is_zero(&sign);
  44. }
  45. static __inline__ void
  46. cond_negate_tw_niels(
  47. struct tw_niels_t *n,
  48. mask_t doNegate
  49. ) {
  50. p448_cond_swap(&n->a, &n->b, doNegate);
  51. p448_cond_neg(&n->c, doNegate);
  52. }
  53. static __inline__ void
  54. cond_negate_tw_pniels(
  55. struct tw_pniels_t *n,
  56. mask_t doNegate
  57. ) {
  58. cond_negate_tw_niels(&n->n, doNegate);
  59. }
  60. void
  61. constant_time_lookup_tw_pniels(
  62. struct tw_pniels_t *out,
  63. const struct tw_pniels_t *in,
  64. int nin,
  65. int idx
  66. ) {
  67. big_register_t big_one = 1, big_i = idx;
  68. big_register_t *o = (big_register_t *)out;
  69. const big_register_t *i = (const big_register_t *)in;
  70. int j;
  71. unsigned int k;
  72. memset(out, 0, sizeof(*out));
  73. for (j=0; j<nin; j++, big_i-=big_one) {
  74. big_register_t mask = br_is_zero(big_i);
  75. for (k=0; k<sizeof(*out)/sizeof(*o); k++) {
  76. o[k] |= mask & i[k+j*sizeof(*out)/sizeof(*o)];
  77. }
  78. }
  79. }
  80. static __inline__ void
  81. constant_time_lookup_tw_niels(
  82. struct tw_niels_t *out,
  83. const struct tw_niels_t *in,
  84. int nin,
  85. int idx
  86. ) {
  87. big_register_t big_one = 1, big_i = idx;
  88. big_register_t *o = (big_register_t *)out;
  89. const big_register_t *i = (const big_register_t *)in;
  90. int j;
  91. unsigned int k;
  92. memset(out, 0, sizeof(*out));
  93. for (j=0; j<nin; j++, big_i-=big_one) {
  94. big_register_t mask = br_is_zero(big_i);
  95. for (k=0; k<sizeof(*out)/sizeof(*o); k++) {
  96. o[k] |= mask & i[k+j*sizeof(*out)/sizeof(*o)];
  97. }
  98. }
  99. }
  100. static void
  101. convert_to_signed_window_form(
  102. word_t *out,
  103. const word_t *scalar,
  104. const word_t *prepared_data,
  105. int nwords
  106. ) {
  107. mask_t mask = -(scalar[0]&1);
  108. word_t carry = add_nr_ext_packed(out, scalar, nwords, prepared_data, nwords, ~mask);
  109. carry += add_nr_ext_packed(out, out, nwords, prepared_data+nwords, nwords, mask);
  110. assert(!(out[0]&1));
  111. int i;
  112. for (i=0; i<nwords; i++) {
  113. out[i] >>= 1;
  114. if (i<nwords-1) {
  115. out[i] |= out[i+1]<<(WORD_BITS-1);
  116. } else {
  117. out[i] |= carry<<(WORD_BITS-1);
  118. }
  119. }
  120. }
  121. void
  122. edwards_scalar_multiply(
  123. struct tw_extensible_t *working,
  124. const uint64_t scalar[7]
  125. ) {
  126. const int nbits=448; /* HACK? */
  127. word_t prepared_data[14] = {
  128. 0x9595b847fdf73126ull,
  129. 0x9bb9b8a856af5200ull,
  130. 0xb3136e22f37d5c4full,
  131. 0x0000000189a19442ull,
  132. 0x0000000000000000ull,
  133. 0x0000000000000000ull,
  134. 0x4000000000000000ull,
  135. 0x721cf5b5529eec33ull,
  136. 0x7a4cf635c8e9c2abull,
  137. 0xeec492d944a725bfull,
  138. 0x000000020cd77058ull,
  139. 0x0000000000000000ull,
  140. 0x0000000000000000ull,
  141. 0x0000000000000000ull
  142. }; /* TODO: split off */
  143. uint64_t scalar2[7];
  144. convert_to_signed_window_form(scalar2,scalar,prepared_data,7);
  145. struct tw_extensible_t tabulator;
  146. copy_tw_extensible(&tabulator, working);
  147. double_tw_extensible(&tabulator);
  148. struct tw_pniels_t pn, multiples[8];
  149. convert_tw_extensible_to_tw_pniels(&pn, &tabulator);
  150. convert_tw_extensible_to_tw_pniels(&multiples[0], working);
  151. int i;
  152. for (i=1; i<8; i++) {
  153. add_tw_pniels_to_tw_extensible(working, &pn);
  154. convert_tw_extensible_to_tw_pniels(&multiples[i], working);
  155. }
  156. i = nbits - 4;
  157. int bits = scalar2[i/64] >> (i%64) & 0xF,
  158. inv = (bits>>3)-1;
  159. bits ^= inv;
  160. constant_time_lookup_tw_pniels(&pn, multiples, 8, bits&7);
  161. cond_negate_tw_pniels(&pn, inv);
  162. convert_tw_pniels_to_tw_extensible(working, &pn);
  163. for (i-=4; i>=0; i-=4) {
  164. double_tw_extensible(working);
  165. double_tw_extensible(working);
  166. double_tw_extensible(working);
  167. double_tw_extensible(working);
  168. bits = scalar2[i/64] >> (i%64) & 0xF;
  169. inv = (bits>>3)-1;
  170. bits ^= inv;
  171. constant_time_lookup_tw_pniels(&pn, multiples, 8, bits&7);
  172. cond_negate_tw_pniels(&pn, inv);
  173. add_tw_pniels_to_tw_extensible(working, &pn);
  174. }
  175. }
  176. void
  177. edwards_scalar_multiply_vlook(
  178. struct tw_extensible_t *working,
  179. const uint64_t scalar[7]
  180. ) {
  181. const int nbits=448; /* HACK? */
  182. word_t prepared_data[14] = {
  183. 0x9595b847fdf73126ull,
  184. 0x9bb9b8a856af5200ull,
  185. 0xb3136e22f37d5c4full,
  186. 0x0000000189a19442ull,
  187. 0x0000000000000000ull,
  188. 0x0000000000000000ull,
  189. 0x4000000000000000ull,
  190. 0x721cf5b5529eec33ull,
  191. 0x7a4cf635c8e9c2abull,
  192. 0xeec492d944a725bfull,
  193. 0x000000020cd77058ull,
  194. 0x0000000000000000ull,
  195. 0x0000000000000000ull,
  196. 0x0000000000000000ull
  197. }; /* TODO: split off */
  198. uint64_t scalar2[7];
  199. convert_to_signed_window_form(scalar2,scalar,prepared_data,7);
  200. struct tw_extensible_t tabulator;
  201. copy_tw_extensible(&tabulator, working);
  202. double_tw_extensible(&tabulator);
  203. struct tw_pniels_t pn, multiples[8];
  204. convert_tw_extensible_to_tw_pniels(&pn, &tabulator);
  205. convert_tw_extensible_to_tw_pniels(&multiples[0], working);
  206. int i;
  207. for (i=1; i<8; i++) {
  208. add_tw_pniels_to_tw_extensible(working, &pn);
  209. convert_tw_extensible_to_tw_pniels(&multiples[i], working);
  210. }
  211. i = nbits - 4;
  212. int bits = scalar2[i/64] >> (i%64) & 0xF,
  213. inv = (bits>>3)-1;
  214. bits ^= inv;
  215. copy_tw_pniels(&pn, &multiples[bits&7]);
  216. cond_negate_tw_pniels(&pn, inv);
  217. convert_tw_pniels_to_tw_extensible(working, &pn);
  218. for (i-=4; i>=0; i-=4) {
  219. double_tw_extensible(working);
  220. double_tw_extensible(working);
  221. double_tw_extensible(working);
  222. double_tw_extensible(working);
  223. bits = scalar2[i/64] >> (i%64) & 0xF;
  224. inv = (bits>>3)-1;
  225. bits ^= inv;
  226. copy_tw_pniels(&pn, &multiples[bits&7]);
  227. cond_negate_tw_pniels(&pn, inv);
  228. add_tw_pniels_to_tw_extensible(working, &pn);
  229. }
  230. }
  231. void
  232. edwards_comb(
  233. struct tw_extensible_t *working,
  234. const word_t scalar[7],
  235. const struct tw_niels_t *table,
  236. int n,
  237. int t,
  238. int s
  239. ) {
  240. word_t prepared_data[14] = {
  241. 0xebec9967f5d3f5c2ull,
  242. 0x0aa09b49b16c9a02ull,
  243. 0x7f6126aec172cd8eull,
  244. 0x00000007b027e54dull,
  245. 0x0000000000000000ull,
  246. 0x0000000000000000ull,
  247. 0x4000000000000000ull,
  248. 0xc873d6d54a7bb0cfull,
  249. 0xe933d8d723a70aadull,
  250. 0xbb124b65129c96fdull,
  251. 0x00000008335dc163ull,
  252. 0x0000000000000000ull,
  253. 0x0000000000000000ull,
  254. 0x0000000000000000ull
  255. }; /* TODO: split off. Above is for 450 bits */
  256. word_t scalar2[7];
  257. convert_to_signed_window_form(scalar2,scalar,prepared_data,7);
  258. /* const int n=3, t=5, s=30; */
  259. int i,j,k;
  260. struct tw_niels_t ni;
  261. for (i=0; i<s; i++) {
  262. if (i) double_tw_extensible(working);
  263. for (j=0; j<n; j++) {
  264. int tab = 0;
  265. /*
  266. * PERF: This computation takes about 1.5µs on SBR, i.e. 2-3% of the
  267. * time of a keygen or sign op. Surely it is possible to speed it up.
  268. */
  269. for (k=0; k<t; k++) {
  270. int bit = (s-1-i) + k*s + j*(s*t);
  271. if (bit < 7*WORD_BITS) {
  272. tab |= (scalar2[bit/WORD_BITS] >> (bit%WORD_BITS) & 1) << k;
  273. }
  274. }
  275. mask_t invert = (tab>>(t-1))-1;
  276. tab ^= invert;
  277. tab &= (1<<(t-1)) - 1;
  278. constant_time_lookup_tw_niels(&ni, table + (j<<(t-1)), 1<<(t-1), tab);
  279. cond_negate_tw_niels(&ni, invert);
  280. if (i||j) {
  281. add_tw_niels_to_tw_extensible(working, &ni);
  282. } else {
  283. convert_tw_niels_to_tw_extensible(working, &ni);
  284. }
  285. }
  286. }
  287. }
  288. void
  289. simultaneous_invert_p448(
  290. struct p448_t *out,
  291. const struct p448_t *in,
  292. int n
  293. ) {
  294. if (!n) return;
  295. p448_copy(&out[1], &in[0]);
  296. int i;
  297. for (i=1; i<n-1; i++) {
  298. p448_mul(&out[i+1], &out[i], &in[i]);
  299. }
  300. p448_mul(&out[0], &out[n-1], &in[n-1]);
  301. struct p448_t tmp;
  302. p448_inverse(&tmp, &out[0]);
  303. p448_copy(&out[0], &tmp);
  304. /* at this point, out[0] = product(in[i]) ^ -1
  305. * out[i] = product(in[0]..in[i-1]) if i != 0
  306. */
  307. for (i=n-1; i>0; i--) {
  308. p448_mul(&tmp, &out[i], &out[0]);
  309. p448_copy(&out[i], &tmp);
  310. p448_mul(&tmp, &out[0], &in[i]);
  311. p448_copy(&out[0], &tmp);
  312. }
  313. }
  314. mask_t
  315. precompute_for_combs(
  316. struct tw_niels_t *out,
  317. const struct tw_extensible_t *const_base,
  318. int n,
  319. int t,
  320. int s
  321. ) {
  322. if (s < 1) return 0;
  323. struct tw_extensible_t working, start;
  324. copy_tw_extensible(&working, const_base);
  325. struct tw_pniels_t pn_tmp;
  326. struct tw_pniels_t *doubles = (struct tw_pniels_t *) malloc(sizeof(*doubles) * (t-1));
  327. struct p448_t *zs = (struct p448_t *) malloc(sizeof(*zs) * (n<<(t-1)));
  328. struct p448_t *zis = (struct p448_t *) malloc(sizeof(*zis) * (n<<(t-1)));
  329. if (!doubles || !zs || !zis) {
  330. free(doubles);
  331. free(zs);
  332. free(zis);
  333. return 0;
  334. }
  335. int i,j,k;
  336. for (i=0; i<n; i++) {
  337. /* doubling phase */
  338. for (j=0; j<t; j++) {
  339. if (j) {
  340. convert_tw_extensible_to_tw_pniels(&pn_tmp, &working);
  341. add_tw_pniels_to_tw_extensible(&start, &pn_tmp);
  342. } else {
  343. copy_tw_extensible(&start, &working);
  344. }
  345. if (j==t-1 && i==n-1) {
  346. break;
  347. }
  348. double_tw_extensible(&working);
  349. if (j<t-1) {
  350. convert_tw_extensible_to_tw_pniels(&doubles[j], &working);
  351. }
  352. for (k=0; k<s-1; k++) {
  353. double_tw_extensible(&working);
  354. }
  355. }
  356. /* Gray-code phase */
  357. for (j=0;; j++) {
  358. int gray = j ^ (j>>1);
  359. int idx = ((i+1)<<(t-1))-1 ^ gray;
  360. convert_tw_extensible_to_tw_pniels(&pn_tmp, &start);
  361. copy_tw_niels(&out[idx], &pn_tmp.n);
  362. p448_copy(&zs[idx], &pn_tmp.z);
  363. if (j >= (1<<(t-1)) - 1) break;
  364. int delta = (j+1) ^ ((j+1)>>1) ^ gray;
  365. for (k=0; delta>1; k++)
  366. delta >>=1;
  367. if (gray & (1<<k)) {
  368. /* start += doubles[k] */
  369. add_tw_pniels_to_tw_extensible(&start, &doubles[k]);
  370. } else {
  371. /* start -= doubles[k] */
  372. sub_tw_pniels_from_tw_extensible(&start, &doubles[k]);
  373. }
  374. }
  375. }
  376. simultaneous_invert_p448(zis, zs, n<<(t-1));
  377. p448_t product;
  378. for (i=0; i<n<<(t-1); i++) {
  379. p448_mul(&product, &out[i].a, &zis[i]);
  380. p448_strong_reduce(&product);
  381. p448_copy(&out[i].a, &product);
  382. p448_mul(&product, &out[i].b, &zis[i]);
  383. p448_strong_reduce(&product);
  384. p448_copy(&out[i].b, &product);
  385. p448_mul(&product, &out[i].c, &zis[i]);
  386. p448_strong_reduce(&product);
  387. p448_copy(&out[i].c, &product);
  388. }
  389. mask_t ret = ~p448_is_zero(&zis[0]);
  390. free(doubles);
  391. free(zs);
  392. free(zis);
  393. return ret;
  394. }
  395. mask_t
  396. precompute_for_wnaf(
  397. struct tw_niels_t *out,
  398. const struct tw_extensible_t *const_base,
  399. int tbits
  400. ) {
  401. int i;
  402. struct p448_t *zs = (struct p448_t *) malloc(sizeof(*zs)<<tbits);
  403. struct p448_t *zis = (struct p448_t *) malloc(sizeof(*zis)<<tbits);
  404. if (!zs || !zis) {
  405. free(zs);
  406. free(zis);
  407. return 0;
  408. }
  409. struct tw_extensible_t base;
  410. copy_tw_extensible(&base,const_base);
  411. struct tw_pniels_t twop, tmp;
  412. convert_tw_extensible_to_tw_pniels(&tmp, &base);
  413. p448_copy(&zs[0], &tmp.z);
  414. copy_tw_niels(&out[0], &tmp.n);
  415. if (tbits > 0) {
  416. double_tw_extensible(&base);
  417. convert_tw_extensible_to_tw_pniels(&twop, &base);
  418. add_tw_pniels_to_tw_extensible(&base, &tmp);
  419. convert_tw_extensible_to_tw_pniels(&tmp, &base);
  420. p448_copy(&zs[1], &tmp.z);
  421. copy_tw_niels(&out[1], &tmp.n);
  422. for (i=2; i < 1<<tbits; i++) {
  423. add_tw_pniels_to_tw_extensible(&base, &twop);
  424. convert_tw_extensible_to_tw_pniels(&tmp, &base);
  425. p448_copy(&zs[i], &tmp.z);
  426. copy_tw_niels(&out[i], &tmp.n);
  427. }
  428. }
  429. simultaneous_invert_p448(zis, zs, 1<<tbits);
  430. p448_t product;
  431. for (i=0; i<1<<tbits; i++) {
  432. p448_mul(&product, &out[i].a, &zis[i]);
  433. p448_strong_reduce(&product);
  434. p448_copy(&out[i].a, &product);
  435. p448_mul(&product, &out[i].b, &zis[i]);
  436. p448_strong_reduce(&product);
  437. p448_copy(&out[i].b, &product);
  438. p448_mul(&product, &out[i].c, &zis[i]);
  439. p448_strong_reduce(&product);
  440. p448_copy(&out[i].c, &product);
  441. }
  442. free(zs);
  443. free(zis);
  444. return -1;
  445. }
  446. /**
  447. * @cond internal
  448. * Control for variable-time scalar multiply algorithms.
  449. */
  450. struct smvt_control {
  451. int power, addend;
  452. };
  453. static int
  454. recode_wnaf(
  455. struct smvt_control *control, /* [nbits/(tableBits+1) + 3] */
  456. const word_t *scalar,
  457. int nbits,
  458. int tableBits)
  459. {
  460. int current = 0, position=0, i;
  461. /* PERF: negate scalar if it's large
  462. * PERF: this is a pretty simplistic algorithm. I'm sure there's a faster one...
  463. */
  464. for (i=nbits-1; i >= -2 - tableBits; i--) {
  465. int bit = (i >= 0)
  466. ? (scalar[i/WORD_BITS] >> (i%WORD_BITS)) & 1
  467. : 0;
  468. current = 2*current + bit;
  469. /*
  470. * Sizing: |current| >= 2^(tableBits+1) -> |current| = 2^0
  471. * So current loses (tableBits+1) bits every time. It otherwise gains
  472. * 1 bit per iteration. The number of iterations is
  473. * (nbits + 2 + tableBits), and an additional control word is added at
  474. * the end. So the total number of control words is at most
  475. * ceil((nbits+1) / (tableBits+1)) + 2 = floor((nbits)/(tableBits+1)) + 2.
  476. * There's also the stopper with power -1, for a total of +3.
  477. */
  478. if (current >= (2<<tableBits) || current <= -1 - (2<<tableBits)) {
  479. int delta = (current + 1) >> 1;
  480. current = -(current & 1);
  481. int j;
  482. for (j=i; (delta & 1) == 0; j++) {
  483. delta >>= 1;
  484. }
  485. control[position].power = j+1;
  486. control[position].addend = delta;
  487. position++;
  488. assert(position <= nbits/(tableBits+1) + 2);
  489. }
  490. }
  491. control[position].power = -1;
  492. control[position].addend = 0;
  493. return position;
  494. }
  495. static void
  496. prepare_wnaf_table(
  497. struct tw_pniels_t *output,
  498. struct tw_extensible_t *working,
  499. int tbits
  500. ) {
  501. convert_tw_extensible_to_tw_pniels(&output[0], working);
  502. if (tbits == 0) return;
  503. double_tw_extensible(working);
  504. struct tw_pniels_t twop;
  505. convert_tw_extensible_to_tw_pniels(&twop, working);
  506. add_tw_pniels_to_tw_extensible(working, &output[0]);
  507. convert_tw_extensible_to_tw_pniels(&output[1], working);
  508. for (int i=2; i < 1<<tbits; i++) {
  509. add_tw_pniels_to_tw_extensible(working, &twop);
  510. convert_tw_extensible_to_tw_pniels(&output[i], working);
  511. }
  512. }
  513. void
  514. edwards_scalar_multiply_vt(
  515. struct tw_extensible_t *working,
  516. const uint64_t scalar[7]
  517. ) {
  518. /* HACK: not 448? */
  519. const int nbits=448, table_bits = 3;
  520. struct smvt_control control[nbits/(table_bits+1)+3];
  521. int control_bits = recode_wnaf(control, scalar, nbits, table_bits);
  522. struct tw_pniels_t precmp[1<<table_bits];
  523. prepare_wnaf_table(precmp, working, table_bits);
  524. if (control_bits > 0) {
  525. assert(control[0].addend > 0);
  526. assert(control[0].power >= 0);
  527. convert_tw_pniels_to_tw_extensible(working, &precmp[control[0].addend >> 1]);
  528. } else {
  529. set_identity_tw_extensible(working);
  530. return;
  531. }
  532. int conti = 1, i;
  533. for (i = control[0].power - 1; i >= 0; i--) {
  534. double_tw_extensible(working);
  535. if (i == control[conti].power) {
  536. assert(control[conti].addend);
  537. if (control[conti].addend > 0) {
  538. add_tw_pniels_to_tw_extensible(working, &precmp[control[conti].addend >> 1]);
  539. } else {
  540. sub_tw_pniels_from_tw_extensible(working, &precmp[(-control[conti].addend) >> 1]);
  541. }
  542. conti++;
  543. assert(conti <= control_bits);
  544. }
  545. }
  546. }
  547. void
  548. edwards_scalar_multiply_vt_pre(
  549. struct tw_extensible_t *working,
  550. const uint64_t scalar[7],
  551. const struct tw_niels_t *precmp,
  552. int table_bits
  553. ) {
  554. /* HACK: not 448? */
  555. const int nbits=448;
  556. struct smvt_control control[nbits/(table_bits+1)+3];
  557. int control_bits = recode_wnaf(control, scalar, nbits, table_bits);
  558. if (control_bits > 0) {
  559. assert(control[0].addend > 0);
  560. assert(control[0].power >= 0);
  561. convert_tw_niels_to_tw_extensible(working, &precmp[control[0].addend >> 1]);
  562. } else {
  563. set_identity_tw_extensible(working);
  564. return;
  565. }
  566. int conti = 1, i;
  567. for (i = control[0].power - 1; i >= 0; i--) {
  568. double_tw_extensible(working);
  569. if (i == control[conti].power) {
  570. assert(control[conti].addend);
  571. if (control[conti].addend > 0) {
  572. add_tw_niels_to_tw_extensible(working, &precmp[control[conti].addend >> 1]);
  573. } else {
  574. sub_tw_niels_from_tw_extensible(working, &precmp[(-control[conti].addend) >> 1]);
  575. }
  576. conti++;
  577. assert(conti <= control_bits);
  578. }
  579. }
  580. }
  581. void
  582. edwards_combo_var_fixed_vt(
  583. struct tw_extensible_t *working,
  584. const uint64_t scalar_var[7],
  585. const uint64_t scalar_pre[7],
  586. const struct tw_niels_t *precmp,
  587. int table_bits_pre
  588. ) {
  589. /* HACK: not 448? */
  590. const int nbits_var=448, nbits_pre=448, table_bits_var = 3;
  591. struct smvt_control control_var[nbits_var/(table_bits_var+1)+3];
  592. struct smvt_control control_pre[nbits_pre/(table_bits_pre+1)+3];
  593. int ncb_var = recode_wnaf(control_var, scalar_var, nbits_var, table_bits_var);
  594. int ncb_pre = recode_wnaf(control_pre, scalar_pre, nbits_pre, table_bits_pre);
  595. (void)ncb_var;
  596. (void)ncb_pre;
  597. struct tw_pniels_t precmp_var[1<<table_bits_var];
  598. prepare_wnaf_table(precmp_var, working, table_bits_var);
  599. int contp=0, contv=0, i;
  600. i = control_var[0].power;
  601. if (i > control_pre[0].power) {
  602. convert_tw_pniels_to_tw_extensible(working, &precmp_var[control_var[0].addend >> 1]);
  603. contv++;
  604. } else if (i == control_pre[0].power && i >=0 ) {
  605. convert_tw_pniels_to_tw_extensible(working, &precmp_var[control_var[0].addend >> 1]);
  606. add_tw_niels_to_tw_extensible(working, &precmp[control_pre[0].addend >> 1]);
  607. contv++; contp++;
  608. } else {
  609. i = control_pre[0].power;
  610. convert_tw_niels_to_tw_extensible(working, &precmp[control_pre[0].addend >> 1]);
  611. contp++;
  612. }
  613. if (i < 0) {
  614. set_identity_tw_extensible(working);
  615. return;
  616. }
  617. for (i--; i >= 0; i--) {
  618. double_tw_extensible(working);
  619. if (i == control_var[contv].power) {
  620. assert(control_var[contv].addend);
  621. if (control_var[contv].addend > 0) {
  622. add_tw_pniels_to_tw_extensible(working, &precmp_var[control_var[contv].addend >> 1]);
  623. } else {
  624. sub_tw_pniels_from_tw_extensible(working, &precmp_var[(-control_var[contv].addend) >> 1]);
  625. }
  626. contv++;
  627. }
  628. if (i == control_pre[contp].power) {
  629. assert(control_pre[contp].addend);
  630. if (control_pre[contp].addend > 0) {
  631. add_tw_niels_to_tw_extensible(working, &precmp[control_pre[contp].addend >> 1]);
  632. } else {
  633. sub_tw_niels_from_tw_extensible(working, &precmp[(-control_pre[contp].addend) >> 1]);
  634. }
  635. contp++;
  636. }
  637. }
  638. assert(contv == ncb_var);
  639. assert(contp == ncb_pre);
  640. }