ec_mult.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710
  1. /*
  2. * Originally written by Bodo Moeller and Nils Larsch for the OpenSSL project.
  3. */
  4. /* ====================================================================
  5. * Copyright (c) 1998-2007 The OpenSSL Project. All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. *
  14. * 2. Redistributions in binary form must reproduce the above copyright
  15. * notice, this list of conditions and the following disclaimer in
  16. * the documentation and/or other materials provided with the
  17. * distribution.
  18. *
  19. * 3. All advertising materials mentioning features or use of this
  20. * software must display the following acknowledgment:
  21. * "This product includes software developed by the OpenSSL Project
  22. * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
  23. *
  24. * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  25. * endorse or promote products derived from this software without
  26. * prior written permission. For written permission, please contact
  27. * openssl-core@openssl.org.
  28. *
  29. * 5. Products derived from this software may not be called "OpenSSL"
  30. * nor may "OpenSSL" appear in their names without prior written
  31. * permission of the OpenSSL Project.
  32. *
  33. * 6. Redistributions of any form whatsoever must retain the following
  34. * acknowledgment:
  35. * "This product includes software developed by the OpenSSL Project
  36. * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
  37. *
  38. * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  39. * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  40. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  41. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
  42. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  43. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  44. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  45. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  46. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  47. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  48. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  49. * OF THE POSSIBILITY OF SUCH DAMAGE.
  50. * ====================================================================
  51. *
  52. * This product includes cryptographic software written by Eric Young
  53. * (eay@cryptsoft.com). This product includes software written by Tim
  54. * Hudson (tjh@cryptsoft.com).
  55. *
  56. */
  57. /* ====================================================================
  58. * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
  59. * Portions of this software developed by SUN MICROSYSTEMS, INC.,
  60. * and contributed to the OpenSSL project.
  61. */
  62. #include <string.h>
  63. #include <openssl/err.h>
  64. #include "internal/bn_int.h"
  65. #include "ec_lcl.h"
  66. /*
  67. * This file implements the wNAF-based interleaving multi-exponentation method
  68. * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp>);
  69. * for multiplication with precomputation, we use wNAF splitting
  70. * (<URL:http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp>).
  71. */
  72. /* structure for precomputed multiples of the generator */
  73. struct ec_pre_comp_st {
  74. const EC_GROUP *group; /* parent EC_GROUP object */
  75. size_t blocksize; /* block size for wNAF splitting */
  76. size_t numblocks; /* max. number of blocks for which we have
  77. * precomputation */
  78. size_t w; /* window size */
  79. EC_POINT **points; /* array with pre-calculated multiples of
  80. * generator: 'num' pointers to EC_POINT
  81. * objects followed by a NULL */
  82. size_t num; /* numblocks * 2^(w-1) */
  83. int references;
  84. };
  85. static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
  86. {
  87. EC_PRE_COMP *ret = NULL;
  88. if (!group)
  89. return NULL;
  90. ret = OPENSSL_zalloc(sizeof(*ret));
  91. if (ret == NULL) {
  92. ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
  93. return ret;
  94. }
  95. ret->group = group;
  96. ret->blocksize = 8; /* default */
  97. ret->w = 4; /* default */
  98. ret->references = 1;
  99. return ret;
  100. }
  101. EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
  102. {
  103. if (pre != NULL)
  104. CRYPTO_add(&pre->references, 1, CRYPTO_LOCK_EC_PRE_COMP);
  105. return pre;
  106. }
  107. void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
  108. {
  109. if (pre == NULL
  110. || CRYPTO_add(&pre->references, -1, CRYPTO_LOCK_EC_PRE_COMP) > 0)
  111. return;
  112. if (pre->points != NULL) {
  113. EC_POINT **pts;
  114. for (pts = pre->points; *pts != NULL; pts++)
  115. EC_POINT_free(*pts);
  116. OPENSSL_free(pre->points);
  117. }
  118. OPENSSL_free(pre);
  119. }
  120. /*
  121. * TODO: table should be optimised for the wNAF-based implementation,
  122. * sometimes smaller windows will give better performance (thus the
  123. * boundaries should be increased)
  124. */
  125. #define EC_window_bits_for_scalar_size(b) \
  126. ((size_t) \
  127. ((b) >= 2000 ? 6 : \
  128. (b) >= 800 ? 5 : \
  129. (b) >= 300 ? 4 : \
  130. (b) >= 70 ? 3 : \
  131. (b) >= 20 ? 2 : \
  132. 1))
  133. /*-
  134. * Compute
  135. * \sum scalars[i]*points[i],
  136. * also including
  137. * scalar*generator
  138. * in the addition if scalar != NULL
  139. */
  140. int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
  141. size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
  142. BN_CTX *ctx)
  143. {
  144. BN_CTX *new_ctx = NULL;
  145. const EC_POINT *generator = NULL;
  146. EC_POINT *tmp = NULL;
  147. size_t totalnum;
  148. size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
  149. size_t pre_points_per_block = 0;
  150. size_t i, j;
  151. int k;
  152. int r_is_inverted = 0;
  153. int r_is_at_infinity = 1;
  154. size_t *wsize = NULL; /* individual window sizes */
  155. signed char **wNAF = NULL; /* individual wNAFs */
  156. size_t *wNAF_len = NULL;
  157. size_t max_len = 0;
  158. size_t num_val;
  159. EC_POINT **val = NULL; /* precomputation */
  160. EC_POINT **v;
  161. EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or
  162. * 'pre_comp->points' */
  163. const EC_PRE_COMP *pre_comp = NULL;
  164. int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be
  165. * treated like other scalars, i.e.
  166. * precomputation is not available */
  167. int ret = 0;
  168. if (group->meth != r->meth) {
  169. ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
  170. return 0;
  171. }
  172. if ((scalar == NULL) && (num == 0)) {
  173. return EC_POINT_set_to_infinity(group, r);
  174. }
  175. for (i = 0; i < num; i++) {
  176. if (group->meth != points[i]->meth) {
  177. ECerr(EC_F_EC_WNAF_MUL, EC_R_INCOMPATIBLE_OBJECTS);
  178. return 0;
  179. }
  180. }
  181. if (ctx == NULL) {
  182. ctx = new_ctx = BN_CTX_new();
  183. if (ctx == NULL)
  184. goto err;
  185. }
  186. if (scalar != NULL) {
  187. generator = EC_GROUP_get0_generator(group);
  188. if (generator == NULL) {
  189. ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
  190. goto err;
  191. }
  192. /* look if we can use precomputed multiples of generator */
  193. pre_comp = group->pre_comp.ec;
  194. if (pre_comp && pre_comp->numblocks
  195. && (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
  196. 0)) {
  197. blocksize = pre_comp->blocksize;
  198. /*
  199. * determine maximum number of blocks that wNAF splitting may
  200. * yield (NB: maximum wNAF length is bit length plus one)
  201. */
  202. numblocks = (BN_num_bits(scalar) / blocksize) + 1;
  203. /*
  204. * we cannot use more blocks than we have precomputation for
  205. */
  206. if (numblocks > pre_comp->numblocks)
  207. numblocks = pre_comp->numblocks;
  208. pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
  209. /* check that pre_comp looks sane */
  210. if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
  211. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  212. goto err;
  213. }
  214. } else {
  215. /* can't use precomputation */
  216. pre_comp = NULL;
  217. numblocks = 1;
  218. num_scalar = 1; /* treat 'scalar' like 'num'-th element of
  219. * 'scalars' */
  220. }
  221. }
  222. totalnum = num + numblocks;
  223. wsize = OPENSSL_malloc(totalnum * sizeof wsize[0]);
  224. wNAF_len = OPENSSL_malloc(totalnum * sizeof wNAF_len[0]);
  225. wNAF = OPENSSL_malloc((totalnum + 1) * sizeof wNAF[0]); /* includes space
  226. * for pivot */
  227. val_sub = OPENSSL_malloc(totalnum * sizeof val_sub[0]);
  228. /* Ensure wNAF is initialised in case we end up going to err */
  229. if (wNAF != NULL)
  230. wNAF[0] = NULL; /* preliminary pivot */
  231. if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
  232. ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
  233. goto err;
  234. }
  235. /*
  236. * num_val will be the total number of temporarily precomputed points
  237. */
  238. num_val = 0;
  239. for (i = 0; i < num + num_scalar; i++) {
  240. size_t bits;
  241. bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
  242. wsize[i] = EC_window_bits_for_scalar_size(bits);
  243. num_val += (size_t)1 << (wsize[i] - 1);
  244. wNAF[i + 1] = NULL; /* make sure we always have a pivot */
  245. wNAF[i] =
  246. bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],
  247. &wNAF_len[i]);
  248. if (wNAF[i] == NULL)
  249. goto err;
  250. if (wNAF_len[i] > max_len)
  251. max_len = wNAF_len[i];
  252. }
  253. if (numblocks) {
  254. /* we go here iff scalar != NULL */
  255. if (pre_comp == NULL) {
  256. if (num_scalar != 1) {
  257. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  258. goto err;
  259. }
  260. /* we have already generated a wNAF for 'scalar' */
  261. } else {
  262. signed char *tmp_wNAF = NULL;
  263. size_t tmp_len = 0;
  264. if (num_scalar != 0) {
  265. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  266. goto err;
  267. }
  268. /*
  269. * use the window size for which we have precomputation
  270. */
  271. wsize[num] = pre_comp->w;
  272. tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len);
  273. if (!tmp_wNAF)
  274. goto err;
  275. if (tmp_len <= max_len) {
  276. /*
  277. * One of the other wNAFs is at least as long as the wNAF
  278. * belonging to the generator, so wNAF splitting will not buy
  279. * us anything.
  280. */
  281. numblocks = 1;
  282. totalnum = num + 1; /* don't use wNAF splitting */
  283. wNAF[num] = tmp_wNAF;
  284. wNAF[num + 1] = NULL;
  285. wNAF_len[num] = tmp_len;
  286. if (tmp_len > max_len)
  287. max_len = tmp_len;
  288. /*
  289. * pre_comp->points starts with the points that we need here:
  290. */
  291. val_sub[num] = pre_comp->points;
  292. } else {
  293. /*
  294. * don't include tmp_wNAF directly into wNAF array - use wNAF
  295. * splitting and include the blocks
  296. */
  297. signed char *pp;
  298. EC_POINT **tmp_points;
  299. if (tmp_len < numblocks * blocksize) {
  300. /*
  301. * possibly we can do with fewer blocks than estimated
  302. */
  303. numblocks = (tmp_len + blocksize - 1) / blocksize;
  304. if (numblocks > pre_comp->numblocks) {
  305. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  306. goto err;
  307. }
  308. totalnum = num + numblocks;
  309. }
  310. /* split wNAF in 'numblocks' parts */
  311. pp = tmp_wNAF;
  312. tmp_points = pre_comp->points;
  313. for (i = num; i < totalnum; i++) {
  314. if (i < totalnum - 1) {
  315. wNAF_len[i] = blocksize;
  316. if (tmp_len < blocksize) {
  317. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  318. goto err;
  319. }
  320. tmp_len -= blocksize;
  321. } else
  322. /*
  323. * last block gets whatever is left (this could be
  324. * more or less than 'blocksize'!)
  325. */
  326. wNAF_len[i] = tmp_len;
  327. wNAF[i + 1] = NULL;
  328. wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
  329. if (wNAF[i] == NULL) {
  330. ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
  331. OPENSSL_free(tmp_wNAF);
  332. goto err;
  333. }
  334. memcpy(wNAF[i], pp, wNAF_len[i]);
  335. if (wNAF_len[i] > max_len)
  336. max_len = wNAF_len[i];
  337. if (*tmp_points == NULL) {
  338. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  339. OPENSSL_free(tmp_wNAF);
  340. goto err;
  341. }
  342. val_sub[i] = tmp_points;
  343. tmp_points += pre_points_per_block;
  344. pp += blocksize;
  345. }
  346. OPENSSL_free(tmp_wNAF);
  347. }
  348. }
  349. }
  350. /*
  351. * All points we precompute now go into a single array 'val'.
  352. * 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a
  353. * subarray of 'pre_comp->points' if we already have precomputation.
  354. */
  355. val = OPENSSL_malloc((num_val + 1) * sizeof val[0]);
  356. if (val == NULL) {
  357. ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
  358. goto err;
  359. }
  360. val[num_val] = NULL; /* pivot element */
  361. /* allocate points for precomputation */
  362. v = val;
  363. for (i = 0; i < num + num_scalar; i++) {
  364. val_sub[i] = v;
  365. for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
  366. *v = EC_POINT_new(group);
  367. if (*v == NULL)
  368. goto err;
  369. v++;
  370. }
  371. }
  372. if (!(v == val + num_val)) {
  373. ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
  374. goto err;
  375. }
  376. if ((tmp = EC_POINT_new(group)) == NULL)
  377. goto err;
  378. /*-
  379. * prepare precomputed values:
  380. * val_sub[i][0] := points[i]
  381. * val_sub[i][1] := 3 * points[i]
  382. * val_sub[i][2] := 5 * points[i]
  383. * ...
  384. */
  385. for (i = 0; i < num + num_scalar; i++) {
  386. if (i < num) {
  387. if (!EC_POINT_copy(val_sub[i][0], points[i]))
  388. goto err;
  389. } else {
  390. if (!EC_POINT_copy(val_sub[i][0], generator))
  391. goto err;
  392. }
  393. if (wsize[i] > 1) {
  394. if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
  395. goto err;
  396. for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {
  397. if (!EC_POINT_add
  398. (group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
  399. goto err;
  400. }
  401. }
  402. }
  403. if (!EC_POINTs_make_affine(group, num_val, val, ctx))
  404. goto err;
  405. r_is_at_infinity = 1;
  406. for (k = max_len - 1; k >= 0; k--) {
  407. if (!r_is_at_infinity) {
  408. if (!EC_POINT_dbl(group, r, r, ctx))
  409. goto err;
  410. }
  411. for (i = 0; i < totalnum; i++) {
  412. if (wNAF_len[i] > (size_t)k) {
  413. int digit = wNAF[i][k];
  414. int is_neg;
  415. if (digit) {
  416. is_neg = digit < 0;
  417. if (is_neg)
  418. digit = -digit;
  419. if (is_neg != r_is_inverted) {
  420. if (!r_is_at_infinity) {
  421. if (!EC_POINT_invert(group, r, ctx))
  422. goto err;
  423. }
  424. r_is_inverted = !r_is_inverted;
  425. }
  426. /* digit > 0 */
  427. if (r_is_at_infinity) {
  428. if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
  429. goto err;
  430. r_is_at_infinity = 0;
  431. } else {
  432. if (!EC_POINT_add
  433. (group, r, r, val_sub[i][digit >> 1], ctx))
  434. goto err;
  435. }
  436. }
  437. }
  438. }
  439. }
  440. if (r_is_at_infinity) {
  441. if (!EC_POINT_set_to_infinity(group, r))
  442. goto err;
  443. } else {
  444. if (r_is_inverted)
  445. if (!EC_POINT_invert(group, r, ctx))
  446. goto err;
  447. }
  448. ret = 1;
  449. err:
  450. BN_CTX_free(new_ctx);
  451. EC_POINT_free(tmp);
  452. OPENSSL_free(wsize);
  453. OPENSSL_free(wNAF_len);
  454. if (wNAF != NULL) {
  455. signed char **w;
  456. for (w = wNAF; *w != NULL; w++)
  457. OPENSSL_free(*w);
  458. OPENSSL_free(wNAF);
  459. }
  460. if (val != NULL) {
  461. for (v = val; *v != NULL; v++)
  462. EC_POINT_clear_free(*v);
  463. OPENSSL_free(val);
  464. }
  465. OPENSSL_free(val_sub);
  466. return ret;
  467. }
  468. /*-
  469. * ec_wNAF_precompute_mult()
  470. * creates an EC_PRE_COMP object with preprecomputed multiples of the generator
  471. * for use with wNAF splitting as implemented in ec_wNAF_mul().
  472. *
  473. * 'pre_comp->points' is an array of multiples of the generator
  474. * of the following form:
  475. * points[0] = generator;
  476. * points[1] = 3 * generator;
  477. * ...
  478. * points[2^(w-1)-1] = (2^(w-1)-1) * generator;
  479. * points[2^(w-1)] = 2^blocksize * generator;
  480. * points[2^(w-1)+1] = 3 * 2^blocksize * generator;
  481. * ...
  482. * points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator
  483. * points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator
  484. * ...
  485. * points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
  486. * points[2^(w-1)*numblocks] = NULL
  487. */
  488. int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
  489. {
  490. const EC_POINT *generator;
  491. EC_POINT *tmp_point = NULL, *base = NULL, **var;
  492. BN_CTX *new_ctx = NULL;
  493. BIGNUM *order;
  494. size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
  495. EC_POINT **points = NULL;
  496. EC_PRE_COMP *pre_comp;
  497. int ret = 0;
  498. /* if there is an old EC_PRE_COMP object, throw it away */
  499. EC_pre_comp_free(group);
  500. if ((pre_comp = ec_pre_comp_new(group)) == NULL)
  501. return 0;
  502. generator = EC_GROUP_get0_generator(group);
  503. if (generator == NULL) {
  504. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
  505. goto err;
  506. }
  507. if (ctx == NULL) {
  508. ctx = new_ctx = BN_CTX_new();
  509. if (ctx == NULL)
  510. goto err;
  511. }
  512. BN_CTX_start(ctx);
  513. order = BN_CTX_get(ctx);
  514. if (order == NULL)
  515. goto err;
  516. if (!EC_GROUP_get_order(group, order, ctx))
  517. goto err;
  518. if (BN_is_zero(order)) {
  519. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
  520. goto err;
  521. }
  522. bits = BN_num_bits(order);
  523. /*
  524. * The following parameters mean we precompute (approximately) one point
  525. * per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other
  526. * bit lengths, other parameter combinations might provide better
  527. * efficiency.
  528. */
  529. blocksize = 8;
  530. w = 4;
  531. if (EC_window_bits_for_scalar_size(bits) > w) {
  532. /* let's not make the window too small ... */
  533. w = EC_window_bits_for_scalar_size(bits);
  534. }
  535. numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks
  536. * to use for wNAF
  537. * splitting */
  538. pre_points_per_block = (size_t)1 << (w - 1);
  539. num = pre_points_per_block * numblocks; /* number of points to compute
  540. * and store */
  541. points = OPENSSL_malloc(sizeof(*points) * (num + 1));
  542. if (points == NULL) {
  543. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
  544. goto err;
  545. }
  546. var = points;
  547. var[num] = NULL; /* pivot */
  548. for (i = 0; i < num; i++) {
  549. if ((var[i] = EC_POINT_new(group)) == NULL) {
  550. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
  551. goto err;
  552. }
  553. }
  554. if ((tmp_point = EC_POINT_new(group)) == NULL
  555. || (base = EC_POINT_new(group)) == NULL) {
  556. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
  557. goto err;
  558. }
  559. if (!EC_POINT_copy(base, generator))
  560. goto err;
  561. /* do the precomputation */
  562. for (i = 0; i < numblocks; i++) {
  563. size_t j;
  564. if (!EC_POINT_dbl(group, tmp_point, base, ctx))
  565. goto err;
  566. if (!EC_POINT_copy(*var++, base))
  567. goto err;
  568. for (j = 1; j < pre_points_per_block; j++, var++) {
  569. /*
  570. * calculate odd multiples of the current base point
  571. */
  572. if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
  573. goto err;
  574. }
  575. if (i < numblocks - 1) {
  576. /*
  577. * get the next base (multiply current one by 2^blocksize)
  578. */
  579. size_t k;
  580. if (blocksize <= 2) {
  581. ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
  582. goto err;
  583. }
  584. if (!EC_POINT_dbl(group, base, tmp_point, ctx))
  585. goto err;
  586. for (k = 2; k < blocksize; k++) {
  587. if (!EC_POINT_dbl(group, base, base, ctx))
  588. goto err;
  589. }
  590. }
  591. }
  592. if (!EC_POINTs_make_affine(group, num, points, ctx))
  593. goto err;
  594. pre_comp->group = group;
  595. pre_comp->blocksize = blocksize;
  596. pre_comp->numblocks = numblocks;
  597. pre_comp->w = w;
  598. pre_comp->points = points;
  599. points = NULL;
  600. pre_comp->num = num;
  601. SETPRECOMP(group, ec, pre_comp);
  602. pre_comp = NULL;
  603. ret = 1;
  604. err:
  605. if (ctx != NULL)
  606. BN_CTX_end(ctx);
  607. BN_CTX_free(new_ctx);
  608. EC_ec_pre_comp_free(pre_comp);
  609. if (points) {
  610. EC_POINT **p;
  611. for (p = points; *p != NULL; p++)
  612. EC_POINT_free(*p);
  613. OPENSSL_free(points);
  614. }
  615. EC_POINT_free(tmp_point);
  616. EC_POINT_free(base);
  617. return ret;
  618. }
  619. int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
  620. {
  621. return HAVEPRECOMP(group, ec);
  622. }