1 /* crypto/ec/ec_lib.c */
3 * Originally written by Bodo Moeller for the OpenSSL project.
5 /* ====================================================================
6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
34 * 6. Redistributions of any form whatsoever must retain the following
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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 * ====================================================================
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).
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.
66 #include <openssl/err.h>
67 #include <openssl/opensslv.h>
71 static const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
74 /* functions for EC_GROUP objects */
76 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
82 ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
85 if (meth->group_init == 0)
87 ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
91 ret = OPENSSL_malloc(sizeof *ret);
94 ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
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;
105 ret->generator = NULL;
106 BN_init(&ret->order);
107 BN_init(&ret->cofactor);
111 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
116 if (!meth->group_init(ret))
126 void EC_GROUP_free(EC_GROUP *group)
130 if (group->meth->group_finish != 0)
131 group->meth->group_finish(group);
133 EC_GROUP_free_extra_data(group);
135 if (group->generator != NULL)
136 EC_POINT_free(group->generator);
137 BN_free(&group->order);
138 BN_free(&group->cofactor);
141 OPENSSL_free(group->seed);
147 void EC_GROUP_clear_free(EC_GROUP *group)
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);
156 EC_GROUP_clear_free_extra_data(group);
158 if (group->generator != NULL)
159 EC_POINT_clear_free(group->generator);
160 BN_clear_free(&group->order);
161 BN_clear_free(&group->cofactor);
165 OPENSSL_cleanse(group->seed, group->seed_len);
166 OPENSSL_free(group->seed);
169 OPENSSL_cleanse(group, sizeof *group);
174 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
176 if (dest->meth->group_copy == 0)
178 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
181 if (dest->meth != src->meth)
183 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
189 EC_GROUP_clear_free_extra_data(dest);
190 if (src->extra_data_dup_func)
192 if (src->extra_data != NULL)
194 dest->extra_data = src->extra_data_dup_func(src->extra_data);
195 if (dest->extra_data == NULL)
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;
204 if (src->generator != NULL)
206 if (dest->generator == NULL)
208 dest->generator = EC_POINT_new(dest);
209 if (dest->generator == NULL) return 0;
211 if (!EC_POINT_copy(dest->generator, src->generator)) return 0;
215 /* src->generator == NULL */
216 if (dest->generator != NULL)
218 EC_POINT_clear_free(dest->generator);
219 dest->generator = NULL;
223 if (!BN_copy(&dest->order, &src->order)) return 0;
224 if (!BN_copy(&dest->cofactor, &src->cofactor)) return 0;
226 dest->curve_name = src->curve_name;
227 dest->asn1_flag = src->asn1_flag;
228 dest->asn1_form = src->asn1_form;
233 OPENSSL_free(dest->seed);
234 dest->seed = OPENSSL_malloc(src->seed_len);
235 if (dest->seed == NULL)
237 if (!memcpy(dest->seed, src->seed, src->seed_len))
239 dest->seed_len = src->seed_len;
244 OPENSSL_free(dest->seed);
250 return dest->meth->group_copy(dest, src);
254 EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
259 if (a == NULL) return NULL;
261 if ((t = EC_GROUP_new(a->meth)) == NULL) return(NULL);
262 if (!EC_GROUP_copy(t, a)) goto err;
269 if (t) EC_GROUP_free(t);
276 const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
282 int EC_METHOD_get_field_type(const EC_METHOD *meth)
284 return meth->field_type;
288 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
290 if (generator == NULL)
292 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
296 if (group->generator == NULL)
298 group->generator = EC_POINT_new(group);
299 if (group->generator == NULL) return 0;
301 if (!EC_POINT_copy(group->generator, generator)) return 0;
304 { if (!BN_copy(&group->order, order)) return 0; }
306 { if (!BN_zero(&group->order)) return 0; }
308 if (cofactor != NULL)
309 { if (!BN_copy(&group->cofactor, cofactor)) return 0; }
311 { if (!BN_zero(&group->cofactor)) return 0; }
317 EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
319 return group->generator;
323 int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
325 if (!BN_copy(order, &group->order))
328 return !BN_is_zero(order);
332 int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
334 if (!BN_copy(cofactor, &group->cofactor))
337 return !BN_is_zero(&group->cofactor);
341 void EC_GROUP_set_nid(EC_GROUP *group, int nid)
343 group->curve_name = nid;
347 int EC_GROUP_get_nid(const EC_GROUP *group)
349 return group->curve_name;
353 void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
355 group->asn1_flag = flag;
359 int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
361 return group->asn1_flag;
365 void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
366 point_conversion_form_t form)
368 group->asn1_form = form;
372 point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
374 return group->asn1_form;
378 size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
382 OPENSSL_free(group->seed);
390 if ((group->seed = OPENSSL_malloc(len)) == NULL)
392 memcpy(group->seed, p, len);
393 group->seed_len = len;
399 unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
405 size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
407 return group->seed_len;
411 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
413 if (group->meth->group_set_curve == 0)
415 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
418 return group->meth->group_set_curve(group, p, a, b, ctx);
422 int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
424 if (group->meth->group_get_curve == 0)
426 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
429 return group->meth->group_get_curve(group, p, a, b, ctx);
433 int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
435 if (group->meth->group_set_curve == 0)
437 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
440 return group->meth->group_set_curve(group, p, a, b, ctx);
444 int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
446 if (group->meth->group_get_curve == 0)
448 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
451 return group->meth->group_get_curve(group, p, a, b, ctx);
455 int EC_GROUP_get_degree(const EC_GROUP *group)
457 if (group->meth->group_get_degree == 0)
459 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
462 return group->meth->group_get_degree(group);
466 int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
468 if (group->meth->group_check_discriminant == 0)
470 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
473 return group->meth->group_check_discriminant(group, ctx);
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 *))
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))
486 ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA, EC_R_SLOT_FULL);
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;
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 *))
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))
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);
512 return group->extra_data;
516 /* this has 'package' visibility */
517 void EC_GROUP_free_extra_data(EC_GROUP *group)
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;
528 /* this has 'package' visibility */
529 void EC_GROUP_clear_free_extra_data(EC_GROUP *group)
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;
542 /* functions for EC_POINT objects */
544 EC_POINT *EC_POINT_new(const EC_GROUP *group)
550 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
553 if (group->meth->point_init == 0)
555 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
559 ret = OPENSSL_malloc(sizeof *ret);
562 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
566 ret->meth = group->meth;
568 if (!ret->meth->point_init(ret))
578 void EC_POINT_free(EC_POINT *point)
582 if (point->meth->point_finish != 0)
583 point->meth->point_finish(point);
588 void EC_POINT_clear_free(EC_POINT *point)
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);
601 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
603 if (dest->meth->point_copy == 0)
605 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
608 if (dest->meth != src->meth)
610 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
615 return dest->meth->point_copy(dest, src);
619 EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
624 if (a == NULL) return NULL;
626 t = EC_POINT_new(group);
627 if (t == NULL) return(NULL);
628 r = EC_POINT_copy(t, a);
638 const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
644 int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
646 if (group->meth->point_set_to_infinity == 0)
648 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
651 if (group->meth != point->meth)
653 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
656 return group->meth->point_set_to_infinity(group, point);
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)
663 if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
665 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
668 if (group->meth != point->meth)
670 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
673 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
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)
680 if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
682 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
685 if (group->meth != point->meth)
687 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
690 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
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)
697 if (group->meth->point_set_affine_coordinates == 0)
699 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
702 if (group->meth != point->meth)
704 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
707 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
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)
714 if (group->meth->point_set_affine_coordinates == 0)
716 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
719 if (group->meth != point->meth)
721 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
724 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
728 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
729 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
731 if (group->meth->point_get_affine_coordinates == 0)
733 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
736 if (group->meth != point->meth)
738 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
741 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
745 int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
746 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
748 if (group->meth->point_get_affine_coordinates == 0)
750 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
753 if (group->meth != point->meth)
755 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
758 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
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)
765 if (group->meth->point_set_compressed_coordinates == 0)
767 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
770 if (group->meth != point->meth)
772 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
775 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
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)
782 if (group->meth->point_set_compressed_coordinates == 0)
784 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
787 if (group->meth != point->meth)
789 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
792 return group->meth->point_set_compressed_coordinates(group, point, x, y_bit, ctx);
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)
799 if (group->meth->point2oct == 0)
801 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
804 if (group->meth != point->meth)
806 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
809 return group->meth->point2oct(group, point, form, buf, len, ctx);
813 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
814 const unsigned char *buf, size_t len, BN_CTX *ctx)
816 if (group->meth->oct2point == 0)
818 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
821 if (group->meth != point->meth)
823 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
826 return group->meth->oct2point(group, point, buf, len, ctx);
830 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
832 if (group->meth->add == 0)
834 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
837 if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
839 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
842 return group->meth->add(group, r, a, b, ctx);
846 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
848 if (group->meth->dbl == 0)
850 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
853 if ((group->meth != r->meth) || (r->meth != a->meth))
855 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
858 return group->meth->dbl(group, r, a, ctx);
862 int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
864 if (group->meth->dbl == 0)
866 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
869 if (group->meth != a->meth)
871 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
874 return group->meth->invert(group, a, ctx);
878 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
880 if (group->meth->is_at_infinity == 0)
882 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
885 if (group->meth != point->meth)
887 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
890 return group->meth->is_at_infinity(group, point);
894 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
896 if (group->meth->is_on_curve == 0)
898 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
901 if (group->meth != point->meth)
903 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
906 return group->meth->is_on_curve(group, point, ctx);
910 int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
912 if (group->meth->point_cmp == 0)
914 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
917 if ((group->meth != a->meth) || (a->meth != b->meth))
919 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
922 return group->meth->point_cmp(group, a, b, ctx);
926 int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
928 if (group->meth->make_affine == 0)
930 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
933 if (group->meth != point->meth)
935 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
938 return group->meth->make_affine(group, point, ctx);
942 int EC_POINTs_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[], BN_CTX *ctx)
946 if (group->meth->points_make_affine == 0)
948 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
951 for (i = 0; i < num; i++)
953 if (group->meth != points[i]->meth)
955 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
959 return group->meth->points_make_affine(group, num, points, ctx);
963 /* Functions for point multiplication.
965 * If group->meth->mul is 0, we use the wNAF-based implementations in ec_mult.c;
966 * otherwise we dispatch through methods.
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)
972 if (group->meth->mul == 0)
974 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
976 return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
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)
982 /* just a convenient interface to EC_POINTs_mul() */
984 const EC_POINT *points[1];
985 const BIGNUM *scalars[1];
988 scalars[0] = p_scalar;
990 return EC_POINTs_mul(group, r, g_scalar, (point != NULL && p_scalar != NULL), points, scalars, ctx);
993 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
995 if (group->meth->mul == 0)
997 return ec_wNAF_precompute_mult(group, ctx);
999 if (group->meth->precompute_mult != 0)
1000 return group->meth->precompute_mult(group, ctx);
1002 return 1; /* nothing to do, so report success */
1005 int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1007 if (group->meth->mul == 0)
1009 return ec_wNAF_have_precompute_mult(group);
1011 if (group->meth->have_precompute_mult != 0)
1012 return group->meth->have_precompute_mult(group);
1014 return 0; /* cannot tell whether precomputation has been performed */