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