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