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