0e850d699ebb7596ee0a700138485fdf82a797ca
[openssl.git] / crypto / ec / ec_lib.c
1 /* crypto/ec/ec_lib.c */
2 /*
3  * Originally written by Bodo Moeller for the OpenSSL project.
4  */
5 /* ====================================================================
6  * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 /* ====================================================================
59  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60  * Binary polynomial ECC support in OpenSSL originally developed by
61  * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
62  */
63
64 #include <string.h>
65
66 #include <openssl/err.h>
67 #include <openssl/opensslv.h>
68
69 #include "ec_lcl.h"
70
71 const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72
73 /* functions for EC_GROUP objects */
74
75 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
76 {
77     EC_GROUP *ret;
78
79     if (meth == NULL) {
80         ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
81         return NULL;
82     }
83     if (meth->group_init == 0) {
84         ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
85         return NULL;
86     }
87
88     ret = OPENSSL_malloc(sizeof *ret);
89     if (ret == NULL) {
90         ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
91         return NULL;
92     }
93
94     ret->meth = meth;
95
96     ret->extra_data = NULL;
97     ret->mont_data = NULL;
98
99     ret->generator = NULL;
100     ret->order = BN_new();
101     ret->cofactor = NULL;
102     if (!ret->order)
103         goto err;
104     ret->cofactor = BN_new();
105     if (!ret->cofactor)
106         goto err;
107
108     ret->curve_name = 0;
109     ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
110     ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
111
112     ret->seed = NULL;
113     ret->seed_len = 0;
114
115     if (!meth->group_init(ret))
116         goto err;
117
118     return ret;
119  err:
120     if (ret->order)
121         BN_free(ret->order);
122     if (ret->cofactor)
123         BN_free(ret->cofactor);
124     OPENSSL_free(ret);
125     return NULL;
126 }
127
128 void EC_GROUP_free(EC_GROUP *group)
129 {
130     if (!group)
131         return;
132
133     if (group->meth->group_finish != 0)
134         group->meth->group_finish(group);
135
136     EC_EX_DATA_free_all_data(&group->extra_data);
137
138     if (group->mont_data)
139         BN_MONT_CTX_free(group->mont_data);
140
141     EC_POINT_free(group->generator);
142     BN_free(group->order);
143     BN_free(group->cofactor);
144
145     if (group->seed)
146         OPENSSL_free(group->seed);
147
148     OPENSSL_free(group);
149 }
150
151 void EC_GROUP_clear_free(EC_GROUP *group)
152 {
153     if (!group)
154         return;
155
156     if (group->meth->group_clear_finish != 0)
157         group->meth->group_clear_finish(group);
158     else if (group->meth->group_finish != 0)
159         group->meth->group_finish(group);
160
161     EC_EX_DATA_clear_free_all_data(&group->extra_data);
162
163     if (group->mont_data)
164         BN_MONT_CTX_free(group->mont_data);
165
166     EC_POINT_clear_free(group->generator);
167     BN_clear_free(group->order);
168     BN_clear_free(group->cofactor);
169
170     if (group->seed) {
171         OPENSSL_cleanse(group->seed, group->seed_len);
172         OPENSSL_free(group->seed);
173     }
174
175     OPENSSL_cleanse(group, sizeof *group);
176     OPENSSL_free(group);
177 }
178
179 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
180 {
181     EC_EXTRA_DATA *d;
182
183     if (dest->meth->group_copy == 0) {
184         ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
185         return 0;
186     }
187     if (dest->meth != src->meth) {
188         ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
189         return 0;
190     }
191     if (dest == src)
192         return 1;
193
194     EC_EX_DATA_free_all_data(&dest->extra_data);
195
196     for (d = src->extra_data; d != NULL; d = d->next) {
197         void *t = d->dup_func(d->data);
198
199         if (t == NULL)
200             return 0;
201         if (!EC_EX_DATA_set_data
202             (&dest->extra_data, t, d->dup_func, d->free_func,
203              d->clear_free_func))
204             return 0;
205     }
206
207     if (src->mont_data != NULL) {
208         if (dest->mont_data == NULL) {
209             dest->mont_data = BN_MONT_CTX_new();
210             if (dest->mont_data == NULL)
211                 return 0;
212         }
213         if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
214             return 0;
215     } else {
216         /* src->generator == NULL */
217         if (dest->mont_data != NULL) {
218             BN_MONT_CTX_free(dest->mont_data);
219             dest->mont_data = NULL;
220         }
221     }
222
223     if (src->generator != NULL) {
224         if (dest->generator == NULL) {
225             dest->generator = EC_POINT_new(dest);
226             if (dest->generator == NULL)
227                 return 0;
228         }
229         if (!EC_POINT_copy(dest->generator, src->generator))
230             return 0;
231     } else {
232         /* src->generator == NULL */
233         EC_POINT_clear_free(dest->generator);
234         dest->generator = NULL;
235     }
236
237     if (!BN_copy(dest->order, src->order))
238         return 0;
239     if (!BN_copy(dest->cofactor, src->cofactor))
240         return 0;
241
242     dest->curve_name = src->curve_name;
243     dest->asn1_flag = src->asn1_flag;
244     dest->asn1_form = src->asn1_form;
245
246     if (src->seed) {
247         if (dest->seed)
248             OPENSSL_free(dest->seed);
249         dest->seed = OPENSSL_malloc(src->seed_len);
250         if (dest->seed == NULL)
251             return 0;
252         if (!memcpy(dest->seed, src->seed, src->seed_len))
253             return 0;
254         dest->seed_len = src->seed_len;
255     } else {
256         if (dest->seed)
257             OPENSSL_free(dest->seed);
258         dest->seed = NULL;
259         dest->seed_len = 0;
260     }
261
262     return dest->meth->group_copy(dest, src);
263 }
264
265 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
266 {
267     EC_GROUP *t = NULL;
268     int ok = 0;
269
270     if (a == NULL)
271         return NULL;
272
273     if ((t = EC_GROUP_new(a->meth)) == NULL)
274         return (NULL);
275     if (!EC_GROUP_copy(t, a))
276         goto err;
277
278     ok = 1;
279
280  err:
281     if (!ok) {
282         EC_GROUP_free(t);
283         return NULL;
284     }
285         return t;
286 }
287
288 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
289 {
290     return group->meth;
291 }
292
293 int EC_METHOD_get_field_type(const EC_METHOD *meth)
294 {
295     return meth->field_type;
296 }
297
298 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
299                            const BIGNUM *order, const BIGNUM *cofactor)
300 {
301     if (generator == NULL) {
302         ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
303         return 0;
304     }
305
306     if (group->generator == NULL) {
307         group->generator = EC_POINT_new(group);
308         if (group->generator == NULL)
309             return 0;
310     }
311     if (!EC_POINT_copy(group->generator, generator))
312         return 0;
313
314     if (order != NULL) {
315         if (!BN_copy(group->order, order))
316             return 0;
317     } else
318         BN_zero(group->order);
319
320     if (cofactor != NULL) {
321         if (!BN_copy(group->cofactor, cofactor))
322             return 0;
323     } else
324         BN_zero(group->cofactor);
325
326     /*
327      * We ignore the return value because some groups have an order with
328      * factors of two, which makes the Montgomery setup fail.
329      * |group->mont_data| will be NULL in this case.
330      */
331     ec_precompute_mont_data(group);
332
333     return 1;
334 }
335
336 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
337 {
338     return group->generator;
339 }
340
341 BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
342 {
343     return group->mont_data;
344 }
345
346 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
347 {
348     if (!BN_copy(order, group->order))
349         return 0;
350
351     return !BN_is_zero(order);
352 }
353
354 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
355                           BN_CTX *ctx)
356 {
357     if (!BN_copy(cofactor, group->cofactor))
358         return 0;
359
360     return !BN_is_zero(group->cofactor);
361 }
362
363 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
364 {
365     group->curve_name = nid;
366 }
367
368 int EC_GROUP_get_curve_name(const EC_GROUP *group)
369 {
370     return group->curve_name;
371 }
372
373 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
374 {
375     group->asn1_flag = flag;
376 }
377
378 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
379 {
380     return group->asn1_flag;
381 }
382
383 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
384                                         point_conversion_form_t form)
385 {
386     group->asn1_form = form;
387 }
388
389 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
390                                                            *group)
391 {
392     return group->asn1_form;
393 }
394
395 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
396 {
397     if (group->seed) {
398         OPENSSL_free(group->seed);
399         group->seed = NULL;
400         group->seed_len = 0;
401     }
402
403     if (!len || !p)
404         return 1;
405
406     if ((group->seed = OPENSSL_malloc(len)) == NULL)
407         return 0;
408     memcpy(group->seed, p, len);
409     group->seed_len = len;
410
411     return len;
412 }
413
414 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
415 {
416     return group->seed;
417 }
418
419 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
420 {
421     return group->seed_len;
422 }
423
424 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
425                            const BIGNUM *b, BN_CTX *ctx)
426 {
427     if (group->meth->group_set_curve == 0) {
428         ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
429         return 0;
430     }
431     return group->meth->group_set_curve(group, p, a, b, ctx);
432 }
433
434 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
435                            BIGNUM *b, BN_CTX *ctx)
436 {
437     if (group->meth->group_get_curve == 0) {
438         ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
439         return 0;
440     }
441     return group->meth->group_get_curve(group, p, a, b, ctx);
442 }
443
444 #ifndef OPENSSL_NO_EC2M
445 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
446                             const BIGNUM *b, BN_CTX *ctx)
447 {
448     if (group->meth->group_set_curve == 0) {
449         ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
450               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
451         return 0;
452     }
453     return group->meth->group_set_curve(group, p, a, b, ctx);
454 }
455
456 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
457                             BIGNUM *b, BN_CTX *ctx)
458 {
459     if (group->meth->group_get_curve == 0) {
460         ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
461               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
462         return 0;
463     }
464     return group->meth->group_get_curve(group, p, a, b, ctx);
465 }
466 #endif
467
468 int EC_GROUP_get_degree(const EC_GROUP *group)
469 {
470     if (group->meth->group_get_degree == 0) {
471         ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
472         return 0;
473     }
474     return group->meth->group_get_degree(group);
475 }
476
477 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
478 {
479     if (group->meth->group_check_discriminant == 0) {
480         ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
481               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
482         return 0;
483     }
484     return group->meth->group_check_discriminant(group, ctx);
485 }
486
487 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
488 {
489     int r = 0;
490     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
491     BN_CTX *ctx_new = NULL;
492
493     /* compare the field types */
494     if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
495         EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
496         return 1;
497     /* compare the curve name (if present in both) */
498     if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
499         EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
500         return 1;
501
502     if (!ctx)
503         ctx_new = ctx = BN_CTX_new();
504     if (!ctx)
505         return -1;
506
507     BN_CTX_start(ctx);
508     a1 = BN_CTX_get(ctx);
509     a2 = BN_CTX_get(ctx);
510     a3 = BN_CTX_get(ctx);
511     b1 = BN_CTX_get(ctx);
512     b2 = BN_CTX_get(ctx);
513     b3 = BN_CTX_get(ctx);
514     if (!b3) {
515         BN_CTX_end(ctx);
516         if (ctx_new)
517             BN_CTX_free(ctx);
518         return -1;
519     }
520
521     /*
522      * XXX This approach assumes that the external representation of curves
523      * over the same field type is the same.
524      */
525     if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
526         !b->meth->group_get_curve(b, b1, b2, b3, ctx))
527         r = 1;
528
529     if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
530         r = 1;
531
532     /* XXX EC_POINT_cmp() assumes that the methods are equal */
533     if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
534                           EC_GROUP_get0_generator(b), ctx))
535         r = 1;
536
537     if (!r) {
538         /* compare the order and cofactor */
539         if (!EC_GROUP_get_order(a, a1, ctx) ||
540             !EC_GROUP_get_order(b, b1, ctx) ||
541             !EC_GROUP_get_cofactor(a, a2, ctx) ||
542             !EC_GROUP_get_cofactor(b, b2, ctx)) {
543             BN_CTX_end(ctx);
544             if (ctx_new)
545                 BN_CTX_free(ctx);
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     if (ctx_new)
554         BN_CTX_free(ctx);
555
556     return r;
557 }
558
559 /* this has 'package' visibility */
560 int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
561                         void *(*dup_func) (void *),
562                         void (*free_func) (void *),
563                         void (*clear_free_func) (void *))
564 {
565     EC_EXTRA_DATA *d;
566
567     if (ex_data == NULL)
568         return 0;
569
570     for (d = *ex_data; d != NULL; d = d->next) {
571         if (d->dup_func == dup_func && d->free_func == free_func
572             && d->clear_free_func == clear_free_func) {
573             ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
574             return 0;
575         }
576     }
577
578     if (data == NULL)
579         /* no explicit entry needed */
580         return 1;
581
582     d = OPENSSL_malloc(sizeof *d);
583     if (d == NULL)
584         return 0;
585
586     d->data = data;
587     d->dup_func = dup_func;
588     d->free_func = free_func;
589     d->clear_free_func = clear_free_func;
590
591     d->next = *ex_data;
592     *ex_data = d;
593
594     return 1;
595 }
596
597 /* this has 'package' visibility */
598 void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
599                           void *(*dup_func) (void *),
600                           void (*free_func) (void *),
601                           void (*clear_free_func) (void *))
602 {
603     const EC_EXTRA_DATA *d;
604
605     for (d = ex_data; d != NULL; d = d->next) {
606         if (d->dup_func == dup_func && d->free_func == free_func
607             && d->clear_free_func == clear_free_func)
608             return d->data;
609     }
610
611     return NULL;
612 }
613
614 /* this has 'package' visibility */
615 void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
616                           void *(*dup_func) (void *),
617                           void (*free_func) (void *),
618                           void (*clear_free_func) (void *))
619 {
620     EC_EXTRA_DATA **p;
621
622     if (ex_data == NULL)
623         return;
624
625     for (p = ex_data; *p != NULL; p = &((*p)->next)) {
626         if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
627             && (*p)->clear_free_func == clear_free_func) {
628             EC_EXTRA_DATA *next = (*p)->next;
629
630             (*p)->free_func((*p)->data);
631             OPENSSL_free(*p);
632
633             *p = next;
634             return;
635         }
636     }
637 }
638
639 /* this has 'package' visibility */
640 void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
641                                 void *(*dup_func) (void *),
642                                 void (*free_func) (void *),
643                                 void (*clear_free_func) (void *))
644 {
645     EC_EXTRA_DATA **p;
646
647     if (ex_data == NULL)
648         return;
649
650     for (p = ex_data; *p != NULL; p = &((*p)->next)) {
651         if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
652             && (*p)->clear_free_func == clear_free_func) {
653             EC_EXTRA_DATA *next = (*p)->next;
654
655             (*p)->clear_free_func((*p)->data);
656             OPENSSL_free(*p);
657
658             *p = next;
659             return;
660         }
661     }
662 }
663
664 /* this has 'package' visibility */
665 void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
666 {
667     EC_EXTRA_DATA *d;
668
669     if (ex_data == NULL)
670         return;
671
672     d = *ex_data;
673     while (d) {
674         EC_EXTRA_DATA *next = d->next;
675
676         d->free_func(d->data);
677         OPENSSL_free(d);
678
679         d = next;
680     }
681     *ex_data = NULL;
682 }
683
684 /* this has 'package' visibility */
685 void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
686 {
687     EC_EXTRA_DATA *d;
688
689     if (ex_data == NULL)
690         return;
691
692     d = *ex_data;
693     while (d) {
694         EC_EXTRA_DATA *next = d->next;
695
696         d->clear_free_func(d->data);
697         OPENSSL_free(d);
698
699         d = next;
700     }
701     *ex_data = NULL;
702 }
703
704 /* functions for EC_POINT objects */
705
706 EC_POINT *EC_POINT_new(const EC_GROUP *group)
707 {
708     EC_POINT *ret;
709
710     if (group == NULL) {
711         ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
712         return NULL;
713     }
714     if (group->meth->point_init == 0) {
715         ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
716         return NULL;
717     }
718
719     ret = OPENSSL_malloc(sizeof *ret);
720     if (ret == NULL) {
721         ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
722         return NULL;
723     }
724
725     ret->meth = group->meth;
726
727     if (!ret->meth->point_init(ret)) {
728         OPENSSL_free(ret);
729         return NULL;
730     }
731
732     return ret;
733 }
734
735 void EC_POINT_free(EC_POINT *point)
736 {
737     if (!point)
738         return;
739
740     if (point->meth->point_finish != 0)
741         point->meth->point_finish(point);
742     OPENSSL_free(point);
743 }
744
745 void EC_POINT_clear_free(EC_POINT *point)
746 {
747     if (!point)
748         return;
749
750     if (point->meth->point_clear_finish != 0)
751         point->meth->point_clear_finish(point);
752     else if (point->meth->point_finish != 0)
753         point->meth->point_finish(point);
754     OPENSSL_cleanse(point, sizeof *point);
755     OPENSSL_free(point);
756 }
757
758 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
759 {
760     if (dest->meth->point_copy == 0) {
761         ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
762         return 0;
763     }
764     if (dest->meth != src->meth) {
765         ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
766         return 0;
767     }
768     if (dest == src)
769         return 1;
770     return dest->meth->point_copy(dest, src);
771 }
772
773 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
774 {
775     EC_POINT *t;
776     int r;
777
778     if (a == NULL)
779         return NULL;
780
781     t = EC_POINT_new(group);
782     if (t == NULL)
783         return (NULL);
784     r = EC_POINT_copy(t, a);
785     if (!r) {
786         EC_POINT_free(t);
787         return NULL;
788     }
789     return t;
790 }
791
792 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
793 {
794     return point->meth;
795 }
796
797 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
798 {
799     if (group->meth->point_set_to_infinity == 0) {
800         ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
801               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
802         return 0;
803     }
804     if (group->meth != point->meth) {
805         ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
806         return 0;
807     }
808     return group->meth->point_set_to_infinity(group, point);
809 }
810
811 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
812                                              EC_POINT *point, const BIGNUM *x,
813                                              const BIGNUM *y, const BIGNUM *z,
814                                              BN_CTX *ctx)
815 {
816     if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
817         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
818               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
819         return 0;
820     }
821     if (group->meth != point->meth) {
822         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
823               EC_R_INCOMPATIBLE_OBJECTS);
824         return 0;
825     }
826     return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
827                                                               y, z, ctx);
828 }
829
830 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
831                                              const EC_POINT *point, BIGNUM *x,
832                                              BIGNUM *y, BIGNUM *z,
833                                              BN_CTX *ctx)
834 {
835     if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
836         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
837               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
838         return 0;
839     }
840     if (group->meth != point->meth) {
841         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
842               EC_R_INCOMPATIBLE_OBJECTS);
843         return 0;
844     }
845     return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
846                                                               y, z, ctx);
847 }
848
849 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
850                                         EC_POINT *point, const BIGNUM *x,
851                                         const BIGNUM *y, BN_CTX *ctx)
852 {
853     if (group->meth->point_set_affine_coordinates == 0) {
854         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
855               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
856         return 0;
857     }
858     if (group->meth != point->meth) {
859         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
860               EC_R_INCOMPATIBLE_OBJECTS);
861         return 0;
862     }
863     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
864 }
865
866 #ifndef OPENSSL_NO_EC2M
867 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
868                                          EC_POINT *point, const BIGNUM *x,
869                                          const BIGNUM *y, BN_CTX *ctx)
870 {
871     if (group->meth->point_set_affine_coordinates == 0) {
872         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
873               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
874         return 0;
875     }
876     if (group->meth != point->meth) {
877         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
878               EC_R_INCOMPATIBLE_OBJECTS);
879         return 0;
880     }
881     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
882 }
883 #endif
884
885 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
886                                         const EC_POINT *point, BIGNUM *x,
887                                         BIGNUM *y, BN_CTX *ctx)
888 {
889     if (group->meth->point_get_affine_coordinates == 0) {
890         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
891               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
892         return 0;
893     }
894     if (group->meth != point->meth) {
895         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
896               EC_R_INCOMPATIBLE_OBJECTS);
897         return 0;
898     }
899     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
900 }
901
902 #ifndef OPENSSL_NO_EC2M
903 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
904                                          const EC_POINT *point, BIGNUM *x,
905                                          BIGNUM *y, BN_CTX *ctx)
906 {
907     if (group->meth->point_get_affine_coordinates == 0) {
908         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
909               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
910         return 0;
911     }
912     if (group->meth != point->meth) {
913         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
914               EC_R_INCOMPATIBLE_OBJECTS);
915         return 0;
916     }
917     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
918 }
919 #endif
920
921 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
922                  const EC_POINT *b, BN_CTX *ctx)
923 {
924     if (group->meth->add == 0) {
925         ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
926         return 0;
927     }
928     if ((group->meth != r->meth) || (r->meth != a->meth)
929         || (a->meth != b->meth)) {
930         ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
931         return 0;
932     }
933     return group->meth->add(group, r, a, b, ctx);
934 }
935
936 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
937                  BN_CTX *ctx)
938 {
939     if (group->meth->dbl == 0) {
940         ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
941         return 0;
942     }
943     if ((group->meth != r->meth) || (r->meth != a->meth)) {
944         ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
945         return 0;
946     }
947     return group->meth->dbl(group, r, a, ctx);
948 }
949
950 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
951 {
952     if (group->meth->invert == 0) {
953         ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
954         return 0;
955     }
956     if (group->meth != a->meth) {
957         ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
958         return 0;
959     }
960     return group->meth->invert(group, a, ctx);
961 }
962
963 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
964 {
965     if (group->meth->is_at_infinity == 0) {
966         ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
967               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
968         return 0;
969     }
970     if (group->meth != point->meth) {
971         ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
972         return 0;
973     }
974     return group->meth->is_at_infinity(group, point);
975 }
976
977 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
978                          BN_CTX *ctx)
979 {
980     if (group->meth->is_on_curve == 0) {
981         ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
982         return 0;
983     }
984     if (group->meth != point->meth) {
985         ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
986         return 0;
987     }
988     return group->meth->is_on_curve(group, point, ctx);
989 }
990
991 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
992                  BN_CTX *ctx)
993 {
994     if (group->meth->point_cmp == 0) {
995         ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
996         return -1;
997     }
998     if ((group->meth != a->meth) || (a->meth != b->meth)) {
999         ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1000         return -1;
1001     }
1002     return group->meth->point_cmp(group, a, b, ctx);
1003 }
1004
1005 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1006 {
1007     if (group->meth->make_affine == 0) {
1008         ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1009         return 0;
1010     }
1011     if (group->meth != point->meth) {
1012         ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1013         return 0;
1014     }
1015     return group->meth->make_affine(group, point, ctx);
1016 }
1017
1018 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1019                           EC_POINT *points[], BN_CTX *ctx)
1020 {
1021     size_t i;
1022
1023     if (group->meth->points_make_affine == 0) {
1024         ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1025         return 0;
1026     }
1027     for (i = 0; i < num; i++) {
1028         if (group->meth != points[i]->meth) {
1029             ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1030             return 0;
1031         }
1032     }
1033     return group->meth->points_make_affine(group, num, points, ctx);
1034 }
1035
1036 /*
1037  * Functions for point multiplication. If group->meth->mul is 0, we use the
1038  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1039  * methods.
1040  */
1041
1042 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1043                   size_t num, const EC_POINT *points[],
1044                   const BIGNUM *scalars[], BN_CTX *ctx)
1045 {
1046     if (group->meth->mul == 0)
1047         /* use default */
1048         return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1049
1050     return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1051 }
1052
1053 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1054                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1055 {
1056     /* just a convenient interface to EC_POINTs_mul() */
1057
1058     const EC_POINT *points[1];
1059     const BIGNUM *scalars[1];
1060
1061     points[0] = point;
1062     scalars[0] = p_scalar;
1063
1064     return EC_POINTs_mul(group, r, g_scalar,
1065                          (point != NULL
1066                           && p_scalar != NULL), points, scalars, ctx);
1067 }
1068
1069 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1070 {
1071     if (group->meth->mul == 0)
1072         /* use default */
1073         return ec_wNAF_precompute_mult(group, ctx);
1074
1075     if (group->meth->precompute_mult != 0)
1076         return group->meth->precompute_mult(group, ctx);
1077     else
1078         return 1;               /* nothing to do, so report success */
1079 }
1080
1081 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1082 {
1083     if (group->meth->mul == 0)
1084         /* use default */
1085         return ec_wNAF_have_precompute_mult(group);
1086
1087     if (group->meth->have_precompute_mult != 0)
1088         return group->meth->have_precompute_mult(group);
1089     else
1090         return 0;               /* cannot tell whether precomputation has
1091                                  * been performed */
1092 }
1093
1094 /*
1095  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1096  * returns one on success. On error it returns zero.
1097  */
1098 int ec_precompute_mont_data(EC_GROUP *group)
1099 {
1100     BN_CTX *ctx = BN_CTX_new();
1101     int ret = 0;
1102
1103     if (group->mont_data) {
1104         BN_MONT_CTX_free(group->mont_data);
1105         group->mont_data = NULL;
1106     }
1107
1108     if (ctx == NULL)
1109         goto err;
1110
1111     group->mont_data = BN_MONT_CTX_new();
1112     if (!group->mont_data)
1113         goto err;
1114
1115     if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
1116         BN_MONT_CTX_free(group->mont_data);
1117         group->mont_data = NULL;
1118         goto err;
1119     }
1120
1121     ret = 1;
1122
1123  err:
1124
1125     if (ctx)
1126         BN_CTX_free(ctx);
1127     return ret;
1128 }