]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - crypto/openssl/crypto/ec/ec_lib.c
Add compiler-rt's libFuzzer, not connected to buildworld yet.
[FreeBSD/FreeBSD.git] / crypto / openssl / 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-2018 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     BN_init(&ret->order);
101     BN_init(&ret->cofactor);
102
103     ret->curve_name = 0;
104     ret->asn1_flag = ~EC_GROUP_ASN1_FLAG_MASK;
105     ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
106
107     ret->seed = NULL;
108     ret->seed_len = 0;
109
110     if (!meth->group_init(ret)) {
111         OPENSSL_free(ret);
112         return NULL;
113     }
114
115     return ret;
116 }
117
118 void EC_GROUP_free(EC_GROUP *group)
119 {
120     if (!group)
121         return;
122
123     if (group->meth->group_finish != 0)
124         group->meth->group_finish(group);
125
126     EC_EX_DATA_free_all_data(&group->extra_data);
127
128     if (EC_GROUP_VERSION(group) && group->mont_data)
129         BN_MONT_CTX_free(group->mont_data);
130
131     if (group->generator != NULL)
132         EC_POINT_free(group->generator);
133     BN_free(&group->order);
134     BN_free(&group->cofactor);
135
136     if (group->seed)
137         OPENSSL_free(group->seed);
138
139     OPENSSL_free(group);
140 }
141
142 void EC_GROUP_clear_free(EC_GROUP *group)
143 {
144     if (!group)
145         return;
146
147     if (group->meth->group_clear_finish != 0)
148         group->meth->group_clear_finish(group);
149     else if (group->meth->group_finish != 0)
150         group->meth->group_finish(group);
151
152     EC_EX_DATA_clear_free_all_data(&group->extra_data);
153
154     if (EC_GROUP_VERSION(group) && group->mont_data)
155         BN_MONT_CTX_free(group->mont_data);
156
157     if (group->generator != NULL)
158         EC_POINT_clear_free(group->generator);
159     BN_clear_free(&group->order);
160     BN_clear_free(&group->cofactor);
161
162     if (group->seed) {
163         OPENSSL_cleanse(group->seed, group->seed_len);
164         OPENSSL_free(group->seed);
165     }
166
167     OPENSSL_cleanse(group, sizeof(*group));
168     OPENSSL_free(group);
169 }
170
171 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
172 {
173     EC_EXTRA_DATA *d;
174
175     if (dest->meth->group_copy == 0) {
176         ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
177         return 0;
178     }
179     if (dest->meth != src->meth) {
180         ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
181         return 0;
182     }
183     if (dest == src)
184         return 1;
185
186     EC_EX_DATA_free_all_data(&dest->extra_data);
187
188     for (d = src->extra_data; d != NULL; d = d->next) {
189         void *t = d->dup_func(d->data);
190
191         if (t == NULL)
192             return 0;
193         if (!EC_EX_DATA_set_data
194             (&dest->extra_data, t, d->dup_func, d->free_func,
195              d->clear_free_func))
196             return 0;
197     }
198
199     if (EC_GROUP_VERSION(src) && src->mont_data != NULL) {
200         if (dest->mont_data == NULL) {
201             dest->mont_data = BN_MONT_CTX_new();
202             if (dest->mont_data == NULL)
203                 return 0;
204         }
205         if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
206             return 0;
207     } else {
208         /* src->generator == NULL */
209         if (EC_GROUP_VERSION(dest) && dest->mont_data != NULL) {
210             BN_MONT_CTX_free(dest->mont_data);
211             dest->mont_data = NULL;
212         }
213     }
214
215     if (src->generator != NULL) {
216         if (dest->generator == NULL) {
217             dest->generator = EC_POINT_new(dest);
218             if (dest->generator == NULL)
219                 return 0;
220         }
221         if (!EC_POINT_copy(dest->generator, src->generator))
222             return 0;
223     } else {
224         /* src->generator == NULL */
225         if (dest->generator != NULL) {
226             EC_POINT_clear_free(dest->generator);
227             dest->generator = NULL;
228         }
229     }
230
231     if (!BN_copy(&dest->order, &src->order))
232         return 0;
233     if (!BN_copy(&dest->cofactor, &src->cofactor))
234         return 0;
235
236     dest->curve_name = src->curve_name;
237     dest->asn1_flag = src->asn1_flag;
238     dest->asn1_form = src->asn1_form;
239
240     if (src->seed) {
241         if (dest->seed)
242             OPENSSL_free(dest->seed);
243         dest->seed = OPENSSL_malloc(src->seed_len);
244         if (dest->seed == NULL)
245             return 0;
246         if (!memcpy(dest->seed, src->seed, src->seed_len))
247             return 0;
248         dest->seed_len = src->seed_len;
249     } else {
250         if (dest->seed)
251             OPENSSL_free(dest->seed);
252         dest->seed = NULL;
253         dest->seed_len = 0;
254     }
255
256     return dest->meth->group_copy(dest, src);
257 }
258
259 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
260 {
261     EC_GROUP *t = NULL;
262     int ok = 0;
263
264     if (a == NULL)
265         return NULL;
266
267     if ((t = EC_GROUP_new(a->meth)) == NULL)
268         return (NULL);
269     if (!EC_GROUP_copy(t, a))
270         goto err;
271
272     ok = 1;
273
274  err:
275     if (!ok) {
276         if (t)
277             EC_GROUP_free(t);
278         return NULL;
279     } else
280         return t;
281 }
282
283 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
284 {
285     return group->meth;
286 }
287
288 int EC_METHOD_get_field_type(const EC_METHOD *meth)
289 {
290     return meth->field_type;
291 }
292
293 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
294                            const BIGNUM *order, const BIGNUM *cofactor)
295 {
296     if (generator == NULL) {
297         ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
298         return 0;
299     }
300
301     if (group->generator == NULL) {
302         group->generator = EC_POINT_new(group);
303         if (group->generator == NULL)
304             return 0;
305     }
306     if (!EC_POINT_copy(group->generator, generator))
307         return 0;
308
309     if (order != NULL) {
310         if (!BN_copy(&group->order, order))
311             return 0;
312     } else
313         BN_zero(&group->order);
314
315     if (cofactor != NULL) {
316         if (!BN_copy(&group->cofactor, cofactor))
317             return 0;
318     } else
319         BN_zero(&group->cofactor);
320
321     /*
322      * Some groups have an order with
323      * factors of two, which makes the Montgomery setup fail.
324      * |group->mont_data| will be NULL in this case.
325      */
326     if (BN_is_odd(&group->order)) {
327         return ec_precompute_mont_data(group);
328     }
329
330     BN_MONT_CTX_free(group->mont_data);
331     group->mont_data = NULL;
332     return 1;
333 }
334
335 const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
336 {
337     return group->generator;
338 }
339
340 BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
341 {
342     return EC_GROUP_VERSION(group) ? group->mont_data : NULL;
343 }
344
345 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
346 {
347     if (!BN_copy(order, &group->order))
348         return 0;
349
350     return !BN_is_zero(order);
351 }
352
353 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
354                           BN_CTX *ctx)
355 {
356     if (!BN_copy(cofactor, &group->cofactor))
357         return 0;
358
359     return !BN_is_zero(&group->cofactor);
360 }
361
362 void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
363 {
364     group->curve_name = nid;
365 }
366
367 int EC_GROUP_get_curve_name(const EC_GROUP *group)
368 {
369     return group->curve_name;
370 }
371
372 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
373 {
374     group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK;
375     group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK;
376 }
377
378 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
379 {
380     return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK;
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     } else
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 /*
978  * Check whether an EC_POINT is on the curve or not. Note that the return
979  * value for this function should NOT be treated as a boolean. Return values:
980  *  1: The point is on the curve
981  *  0: The point is not on the curve
982  * -1: An error occurred
983  */
984 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
985                          BN_CTX *ctx)
986 {
987     if (group->meth->is_on_curve == 0) {
988         ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
989         return 0;
990     }
991     if (group->meth != point->meth) {
992         ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
993         return 0;
994     }
995     return group->meth->is_on_curve(group, point, ctx);
996 }
997
998 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
999                  BN_CTX *ctx)
1000 {
1001     if (group->meth->point_cmp == 0) {
1002         ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1003         return -1;
1004     }
1005     if ((group->meth != a->meth) || (a->meth != b->meth)) {
1006         ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1007         return -1;
1008     }
1009     return group->meth->point_cmp(group, a, b, ctx);
1010 }
1011
1012 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1013 {
1014     if (group->meth->make_affine == 0) {
1015         ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1016         return 0;
1017     }
1018     if (group->meth != point->meth) {
1019         ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1020         return 0;
1021     }
1022     return group->meth->make_affine(group, point, ctx);
1023 }
1024
1025 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1026                           EC_POINT *points[], BN_CTX *ctx)
1027 {
1028     size_t i;
1029
1030     if (group->meth->points_make_affine == 0) {
1031         ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1032         return 0;
1033     }
1034     for (i = 0; i < num; i++) {
1035         if (group->meth != points[i]->meth) {
1036             ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1037             return 0;
1038         }
1039     }
1040     return group->meth->points_make_affine(group, num, points, ctx);
1041 }
1042
1043 /*
1044  * Functions for point multiplication. If group->meth->mul is 0, we use the
1045  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1046  * methods.
1047  */
1048
1049 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1050                   size_t num, const EC_POINT *points[],
1051                   const BIGNUM *scalars[], BN_CTX *ctx)
1052 {
1053     if (group->meth->mul == 0)
1054         /* use default */
1055         return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1056
1057     return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1058 }
1059
1060 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1061                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1062 {
1063     /* just a convenient interface to EC_POINTs_mul() */
1064
1065     const EC_POINT *points[1];
1066     const BIGNUM *scalars[1];
1067
1068     points[0] = point;
1069     scalars[0] = p_scalar;
1070
1071     return EC_POINTs_mul(group, r, g_scalar,
1072                          (point != NULL
1073                           && p_scalar != NULL), points, scalars, ctx);
1074 }
1075
1076 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1077 {
1078     if (group->meth->mul == 0)
1079         /* use default */
1080         return ec_wNAF_precompute_mult(group, ctx);
1081
1082     if (group->meth->precompute_mult != 0)
1083         return group->meth->precompute_mult(group, ctx);
1084     else
1085         return 1;               /* nothing to do, so report success */
1086 }
1087
1088 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1089 {
1090     if (group->meth->mul == 0)
1091         /* use default */
1092         return ec_wNAF_have_precompute_mult(group);
1093
1094     if (group->meth->have_precompute_mult != 0)
1095         return group->meth->have_precompute_mult(group);
1096     else
1097         return 0;               /* cannot tell whether precomputation has
1098                                  * been performed */
1099 }
1100
1101 /*
1102  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1103  * returns one on success. On error it returns zero.
1104  */
1105 int ec_precompute_mont_data(EC_GROUP *group)
1106 {
1107     BN_CTX *ctx = BN_CTX_new();
1108     int ret = 0;
1109
1110     if (!EC_GROUP_VERSION(group))
1111         goto err;
1112
1113     if (group->mont_data) {
1114         BN_MONT_CTX_free(group->mont_data);
1115         group->mont_data = NULL;
1116     }
1117
1118     if (ctx == NULL)
1119         goto err;
1120
1121     group->mont_data = BN_MONT_CTX_new();
1122     if (!group->mont_data)
1123         goto err;
1124
1125     if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) {
1126         BN_MONT_CTX_free(group->mont_data);
1127         group->mont_data = NULL;
1128         goto err;
1129     }
1130
1131     ret = 1;
1132
1133  err:
1134
1135     if (ctx)
1136         BN_CTX_free(ctx);
1137     return ret;
1138 }