abb15a50769c73d849f5e0465fe94cd469443a1c
[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      * We ignore the return value because some groups have an order with
332      * factors of two, which makes the Montgomery setup fail.
333      * |group->mont_data| will be NULL in this case.
334      */
335     ec_precompute_mont_data(group);
336
337     return 1;
338 }
339
340 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
341 {
342     return group->generator;
343 }
344
345 BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
346 {
347     return group->mont_data;
348 }
349
350 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
351 {
352     if (group->order == NULL)
353         return 0;
354     if (!BN_copy(order, group->order))
355         return 0;
356
357     return !BN_is_zero(order);
358 }
359
360 const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
361 {
362     return group->order;
363 }
364
365 int EC_GROUP_order_bits(const EC_GROUP *group)
366 {
367     if (group->order)
368         return BN_num_bits(group->order);
369     return 0;
370 }
371
372 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
373                           BN_CTX *ctx)
374 {
375
376     if (group->cofactor == NULL)
377         return 0;
378     if (!BN_copy(cofactor, group->cofactor))
379         return 0;
380
381     return !BN_is_zero(group->cofactor);
382 }
383
384 const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
385 {
386     return group->cofactor;
387 }
388
389 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
390 {
391     group->curve_name = nid;
392 }
393
394 int EC_GROUP_get_curve_name(const EC_GROUP *group)
395 {
396     return group->curve_name;
397 }
398
399 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
400 {
401     group->asn1_flag = flag;
402 }
403
404 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
405 {
406     return group->asn1_flag;
407 }
408
409 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
410                                         point_conversion_form_t form)
411 {
412     group->asn1_form = form;
413 }
414
415 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
416                                                            *group)
417 {
418     return group->asn1_form;
419 }
420
421 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
422 {
423     OPENSSL_free(group->seed);
424     group->seed = NULL;
425     group->seed_len = 0;
426
427     if (!len || !p)
428         return 1;
429
430     if ((group->seed = OPENSSL_malloc(len)) == NULL)
431         return 0;
432     memcpy(group->seed, p, len);
433     group->seed_len = len;
434
435     return len;
436 }
437
438 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
439 {
440     return group->seed;
441 }
442
443 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
444 {
445     return group->seed_len;
446 }
447
448 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
449                            const BIGNUM *b, BN_CTX *ctx)
450 {
451     if (group->meth->group_set_curve == 0) {
452         ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
453         return 0;
454     }
455     return group->meth->group_set_curve(group, p, a, b, ctx);
456 }
457
458 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
459                            BIGNUM *b, BN_CTX *ctx)
460 {
461     if (group->meth->group_get_curve == 0) {
462         ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
463         return 0;
464     }
465     return group->meth->group_get_curve(group, p, a, b, ctx);
466 }
467
468 #ifndef OPENSSL_NO_EC2M
469 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
470                             const BIGNUM *b, BN_CTX *ctx)
471 {
472     if (group->meth->group_set_curve == 0) {
473         ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
474               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
475         return 0;
476     }
477     return group->meth->group_set_curve(group, p, a, b, ctx);
478 }
479
480 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
481                             BIGNUM *b, BN_CTX *ctx)
482 {
483     if (group->meth->group_get_curve == 0) {
484         ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
485               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
486         return 0;
487     }
488     return group->meth->group_get_curve(group, p, a, b, ctx);
489 }
490 #endif
491
492 int EC_GROUP_get_degree(const EC_GROUP *group)
493 {
494     if (group->meth->group_get_degree == 0) {
495         ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
496         return 0;
497     }
498     return group->meth->group_get_degree(group);
499 }
500
501 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
502 {
503     if (group->meth->group_check_discriminant == 0) {
504         ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
505               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
506         return 0;
507     }
508     return group->meth->group_check_discriminant(group, ctx);
509 }
510
511 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
512 {
513     int r = 0;
514     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
515     BN_CTX *ctx_new = NULL;
516
517     /* compare the field types */
518     if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
519         EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
520         return 1;
521     /* compare the curve name (if present in both) */
522     if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
523         EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
524         return 1;
525
526     if (ctx == NULL)
527         ctx_new = ctx = BN_CTX_new();
528     if (ctx == NULL)
529         return -1;
530
531     BN_CTX_start(ctx);
532     a1 = BN_CTX_get(ctx);
533     a2 = BN_CTX_get(ctx);
534     a3 = BN_CTX_get(ctx);
535     b1 = BN_CTX_get(ctx);
536     b2 = BN_CTX_get(ctx);
537     b3 = BN_CTX_get(ctx);
538     if (b3 == NULL) {
539         BN_CTX_end(ctx);
540         BN_CTX_free(ctx_new);
541         return -1;
542     }
543
544     /*
545      * XXX This approach assumes that the external representation of curves
546      * over the same field type is the same.
547      */
548     if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
549         !b->meth->group_get_curve(b, b1, b2, b3, ctx))
550         r = 1;
551
552     if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
553         r = 1;
554
555     /* XXX EC_POINT_cmp() assumes that the methods are equal */
556     if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
557                           EC_GROUP_get0_generator(b), ctx))
558         r = 1;
559
560     if (!r) {
561         const BIGNUM *ao, *bo, *ac, *bc;
562         /* compare the order and cofactor */
563         ao = EC_GROUP_get0_order(a);
564         bo = EC_GROUP_get0_order(b);
565         ac = EC_GROUP_get0_cofactor(a);
566         bc = EC_GROUP_get0_cofactor(b);
567         if (ao == NULL || bo == NULL) {
568             BN_CTX_end(ctx);
569             BN_CTX_free(ctx_new);
570             return -1;
571         }
572         if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
573             r = 1;
574     }
575
576     BN_CTX_end(ctx);
577     BN_CTX_free(ctx_new);
578
579     return r;
580 }
581
582 /* functions for EC_POINT objects */
583
584 EC_POINT *EC_POINT_new(const EC_GROUP *group)
585 {
586     EC_POINT *ret;
587
588     if (group == NULL) {
589         ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
590         return NULL;
591     }
592     if (group->meth->point_init == 0) {
593         ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
594         return NULL;
595     }
596
597     ret = OPENSSL_zalloc(sizeof(*ret));
598     if (ret == NULL) {
599         ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
600         return NULL;
601     }
602
603     ret->meth = group->meth;
604
605     if (!ret->meth->point_init(ret)) {
606         OPENSSL_free(ret);
607         return NULL;
608     }
609
610     return ret;
611 }
612
613 void EC_POINT_free(EC_POINT *point)
614 {
615     if (!point)
616         return;
617
618     if (point->meth->point_finish != 0)
619         point->meth->point_finish(point);
620     OPENSSL_free(point);
621 }
622
623 void EC_POINT_clear_free(EC_POINT *point)
624 {
625     if (!point)
626         return;
627
628     if (point->meth->point_clear_finish != 0)
629         point->meth->point_clear_finish(point);
630     else if (point->meth->point_finish != 0)
631         point->meth->point_finish(point);
632     OPENSSL_clear_free(point, sizeof(*point));
633 }
634
635 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
636 {
637     if (dest->meth->point_copy == 0) {
638         ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
639         return 0;
640     }
641     if (dest->meth != src->meth) {
642         ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
643         return 0;
644     }
645     if (dest == src)
646         return 1;
647     return dest->meth->point_copy(dest, src);
648 }
649
650 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
651 {
652     EC_POINT *t;
653     int r;
654
655     if (a == NULL)
656         return NULL;
657
658     t = EC_POINT_new(group);
659     if (t == NULL)
660         return (NULL);
661     r = EC_POINT_copy(t, a);
662     if (!r) {
663         EC_POINT_free(t);
664         return NULL;
665     }
666     return t;
667 }
668
669 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
670 {
671     return point->meth;
672 }
673
674 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
675 {
676     if (group->meth->point_set_to_infinity == 0) {
677         ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
678               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
679         return 0;
680     }
681     if (group->meth != point->meth) {
682         ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
683         return 0;
684     }
685     return group->meth->point_set_to_infinity(group, point);
686 }
687
688 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
689                                              EC_POINT *point, const BIGNUM *x,
690                                              const BIGNUM *y, const BIGNUM *z,
691                                              BN_CTX *ctx)
692 {
693     if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
694         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
695               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
696         return 0;
697     }
698     if (group->meth != point->meth) {
699         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
700               EC_R_INCOMPATIBLE_OBJECTS);
701         return 0;
702     }
703     return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
704                                                               y, z, ctx);
705 }
706
707 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
708                                              const EC_POINT *point, BIGNUM *x,
709                                              BIGNUM *y, BIGNUM *z,
710                                              BN_CTX *ctx)
711 {
712     if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
713         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
714               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
715         return 0;
716     }
717     if (group->meth != point->meth) {
718         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
719               EC_R_INCOMPATIBLE_OBJECTS);
720         return 0;
721     }
722     return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
723                                                               y, z, ctx);
724 }
725
726 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
727                                         EC_POINT *point, const BIGNUM *x,
728                                         const BIGNUM *y, BN_CTX *ctx)
729 {
730     if (group->meth->point_set_affine_coordinates == 0) {
731         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
732               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
733         return 0;
734     }
735     if (group->meth != point->meth) {
736         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
737               EC_R_INCOMPATIBLE_OBJECTS);
738         return 0;
739     }
740     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
741 }
742
743 #ifndef OPENSSL_NO_EC2M
744 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
745                                          EC_POINT *point, const BIGNUM *x,
746                                          const BIGNUM *y, BN_CTX *ctx)
747 {
748     if (group->meth->point_set_affine_coordinates == 0) {
749         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
750               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
751         return 0;
752     }
753     if (group->meth != point->meth) {
754         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
755               EC_R_INCOMPATIBLE_OBJECTS);
756         return 0;
757     }
758     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
759 }
760 #endif
761
762 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
763                                         const EC_POINT *point, BIGNUM *x,
764                                         BIGNUM *y, BN_CTX *ctx)
765 {
766     if (group->meth->point_get_affine_coordinates == 0) {
767         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
768               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
769         return 0;
770     }
771     if (group->meth != point->meth) {
772         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
773               EC_R_INCOMPATIBLE_OBJECTS);
774         return 0;
775     }
776     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
777 }
778
779 #ifndef OPENSSL_NO_EC2M
780 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
781                                          const EC_POINT *point, BIGNUM *x,
782                                          BIGNUM *y, BN_CTX *ctx)
783 {
784     if (group->meth->point_get_affine_coordinates == 0) {
785         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
786               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
787         return 0;
788     }
789     if (group->meth != point->meth) {
790         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
791               EC_R_INCOMPATIBLE_OBJECTS);
792         return 0;
793     }
794     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
795 }
796 #endif
797
798 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
799                  const EC_POINT *b, BN_CTX *ctx)
800 {
801     if (group->meth->add == 0) {
802         ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
803         return 0;
804     }
805     if ((group->meth != r->meth) || (r->meth != a->meth)
806         || (a->meth != b->meth)) {
807         ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
808         return 0;
809     }
810     return group->meth->add(group, r, a, b, ctx);
811 }
812
813 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
814                  BN_CTX *ctx)
815 {
816     if (group->meth->dbl == 0) {
817         ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
818         return 0;
819     }
820     if ((group->meth != r->meth) || (r->meth != a->meth)) {
821         ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
822         return 0;
823     }
824     return group->meth->dbl(group, r, a, ctx);
825 }
826
827 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
828 {
829     if (group->meth->invert == 0) {
830         ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
831         return 0;
832     }
833     if (group->meth != a->meth) {
834         ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
835         return 0;
836     }
837     return group->meth->invert(group, a, ctx);
838 }
839
840 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
841 {
842     if (group->meth->is_at_infinity == 0) {
843         ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
844               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
845         return 0;
846     }
847     if (group->meth != point->meth) {
848         ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
849         return 0;
850     }
851     return group->meth->is_at_infinity(group, point);
852 }
853
854 /*
855  * Check whether an EC_POINT is on the curve or not. Note that the return
856  * value for this function should NOT be treated as a boolean. Return values:
857  *  1: The point is on the curve
858  *  0: The point is not on the curve
859  * -1: An error occurred
860  */
861 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
862                          BN_CTX *ctx)
863 {
864     if (group->meth->is_on_curve == 0) {
865         ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
866         return 0;
867     }
868     if (group->meth != point->meth) {
869         ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
870         return 0;
871     }
872     return group->meth->is_on_curve(group, point, ctx);
873 }
874
875 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
876                  BN_CTX *ctx)
877 {
878     if (group->meth->point_cmp == 0) {
879         ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
880         return -1;
881     }
882     if ((group->meth != a->meth) || (a->meth != b->meth)) {
883         ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
884         return -1;
885     }
886     return group->meth->point_cmp(group, a, b, ctx);
887 }
888
889 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
890 {
891     if (group->meth->make_affine == 0) {
892         ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
893         return 0;
894     }
895     if (group->meth != point->meth) {
896         ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
897         return 0;
898     }
899     return group->meth->make_affine(group, point, ctx);
900 }
901
902 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
903                           EC_POINT *points[], BN_CTX *ctx)
904 {
905     size_t i;
906
907     if (group->meth->points_make_affine == 0) {
908         ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
909         return 0;
910     }
911     for (i = 0; i < num; i++) {
912         if (group->meth != points[i]->meth) {
913             ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
914             return 0;
915         }
916     }
917     return group->meth->points_make_affine(group, num, points, ctx);
918 }
919
920 /*
921  * Functions for point multiplication. If group->meth->mul is 0, we use the
922  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
923  * methods.
924  */
925
926 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
927                   size_t num, const EC_POINT *points[],
928                   const BIGNUM *scalars[], BN_CTX *ctx)
929 {
930     if (group->meth->mul == 0)
931         /* use default */
932         return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
933
934     return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
935 }
936
937 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
938                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
939 {
940     /* just a convenient interface to EC_POINTs_mul() */
941
942     const EC_POINT *points[1];
943     const BIGNUM *scalars[1];
944
945     points[0] = point;
946     scalars[0] = p_scalar;
947
948     return EC_POINTs_mul(group, r, g_scalar,
949                          (point != NULL
950                           && p_scalar != NULL), points, scalars, ctx);
951 }
952
953 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
954 {
955     if (group->meth->mul == 0)
956         /* use default */
957         return ec_wNAF_precompute_mult(group, ctx);
958
959     if (group->meth->precompute_mult != 0)
960         return group->meth->precompute_mult(group, ctx);
961     else
962         return 1;               /* nothing to do, so report success */
963 }
964
965 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
966 {
967     if (group->meth->mul == 0)
968         /* use default */
969         return ec_wNAF_have_precompute_mult(group);
970
971     if (group->meth->have_precompute_mult != 0)
972         return group->meth->have_precompute_mult(group);
973     else
974         return 0;               /* cannot tell whether precomputation has
975                                  * been performed */
976 }
977
978 /*
979  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
980  * returns one on success. On error it returns zero.
981  */
982 int ec_precompute_mont_data(EC_GROUP *group)
983 {
984     BN_CTX *ctx = BN_CTX_new();
985     int ret = 0;
986
987     BN_MONT_CTX_free(group->mont_data);
988     group->mont_data = NULL;
989
990     if (ctx == NULL)
991         goto err;
992
993     group->mont_data = BN_MONT_CTX_new();
994     if (group->mont_data == NULL)
995         goto err;
996
997     if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
998         BN_MONT_CTX_free(group->mont_data);
999         group->mont_data = NULL;
1000         goto err;
1001     }
1002
1003     ret = 1;
1004
1005  err:
1006
1007     BN_CTX_free(ctx);
1008     return ret;
1009 }
1010
1011 int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
1012 {
1013     return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
1014 }
1015
1016 void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
1017 {
1018     return CRYPTO_get_ex_data(&key->ex_data, idx);
1019 }