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