1 /* crypto/ec/ec_lib.c */
2 /* ====================================================================
3 * Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
17 * 3. All advertising materials mentioning features or use of this
18 * software must display the following acknowledgment:
19 * "This product includes software developed by the OpenSSL Project
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 * endorse or promote products derived from this software without
24 * prior written permission. For written permission, please contact
25 * openssl-core@openssl.org.
27 * 5. Products derived from this software may not be called "OpenSSL"
28 * nor may "OpenSSL" appear in their names without prior written
29 * permission of the OpenSSL Project.
31 * 6. Redistributions of any form whatsoever must retain the following
33 * "This product includes software developed by the OpenSSL Project
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 * OF THE POSSIBILITY OF SUCH DAMAGE.
48 * ====================================================================
50 * This product includes cryptographic software written by Eric Young
51 * (eay@cryptsoft.com). This product includes software written by Tim
52 * Hudson (tjh@cryptsoft.com).
58 #include <openssl/err.h>
59 #include <openssl/opensslv.h>
63 static const char EC_version
[] = "EC" OPENSSL_VERSION_PTEXT
;
66 /* functions for EC_GROUP objects */
68 EC_GROUP
*EC_GROUP_new(const EC_METHOD
*meth
)
74 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_PASSED_NULL_PARAMETER
);
77 if (meth
->group_init
== 0)
79 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
83 ret
= OPENSSL_malloc(sizeof *ret
);
86 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_MALLOC_FAILURE
);
92 ret
->extra_data
= NULL
;
93 ret
->extra_data_dup_func
= 0;
94 ret
->extra_data_free_func
= 0;
95 ret
->extra_data_clear_free_func
= 0;
99 if (!meth
->group_init(ret
))
109 void EC_GROUP_free(EC_GROUP
*group
)
111 if (group
->meth
->group_finish
!= 0)
112 group
->meth
->group_finish(group
);
114 EC_GROUP_free_extra_data(group
);
120 void EC_GROUP_clear_free(EC_GROUP
*group
)
122 if (group
->meth
->group_clear_finish
!= 0)
123 group
->meth
->group_clear_finish(group
);
124 else if (group
->meth
!= NULL
&& group
->meth
->group_finish
!= 0)
125 group
->meth
->group_finish(group
);
127 EC_GROUP_clear_free_extra_data(group
);
129 memset(group
, 0, sizeof *group
);
134 int EC_GROUP_copy(EC_GROUP
*dest
, const EC_GROUP
*src
)
136 if (dest
->meth
->group_copy
== 0)
138 ECerr(EC_F_EC_GROUP_COPY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
141 if (dest
->meth
!= src
->meth
)
143 ECerr(EC_F_EC_GROUP_COPY
, EC_R_INCOMPATIBLE_OBJECTS
);
149 EC_GROUP_clear_free_extra_data(dest
);
150 if (src
->extra_data_dup_func
)
152 if (src
->extra_data
!= NULL
)
154 dest
->extra_data
= src
->extra_data_dup_func(src
->extra_data
);
155 if (dest
->extra_data
== NULL
)
159 dest
->extra_data_dup_func
= src
->extra_data_dup_func
;
160 dest
->extra_data_free_func
= src
->extra_data_free_func
;
161 dest
->extra_data_clear_free_func
= src
->extra_data_clear_free_func
;
164 return dest
->meth
->group_copy(dest
, src
);
168 const EC_METHOD
*EC_GROUP_method_of(const EC_GROUP
*group
)
174 int EC_GROUP_set_curve_GFp(EC_GROUP
*group
, const BIGNUM
*p
, const BIGNUM
*a
, const BIGNUM
*b
, BN_CTX
*ctx
)
176 if (group
->meth
->group_set_curve_GFp
== 0)
178 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
181 return group
->meth
->group_set_curve_GFp(group
, p
, a
, b
, ctx
);
185 int EC_GROUP_get_curve_GFp(const EC_GROUP
*group
, BIGNUM
*p
, BIGNUM
*a
, BIGNUM
*b
, BN_CTX
*ctx
)
187 if (group
->meth
->group_get_curve_GFp
== 0)
189 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
192 return group
->meth
->group_get_curve_GFp(group
, p
, a
, b
, ctx
);
196 int EC_GROUP_set_generator(EC_GROUP
*group
, const EC_POINT
*generator
, const BIGNUM
*order
, const BIGNUM
*cofactor
)
198 if (group
->meth
->group_set_generator
== 0)
200 ECerr(EC_F_EC_GROUP_SET_GENERATOR
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
203 return group
->meth
->group_set_generator(group
, generator
, order
, cofactor
);
207 EC_POINT
*EC_GROUP_get0_generator(const EC_GROUP
*group
)
209 if (group
->meth
->group_get0_generator
== 0)
211 ECerr(EC_F_EC_GROUP_GET0_GENERATOR
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
214 return group
->meth
->group_get0_generator(group
);
218 int EC_GROUP_get_order(const EC_GROUP
*group
, BIGNUM
*order
, BN_CTX
*ctx
)
220 if (group
->meth
->group_get_order
== 0)
222 ECerr(EC_F_EC_GROUP_GET_ORDER
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
225 return group
->meth
->group_get_order(group
, order
, ctx
);
229 int EC_GROUP_get_cofactor(const EC_GROUP
*group
, BIGNUM
*cofactor
, BN_CTX
*ctx
)
231 if (group
->meth
->group_get_cofactor
== 0)
233 ECerr(EC_F_EC_GROUP_GET_COFACTOR
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
236 return group
->meth
->group_get_cofactor(group
, cofactor
, ctx
);
240 /* this has 'package' visibility */
241 int EC_GROUP_set_extra_data(EC_GROUP
*group
, void *extra_data
, void *(*extra_data_dup_func
)(void *),
242 void (*extra_data_free_func
)(void *), void (*extra_data_clear_free_func
)(void *))
244 if ((group
->extra_data
!= NULL
)
245 || (group
->extra_data_dup_func
!= 0)
246 || (group
->extra_data_free_func
!= 0)
247 || (group
->extra_data_clear_free_func
!= 0))
249 ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA
, EC_R_SLOT_FULL
);
253 group
->extra_data
= extra_data
;
254 group
->extra_data_dup_func
= extra_data_dup_func
;
255 group
->extra_data_free_func
= extra_data_free_func
;
256 group
->extra_data_clear_free_func
= extra_data_clear_free_func
;
261 /* this has 'package' visibility */
262 void *EC_GROUP_get_extra_data(const EC_GROUP
*group
, void *(*extra_data_dup_func
)(void *),
263 void (*extra_data_free_func
)(void *), void (*extra_data_clear_free_func
)(void *))
265 if ((group
->extra_data_dup_func
!= extra_data_dup_func
)
266 || (group
->extra_data_free_func
!= extra_data_free_func
)
267 || (group
->extra_data_clear_free_func
!= extra_data_clear_free_func
))
269 ECerr(EC_F_EC_GROUP_GET_EXTRA_DATA
, EC_R_NO_SUCH_EXTRA_DATA
);
273 return group
->extra_data
;
277 /* this has 'package' visibility */
278 void EC_GROUP_free_extra_data(EC_GROUP
*group
)
280 if (group
->extra_data_free_func
)
281 group
->extra_data_free_func(group
->extra_data
);
282 group
->extra_data
= NULL
;
283 group
->extra_data_dup_func
= 0;
284 group
->extra_data_free_func
= 0;
285 group
->extra_data_clear_free_func
= 0;
289 /* this has 'package' visibility */
290 void EC_GROUP_clear_free_extra_data(EC_GROUP
*group
)
292 if (group
->extra_data_clear_free_func
)
293 group
->extra_data_clear_free_func(group
->extra_data
);
294 else if (group
->extra_data_free_func
)
295 group
->extra_data_free_func(group
->extra_data
);
296 group
->extra_data
= NULL
;
297 group
->extra_data_dup_func
= 0;
298 group
->extra_data_free_func
= 0;
299 group
->extra_data_clear_free_func
= 0;
302 void EC_GROUP_set_nid(EC_GROUP
*group
, int nid
)
307 int EC_GROUP_get_nid(const EC_GROUP
*group
)
314 /* functions for EC_POINT objects */
316 EC_POINT
*EC_POINT_new(const EC_GROUP
*group
)
322 ECerr(EC_F_EC_POINT_NEW
, ERR_R_PASSED_NULL_PARAMETER
);
325 if (group
->meth
->point_init
== 0)
327 ECerr(EC_F_EC_POINT_NEW
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
331 ret
= OPENSSL_malloc(sizeof *ret
);
334 ECerr(EC_F_EC_POINT_NEW
, ERR_R_MALLOC_FAILURE
);
338 ret
->meth
= group
->meth
;
340 if (!ret
->meth
->point_init(ret
))
350 void EC_POINT_free(EC_POINT
*point
)
352 if (point
->meth
->point_finish
!= 0)
353 point
->meth
->point_finish(point
);
358 void EC_POINT_clear_free(EC_POINT
*point
)
360 if (point
->meth
->point_clear_finish
!= 0)
361 point
->meth
->point_clear_finish(point
);
362 else if (point
->meth
!= NULL
&& point
->meth
->point_finish
!= 0)
363 point
->meth
->point_finish(point
);
364 memset(point
, 0, sizeof *point
);
369 int EC_POINT_copy(EC_POINT
*dest
, const EC_POINT
*src
)
371 if (dest
->meth
->point_copy
== 0)
373 ECerr(EC_F_EC_POINT_COPY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
376 if (dest
->meth
!= src
->meth
)
378 ECerr(EC_F_EC_POINT_COPY
, EC_R_INCOMPATIBLE_OBJECTS
);
383 return dest
->meth
->point_copy(dest
, src
);
387 const EC_METHOD
*EC_POINT_method_of(const EC_POINT
*point
)
393 int EC_POINT_set_to_infinity(const EC_GROUP
*group
, EC_POINT
*point
)
395 if (group
->meth
->point_set_to_infinity
== 0)
397 ECerr(EC_F_EC_POINT_SET_TO_INFINITY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
400 if (group
->meth
!= point
->meth
)
402 ECerr(EC_F_EC_POINT_SET_TO_INFINITY
, EC_R_INCOMPATIBLE_OBJECTS
);
405 return group
->meth
->point_set_to_infinity(group
, point
);
409 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
410 const BIGNUM
*x
, const BIGNUM
*y
, const BIGNUM
*z
, BN_CTX
*ctx
)
412 if (group
->meth
->point_set_Jprojective_coordinates_GFp
== 0)
414 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
417 if (group
->meth
!= point
->meth
)
419 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
422 return group
->meth
->point_set_Jprojective_coordinates_GFp(group
, point
, x
, y
, z
, ctx
);
426 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP
*group
, const EC_POINT
*point
,
427 BIGNUM
*x
, BIGNUM
*y
, BIGNUM
*z
, BN_CTX
*ctx
)
429 if (group
->meth
->point_get_Jprojective_coordinates_GFp
== 0)
431 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
434 if (group
->meth
!= point
->meth
)
436 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
439 return group
->meth
->point_get_Jprojective_coordinates_GFp(group
, point
, x
, y
, z
, ctx
);
443 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
444 const BIGNUM
*x
, const BIGNUM
*y
, BN_CTX
*ctx
)
446 if (group
->meth
->point_set_affine_coordinates_GFp
== 0)
448 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
451 if (group
->meth
!= point
->meth
)
453 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
456 return group
->meth
->point_set_affine_coordinates_GFp(group
, point
, x
, y
, ctx
);
460 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP
*group
, const EC_POINT
*point
,
461 BIGNUM
*x
, BIGNUM
*y
, BN_CTX
*ctx
)
463 if (group
->meth
->point_get_affine_coordinates_GFp
== 0)
465 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
468 if (group
->meth
!= point
->meth
)
470 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
473 return group
->meth
->point_get_affine_coordinates_GFp(group
, point
, x
, y
, ctx
);
477 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
478 const BIGNUM
*x
, int y_bit
, BN_CTX
*ctx
)
480 if (group
->meth
->point_set_compressed_coordinates_GFp
== 0)
482 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
485 if (group
->meth
!= point
->meth
)
487 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
490 return group
->meth
->point_set_compressed_coordinates_GFp(group
, point
, x
, y_bit
, ctx
);
494 size_t EC_POINT_point2oct(const EC_GROUP
*group
, const EC_POINT
*point
, point_conversion_form_t form
,
495 unsigned char *buf
, size_t len
, BN_CTX
*ctx
)
497 if (group
->meth
->point2oct
== 0)
499 ECerr(EC_F_EC_POINT_POINT2OCT
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
502 if (group
->meth
!= point
->meth
)
504 ECerr(EC_F_EC_POINT_POINT2OCT
, EC_R_INCOMPATIBLE_OBJECTS
);
507 return group
->meth
->point2oct(group
, point
, form
, buf
, len
, ctx
);
511 int EC_POINT_oct2point(const EC_GROUP
*group
, EC_POINT
*point
,
512 const unsigned char *buf
, size_t len
, BN_CTX
*ctx
)
514 if (group
->meth
->oct2point
== 0)
516 ECerr(EC_F_EC_POINT_OCT2POINT
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
519 if (group
->meth
!= point
->meth
)
521 ECerr(EC_F_EC_POINT_OCT2POINT
, EC_R_INCOMPATIBLE_OBJECTS
);
524 return group
->meth
->oct2point(group
, point
, buf
, len
, ctx
);
528 int EC_POINT_add(const EC_GROUP
*group
, EC_POINT
*r
, const EC_POINT
*a
, const EC_POINT
*b
, BN_CTX
*ctx
)
530 if (group
->meth
->add
== 0)
532 ECerr(EC_F_EC_POINT_ADD
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
535 if ((group
->meth
!= r
->meth
) || (r
->meth
!= a
->meth
) || (a
->meth
!= b
->meth
))
537 ECerr(EC_F_EC_POINT_ADD
, EC_R_INCOMPATIBLE_OBJECTS
);
540 return group
->meth
->add(group
, r
, a
, b
, ctx
);
544 int EC_POINT_dbl(const EC_GROUP
*group
, EC_POINT
*r
, const EC_POINT
*a
, BN_CTX
*ctx
)
546 if (group
->meth
->dbl
== 0)
548 ECerr(EC_F_EC_POINT_DBL
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
551 if ((group
->meth
!= r
->meth
) || (r
->meth
!= a
->meth
))
553 ECerr(EC_F_EC_POINT_DBL
, EC_R_INCOMPATIBLE_OBJECTS
);
556 return group
->meth
->dbl(group
, r
, a
, ctx
);
560 int EC_POINT_invert(const EC_GROUP
*group
, EC_POINT
*a
, BN_CTX
*ctx
)
562 if (group
->meth
->dbl
== 0)
564 ECerr(EC_F_EC_POINT_DBL
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
567 if (group
->meth
!= a
->meth
)
569 ECerr(EC_F_EC_POINT_DBL
, EC_R_INCOMPATIBLE_OBJECTS
);
572 return group
->meth
->invert(group
, a
, ctx
);
576 int EC_POINT_is_at_infinity(const EC_GROUP
*group
, const EC_POINT
*point
)
578 if (group
->meth
->is_at_infinity
== 0)
580 ECerr(EC_F_EC_POINT_IS_AT_INFINITY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
583 if (group
->meth
!= point
->meth
)
585 ECerr(EC_F_EC_POINT_IS_AT_INFINITY
, EC_R_INCOMPATIBLE_OBJECTS
);
588 return group
->meth
->is_at_infinity(group
, point
);
592 int EC_POINT_is_on_curve(const EC_GROUP
*group
, const EC_POINT
*point
, BN_CTX
*ctx
)
594 if (group
->meth
->is_on_curve
== 0)
596 ECerr(EC_F_EC_POINT_IS_ON_CURVE
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
599 if (group
->meth
!= point
->meth
)
601 ECerr(EC_F_EC_POINT_IS_ON_CURVE
, EC_R_INCOMPATIBLE_OBJECTS
);
604 return group
->meth
->is_on_curve(group
, point
, ctx
);
608 int EC_POINT_cmp(const EC_GROUP
*group
, const EC_POINT
*a
, const EC_POINT
*b
, BN_CTX
*ctx
)
610 if (group
->meth
->point_cmp
== 0)
612 ECerr(EC_F_EC_POINT_CMP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
615 if ((group
->meth
!= a
->meth
) || (a
->meth
!= b
->meth
))
617 ECerr(EC_F_EC_POINT_CMP
, EC_R_INCOMPATIBLE_OBJECTS
);
620 return group
->meth
->point_cmp(group
, a
, b
, ctx
);
624 int EC_POINT_make_affine(const EC_GROUP
*group
, EC_POINT
*point
, BN_CTX
*ctx
)
626 if (group
->meth
->make_affine
== 0)
628 ECerr(EC_F_EC_POINT_MAKE_AFFINE
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
631 if (group
->meth
!= point
->meth
)
633 ECerr(EC_F_EC_POINT_MAKE_AFFINE
, EC_R_INCOMPATIBLE_OBJECTS
);
636 return group
->meth
->make_affine(group
, point
, ctx
);
640 int EC_POINTs_make_affine(const EC_GROUP
*group
, size_t num
, EC_POINT
*points
[], BN_CTX
*ctx
)
644 if (group
->meth
->points_make_affine
== 0)
646 ECerr(EC_F_EC_POINTS_MAKE_AFFINE
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
649 for (i
= 0; i
< num
; i
++)
651 if (group
->meth
!= points
[i
]->meth
)
653 ECerr(EC_F_EC_POINTS_MAKE_AFFINE
, EC_R_INCOMPATIBLE_OBJECTS
);
657 return group
->meth
->points_make_affine(group
, num
, points
, ctx
);