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