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