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