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