]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ec_lib.c
implement fast point multiplication with precomputation
[thirdparty/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 static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72
73
74 /* functions for EC_GROUP objects */
75
76 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
77 {
78 EC_GROUP *ret;
79
80 if (meth == NULL)
81 {
82 ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
83 return NULL;
84 }
85 if (meth->group_init == 0)
86 {
87 ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
88 return NULL;
89 }
90
91 ret = OPENSSL_malloc(sizeof *ret);
92 if (ret == NULL)
93 {
94 ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
95 return NULL;
96 }
97
98 ret->meth = meth;
99
100 ret->extra_data = NULL;
101 ret->extra_data_dup_func = 0;
102 ret->extra_data_free_func = 0;
103 ret->extra_data_clear_free_func = 0;
104
105 ret->generator = NULL;
106 BN_init(&ret->order);
107 BN_init(&ret->cofactor);
108
109 ret->curve_name = 0;
110 ret->asn1_flag = 0;
111 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
112
113 ret->seed = NULL;
114 ret->seed_len = 0;
115
116 if (!meth->group_init(ret))
117 {
118 OPENSSL_free(ret);
119 return NULL;
120 }
121
122 return ret;
123 }
124
125
126 void EC_GROUP_free(EC_GROUP *group)
127 {
128 if (!group) return;
129
130 if (group->meth->group_finish != 0)
131 group->meth->group_finish(group);
132
133 EC_GROUP_free_extra_data(group);
134
135 if (group->generator != NULL)
136 EC_POINT_free(group->generator);
137 BN_free(&group->order);
138 BN_free(&group->cofactor);
139
140 if (group->seed)
141 OPENSSL_free(group->seed);
142
143 OPENSSL_free(group);
144 }
145
146
147 void EC_GROUP_clear_free(EC_GROUP *group)
148 {
149 if (!group) return;
150
151 if (group->meth->group_clear_finish != 0)
152 group->meth->group_clear_finish(group);
153 else if (group->meth != NULL && group->meth->group_finish != 0)
154 group->meth->group_finish(group);
155
156 EC_GROUP_clear_free_extra_data(group);
157
158 if (group->generator != NULL)
159 EC_POINT_clear_free(group->generator);
160 BN_clear_free(&group->order);
161 BN_clear_free(&group->cofactor);
162
163 if (group->seed)
164 {
165 OPENSSL_cleanse(group->seed, group->seed_len);
166 OPENSSL_free(group->seed);
167 }
168
169 OPENSSL_cleanse(group, sizeof *group);
170 OPENSSL_free(group);
171 }
172
173
174 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
175 {
176 if (dest->meth->group_copy == 0)
177 {
178 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
179 return 0;
180 }
181 if (dest->meth != src->meth)
182 {
183 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
184 return 0;
185 }
186 if (dest == src)
187 return 1;
188
189 EC_GROUP_clear_free_extra_data(dest);
190 if (src->extra_data_dup_func)
191 {
192 if (src->extra_data != NULL)
193 {
194 dest->extra_data = src->extra_data_dup_func(src->extra_data);
195 if (dest->extra_data == NULL)
196 return 0;
197 }
198
199 dest->extra_data_dup_func = src->extra_data_dup_func;
200 dest->extra_data_free_func = src->extra_data_free_func;
201 dest->extra_data_clear_free_func = src->extra_data_clear_free_func;
202 }
203
204 if (src->generator != NULL)
205 {
206 if (dest->generator == NULL)
207 {
208 dest->generator = EC_POINT_new(dest);
209 if (dest->generator == NULL) return 0;
210 }
211 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
212 }
213 else
214 {
215 /* src->generator == NULL */
216 if (dest->generator != NULL)
217 {
218 EC_POINT_clear_free(dest->generator);
219 dest->generator = NULL;
220 }
221 }
222
223 if (!BN_copy(&dest->order, &src->order)) return 0;
224 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
225
226 dest->curve_name = src->curve_name;
227 dest->asn1_flag = src->asn1_flag;
228 dest->asn1_form = src->asn1_form;
229
230 if (src->seed)
231 {
232 if (dest->seed)
233 OPENSSL_free(dest->seed);
234 dest->seed = OPENSSL_malloc(src->seed_len);
235 if (dest->seed == NULL)
236 return 0;
237 if (!memcpy(dest->seed, src->seed, src->seed_len))
238 return 0;
239 dest->seed_len = src->seed_len;
240 }
241 else
242 {
243 if (dest->seed)
244 OPENSSL_free(dest->seed);
245 dest->seed = NULL;
246 dest->seed_len = 0;
247 }
248
249
250 return dest->meth->group_copy(dest, src);
251 }
252
253
254 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
255 {
256 EC_GROUP *t = NULL;
257 int ok = 0;
258
259 if (a == NULL) return NULL;
260
261 if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
262 if (!EC_GROUP_copy(t, a)) goto err;
263
264 ok = 1;
265
266 err:
267 if (!ok)
268 {
269 if (t) EC_GROUP_free(t);
270 return NULL;
271 }
272 else return t;
273 }
274
275
276 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
277 {
278 return group->meth;
279 }
280
281
282 int EC_METHOD_get_field_type(const EC_METHOD *meth)
283 {
284 return meth->field_type;
285 }
286
287
288 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
289 {
290 if (generator == NULL)
291 {
292 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
293 return 0 ;
294 }
295
296 if (group->generator == NULL)
297 {
298 group->generator = EC_POINT_new(group);
299 if (group->generator == NULL) return 0;
300 }
301 if (!EC_POINT_copy(group->generator, generator)) return 0;
302
303 if (order != NULL)
304 { if (!BN_copy(&group->order, order)) return 0; }
305 else
306 { if (!BN_zero(&group->order)) return 0; }
307
308 if (cofactor != NULL)
309 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
310 else
311 { if (!BN_zero(&group->cofactor)) return 0; }
312
313 return 1;
314 }
315
316
317 EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
318 {
319 return group->generator;
320 }
321
322
323 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
324 {
325 if (!BN_copy(order, &group->order))
326 return 0;
327
328 return !BN_is_zero(order);
329 }
330
331
332 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
333 {
334 if (!BN_copy(cofactor, &group->cofactor))
335 return 0;
336
337 return !BN_is_zero(&group->cofactor);
338 }
339
340
341 void EC_GROUP_set_nid(EC_GROUP *group, int nid)
342 {
343 group->curve_name = nid;
344 }
345
346
347 int EC_GROUP_get_nid(const EC_GROUP *group)
348 {
349 return group->curve_name;
350 }
351
352
353 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
354 {
355 group->asn1_flag = flag;
356 }
357
358
359 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
360 {
361 return group->asn1_flag;
362 }
363
364
365 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
366 point_conversion_form_t form)
367 {
368 group->asn1_form = form;
369 }
370
371
372 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
373 {
374 return group->asn1_form;
375 }
376
377
378 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
379 {
380 if (group->seed)
381 {
382 OPENSSL_free(group->seed);
383 group->seed = NULL;
384 group->seed_len = 0;
385 }
386
387 if (!len || !p)
388 return 1;
389
390 if ((group->seed = OPENSSL_malloc(len)) == NULL)
391 return 0;
392 memcpy(group->seed, p, len);
393 group->seed_len = len;
394
395 return len;
396 }
397
398
399 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
400 {
401 return group->seed;
402 }
403
404
405 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
406 {
407 return group->seed_len;
408 }
409
410
411 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
412 {
413 if (group->meth->group_set_curve == 0)
414 {
415 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, 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
422 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
423 {
424 if (group->meth->group_get_curve == 0)
425 {
426 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, 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
432
433 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
434 {
435 if (group->meth->group_set_curve == 0)
436 {
437 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
438 return 0;
439 }
440 return group->meth->group_set_curve(group, p, a, b, ctx);
441 }
442
443
444 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
445 {
446 if (group->meth->group_get_curve == 0)
447 {
448 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
449 return 0;
450 }
451 return group->meth->group_get_curve(group, p, a, b, ctx);
452 }
453
454
455 int EC_GROUP_get_degree(const EC_GROUP *group)
456 {
457 if (group->meth->group_get_degree == 0)
458 {
459 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
460 return 0;
461 }
462 return group->meth->group_get_degree(group);
463 }
464
465
466 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
467 {
468 if (group->meth->group_check_discriminant == 0)
469 {
470 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
471 return 0;
472 }
473 return group->meth->group_check_discriminant(group, ctx);
474 }
475
476
477 /* this has 'package' visibility */
478 int EC_GROUP_set_extra_data(EC_GROUP *group, void *extra_data, void *(*extra_data_dup_func)(void *),
479 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
480 {
481 if ((group->extra_data != NULL)
482 || (group->extra_data_dup_func != 0)
483 || (group->extra_data_free_func != 0)
484 || (group->extra_data_clear_free_func != 0))
485 {
486 ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL);
487 return 0;
488 }
489
490 group->extra_data = extra_data;
491 group->extra_data_dup_func = extra_data_dup_func;
492 group->extra_data_free_func = extra_data_free_func;
493 group->extra_data_clear_free_func = extra_data_clear_free_func;
494 return 1;
495 }
496
497
498 /* this has 'package' visibility */
499 void *EC_GROUP_get_extra_data(const EC_GROUP *group, void *(*extra_data_dup_func)(void *),
500 void (*extra_data_free_func)(void *), void (*extra_data_clear_free_func)(void *))
501 {
502 if ((group->extra_data_dup_func != extra_data_dup_func)
503 || (group->extra_data_free_func != extra_data_free_func)
504 || (group->extra_data_clear_free_func != extra_data_clear_free_func))
505 {
506 #if 0 /* this was an error in 0.9.7, but that does not make a lot of sense */
507 ECerr(EC_F_EC_GROUP_GET_EXTRA_DATA, EC_R_NO_SUCH_EXTRA_DATA);
508 #endif
509 return NULL;
510 }
511
512 return group->extra_data;
513 }
514
515
516 /* this has 'package' visibility */
517 void EC_GROUP_free_extra_data(EC_GROUP *group)
518 {
519 if (group->extra_data_free_func)
520 group->extra_data_free_func(group->extra_data);
521 group->extra_data = NULL;
522 group->extra_data_dup_func = 0;
523 group->extra_data_free_func = 0;
524 group->extra_data_clear_free_func = 0;
525 }
526
527
528 /* this has 'package' visibility */
529 void EC_GROUP_clear_free_extra_data(EC_GROUP *group)
530 {
531 if (group->extra_data_clear_free_func)
532 group->extra_data_clear_free_func(group->extra_data);
533 else if (group->extra_data_free_func)
534 group->extra_data_free_func(group->extra_data);
535 group->extra_data = NULL;
536 group->extra_data_dup_func = 0;
537 group->extra_data_free_func = 0;
538 group->extra_data_clear_free_func = 0;
539 }
540
541
542 /* functions for EC_POINT objects */
543
544 EC_POINT *EC_POINT_new(const EC_GROUP *group)
545 {
546 EC_POINT *ret;
547
548 if (group == NULL)
549 {
550 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
551 return NULL;
552 }
553 if (group->meth->point_init == 0)
554 {
555 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
556 return NULL;
557 }
558
559 ret = OPENSSL_malloc(sizeof *ret);
560 if (ret == NULL)
561 {
562 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
563 return NULL;
564 }
565
566 ret->meth = group->meth;
567
568 if (!ret->meth->point_init(ret))
569 {
570 OPENSSL_free(ret);
571 return NULL;
572 }
573
574 return ret;
575 }
576
577
578 void EC_POINT_free(EC_POINT *point)
579 {
580 if (!point) return;
581
582 if (point->meth->point_finish != 0)
583 point->meth->point_finish(point);
584 OPENSSL_free(point);
585 }
586
587
588 void EC_POINT_clear_free(EC_POINT *point)
589 {
590 if (!point) return;
591
592 if (point->meth->point_clear_finish != 0)
593 point->meth->point_clear_finish(point);
594 else if (point->meth != NULL && point->meth->point_finish != 0)
595 point->meth->point_finish(point);
596 OPENSSL_cleanse(point, sizeof *point);
597 OPENSSL_free(point);
598 }
599
600
601 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
602 {
603 if (dest->meth->point_copy == 0)
604 {
605 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
606 return 0;
607 }
608 if (dest->meth != src->meth)
609 {
610 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
611 return 0;
612 }
613 if (dest == src)
614 return 1;
615 return dest->meth->point_copy(dest, src);
616 }
617
618
619 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
620 {
621 EC_POINT *t;
622 int r;
623
624 if (a == NULL) return NULL;
625
626 t = EC_POINT_new(group);
627 if (t == NULL) return(NULL);
628 r = EC_POINT_copy(t, a);
629 if (!r)
630 {
631 EC_POINT_free(t);
632 return NULL;
633 }
634 else return t;
635 }
636
637
638 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
639 {
640 return point->meth;
641 }
642
643
644 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
645 {
646 if (group->meth->point_set_to_infinity == 0)
647 {
648 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
649 return 0;
650 }
651 if (group->meth != point->meth)
652 {
653 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
654 return 0;
655 }
656 return group->meth->point_set_to_infinity(group, point);
657 }
658
659
660 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
661 const BIGNUM *x, const BIGNUM *y, const BIGNUM *z, BN_CTX *ctx)
662 {
663 if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
664 {
665 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
666 return 0;
667 }
668 if (group->meth != point->meth)
669 {
670 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
671 return 0;
672 }
673 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
674 }
675
676
677 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
678 BIGNUM *x, BIGNUM *y, BIGNUM *z, BN_CTX *ctx)
679 {
680 if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
681 {
682 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
683 return 0;
684 }
685 if (group->meth != point->meth)
686 {
687 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
688 return 0;
689 }
690 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
691 }
692
693
694 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
695 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
696 {
697 if (group->meth->point_set_affine_coordinates == 0)
698 {
699 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
700 return 0;
701 }
702 if (group->meth != point->meth)
703 {
704 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
705 return 0;
706 }
707 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
708 }
709
710
711 int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
712 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
713 {
714 if (group->meth->point_set_affine_coordinates == 0)
715 {
716 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
717 return 0;
718 }
719 if (group->meth != point->meth)
720 {
721 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
722 return 0;
723 }
724 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
725 }
726
727
728 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
729 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
730 {
731 if (group->meth->point_get_affine_coordinates == 0)
732 {
733 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
734 return 0;
735 }
736 if (group->meth != point->meth)
737 {
738 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
739 return 0;
740 }
741 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
742 }
743
744
745 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
746 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
747 {
748 if (group->meth->point_get_affine_coordinates == 0)
749 {
750 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
751 return 0;
752 }
753 if (group->meth != point->meth)
754 {
755 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
756 return 0;
757 }
758 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
759 }
760
761
762 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
763 const BIGNUM *x, int y_bit, BN_CTX *ctx)
764 {
765 if (group->meth->point_set_compressed_coordinates == 0)
766 {
767 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
768 return 0;
769 }
770 if (group->meth != point->meth)
771 {
772 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
773 return 0;
774 }
775 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
776 }
777
778
779 int EC_POINT_set_compressed_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
780 const BIGNUM *x, int y_bit, BN_CTX *ctx)
781 {
782 if (group->meth->point_set_compressed_coordinates == 0)
783 {
784 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
785 return 0;
786 }
787 if (group->meth != point->meth)
788 {
789 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
790 return 0;
791 }
792 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
793 }
794
795
796 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
797 unsigned char *buf, size_t len, BN_CTX *ctx)
798 {
799 if (group->meth->point2oct == 0)
800 {
801 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
802 return 0;
803 }
804 if (group->meth != point->meth)
805 {
806 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
807 return 0;
808 }
809 return group->meth->point2oct(group, point, form, buf, len, ctx);
810 }
811
812
813 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
814 const unsigned char *buf, size_t len, BN_CTX *ctx)
815 {
816 if (group->meth->oct2point == 0)
817 {
818 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
819 return 0;
820 }
821 if (group->meth != point->meth)
822 {
823 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
824 return 0;
825 }
826 return group->meth->oct2point(group, point, buf, len, ctx);
827 }
828
829
830 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
831 {
832 if (group->meth->add == 0)
833 {
834 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
835 return 0;
836 }
837 if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
838 {
839 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
840 return 0;
841 }
842 return group->meth->add(group, r, a, b, ctx);
843 }
844
845
846 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
847 {
848 if (group->meth->dbl == 0)
849 {
850 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
851 return 0;
852 }
853 if ((group->meth != r->meth) || (r->meth != a->meth))
854 {
855 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
856 return 0;
857 }
858 return group->meth->dbl(group, r, a, ctx);
859 }
860
861
862 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
863 {
864 if (group->meth->dbl == 0)
865 {
866 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
867 return 0;
868 }
869 if (group->meth != a->meth)
870 {
871 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
872 return 0;
873 }
874 return group->meth->invert(group, a, ctx);
875 }
876
877
878 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
879 {
880 if (group->meth->is_at_infinity == 0)
881 {
882 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
883 return 0;
884 }
885 if (group->meth != point->meth)
886 {
887 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
888 return 0;
889 }
890 return group->meth->is_at_infinity(group, point);
891 }
892
893
894 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
895 {
896 if (group->meth->is_on_curve == 0)
897 {
898 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
899 return 0;
900 }
901 if (group->meth != point->meth)
902 {
903 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
904 return 0;
905 }
906 return group->meth->is_on_curve(group, point, ctx);
907 }
908
909
910 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
911 {
912 if (group->meth->point_cmp == 0)
913 {
914 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
915 return 0;
916 }
917 if ((group->meth != a->meth) || (a->meth != b->meth))
918 {
919 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
920 return 0;
921 }
922 return group->meth->point_cmp(group, a, b, ctx);
923 }
924
925
926 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
927 {
928 if (group->meth->make_affine == 0)
929 {
930 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
931 return 0;
932 }
933 if (group->meth != point->meth)
934 {
935 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
936 return 0;
937 }
938 return group->meth->make_affine(group, point, ctx);
939 }
940
941
942 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
943 {
944 size_t i;
945
946 if (group->meth->points_make_affine == 0)
947 {
948 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
949 return 0;
950 }
951 for (i = 0; i < num; i++)
952 {
953 if (group->meth != points[i]->meth)
954 {
955 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
956 return 0;
957 }
958 }
959 return group->meth->points_make_affine(group, num, points, ctx);
960 }
961
962
963 /* Functions for point multiplication.
964 *
965 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
966 * otherwise we dispatch through methods.
967 */
968
969 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
970 size_t num, const EC_POINT *points[], const BIGNUM *scalars[], BN_CTX *ctx)
971 {
972 if (group->meth->mul == 0)
973 /* use default */
974 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
975
976 return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
977 }
978
979 int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
980 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
981 {
982 /* just a convenient interface to EC_POINTs_mul() */
983
984 const EC_POINT *points[1];
985 const BIGNUM *scalars[1];
986
987 points[0] = point;
988 scalars[0] = p_scalar;
989
990 return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
991 }
992
993 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
994 {
995 if (group->meth->mul == 0)
996 /* use default */
997 return ec_wNAF_precompute_mult(group, ctx);
998
999 if (group->meth->precompute_mult != 0)
1000 return group->meth->precompute_mult(group, ctx);
1001 else
1002 return 1; /* nothing to do, so report success */
1003 }
1004
1005 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1006 {
1007 if (group->meth->mul == 0)
1008 /* use default */
1009 return ec_wNAF_have_precompute_mult(group);
1010
1011 if (group->meth->have_precompute_mult != 0)
1012 return group->meth->have_precompute_mult(group);
1013 else
1014 return 0; /* cannot tell whether precomputation has been performed */
1015 }