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