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