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