1 /* $OpenBSD: ec_lib.c,v 1.45 2022/04/07 17:37:25 tb Exp $ */
2 /*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
5 /* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
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
13 * notice, this list of conditions and the following disclaimer.
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 */
58 /* ====================================================================
59 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60 * Binary polynomial ECC support in OpenSSL originally developed by
61 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62 */
63
64 #include <string.h>
65
66 #include <openssl/opensslconf.h>
67
68 #include <openssl/err.h>
69 #include <openssl/opensslv.h>
70
71 #include "bn_lcl.h"
72 #include "ec_lcl.h"
73
74 /* functions for EC_GROUP objects */
75
76 EC_GROUP *
EC_GROUP_new(const EC_METHOD * meth)77 EC_GROUP_new(const EC_METHOD * meth)
78 {
79 EC_GROUP *ret;
80
81 if (meth == NULL) {
82 ECerror(EC_R_SLOT_FULL);
83 return NULL;
84 }
85 if (meth->group_init == 0) {
86 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
87 return NULL;
88 }
89 ret = malloc(sizeof *ret);
90 if (ret == NULL) {
91 ECerror(ERR_R_MALLOC_FAILURE);
92 return NULL;
93 }
94 ret->meth = meth;
95
96 ret->extra_data = NULL;
97
98 ret->generator = NULL;
99 BN_init(&ret->order);
100 BN_init(&ret->cofactor);
101
102 ret->curve_name = 0;
103 ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
104 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
105
106 ret->seed = NULL;
107 ret->seed_len = 0;
108
109 if (!meth->group_init(ret)) {
110 free(ret);
111 return NULL;
112 }
113 return ret;
114 }
115
116
117 void
EC_GROUP_free(EC_GROUP * group)118 EC_GROUP_free(EC_GROUP * group)
119 {
120 if (!group)
121 return;
122
123 if (group->meth->group_finish != 0)
124 group->meth->group_finish(group);
125
126 EC_EX_DATA_free_all_data(&group->extra_data);
127
128 EC_POINT_free(group->generator);
129 BN_free(&group->order);
130 BN_free(&group->cofactor);
131
132 free(group->seed);
133
134 free(group);
135 }
136
137
138 void
EC_GROUP_clear_free(EC_GROUP * group)139 EC_GROUP_clear_free(EC_GROUP * group)
140 {
141 if (!group)
142 return;
143
144 if (group->meth->group_clear_finish != 0)
145 group->meth->group_clear_finish(group);
146 else if (group->meth->group_finish != 0)
147 group->meth->group_finish(group);
148
149 EC_EX_DATA_clear_free_all_data(&group->extra_data);
150
151 EC_POINT_clear_free(group->generator);
152 BN_clear_free(&group->order);
153 BN_clear_free(&group->cofactor);
154
155 freezero(group->seed, group->seed_len);
156 freezero(group, sizeof *group);
157 }
158
159
160 int
EC_GROUP_copy(EC_GROUP * dest,const EC_GROUP * src)161 EC_GROUP_copy(EC_GROUP * dest, const EC_GROUP * src)
162 {
163 EC_EXTRA_DATA *d;
164
165 if (dest->meth->group_copy == 0) {
166 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
167 return 0;
168 }
169 if (dest->meth != src->meth) {
170 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
171 return 0;
172 }
173 if (dest == src)
174 return 1;
175
176 EC_EX_DATA_free_all_data(&dest->extra_data);
177
178 for (d = src->extra_data; d != NULL; d = d->next) {
179 void *t = d->dup_func(d->data);
180
181 if (t == NULL)
182 return 0;
183 if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func,
184 d->free_func, d->clear_free_func))
185 return 0;
186 }
187
188 if (src->generator != NULL) {
189 if (dest->generator == NULL) {
190 dest->generator = EC_POINT_new(dest);
191 if (dest->generator == NULL)
192 return 0;
193 }
194 if (!EC_POINT_copy(dest->generator, src->generator))
195 return 0;
196 } else {
197 /* src->generator == NULL */
198 EC_POINT_clear_free(dest->generator);
199 dest->generator = NULL;
200 }
201
202 if (!BN_copy(&dest->order, &src->order))
203 return 0;
204 if (!BN_copy(&dest->cofactor, &src->cofactor))
205 return 0;
206
207 dest->curve_name = src->curve_name;
208 dest->asn1_flag = src->asn1_flag;
209 dest->asn1_form = src->asn1_form;
210
211 if (src->seed) {
212 free(dest->seed);
213 dest->seed = malloc(src->seed_len);
214 if (dest->seed == NULL)
215 return 0;
216 memcpy(dest->seed, src->seed, src->seed_len);
217 dest->seed_len = src->seed_len;
218 } else {
219 free(dest->seed);
220 dest->seed = NULL;
221 dest->seed_len = 0;
222 }
223
224
225 return dest->meth->group_copy(dest, src);
226 }
227
228
229 EC_GROUP *
EC_GROUP_dup(const EC_GROUP * a)230 EC_GROUP_dup(const EC_GROUP * a)
231 {
232 EC_GROUP *t = NULL;
233
234 if ((a != NULL) && ((t = EC_GROUP_new(a->meth)) != NULL) &&
235 (!EC_GROUP_copy(t, a))) {
236 EC_GROUP_free(t);
237 t = NULL;
238 }
239 return t;
240 }
241
242
243 const EC_METHOD *
EC_GROUP_method_of(const EC_GROUP * group)244 EC_GROUP_method_of(const EC_GROUP *group)
245 {
246 return group->meth;
247 }
248
249
250 int
EC_METHOD_get_field_type(const EC_METHOD * meth)251 EC_METHOD_get_field_type(const EC_METHOD *meth)
252 {
253 return meth->field_type;
254 }
255
256 /*
257 * Try computing the cofactor from generator order n and field cardinality q.
258 * This works for all curves of cryptographic interest.
259 *
260 * Hasse's theorem: | h * n - (q + 1) | <= 2 * sqrt(q)
261 *
262 * So: h_min = (q + 1 - 2*sqrt(q)) / n and h_max = (q + 1 + 2*sqrt(q)) / n and
263 * therefore h_max - h_min = 4*sqrt(q) / n. So if n > 4*sqrt(q) holds, there is
264 * only one possible value for h:
265 *
266 * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
267 *
268 * Otherwise, zero cofactor and return success.
269 */
270 static int
ec_guess_cofactor(EC_GROUP * group)271 ec_guess_cofactor(EC_GROUP *group)
272 {
273 BN_CTX *ctx = NULL;
274 BIGNUM *q = NULL;
275 int ret = 0;
276
277 /*
278 * If the cofactor is too large, we cannot guess it and default to zero.
279 * The RHS of below is a strict overestimate of log(4 * sqrt(q)).
280 */
281 if (BN_num_bits(&group->order) <=
282 (BN_num_bits(&group->field) + 1) / 2 + 3) {
283 BN_zero(&group->cofactor);
284 return 1;
285 }
286
287 if ((ctx = BN_CTX_new()) == NULL)
288 goto err;
289
290 BN_CTX_start(ctx);
291 if ((q = BN_CTX_get(ctx)) == NULL)
292 goto err;
293
294 /* Set q = 2**m for binary fields; q = p otherwise. */
295 if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
296 BN_zero(q);
297 if (!BN_set_bit(q, BN_num_bits(&group->field) - 1))
298 goto err;
299 } else {
300 if (!BN_copy(q, &group->field))
301 goto err;
302 }
303
304 /*
305 * Compute
306 * h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2) / n \rfloor.
307 */
308
309 /* h = n/2 */
310 if (!BN_rshift1(&group->cofactor, &group->order))
311 goto err;
312 /* h = 1 + n/2 */
313 if (!BN_add(&group->cofactor, &group->cofactor, BN_value_one()))
314 goto err;
315 /* h = q + 1 + n/2 */
316 if (!BN_add(&group->cofactor, &group->cofactor, q))
317 goto err;
318 /* h = (q + 1 + n/2) / n */
319 if (!BN_div_ct(&group->cofactor, NULL, &group->cofactor, &group->order,
320 ctx))
321 goto err;
322
323 ret = 1;
324
325 err:
326 BN_CTX_end(ctx);
327 BN_CTX_free(ctx);
328
329 if (ret != 1)
330 BN_zero(&group->cofactor);
331
332 return ret;
333 }
334
335 int
EC_GROUP_set_generator(EC_GROUP * group,const EC_POINT * generator,const BIGNUM * order,const BIGNUM * cofactor)336 EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
337 const BIGNUM *order, const BIGNUM *cofactor)
338 {
339 if (generator == NULL) {
340 ECerror(ERR_R_PASSED_NULL_PARAMETER);
341 return 0;
342 }
343
344 /* Require group->field >= 1. */
345 if (BN_is_zero(&group->field) || BN_is_negative(&group->field)) {
346 ECerror(EC_R_INVALID_FIELD);
347 return 0;
348 }
349
350 /*
351 * Require order > 1 and enforce an upper bound of at most one bit more
352 * than the field cardinality due to Hasse's theorem.
353 */
354 if (order == NULL || BN_cmp(order, BN_value_one()) <= 0 ||
355 BN_num_bits(order) > BN_num_bits(&group->field) + 1) {
356 ECerror(EC_R_INVALID_GROUP_ORDER);
357 return 0;
358 }
359
360 /*
361 * Unfortunately, the cofactor is an optional field in many standards.
362 * Internally, the library uses a 0 cofactor as a marker for "unknown
363 * cofactor". So accept cofactor == NULL or cofactor >= 0.
364 */
365 if (cofactor != NULL && BN_is_negative(cofactor)) {
366 ECerror(EC_R_UNKNOWN_COFACTOR);
367 return 0;
368 }
369
370 if (group->generator == NULL) {
371 group->generator = EC_POINT_new(group);
372 if (group->generator == NULL)
373 return 0;
374 }
375 if (!EC_POINT_copy(group->generator, generator))
376 return 0;
377
378 if (!BN_copy(&group->order, order))
379 return 0;
380
381 /* Either take the provided positive cofactor, or try to compute it. */
382 if (cofactor != NULL && !BN_is_zero(cofactor)) {
383 if (!BN_copy(&group->cofactor, cofactor))
384 return 0;
385 } else if (!ec_guess_cofactor(group))
386 return 0;
387
388 /* Use Hasse's theorem to bound the cofactor. */
389 if (BN_num_bits(&group->cofactor) > BN_num_bits(&group->field) + 1) {
390 ECerror(EC_R_INVALID_GROUP_ORDER);
391 return 0;
392 }
393
394 return 1;
395 }
396
397
398 const EC_POINT *
EC_GROUP_get0_generator(const EC_GROUP * group)399 EC_GROUP_get0_generator(const EC_GROUP *group)
400 {
401 return group->generator;
402 }
403
404
405 int
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)406 EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
407 {
408 if (!BN_copy(order, &group->order))
409 return 0;
410
411 return !BN_is_zero(order);
412 }
413
414 int
EC_GROUP_order_bits(const EC_GROUP * group)415 EC_GROUP_order_bits(const EC_GROUP *group)
416 {
417 return group->meth->group_order_bits(group);
418 }
419
420 int
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)421 EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
422 {
423 if (!BN_copy(cofactor, &group->cofactor))
424 return 0;
425
426 return !BN_is_zero(&group->cofactor);
427 }
428
429
430 void
EC_GROUP_set_curve_name(EC_GROUP * group,int nid)431 EC_GROUP_set_curve_name(EC_GROUP * group, int nid)
432 {
433 group->curve_name = nid;
434 }
435
436
437 int
EC_GROUP_get_curve_name(const EC_GROUP * group)438 EC_GROUP_get_curve_name(const EC_GROUP * group)
439 {
440 return group->curve_name;
441 }
442
443
444 void
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)445 EC_GROUP_set_asn1_flag(EC_GROUP * group, int flag)
446 {
447 group->asn1_flag = flag;
448 }
449
450
451 int
EC_GROUP_get_asn1_flag(const EC_GROUP * group)452 EC_GROUP_get_asn1_flag(const EC_GROUP * group)
453 {
454 return group->asn1_flag;
455 }
456
457
458 void
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)459 EC_GROUP_set_point_conversion_form(EC_GROUP * group,
460 point_conversion_form_t form)
461 {
462 group->asn1_form = form;
463 }
464
465
466 point_conversion_form_t
EC_GROUP_get_point_conversion_form(const EC_GROUP * group)467 EC_GROUP_get_point_conversion_form(const EC_GROUP * group)
468 {
469 return group->asn1_form;
470 }
471
472
473 size_t
EC_GROUP_set_seed(EC_GROUP * group,const unsigned char * p,size_t len)474 EC_GROUP_set_seed(EC_GROUP * group, const unsigned char *p, size_t len)
475 {
476 if (group->seed) {
477 free(group->seed);
478 group->seed = NULL;
479 group->seed_len = 0;
480 }
481 if (!len || !p)
482 return 1;
483
484 if ((group->seed = malloc(len)) == NULL)
485 return 0;
486 memcpy(group->seed, p, len);
487 group->seed_len = len;
488
489 return len;
490 }
491
492
493 unsigned char *
EC_GROUP_get0_seed(const EC_GROUP * group)494 EC_GROUP_get0_seed(const EC_GROUP * group)
495 {
496 return group->seed;
497 }
498
499
500 size_t
EC_GROUP_get_seed_len(const EC_GROUP * group)501 EC_GROUP_get_seed_len(const EC_GROUP * group)
502 {
503 return group->seed_len;
504 }
505
506 int
EC_GROUP_set_curve(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)507 EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
508 const BIGNUM *b, BN_CTX *ctx)
509 {
510 if (group->meth->group_set_curve == NULL) {
511 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
512 return 0;
513 }
514 return group->meth->group_set_curve(group, p, a, b, ctx);
515 }
516
517 int
EC_GROUP_get_curve(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)518 EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
519 BN_CTX *ctx)
520 {
521 if (group->meth->group_get_curve == NULL) {
522 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
523 return 0;
524 }
525 return group->meth->group_get_curve(group, p, a, b, ctx);
526 }
527
528 int
EC_GROUP_set_curve_GFp(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)529 EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
530 const BIGNUM *b, BN_CTX *ctx)
531 {
532 return EC_GROUP_set_curve(group, p, a, b, ctx);
533 }
534
535 int
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)536 EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
537 BN_CTX *ctx)
538 {
539 return EC_GROUP_get_curve(group, p, a, b, ctx);
540 }
541
542 #ifndef OPENSSL_NO_EC2M
543 int
EC_GROUP_set_curve_GF2m(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)544 EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
545 const BIGNUM *b, BN_CTX *ctx)
546 {
547 return EC_GROUP_set_curve(group, p, a, b, ctx);
548 }
549
550 int
EC_GROUP_get_curve_GF2m(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)551 EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
552 BIGNUM *b, BN_CTX *ctx)
553 {
554 return EC_GROUP_get_curve(group, p, a, b, ctx);
555 }
556 #endif
557
558 int
EC_GROUP_get_degree(const EC_GROUP * group)559 EC_GROUP_get_degree(const EC_GROUP * group)
560 {
561 if (group->meth->group_get_degree == 0) {
562 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
563 return 0;
564 }
565 return group->meth->group_get_degree(group);
566 }
567
568
569 int
EC_GROUP_check_discriminant(const EC_GROUP * group,BN_CTX * ctx)570 EC_GROUP_check_discriminant(const EC_GROUP * group, BN_CTX * ctx)
571 {
572 if (group->meth->group_check_discriminant == 0) {
573 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
574 return 0;
575 }
576 return group->meth->group_check_discriminant(group, ctx);
577 }
578
579
580 int
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ctx)581 EC_GROUP_cmp(const EC_GROUP * a, const EC_GROUP * b, BN_CTX * ctx)
582 {
583 int r = 0;
584 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
585 BN_CTX *ctx_new = NULL;
586
587 /* compare the field types */
588 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
589 EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
590 return 1;
591 /* compare the curve name (if present in both) */
592 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
593 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
594 return 1;
595
596 if (!ctx)
597 ctx_new = ctx = BN_CTX_new();
598 if (!ctx)
599 return -1;
600
601 BN_CTX_start(ctx);
602 if ((a1 = BN_CTX_get(ctx)) == NULL)
603 goto err;
604 if ((a2 = BN_CTX_get(ctx)) == NULL)
605 goto err;
606 if ((a3 = BN_CTX_get(ctx)) == NULL)
607 goto err;
608 if ((b1 = BN_CTX_get(ctx)) == NULL)
609 goto err;
610 if ((b2 = BN_CTX_get(ctx)) == NULL)
611 goto err;
612 if ((b3 = BN_CTX_get(ctx)) == NULL)
613 goto err;
614
615 /*
616 * XXX This approach assumes that the external representation of
617 * curves over the same field type is the same.
618 */
619 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
620 !b->meth->group_get_curve(b, b1, b2, b3, ctx))
621 r = 1;
622
623 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
624 r = 1;
625
626 /* XXX EC_POINT_cmp() assumes that the methods are equal */
627 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
628 EC_GROUP_get0_generator(b), ctx))
629 r = 1;
630
631 if (!r) {
632 /* compare the order and cofactor */
633 if (!EC_GROUP_get_order(a, a1, ctx) ||
634 !EC_GROUP_get_order(b, b1, ctx) ||
635 !EC_GROUP_get_cofactor(a, a2, ctx) ||
636 !EC_GROUP_get_cofactor(b, b2, ctx))
637 goto err;
638 if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
639 r = 1;
640 }
641 BN_CTX_end(ctx);
642 if (ctx_new)
643 BN_CTX_free(ctx);
644
645 return r;
646
647 err:
648 BN_CTX_end(ctx);
649 if (ctx_new)
650 BN_CTX_free(ctx);
651 return -1;
652 }
653
654 /*
655 * Coordinate blinding for EC_POINT.
656 *
657 * The underlying EC_METHOD can optionally implement this function:
658 * underlying implementations should return 0 on errors, or 1 on success.
659 *
660 * This wrapper returns 1 in case the underlying EC_METHOD does not support
661 * coordinate blinding.
662 */
663 int
ec_point_blind_coordinates(const EC_GROUP * group,EC_POINT * p,BN_CTX * ctx)664 ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
665 {
666 if (group->meth->blind_coordinates == NULL)
667 return 1;
668
669 return group->meth->blind_coordinates(group, p, ctx);
670 }
671
672 /* this has 'package' visibility */
673 int
EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data,void * data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))674 EC_EX_DATA_set_data(EC_EXTRA_DATA ** ex_data, void *data,
675 void *(*dup_func) (void *),
676 void (*free_func) (void *),
677 void (*clear_free_func) (void *))
678 {
679 EC_EXTRA_DATA *d;
680
681 if (ex_data == NULL)
682 return 0;
683
684 for (d = *ex_data; d != NULL; d = d->next) {
685 if (d->dup_func == dup_func && d->free_func == free_func &&
686 d->clear_free_func == clear_free_func) {
687 ECerror(EC_R_SLOT_FULL);
688 return 0;
689 }
690 }
691
692 if (data == NULL)
693 /* no explicit entry needed */
694 return 1;
695
696 d = malloc(sizeof *d);
697 if (d == NULL)
698 return 0;
699
700 d->data = data;
701 d->dup_func = dup_func;
702 d->free_func = free_func;
703 d->clear_free_func = clear_free_func;
704
705 d->next = *ex_data;
706 *ex_data = d;
707
708 return 1;
709 }
710
711 /* this has 'package' visibility */
712 void *
EC_EX_DATA_get_data(const EC_EXTRA_DATA * ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))713 EC_EX_DATA_get_data(const EC_EXTRA_DATA * ex_data,
714 void *(*dup_func) (void *),
715 void (*free_func) (void *),
716 void (*clear_free_func) (void *))
717 {
718 const EC_EXTRA_DATA *d;
719
720 for (d = ex_data; d != NULL; d = d->next) {
721 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
722 return d->data;
723 }
724
725 return NULL;
726 }
727
728 /* this has 'package' visibility */
729 void
EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))730 EC_EX_DATA_free_data(EC_EXTRA_DATA ** ex_data,
731 void *(*dup_func) (void *),
732 void (*free_func) (void *),
733 void (*clear_free_func) (void *))
734 {
735 EC_EXTRA_DATA **p;
736
737 if (ex_data == NULL)
738 return;
739
740 for (p = ex_data; *p != NULL; p = &((*p)->next)) {
741 if ((*p)->dup_func == dup_func &&
742 (*p)->free_func == free_func &&
743 (*p)->clear_free_func == clear_free_func) {
744 EC_EXTRA_DATA *next = (*p)->next;
745
746 (*p)->free_func((*p)->data);
747 free(*p);
748
749 *p = next;
750 return;
751 }
752 }
753 }
754
755 /* this has 'package' visibility */
756 void
EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data,void * (* dup_func)(void *),void (* free_func)(void *),void (* clear_free_func)(void *))757 EC_EX_DATA_clear_free_data(EC_EXTRA_DATA ** ex_data,
758 void *(*dup_func) (void *),
759 void (*free_func) (void *),
760 void (*clear_free_func) (void *))
761 {
762 EC_EXTRA_DATA **p;
763
764 if (ex_data == NULL)
765 return;
766
767 for (p = ex_data; *p != NULL; p = &((*p)->next)) {
768 if ((*p)->dup_func == dup_func &&
769 (*p)->free_func == free_func &&
770 (*p)->clear_free_func == clear_free_func) {
771 EC_EXTRA_DATA *next = (*p)->next;
772
773 (*p)->clear_free_func((*p)->data);
774 free(*p);
775
776 *p = next;
777 return;
778 }
779 }
780 }
781
782 /* this has 'package' visibility */
783 void
EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data)784 EC_EX_DATA_free_all_data(EC_EXTRA_DATA ** ex_data)
785 {
786 EC_EXTRA_DATA *d;
787
788 if (ex_data == NULL)
789 return;
790
791 d = *ex_data;
792 while (d) {
793 EC_EXTRA_DATA *next = d->next;
794
795 d->free_func(d->data);
796 free(d);
797
798 d = next;
799 }
800 *ex_data = NULL;
801 }
802
803 /* this has 'package' visibility */
804 void
EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data)805 EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA ** ex_data)
806 {
807 EC_EXTRA_DATA *d;
808
809 if (ex_data == NULL)
810 return;
811
812 d = *ex_data;
813 while (d) {
814 EC_EXTRA_DATA *next = d->next;
815
816 d->clear_free_func(d->data);
817 free(d);
818
819 d = next;
820 }
821 *ex_data = NULL;
822 }
823
824
825 /* functions for EC_POINT objects */
826
827 EC_POINT *
EC_POINT_new(const EC_GROUP * group)828 EC_POINT_new(const EC_GROUP * group)
829 {
830 EC_POINT *ret;
831
832 if (group == NULL) {
833 ECerror(ERR_R_PASSED_NULL_PARAMETER);
834 return NULL;
835 }
836 if (group->meth->point_init == 0) {
837 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
838 return NULL;
839 }
840 ret = malloc(sizeof *ret);
841 if (ret == NULL) {
842 ECerror(ERR_R_MALLOC_FAILURE);
843 return NULL;
844 }
845 ret->meth = group->meth;
846
847 if (!ret->meth->point_init(ret)) {
848 free(ret);
849 return NULL;
850 }
851 return ret;
852 }
853
854
855 void
EC_POINT_free(EC_POINT * point)856 EC_POINT_free(EC_POINT * point)
857 {
858 if (!point)
859 return;
860
861 if (point->meth->point_finish != 0)
862 point->meth->point_finish(point);
863 free(point);
864 }
865
866
867 void
EC_POINT_clear_free(EC_POINT * point)868 EC_POINT_clear_free(EC_POINT * point)
869 {
870 if (!point)
871 return;
872
873 if (point->meth->point_clear_finish != 0)
874 point->meth->point_clear_finish(point);
875 else if (point->meth->point_finish != 0)
876 point->meth->point_finish(point);
877 freezero(point, sizeof *point);
878 }
879
880
881 int
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)882 EC_POINT_copy(EC_POINT * dest, const EC_POINT * src)
883 {
884 if (dest->meth->point_copy == 0) {
885 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
886 return 0;
887 }
888 if (dest->meth != src->meth) {
889 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
890 return 0;
891 }
892 if (dest == src)
893 return 1;
894 return dest->meth->point_copy(dest, src);
895 }
896
897
898 EC_POINT *
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)899 EC_POINT_dup(const EC_POINT * a, const EC_GROUP * group)
900 {
901 EC_POINT *t;
902 int r;
903
904 if (a == NULL)
905 return NULL;
906
907 t = EC_POINT_new(group);
908 if (t == NULL)
909 return (NULL);
910 r = EC_POINT_copy(t, a);
911 if (!r) {
912 EC_POINT_free(t);
913 return NULL;
914 } else
915 return t;
916 }
917
918
919 const EC_METHOD *
EC_POINT_method_of(const EC_POINT * point)920 EC_POINT_method_of(const EC_POINT * point)
921 {
922 return point->meth;
923 }
924
925
926 int
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)927 EC_POINT_set_to_infinity(const EC_GROUP * group, EC_POINT * point)
928 {
929 if (group->meth->point_set_to_infinity == 0) {
930 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
931 return 0;
932 }
933 if (group->meth != point->meth) {
934 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
935 return 0;
936 }
937 return group->meth->point_set_to_infinity(group, point);
938 }
939
940 int
EC_POINT_set_Jprojective_coordinates(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,const BIGNUM * z,BN_CTX * ctx)941 EC_POINT_set_Jprojective_coordinates(const EC_GROUP *group, EC_POINT *point,
942 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
943 {
944 if (group->meth->point_set_Jprojective_coordinates == NULL) {
945 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
946 return 0;
947 }
948 if (group->meth != point->meth) {
949 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
950 return 0;
951 }
952 return group->meth->point_set_Jprojective_coordinates(group, point,
953 x, y, z, ctx);
954 }
955
956 int
EC_POINT_get_Jprojective_coordinates(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BIGNUM * z,BN_CTX * ctx)957 EC_POINT_get_Jprojective_coordinates(const EC_GROUP *group,
958 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
959 {
960 if (group->meth->point_get_Jprojective_coordinates == NULL) {
961 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
962 return 0;
963 }
964 if (group->meth != point->meth) {
965 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
966 return 0;
967 }
968 return group->meth->point_get_Jprojective_coordinates(group, point,
969 x, y, z, ctx);
970 }
971
972 int
EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,const BIGNUM * z,BN_CTX * ctx)973 EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
974 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
975 {
976 return EC_POINT_set_Jprojective_coordinates(group, point, x, y, z, ctx);
977 }
978
979 int
EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BIGNUM * z,BN_CTX * ctx)980 EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
981 const EC_POINT *point, BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
982 {
983 return EC_POINT_get_Jprojective_coordinates(group, point, x, y, z, ctx);
984 }
985
986 int
EC_POINT_set_affine_coordinates(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)987 EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
988 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
989 {
990 if (group->meth->point_set_affine_coordinates == NULL) {
991 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
992 return 0;
993 }
994 if (group->meth != point->meth) {
995 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
996 return 0;
997 }
998 if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
999 return 0;
1000 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
1001 ECerror(EC_R_POINT_IS_NOT_ON_CURVE);
1002 return 0;
1003 }
1004 return 1;
1005 }
1006
1007 int
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)1008 EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
1009 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
1010 {
1011 return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
1012 }
1013
1014 #ifndef OPENSSL_NO_EC2M
1015 int
EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)1016 EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
1017 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
1018 {
1019 return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
1020 }
1021 #endif
1022
1023 int
EC_POINT_get_affine_coordinates(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)1024 EC_POINT_get_affine_coordinates(const EC_GROUP *group, const EC_POINT *point,
1025 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1026 {
1027 if (group->meth->point_get_affine_coordinates == NULL) {
1028 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1029 return 0;
1030 }
1031 if (group->meth != point->meth) {
1032 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1033 return 0;
1034 }
1035 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
1036 }
1037
1038 int
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)1039 EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
1040 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1041 {
1042 return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
1043 }
1044
1045 #ifndef OPENSSL_NO_EC2M
1046 int
EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)1047 EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
1048 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
1049 {
1050 return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
1051 }
1052 #endif
1053
1054 int
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)1055 EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
1056 const EC_POINT *b, BN_CTX *ctx)
1057 {
1058 if (group->meth->add == 0) {
1059 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1060 return 0;
1061 }
1062 if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth)) {
1063 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1064 return 0;
1065 }
1066 return group->meth->add(group, r, a, b, ctx);
1067 }
1068
1069
1070 int
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)1071 EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
1072 {
1073 if (group->meth->dbl == 0) {
1074 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1075 return 0;
1076 }
1077 if ((group->meth != r->meth) || (r->meth != a->meth)) {
1078 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1079 return 0;
1080 }
1081 return group->meth->dbl(group, r, a, ctx);
1082 }
1083
1084
1085 int
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)1086 EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
1087 {
1088 if (group->meth->invert == 0) {
1089 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1090 return 0;
1091 }
1092 if (group->meth != a->meth) {
1093 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1094 return 0;
1095 }
1096 return group->meth->invert(group, a, ctx);
1097 }
1098
1099
1100 int
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)1101 EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
1102 {
1103 if (group->meth->is_at_infinity == 0) {
1104 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1105 return 0;
1106 }
1107 if (group->meth != point->meth) {
1108 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1109 return 0;
1110 }
1111 return group->meth->is_at_infinity(group, point);
1112 }
1113
1114
1115 int
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)1116 EC_POINT_is_on_curve(const EC_GROUP * group, const EC_POINT * point, BN_CTX * ctx)
1117 {
1118 if (group->meth->is_on_curve == 0) {
1119 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1120 return 0;
1121 }
1122 if (group->meth != point->meth) {
1123 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1124 return 0;
1125 }
1126 return group->meth->is_on_curve(group, point, ctx);
1127 }
1128
1129
1130 int
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)1131 EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
1132 BN_CTX * ctx)
1133 {
1134 if (group->meth->point_cmp == 0) {
1135 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1136 return -1;
1137 }
1138 if ((group->meth != a->meth) || (a->meth != b->meth)) {
1139 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1140 return -1;
1141 }
1142 return group->meth->point_cmp(group, a, b, ctx);
1143 }
1144
1145
1146 int
EC_POINT_make_affine(const EC_GROUP * group,EC_POINT * point,BN_CTX * ctx)1147 EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1148 {
1149 if (group->meth->make_affine == 0) {
1150 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1151 return 0;
1152 }
1153 if (group->meth != point->meth) {
1154 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1155 return 0;
1156 }
1157 return group->meth->make_affine(group, point, ctx);
1158 }
1159
1160
1161 int
EC_POINTs_make_affine(const EC_GROUP * group,size_t num,EC_POINT * points[],BN_CTX * ctx)1162 EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
1163 BN_CTX *ctx)
1164 {
1165 size_t i;
1166
1167 if (group->meth->points_make_affine == 0) {
1168 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1169 return 0;
1170 }
1171 for (i = 0; i < num; i++) {
1172 if (group->meth != points[i]->meth) {
1173 ECerror(EC_R_INCOMPATIBLE_OBJECTS);
1174 return 0;
1175 }
1176 }
1177 return group->meth->points_make_affine(group, num, points, ctx);
1178 }
1179
1180
1181 /* Functions for point multiplication */
1182 int
EC_POINTs_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * scalar,size_t num,const EC_POINT * points[],const BIGNUM * scalars[],BN_CTX * ctx)1183 EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1184 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
1185 {
1186 /*
1187 * The function pointers must be set, and only support num == 0 and
1188 * num == 1.
1189 */
1190 if (group->meth->mul_generator_ct == NULL ||
1191 group->meth->mul_single_ct == NULL ||
1192 group->meth->mul_double_nonct == NULL ||
1193 num > 1) {
1194 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1195 return 0;
1196 }
1197
1198 /* Either bP or aG + bP, this is sane. */
1199 if (num == 1 && points != NULL && scalars != NULL)
1200 return EC_POINT_mul(group, r, scalar, points[0], scalars[0],
1201 ctx);
1202
1203 /* aG, this is sane */
1204 if (scalar != NULL && points == NULL && scalars == NULL)
1205 return EC_POINT_mul(group, r, scalar, NULL, NULL, ctx);
1206
1207 /* anything else is an error */
1208 ECerror(ERR_R_EC_LIB);
1209 return 0;
1210 }
1211
1212 int
EC_POINT_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * point,const BIGNUM * p_scalar,BN_CTX * ctx)1213 EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1214 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1215 {
1216 if (group->meth->mul_generator_ct == NULL ||
1217 group->meth->mul_single_ct == NULL ||
1218 group->meth->mul_double_nonct == NULL) {
1219 ECerror(ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1220 return 0;
1221 }
1222 if (g_scalar != NULL && point == NULL && p_scalar == NULL) {
1223 /*
1224 * In this case we want to compute g_scalar * GeneratorPoint:
1225 * this codepath is reached most prominently by (ephemeral) key
1226 * generation of EC cryptosystems (i.e. ECDSA keygen and sign
1227 * setup, ECDH keygen/first half), where the scalar is always
1228 * secret. This is why we ignore if BN_FLG_CONSTTIME is actually
1229 * set and we always call the constant time version.
1230 */
1231 return group->meth->mul_generator_ct(group, r, g_scalar, ctx);
1232 }
1233 if (g_scalar == NULL && point != NULL && p_scalar != NULL) {
1234 /* In this case we want to compute p_scalar * GenericPoint:
1235 * this codepath is reached most prominently by the second half
1236 * of ECDH, where the secret scalar is multiplied by the peer's
1237 * public point. To protect the secret scalar, we ignore if
1238 * BN_FLG_CONSTTIME is actually set and we always call the
1239 * constant time version.
1240 */
1241 return group->meth->mul_single_ct(group, r, p_scalar, point,
1242 ctx);
1243 }
1244 if (g_scalar != NULL && point != NULL && p_scalar != NULL) {
1245 /*
1246 * In this case we want to compute
1247 * g_scalar * GeneratorPoint + p_scalar * GenericPoint:
1248 * this codepath is reached most prominently by ECDSA signature
1249 * verification. So we call the non-ct version.
1250 */
1251 return group->meth->mul_double_nonct(group, r, g_scalar,
1252 p_scalar, point, ctx);
1253 }
1254
1255 /* Anything else is an error. */
1256 ECerror(ERR_R_EC_LIB);
1257 return 0;
1258 }
1259
1260 int
EC_GROUP_precompute_mult(EC_GROUP * group,BN_CTX * ctx)1261 EC_GROUP_precompute_mult(EC_GROUP * group, BN_CTX * ctx)
1262 {
1263 if (group->meth->precompute_mult != 0)
1264 return group->meth->precompute_mult(group, ctx);
1265 else
1266 return 1; /* nothing to do, so report success */
1267 }
1268
1269 int
EC_GROUP_have_precompute_mult(const EC_GROUP * group)1270 EC_GROUP_have_precompute_mult(const EC_GROUP * group)
1271 {
1272 if (group->meth->have_precompute_mult != 0)
1273 return group->meth->have_precompute_mult(group);
1274 else
1275 return 0; /* cannot tell whether precomputation has
1276 * been performed */
1277 }
1278
1279 int
ec_group_simple_order_bits(const EC_GROUP * group)1280 ec_group_simple_order_bits(const EC_GROUP *group)
1281 {
1282 /* XXX change group->order to a pointer? */
1283 #if 0
1284 if (group->order == NULL)
1285 return 0;
1286 #endif
1287 return BN_num_bits(&group->order);
1288 }
1289
1290 EC_KEY *
ECParameters_dup(EC_KEY * key)1291 ECParameters_dup(EC_KEY *key)
1292 {
1293 unsigned char *p = NULL;
1294 EC_KEY *k = NULL;
1295 int len;
1296
1297 if (key == NULL)
1298 return (NULL);
1299
1300 if ((len = i2d_ECParameters(key, &p)) > 0)
1301 k = d2i_ECParameters(NULL, (const unsigned char **)&p, len);
1302
1303 return (k);
1304 }
1305