Fix BN_gcd errors for some curves
[openssl.git] / crypto / ec / ec_lib.c
1 /*
2  * Originally written by Bodo Moeller for the OpenSSL project.
3  */
4 /* ====================================================================
5  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. All advertising materials mentioning features or use of this
20  *    software must display the following acknowledgment:
21  *    "This product includes software developed by the OpenSSL Project
22  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23  *
24  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25  *    endorse or promote products derived from this software without
26  *    prior written permission. For written permission, please contact
27  *    openssl-core@openssl.org.
28  *
29  * 5. Products derived from this software may not be called "OpenSSL"
30  *    nor may "OpenSSL" appear in their names without prior written
31  *    permission of the OpenSSL Project.
32  *
33  * 6. Redistributions of any form whatsoever must retain the following
34  *    acknowledgment:
35  *    "This product includes software developed by the OpenSSL Project
36  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49  * OF THE POSSIBILITY OF SUCH DAMAGE.
50  * ====================================================================
51  *
52  * This product includes cryptographic software written by Eric Young
53  * (eay@cryptsoft.com).  This product includes software written by Tim
54  * Hudson (tjh@cryptsoft.com).
55  *
56  */
57 /* ====================================================================
58  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
59  * Binary polynomial ECC support in OpenSSL originally developed by
60  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
61  */
62
63 #include <string.h>
64
65 #include <openssl/err.h>
66 #include <openssl/opensslv.h>
67
68 #include "ec_lcl.h"
69
70 /* functions for EC_GROUP objects */
71
72 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
73 {
74     EC_GROUP *ret;
75
76     if (meth == NULL) {
77         ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
78         return NULL;
79     }
80     if (meth->group_init == 0) {
81         ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
82         return NULL;
83     }
84
85     ret = OPENSSL_zalloc(sizeof(*ret));
86     if (ret == NULL) {
87         ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
88         return NULL;
89     }
90
91     ret->meth = meth;
92     ret->order = BN_new();
93     if (ret->order == NULL)
94         goto err;
95     ret->cofactor = BN_new();
96     if (ret->cofactor == NULL)
97         goto err;
98     ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
99     ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
100     if (!meth->group_init(ret))
101         goto err;
102     return ret;
103
104  err:
105     BN_free(ret->order);
106     BN_free(ret->cofactor);
107     OPENSSL_free(ret);
108     return NULL;
109 }
110
111 void EC_pre_comp_free(EC_GROUP *group)
112 {
113     switch (group->pre_comp_type) {
114     default:
115         break;
116 #ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
117     case pct_nistz256:
118         EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
119         break;
120 #endif
121 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
122     case pct_nistp224:
123         EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
124         break;
125     case pct_nistp256:
126         EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
127         break;
128     case pct_nistp521:
129         EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
130         break;
131 #endif
132     case pct_ec:
133         EC_ec_pre_comp_free(group->pre_comp.ec);
134         break;
135     }
136     group->pre_comp.ec = NULL;
137 }
138
139 void EC_GROUP_free(EC_GROUP *group)
140 {
141     if (!group)
142         return;
143
144     if (group->meth->group_finish != 0)
145         group->meth->group_finish(group);
146
147     EC_pre_comp_free(group);
148     BN_MONT_CTX_free(group->mont_data);
149     EC_POINT_free(group->generator);
150     BN_free(group->order);
151     BN_free(group->cofactor);
152     OPENSSL_free(group->seed);
153     OPENSSL_free(group);
154 }
155
156 void EC_GROUP_clear_free(EC_GROUP *group)
157 {
158     if (!group)
159         return;
160
161     if (group->meth->group_clear_finish != 0)
162         group->meth->group_clear_finish(group);
163     else if (group->meth->group_finish != 0)
164         group->meth->group_finish(group);
165
166     EC_pre_comp_free(group);
167     BN_MONT_CTX_free(group->mont_data);
168     EC_POINT_clear_free(group->generator);
169     BN_clear_free(group->order);
170     BN_clear_free(group->cofactor);
171     OPENSSL_clear_free(group->seed, group->seed_len);
172     OPENSSL_clear_free(group, sizeof(*group));
173 }
174
175 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
176 {
177     if (dest->meth->group_copy == 0) {
178         ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
179         return 0;
180     }
181     if (dest->meth != src->meth) {
182         ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
183         return 0;
184     }
185     if (dest == src)
186         return 1;
187
188     /* Copy precomputed */
189     dest->pre_comp_type = src->pre_comp_type;
190     switch (src->pre_comp_type) {
191     default:
192         dest->pre_comp.ec = NULL;
193         break;
194 #ifdef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
195     case pct_nistz256:
196         dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
197         break;
198 #endif
199 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
200     case pct_nistp224:
201         dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
202         break;
203     case pct_nistp256:
204         dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
205         break;
206     case pct_nistp521:
207         dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
208         break;
209 #endif
210     case pct_ec:
211         dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
212         break;
213     }
214
215     if (src->mont_data != NULL) {
216         if (dest->mont_data == NULL) {
217             dest->mont_data = BN_MONT_CTX_new();
218             if (dest->mont_data == NULL)
219                 return 0;
220         }
221         if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
222             return 0;
223     } else {
224         /* src->generator == NULL */
225         BN_MONT_CTX_free(dest->mont_data);
226         dest->mont_data = NULL;
227     }
228
229     if (src->generator != NULL) {
230         if (dest->generator == NULL) {
231             dest->generator = EC_POINT_new(dest);
232             if (dest->generator == NULL)
233                 return 0;
234         }
235         if (!EC_POINT_copy(dest->generator, src->generator))
236             return 0;
237     } else {
238         /* src->generator == NULL */
239         EC_POINT_clear_free(dest->generator);
240         dest->generator = NULL;
241     }
242
243     if (!BN_copy(dest->order, src->order))
244         return 0;
245     if (!BN_copy(dest->cofactor, src->cofactor))
246         return 0;
247
248     dest->curve_name = src->curve_name;
249     dest->asn1_flag = src->asn1_flag;
250     dest->asn1_form = src->asn1_form;
251
252     if (src->seed) {
253         OPENSSL_free(dest->seed);
254         dest->seed = OPENSSL_malloc(src->seed_len);
255         if (dest->seed == NULL)
256             return 0;
257         if (!memcpy(dest->seed, src->seed, src->seed_len))
258             return 0;
259         dest->seed_len = src->seed_len;
260     } else {
261         OPENSSL_free(dest->seed);
262         dest->seed = NULL;
263         dest->seed_len = 0;
264     }
265
266     return dest->meth->group_copy(dest, src);
267 }
268
269 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
270 {
271     EC_GROUP *t = NULL;
272     int ok = 0;
273
274     if (a == NULL)
275         return NULL;
276
277     if ((t = EC_GROUP_new(a->meth)) == NULL)
278         return (NULL);
279     if (!EC_GROUP_copy(t, a))
280         goto err;
281
282     ok = 1;
283
284  err:
285     if (!ok) {
286         EC_GROUP_free(t);
287         return NULL;
288     }
289         return t;
290 }
291
292 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
293 {
294     return group->meth;
295 }
296
297 int EC_METHOD_get_field_type(const EC_METHOD *meth)
298 {
299     return meth->field_type;
300 }
301
302 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
303                            const BIGNUM *order, const BIGNUM *cofactor)
304 {
305     if (generator == NULL) {
306         ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
307         return 0;
308     }
309
310     if (group->generator == NULL) {
311         group->generator = EC_POINT_new(group);
312         if (group->generator == NULL)
313             return 0;
314     }
315     if (!EC_POINT_copy(group->generator, generator))
316         return 0;
317
318     if (order != NULL) {
319         if (!BN_copy(group->order, order))
320             return 0;
321     } else
322         BN_zero(group->order);
323
324     if (cofactor != NULL) {
325         if (!BN_copy(group->cofactor, cofactor))
326             return 0;
327     } else
328         BN_zero(group->cofactor);
329
330  
331     /*
332      * Some groups have an order with
333      * factors of two, which makes the Montgomery setup fail.
334      * |group->mont_data| will be NULL in this case.
335      */
336     if (BN_is_odd(group->order)) {
337         return ec_precompute_mont_data(group);
338     }
339
340     BN_MONT_CTX_free(group->mont_data);
341     group->mont_data = NULL;
342     return 1;
343 }
344
345 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
346 {
347     return group->generator;
348 }
349
350 BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
351 {
352     return group->mont_data;
353 }
354
355 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
356 {
357     if (group->order == NULL)
358         return 0;
359     if (!BN_copy(order, group->order))
360         return 0;
361
362     return !BN_is_zero(order);
363 }
364
365 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
366 {
367     return group->order;
368 }
369
370 int EC_GROUP_order_bits(const EC_GROUP *group)
371 {
372     if (group->order)
373         return BN_num_bits(group->order);
374     return 0;
375 }
376
377 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
378                           BN_CTX *ctx)
379 {
380
381     if (group->cofactor == NULL)
382         return 0;
383     if (!BN_copy(cofactor, group->cofactor))
384         return 0;
385
386     return !BN_is_zero(group->cofactor);
387 }
388
389 const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
390 {
391     return group->cofactor;
392 }
393
394 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
395 {
396     group->curve_name = nid;
397 }
398
399 int EC_GROUP_get_curve_name(const EC_GROUP *group)
400 {
401     return group->curve_name;
402 }
403
404 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
405 {
406     group->asn1_flag = flag;
407 }
408
409 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
410 {
411     return group->asn1_flag;
412 }
413
414 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
415                                         point_conversion_form_t form)
416 {
417     group->asn1_form = form;
418 }
419
420 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
421                                                            *group)
422 {
423     return group->asn1_form;
424 }
425
426 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
427 {
428     OPENSSL_free(group->seed);
429     group->seed = NULL;
430     group->seed_len = 0;
431
432     if (!len || !p)
433         return 1;
434
435     if ((group->seed = OPENSSL_malloc(len)) == NULL)
436         return 0;
437     memcpy(group->seed, p, len);
438     group->seed_len = len;
439
440     return len;
441 }
442
443 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
444 {
445     return group->seed;
446 }
447
448 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
449 {
450     return group->seed_len;
451 }
452
453 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
454                            const BIGNUM *b, BN_CTX *ctx)
455 {
456     if (group->meth->group_set_curve == 0) {
457         ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
458         return 0;
459     }
460     return group->meth->group_set_curve(group, p, a, b, ctx);
461 }
462
463 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
464                            BIGNUM *b, BN_CTX *ctx)
465 {
466     if (group->meth->group_get_curve == 0) {
467         ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
468         return 0;
469     }
470     return group->meth->group_get_curve(group, p, a, b, ctx);
471 }
472
473 #ifndef OPENSSL_NO_EC2M
474 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
475                             const BIGNUM *b, BN_CTX *ctx)
476 {
477     if (group->meth->group_set_curve == 0) {
478         ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
479               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
480         return 0;
481     }
482     return group->meth->group_set_curve(group, p, a, b, ctx);
483 }
484
485 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
486                             BIGNUM *b, BN_CTX *ctx)
487 {
488     if (group->meth->group_get_curve == 0) {
489         ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
490               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
491         return 0;
492     }
493     return group->meth->group_get_curve(group, p, a, b, ctx);
494 }
495 #endif
496
497 int EC_GROUP_get_degree(const EC_GROUP *group)
498 {
499     if (group->meth->group_get_degree == 0) {
500         ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
501         return 0;
502     }
503     return group->meth->group_get_degree(group);
504 }
505
506 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
507 {
508     if (group->meth->group_check_discriminant == 0) {
509         ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
510               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
511         return 0;
512     }
513     return group->meth->group_check_discriminant(group, ctx);
514 }
515
516 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
517 {
518     int r = 0;
519     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
520     BN_CTX *ctx_new = NULL;
521
522     /* compare the field types */
523     if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
524         EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
525         return 1;
526     /* compare the curve name (if present in both) */
527     if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
528         EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
529         return 1;
530
531     if (ctx == NULL)
532         ctx_new = ctx = BN_CTX_new();
533     if (ctx == NULL)
534         return -1;
535
536     BN_CTX_start(ctx);
537     a1 = BN_CTX_get(ctx);
538     a2 = BN_CTX_get(ctx);
539     a3 = BN_CTX_get(ctx);
540     b1 = BN_CTX_get(ctx);
541     b2 = BN_CTX_get(ctx);
542     b3 = BN_CTX_get(ctx);
543     if (b3 == NULL) {
544         BN_CTX_end(ctx);
545         BN_CTX_free(ctx_new);
546         return -1;
547     }
548
549     /*
550      * XXX This approach assumes that the external representation of curves
551      * over the same field type is the same.
552      */
553     if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
554         !b->meth->group_get_curve(b, b1, b2, b3, ctx))
555         r = 1;
556
557     if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
558         r = 1;
559
560     /* XXX EC_POINT_cmp() assumes that the methods are equal */
561     if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
562                           EC_GROUP_get0_generator(b), ctx))
563         r = 1;
564
565     if (!r) {
566         const BIGNUM *ao, *bo, *ac, *bc;
567         /* compare the order and cofactor */
568         ao = EC_GROUP_get0_order(a);
569         bo = EC_GROUP_get0_order(b);
570         ac = EC_GROUP_get0_cofactor(a);
571         bc = EC_GROUP_get0_cofactor(b);
572         if (ao == NULL || bo == NULL) {
573             BN_CTX_end(ctx);
574             BN_CTX_free(ctx_new);
575             return -1;
576         }
577         if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
578             r = 1;
579     }
580
581     BN_CTX_end(ctx);
582     BN_CTX_free(ctx_new);
583
584     return r;
585 }
586
587 /* functions for EC_POINT objects */
588
589 EC_POINT *EC_POINT_new(const EC_GROUP *group)
590 {
591     EC_POINT *ret;
592
593     if (group == NULL) {
594         ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
595         return NULL;
596     }
597     if (group->meth->point_init == 0) {
598         ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
599         return NULL;
600     }
601
602     ret = OPENSSL_zalloc(sizeof(*ret));
603     if (ret == NULL) {
604         ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
605         return NULL;
606     }
607
608     ret->meth = group->meth;
609
610     if (!ret->meth->point_init(ret)) {
611         OPENSSL_free(ret);
612         return NULL;
613     }
614
615     return ret;
616 }
617
618 void EC_POINT_free(EC_POINT *point)
619 {
620     if (!point)
621         return;
622
623     if (point->meth->point_finish != 0)
624         point->meth->point_finish(point);
625     OPENSSL_free(point);
626 }
627
628 void EC_POINT_clear_free(EC_POINT *point)
629 {
630     if (!point)
631         return;
632
633     if (point->meth->point_clear_finish != 0)
634         point->meth->point_clear_finish(point);
635     else if (point->meth->point_finish != 0)
636         point->meth->point_finish(point);
637     OPENSSL_clear_free(point, sizeof(*point));
638 }
639
640 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
641 {
642     if (dest->meth->point_copy == 0) {
643         ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
644         return 0;
645     }
646     if (dest->meth != src->meth) {
647         ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
648         return 0;
649     }
650     if (dest == src)
651         return 1;
652     return dest->meth->point_copy(dest, src);
653 }
654
655 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
656 {
657     EC_POINT *t;
658     int r;
659
660     if (a == NULL)
661         return NULL;
662
663     t = EC_POINT_new(group);
664     if (t == NULL)
665         return (NULL);
666     r = EC_POINT_copy(t, a);
667     if (!r) {
668         EC_POINT_free(t);
669         return NULL;
670     }
671     return t;
672 }
673
674 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
675 {
676     return point->meth;
677 }
678
679 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
680 {
681     if (group->meth->point_set_to_infinity == 0) {
682         ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
683               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
684         return 0;
685     }
686     if (group->meth != point->meth) {
687         ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
688         return 0;
689     }
690     return group->meth->point_set_to_infinity(group, point);
691 }
692
693 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
694                                              EC_POINT *point, const BIGNUM *x,
695                                              const BIGNUM *y, const BIGNUM *z,
696                                              BN_CTX *ctx)
697 {
698     if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
699         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
700               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
701         return 0;
702     }
703     if (group->meth != point->meth) {
704         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
705               EC_R_INCOMPATIBLE_OBJECTS);
706         return 0;
707     }
708     return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
709                                                               y, z, ctx);
710 }
711
712 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
713                                              const EC_POINT *point, BIGNUM *x,
714                                              BIGNUM *y, BIGNUM *z,
715                                              BN_CTX *ctx)
716 {
717     if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
718         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
719               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
720         return 0;
721     }
722     if (group->meth != point->meth) {
723         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
724               EC_R_INCOMPATIBLE_OBJECTS);
725         return 0;
726     }
727     return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
728                                                               y, z, ctx);
729 }
730
731 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
732                                         EC_POINT *point, const BIGNUM *x,
733                                         const BIGNUM *y, BN_CTX *ctx)
734 {
735     if (group->meth->point_set_affine_coordinates == 0) {
736         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
737               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
738         return 0;
739     }
740     if (group->meth != point->meth) {
741         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
742               EC_R_INCOMPATIBLE_OBJECTS);
743         return 0;
744     }
745     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
746 }
747
748 #ifndef OPENSSL_NO_EC2M
749 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
750                                          EC_POINT *point, const BIGNUM *x,
751                                          const BIGNUM *y, BN_CTX *ctx)
752 {
753     if (group->meth->point_set_affine_coordinates == 0) {
754         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
755               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
756         return 0;
757     }
758     if (group->meth != point->meth) {
759         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
760               EC_R_INCOMPATIBLE_OBJECTS);
761         return 0;
762     }
763     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
764 }
765 #endif
766
767 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
768                                         const EC_POINT *point, BIGNUM *x,
769                                         BIGNUM *y, BN_CTX *ctx)
770 {
771     if (group->meth->point_get_affine_coordinates == 0) {
772         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
773               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
774         return 0;
775     }
776     if (group->meth != point->meth) {
777         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
778               EC_R_INCOMPATIBLE_OBJECTS);
779         return 0;
780     }
781     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
782 }
783
784 #ifndef OPENSSL_NO_EC2M
785 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
786                                          const EC_POINT *point, BIGNUM *x,
787                                          BIGNUM *y, BN_CTX *ctx)
788 {
789     if (group->meth->point_get_affine_coordinates == 0) {
790         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
791               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
792         return 0;
793     }
794     if (group->meth != point->meth) {
795         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
796               EC_R_INCOMPATIBLE_OBJECTS);
797         return 0;
798     }
799     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
800 }
801 #endif
802
803 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
804                  const EC_POINT *b, BN_CTX *ctx)
805 {
806     if (group->meth->add == 0) {
807         ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
808         return 0;
809     }
810     if ((group->meth != r->meth) || (r->meth != a->meth)
811         || (a->meth != b->meth)) {
812         ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
813         return 0;
814     }
815     return group->meth->add(group, r, a, b, ctx);
816 }
817
818 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
819                  BN_CTX *ctx)
820 {
821     if (group->meth->dbl == 0) {
822         ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
823         return 0;
824     }
825     if ((group->meth != r->meth) || (r->meth != a->meth)) {
826         ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
827         return 0;
828     }
829     return group->meth->dbl(group, r, a, ctx);
830 }
831
832 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
833 {
834     if (group->meth->invert == 0) {
835         ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
836         return 0;
837     }
838     if (group->meth != a->meth) {
839         ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
840         return 0;
841     }
842     return group->meth->invert(group, a, ctx);
843 }
844
845 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
846 {
847     if (group->meth->is_at_infinity == 0) {
848         ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
849               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
850         return 0;
851     }
852     if (group->meth != point->meth) {
853         ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
854         return 0;
855     }
856     return group->meth->is_at_infinity(group, point);
857 }
858
859 /*
860  * Check whether an EC_POINT is on the curve or not. Note that the return
861  * value for this function should NOT be treated as a boolean. Return values:
862  *  1: The point is on the curve
863  *  0: The point is not on the curve
864  * -1: An error occurred
865  */
866 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
867                          BN_CTX *ctx)
868 {
869     if (group->meth->is_on_curve == 0) {
870         ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
871         return 0;
872     }
873     if (group->meth != point->meth) {
874         ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
875         return 0;
876     }
877     return group->meth->is_on_curve(group, point, ctx);
878 }
879
880 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
881                  BN_CTX *ctx)
882 {
883     if (group->meth->point_cmp == 0) {
884         ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
885         return -1;
886     }
887     if ((group->meth != a->meth) || (a->meth != b->meth)) {
888         ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
889         return -1;
890     }
891     return group->meth->point_cmp(group, a, b, ctx);
892 }
893
894 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
895 {
896     if (group->meth->make_affine == 0) {
897         ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
898         return 0;
899     }
900     if (group->meth != point->meth) {
901         ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
902         return 0;
903     }
904     return group->meth->make_affine(group, point, ctx);
905 }
906
907 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
908                           EC_POINT *points[], BN_CTX *ctx)
909 {
910     size_t i;
911
912     if (group->meth->points_make_affine == 0) {
913         ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
914         return 0;
915     }
916     for (i = 0; i < num; i++) {
917         if (group->meth != points[i]->meth) {
918             ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
919             return 0;
920         }
921     }
922     return group->meth->points_make_affine(group, num, points, ctx);
923 }
924
925 /*
926  * Functions for point multiplication. If group->meth->mul is 0, we use the
927  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
928  * methods.
929  */
930
931 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
932                   size_t num, const EC_POINT *points[],
933                   const BIGNUM *scalars[], BN_CTX *ctx)
934 {
935     if (group->meth->mul == 0)
936         /* use default */
937         return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
938
939     return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
940 }
941
942 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
943                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
944 {
945     /* just a convenient interface to EC_POINTs_mul() */
946
947     const EC_POINT *points[1];
948     const BIGNUM *scalars[1];
949
950     points[0] = point;
951     scalars[0] = p_scalar;
952
953     return EC_POINTs_mul(group, r, g_scalar,
954                          (point != NULL
955                           && p_scalar != NULL), points, scalars, ctx);
956 }
957
958 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
959 {
960     if (group->meth->mul == 0)
961         /* use default */
962         return ec_wNAF_precompute_mult(group, ctx);
963
964     if (group->meth->precompute_mult != 0)
965         return group->meth->precompute_mult(group, ctx);
966     else
967         return 1;               /* nothing to do, so report success */
968 }
969
970 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
971 {
972     if (group->meth->mul == 0)
973         /* use default */
974         return ec_wNAF_have_precompute_mult(group);
975
976     if (group->meth->have_precompute_mult != 0)
977         return group->meth->have_precompute_mult(group);
978     else
979         return 0;               /* cannot tell whether precomputation has
980                                  * been performed */
981 }
982
983 /*
984  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
985  * returns one on success. On error it returns zero.
986  */
987 int ec_precompute_mont_data(EC_GROUP *group)
988 {
989     BN_CTX *ctx = BN_CTX_new();
990     int ret = 0;
991
992     BN_MONT_CTX_free(group->mont_data);
993     group->mont_data = NULL;
994
995     if (ctx == NULL)
996         goto err;
997
998     group->mont_data = BN_MONT_CTX_new();
999     if (group->mont_data == NULL)
1000         goto err;
1001
1002     if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
1003         BN_MONT_CTX_free(group->mont_data);
1004         group->mont_data = NULL;
1005         goto err;
1006     }
1007
1008     ret = 1;
1009
1010  err:
1011
1012     BN_CTX_free(ctx);
1013     return ret;
1014 }
1015
1016 int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
1017 {
1018     return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
1019 }
1020
1021 void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
1022 {
1023     return CRYPTO_get_ex_data(&key->ex_data, idx);
1024 }