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