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