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