7cb4759f65b78b6e26e9ac97738b3f54db8b7b5b
[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 /* functions for EC_GROUP objects */
72
73 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
74 {
75     EC_GROUP *ret;
76
77     if (meth == NULL) {
78         ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
79         return NULL;
80     }
81     if (meth->group_init == 0) {
82         ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
83         return NULL;
84     }
85
86     ret = OPENSSL_zalloc(sizeof(*ret));
87     if (ret == NULL) {
88         ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
89         return NULL;
90     }
91
92     ret->meth = meth;
93     ret->order = BN_new();
94     if (ret->order == NULL)
95         goto err;
96     ret->cofactor = BN_new();
97     if (ret->cofactor == NULL)
98         goto err;
99     ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
100     ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
101     if (!meth->group_init(ret))
102         goto err;
103     return ret;
104
105  err:
106     BN_free(ret->order);
107     BN_free(ret->cofactor);
108     OPENSSL_free(ret);
109     return NULL;
110 }
111
112 void EC_GROUP_free(EC_GROUP *group)
113 {
114     if (!group)
115         return;
116
117     if (group->meth->group_finish != 0)
118         group->meth->group_finish(group);
119
120     EC_EX_DATA_free_all_data(&group->extra_data);
121     BN_MONT_CTX_free(group->mont_data);
122     EC_POINT_free(group->generator);
123     BN_free(group->order);
124     BN_free(group->cofactor);
125     OPENSSL_free(group->seed);
126     OPENSSL_free(group);
127 }
128
129 void EC_GROUP_clear_free(EC_GROUP *group)
130 {
131     if (!group)
132         return;
133
134     if (group->meth->group_clear_finish != 0)
135         group->meth->group_clear_finish(group);
136     else if (group->meth->group_finish != 0)
137         group->meth->group_finish(group);
138
139     EC_EX_DATA_clear_free_all_data(&group->extra_data);
140
141     BN_MONT_CTX_free(group->mont_data);
142
143     EC_POINT_clear_free(group->generator);
144     BN_clear_free(group->order);
145     BN_clear_free(group->cofactor);
146     OPENSSL_clear_free(group->seed, group->seed_len);
147     OPENSSL_clear_free(group, sizeof(*group));
148 }
149
150 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
151 {
152     EC_EXTRA_DATA *d;
153
154     if (dest->meth->group_copy == 0) {
155         ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
156         return 0;
157     }
158     if (dest->meth != src->meth) {
159         ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
160         return 0;
161     }
162     if (dest == src)
163         return 1;
164
165     EC_EX_DATA_free_all_data(&dest->extra_data);
166
167     for (d = src->extra_data; d != NULL; d = d->next) {
168         void *t = d->dup_func(d->data);
169
170         if (t == NULL)
171             return 0;
172         if (!EC_EX_DATA_set_data
173             (&dest->extra_data, t, d->dup_func, d->free_func,
174              d->clear_free_func))
175             return 0;
176     }
177
178     if (src->mont_data != NULL) {
179         if (dest->mont_data == NULL) {
180             dest->mont_data = BN_MONT_CTX_new();
181             if (dest->mont_data == NULL)
182                 return 0;
183         }
184         if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
185             return 0;
186     } else {
187         /* src->generator == NULL */
188         BN_MONT_CTX_free(dest->mont_data);
189         dest->mont_data = NULL;
190     }
191
192     if (src->generator != NULL) {
193         if (dest->generator == NULL) {
194             dest->generator = EC_POINT_new(dest);
195             if (dest->generator == NULL)
196                 return 0;
197         }
198         if (!EC_POINT_copy(dest->generator, src->generator))
199             return 0;
200     } else {
201         /* src->generator == NULL */
202         EC_POINT_clear_free(dest->generator);
203         dest->generator = NULL;
204     }
205
206     if (!BN_copy(dest->order, src->order))
207         return 0;
208     if (!BN_copy(dest->cofactor, src->cofactor))
209         return 0;
210
211     dest->curve_name = src->curve_name;
212     dest->asn1_flag = src->asn1_flag;
213     dest->asn1_form = src->asn1_form;
214
215     if (src->seed) {
216         OPENSSL_free(dest->seed);
217         dest->seed = OPENSSL_malloc(src->seed_len);
218         if (dest->seed == NULL)
219             return 0;
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 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
266                            const BIGNUM *order, const BIGNUM *cofactor)
267 {
268     if (generator == NULL) {
269         ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
270         return 0;
271     }
272
273     if (group->generator == NULL) {
274         group->generator = EC_POINT_new(group);
275         if (group->generator == NULL)
276             return 0;
277     }
278     if (!EC_POINT_copy(group->generator, generator))
279         return 0;
280
281     if (order != NULL) {
282         if (!BN_copy(group->order, order))
283             return 0;
284     } else
285         BN_zero(group->order);
286
287     if (cofactor != NULL) {
288         if (!BN_copy(group->cofactor, cofactor))
289             return 0;
290     } else
291         BN_zero(group->cofactor);
292
293     /*
294      * We ignore the return value because some groups have an order with
295      * factors of two, which makes the Montgomery setup fail.
296      * |group->mont_data| will be NULL in this case.
297      */
298     ec_precompute_mont_data(group);
299
300     return 1;
301 }
302
303 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
304 {
305     return group->generator;
306 }
307
308 BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
309 {
310     return group->mont_data;
311 }
312
313 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
314 {
315     if (!BN_copy(order, group->order))
316         return 0;
317
318     return !BN_is_zero(order);
319 }
320
321 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
322                           BN_CTX *ctx)
323 {
324     if (!BN_copy(cofactor, group->cofactor))
325         return 0;
326
327     return !BN_is_zero(group->cofactor);
328 }
329
330 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
331 {
332     group->curve_name = nid;
333 }
334
335 int EC_GROUP_get_curve_name(const EC_GROUP *group)
336 {
337     return group->curve_name;
338 }
339
340 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
341 {
342     group->asn1_flag = flag;
343 }
344
345 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
346 {
347     return group->asn1_flag;
348 }
349
350 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
351                                         point_conversion_form_t form)
352 {
353     group->asn1_form = form;
354 }
355
356 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
357                                                            *group)
358 {
359     return group->asn1_form;
360 }
361
362 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
363 {
364     OPENSSL_free(group->seed);
365     group->seed = NULL;
366     group->seed_len = 0;
367
368     if (!len || !p)
369         return 1;
370
371     if ((group->seed = OPENSSL_malloc(len)) == NULL)
372         return 0;
373     memcpy(group->seed, p, len);
374     group->seed_len = len;
375
376     return len;
377 }
378
379 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
380 {
381     return group->seed;
382 }
383
384 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
385 {
386     return group->seed_len;
387 }
388
389 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
390                            const BIGNUM *b, BN_CTX *ctx)
391 {
392     if (group->meth->group_set_curve == 0) {
393         ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
394         return 0;
395     }
396     return group->meth->group_set_curve(group, p, a, b, ctx);
397 }
398
399 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
400                            BIGNUM *b, BN_CTX *ctx)
401 {
402     if (group->meth->group_get_curve == 0) {
403         ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
404         return 0;
405     }
406     return group->meth->group_get_curve(group, p, a, b, ctx);
407 }
408
409 #ifndef OPENSSL_NO_EC2M
410 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
411                             const BIGNUM *b, BN_CTX *ctx)
412 {
413     if (group->meth->group_set_curve == 0) {
414         ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
415               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
416         return 0;
417     }
418     return group->meth->group_set_curve(group, p, a, b, ctx);
419 }
420
421 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
422                             BIGNUM *b, BN_CTX *ctx)
423 {
424     if (group->meth->group_get_curve == 0) {
425         ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
426               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 #endif
432
433 int EC_GROUP_get_degree(const EC_GROUP *group)
434 {
435     if (group->meth->group_get_degree == 0) {
436         ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
437         return 0;
438     }
439     return group->meth->group_get_degree(group);
440 }
441
442 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
443 {
444     if (group->meth->group_check_discriminant == 0) {
445         ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
446               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
447         return 0;
448     }
449     return group->meth->group_check_discriminant(group, ctx);
450 }
451
452 int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
453 {
454     int r = 0;
455     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
456     BN_CTX *ctx_new = NULL;
457
458     /* compare the field types */
459     if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
460         EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
461         return 1;
462     /* compare the curve name (if present in both) */
463     if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
464         EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
465         return 1;
466
467     if (ctx == NULL)
468         ctx_new = ctx = BN_CTX_new();
469     if (ctx == NULL)
470         return -1;
471
472     BN_CTX_start(ctx);
473     a1 = BN_CTX_get(ctx);
474     a2 = BN_CTX_get(ctx);
475     a3 = BN_CTX_get(ctx);
476     b1 = BN_CTX_get(ctx);
477     b2 = BN_CTX_get(ctx);
478     b3 = BN_CTX_get(ctx);
479     if (b3 == NULL) {
480         BN_CTX_end(ctx);
481         BN_CTX_free(ctx_new);
482         return -1;
483     }
484
485     /*
486      * XXX This approach assumes that the external representation of curves
487      * over the same field type is the same.
488      */
489     if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
490         !b->meth->group_get_curve(b, b1, b2, b3, ctx))
491         r = 1;
492
493     if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
494         r = 1;
495
496     /* XXX EC_POINT_cmp() assumes that the methods are equal */
497     if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
498                           EC_GROUP_get0_generator(b), ctx))
499         r = 1;
500
501     if (!r) {
502         /* compare the order and cofactor */
503         if (!EC_GROUP_get_order(a, a1, ctx) ||
504             !EC_GROUP_get_order(b, b1, ctx) ||
505             !EC_GROUP_get_cofactor(a, a2, ctx) ||
506             !EC_GROUP_get_cofactor(b, b2, ctx)) {
507             BN_CTX_end(ctx);
508             BN_CTX_free(ctx_new);
509             return -1;
510         }
511         if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
512             r = 1;
513     }
514
515     BN_CTX_end(ctx);
516     BN_CTX_free(ctx_new);
517
518     return r;
519 }
520
521 /* this has 'package' visibility */
522 int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
523                         void *(*dup_func) (void *),
524                         void (*free_func) (void *),
525                         void (*clear_free_func) (void *))
526 {
527     EC_EXTRA_DATA *d;
528
529     if (ex_data == NULL)
530         return 0;
531
532     for (d = *ex_data; d != NULL; d = d->next) {
533         if (d->dup_func == dup_func && d->free_func == free_func
534             && d->clear_free_func == clear_free_func) {
535             ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
536             return 0;
537         }
538     }
539
540     if (data == NULL)
541         /* no explicit entry needed */
542         return 1;
543
544     d = OPENSSL_malloc(sizeof(*d));
545     if (d == NULL)
546         return 0;
547
548     d->data = data;
549     d->dup_func = dup_func;
550     d->free_func = free_func;
551     d->clear_free_func = clear_free_func;
552
553     d->next = *ex_data;
554     *ex_data = d;
555
556     return 1;
557 }
558
559 /* this has 'package' visibility */
560 void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
561                           void *(*dup_func) (void *),
562                           void (*free_func) (void *),
563                           void (*clear_free_func) (void *))
564 {
565     const EC_EXTRA_DATA *d;
566
567     for (d = ex_data; d != NULL; d = d->next) {
568         if (d->dup_func == dup_func && d->free_func == free_func
569             && d->clear_free_func == clear_free_func)
570             return d->data;
571     }
572
573     return NULL;
574 }
575
576 /* this has 'package' visibility */
577 void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
578                           void *(*dup_func) (void *),
579                           void (*free_func) (void *),
580                           void (*clear_free_func) (void *))
581 {
582     EC_EXTRA_DATA **p;
583
584     if (ex_data == NULL)
585         return;
586
587     for (p = ex_data; *p != NULL; p = &((*p)->next)) {
588         if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
589             && (*p)->clear_free_func == clear_free_func) {
590             EC_EXTRA_DATA *next = (*p)->next;
591
592             (*p)->free_func((*p)->data);
593             OPENSSL_free(*p);
594
595             *p = next;
596             return;
597         }
598     }
599 }
600
601 /* this has 'package' visibility */
602 void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
603                                 void *(*dup_func) (void *),
604                                 void (*free_func) (void *),
605                                 void (*clear_free_func) (void *))
606 {
607     EC_EXTRA_DATA **p;
608
609     if (ex_data == NULL)
610         return;
611
612     for (p = ex_data; *p != NULL; p = &((*p)->next)) {
613         if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
614             && (*p)->clear_free_func == clear_free_func) {
615             EC_EXTRA_DATA *next = (*p)->next;
616
617             (*p)->clear_free_func((*p)->data);
618             OPENSSL_free(*p);
619
620             *p = next;
621             return;
622         }
623     }
624 }
625
626 /* this has 'package' visibility */
627 void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
628 {
629     EC_EXTRA_DATA *d;
630
631     if (ex_data == NULL)
632         return;
633
634     d = *ex_data;
635     while (d) {
636         EC_EXTRA_DATA *next = d->next;
637
638         d->free_func(d->data);
639         OPENSSL_free(d);
640
641         d = next;
642     }
643     *ex_data = NULL;
644 }
645
646 /* this has 'package' visibility */
647 void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
648 {
649     EC_EXTRA_DATA *d;
650
651     if (ex_data == NULL)
652         return;
653
654     d = *ex_data;
655     while (d) {
656         EC_EXTRA_DATA *next = d->next;
657
658         d->clear_free_func(d->data);
659         OPENSSL_free(d);
660
661         d = next;
662     }
663     *ex_data = NULL;
664 }
665
666 /* functions for EC_POINT objects */
667
668 EC_POINT *EC_POINT_new(const EC_GROUP *group)
669 {
670     EC_POINT *ret;
671
672     if (group == NULL) {
673         ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
674         return NULL;
675     }
676     if (group->meth->point_init == 0) {
677         ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
678         return NULL;
679     }
680
681     ret = OPENSSL_malloc(sizeof(*ret));
682     if (ret == NULL) {
683         ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
684         return NULL;
685     }
686
687     ret->meth = group->meth;
688
689     if (!ret->meth->point_init(ret)) {
690         OPENSSL_free(ret);
691         return NULL;
692     }
693
694     return ret;
695 }
696
697 void EC_POINT_free(EC_POINT *point)
698 {
699     if (!point)
700         return;
701
702     if (point->meth->point_finish != 0)
703         point->meth->point_finish(point);
704     OPENSSL_free(point);
705 }
706
707 void EC_POINT_clear_free(EC_POINT *point)
708 {
709     if (!point)
710         return;
711
712     if (point->meth->point_clear_finish != 0)
713         point->meth->point_clear_finish(point);
714     else if (point->meth->point_finish != 0)
715         point->meth->point_finish(point);
716     OPENSSL_clear_free(point, sizeof(*point));
717 }
718
719 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
720 {
721     if (dest->meth->point_copy == 0) {
722         ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
723         return 0;
724     }
725     if (dest->meth != src->meth) {
726         ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
727         return 0;
728     }
729     if (dest == src)
730         return 1;
731     return dest->meth->point_copy(dest, src);
732 }
733
734 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
735 {
736     EC_POINT *t;
737     int r;
738
739     if (a == NULL)
740         return NULL;
741
742     t = EC_POINT_new(group);
743     if (t == NULL)
744         return (NULL);
745     r = EC_POINT_copy(t, a);
746     if (!r) {
747         EC_POINT_free(t);
748         return NULL;
749     }
750     return t;
751 }
752
753 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
754 {
755     return point->meth;
756 }
757
758 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
759 {
760     if (group->meth->point_set_to_infinity == 0) {
761         ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
762               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
763         return 0;
764     }
765     if (group->meth != point->meth) {
766         ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
767         return 0;
768     }
769     return group->meth->point_set_to_infinity(group, point);
770 }
771
772 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
773                                              EC_POINT *point, const BIGNUM *x,
774                                              const BIGNUM *y, const BIGNUM *z,
775                                              BN_CTX *ctx)
776 {
777     if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
778         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
779               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
780         return 0;
781     }
782     if (group->meth != point->meth) {
783         ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
784               EC_R_INCOMPATIBLE_OBJECTS);
785         return 0;
786     }
787     return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
788                                                               y, z, ctx);
789 }
790
791 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
792                                              const EC_POINT *point, BIGNUM *x,
793                                              BIGNUM *y, BIGNUM *z,
794                                              BN_CTX *ctx)
795 {
796     if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
797         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
798               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
799         return 0;
800     }
801     if (group->meth != point->meth) {
802         ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
803               EC_R_INCOMPATIBLE_OBJECTS);
804         return 0;
805     }
806     return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
807                                                               y, z, ctx);
808 }
809
810 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
811                                         EC_POINT *point, const BIGNUM *x,
812                                         const BIGNUM *y, BN_CTX *ctx)
813 {
814     if (group->meth->point_set_affine_coordinates == 0) {
815         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
816               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
817         return 0;
818     }
819     if (group->meth != point->meth) {
820         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
821               EC_R_INCOMPATIBLE_OBJECTS);
822         return 0;
823     }
824     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
825 }
826
827 #ifndef OPENSSL_NO_EC2M
828 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
829                                          EC_POINT *point, const BIGNUM *x,
830                                          const BIGNUM *y, BN_CTX *ctx)
831 {
832     if (group->meth->point_set_affine_coordinates == 0) {
833         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
834               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
835         return 0;
836     }
837     if (group->meth != point->meth) {
838         ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
839               EC_R_INCOMPATIBLE_OBJECTS);
840         return 0;
841     }
842     return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
843 }
844 #endif
845
846 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
847                                         const EC_POINT *point, BIGNUM *x,
848                                         BIGNUM *y, BN_CTX *ctx)
849 {
850     if (group->meth->point_get_affine_coordinates == 0) {
851         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
852               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
853         return 0;
854     }
855     if (group->meth != point->meth) {
856         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
857               EC_R_INCOMPATIBLE_OBJECTS);
858         return 0;
859     }
860     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
861 }
862
863 #ifndef OPENSSL_NO_EC2M
864 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
865                                          const EC_POINT *point, BIGNUM *x,
866                                          BIGNUM *y, BN_CTX *ctx)
867 {
868     if (group->meth->point_get_affine_coordinates == 0) {
869         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
870               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
871         return 0;
872     }
873     if (group->meth != point->meth) {
874         ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
875               EC_R_INCOMPATIBLE_OBJECTS);
876         return 0;
877     }
878     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
879 }
880 #endif
881
882 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
883                  const EC_POINT *b, BN_CTX *ctx)
884 {
885     if (group->meth->add == 0) {
886         ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
887         return 0;
888     }
889     if ((group->meth != r->meth) || (r->meth != a->meth)
890         || (a->meth != b->meth)) {
891         ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
892         return 0;
893     }
894     return group->meth->add(group, r, a, b, ctx);
895 }
896
897 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
898                  BN_CTX *ctx)
899 {
900     if (group->meth->dbl == 0) {
901         ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
902         return 0;
903     }
904     if ((group->meth != r->meth) || (r->meth != a->meth)) {
905         ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
906         return 0;
907     }
908     return group->meth->dbl(group, r, a, ctx);
909 }
910
911 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
912 {
913     if (group->meth->invert == 0) {
914         ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
915         return 0;
916     }
917     if (group->meth != a->meth) {
918         ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
919         return 0;
920     }
921     return group->meth->invert(group, a, ctx);
922 }
923
924 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
925 {
926     if (group->meth->is_at_infinity == 0) {
927         ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
928               ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
929         return 0;
930     }
931     if (group->meth != point->meth) {
932         ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
933         return 0;
934     }
935     return group->meth->is_at_infinity(group, point);
936 }
937
938 /*
939  * Check whether an EC_POINT is on the curve or not. Note that the return
940  * value for this function should NOT be treated as a boolean. Return values:
941  *  1: The point is on the curve
942  *  0: The point is not on the curve
943  * -1: An error occurred
944  */
945 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
946                          BN_CTX *ctx)
947 {
948     if (group->meth->is_on_curve == 0) {
949         ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
950         return 0;
951     }
952     if (group->meth != point->meth) {
953         ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
954         return 0;
955     }
956     return group->meth->is_on_curve(group, point, ctx);
957 }
958
959 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
960                  BN_CTX *ctx)
961 {
962     if (group->meth->point_cmp == 0) {
963         ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
964         return -1;
965     }
966     if ((group->meth != a->meth) || (a->meth != b->meth)) {
967         ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
968         return -1;
969     }
970     return group->meth->point_cmp(group, a, b, ctx);
971 }
972
973 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
974 {
975     if (group->meth->make_affine == 0) {
976         ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
977         return 0;
978     }
979     if (group->meth != point->meth) {
980         ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
981         return 0;
982     }
983     return group->meth->make_affine(group, point, ctx);
984 }
985
986 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
987                           EC_POINT *points[], BN_CTX *ctx)
988 {
989     size_t i;
990
991     if (group->meth->points_make_affine == 0) {
992         ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
993         return 0;
994     }
995     for (i = 0; i < num; i++) {
996         if (group->meth != points[i]->meth) {
997             ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
998             return 0;
999         }
1000     }
1001     return group->meth->points_make_affine(group, num, points, ctx);
1002 }
1003
1004 /*
1005  * Functions for point multiplication. If group->meth->mul is 0, we use the
1006  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1007  * methods.
1008  */
1009
1010 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1011                   size_t num, const EC_POINT *points[],
1012                   const BIGNUM *scalars[], BN_CTX *ctx)
1013 {
1014     if (group->meth->mul == 0)
1015         /* use default */
1016         return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1017
1018     return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1019 }
1020
1021 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1022                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1023 {
1024     /* just a convenient interface to EC_POINTs_mul() */
1025
1026     const EC_POINT *points[1];
1027     const BIGNUM *scalars[1];
1028
1029     points[0] = point;
1030     scalars[0] = p_scalar;
1031
1032     return EC_POINTs_mul(group, r, g_scalar,
1033                          (point != NULL
1034                           && p_scalar != NULL), points, scalars, ctx);
1035 }
1036
1037 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1038 {
1039     if (group->meth->mul == 0)
1040         /* use default */
1041         return ec_wNAF_precompute_mult(group, ctx);
1042
1043     if (group->meth->precompute_mult != 0)
1044         return group->meth->precompute_mult(group, ctx);
1045     else
1046         return 1;               /* nothing to do, so report success */
1047 }
1048
1049 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1050 {
1051     if (group->meth->mul == 0)
1052         /* use default */
1053         return ec_wNAF_have_precompute_mult(group);
1054
1055     if (group->meth->have_precompute_mult != 0)
1056         return group->meth->have_precompute_mult(group);
1057     else
1058         return 0;               /* cannot tell whether precomputation has
1059                                  * been performed */
1060 }
1061
1062 /*
1063  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1064  * returns one on success. On error it returns zero.
1065  */
1066 int ec_precompute_mont_data(EC_GROUP *group)
1067 {
1068     BN_CTX *ctx = BN_CTX_new();
1069     int ret = 0;
1070
1071     BN_MONT_CTX_free(group->mont_data);
1072     group->mont_data = NULL;
1073
1074     if (ctx == NULL)
1075         goto err;
1076
1077     group->mont_data = BN_MONT_CTX_new();
1078     if (group->mont_data == NULL)
1079         goto err;
1080
1081     if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
1082         BN_MONT_CTX_free(group->mont_data);
1083         group->mont_data = NULL;
1084         goto err;
1085     }
1086
1087     ret = 1;
1088
1089  err:
1090
1091     BN_CTX_free(ctx);
1092     return ret;
1093 }