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