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