1 /* crypto/ec/ec_lib.c */
2 /* ====================================================================
3 * Copyright (c) 1998-2001 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>
63 /* functions for EC_GROUP objects */
65 EC_GROUP
*EC_GROUP_new(const EC_METHOD
*meth
)
71 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_PASSED_NULL_PARAMETER
);
74 if (meth
->group_init
== 0)
76 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
80 ret
= OPENSSL_malloc(sizeof *ret
);
83 ECerr(EC_F_EC_GROUP_NEW
, ERR_R_MALLOC_FAILURE
);
89 ret
->extra_data
= NULL
;
90 ret
->extra_data_dup_func
= 0;
91 ret
->extra_data_free_func
= 0;
92 ret
->extra_data_clear_free_func
= 0;
94 if (!meth
->group_init(ret
))
104 int EC_GROUP_set_curve_GFp(EC_GROUP
*group
, const BIGNUM
*p
, const BIGNUM
*a
, const BIGNUM
*b
, BN_CTX
*ctx
)
106 if (group
->meth
->group_set_curve_GFp
== 0)
108 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
111 return group
->meth
->group_set_curve_GFp(group
, p
, a
, b
, ctx
);
115 void EC_GROUP_free(EC_GROUP
*group
)
117 if (group
->meth
->group_finish
!= 0)
118 group
->meth
->group_finish(group
);
120 EC_GROUP_free_extra_data(group
);
126 void EC_GROUP_clear_free(EC_GROUP
*group
)
128 if (group
->meth
->group_clear_finish
!= 0)
129 group
->meth
->group_clear_finish(group
);
130 else if (group
->meth
!= NULL
&& group
->meth
->group_finish
!= 0)
131 group
->meth
->group_finish(group
);
133 EC_GROUP_clear_free_extra_data(group
);
135 memset(group
, 0, sizeof *group
);
140 int EC_GROUP_copy(EC_GROUP
*dest
, const EC_GROUP
*src
)
142 if (dest
->meth
->group_copy
== 0)
144 ECerr(EC_F_EC_GROUP_COPY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
147 if (dest
->meth
!= src
->meth
)
149 ECerr(EC_F_EC_GROUP_COPY
, EC_R_INCOMPATIBLE_OBJECTS
);
155 EC_GROUP_clear_free_extra_data(dest
);
156 if (src
->extra_data_dup_func
)
158 if (src
->extra_data
!= NULL
)
160 dest
->extra_data
= src
->extra_data_dup_func(src
->extra_data
);
161 if (dest
->extra_data
== NULL
)
165 dest
->extra_data_dup_func
= src
->extra_data_dup_func
;
166 dest
->extra_data_free_func
= src
->extra_data_free_func
;
167 dest
->extra_data_clear_free_func
= src
->extra_data_clear_free_func
;
170 return dest
->meth
->group_copy(dest
, src
);
174 int EC_GROUP_set_generator(EC_GROUP
*group
, const EC_POINT
*generator
, const BIGNUM
*order
, const BIGNUM
*cofactor
)
176 if (group
->meth
->group_set_generator
== 0)
178 ECerr(EC_F_EC_GROUP_SET_GENERATOR
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
181 return group
->meth
->group_set_generator(group
, generator
, order
, cofactor
);
185 /* TODO: 'set' and 'get' functions for EC_GROUPs */
188 /* this has 'package' visibility */
189 int EC_GROUP_set_extra_data(EC_GROUP
*group
, void *extra_data
, void *(*extra_data_dup_func
)(void *),
190 void (*extra_data_free_func
)(void *), void (*extra_data_clear_free_func
)(void *))
192 if ((group
->extra_data
!= NULL
)
193 || (group
->extra_data_dup_func
!= 0)
194 || (group
->extra_data_free_func
!= 0)
195 || (group
->extra_data_clear_free_func
!= 0))
197 ECerr(EC_F_EC_GROUP_SET_EXTRA_DATA
, EC_R_SLOT_FULL
);
201 group
->extra_data
= extra_data
;
202 group
->extra_data_dup_func
= extra_data_dup_func
;
203 group
->extra_data_free_func
= extra_data_free_func
;
204 group
->extra_data_clear_free_func
= extra_data_clear_free_func
;
209 /* this has 'package' visibility */
210 void *EC_GROUP_get_extra_data(EC_GROUP
*group
, void *(*extra_data_dup_func
)(void *),
211 void (*extra_data_free_func
)(void *), void (*extra_data_clear_free_func
)(void *))
213 if ((group
->extra_data_dup_func
!= extra_data_dup_func
)
214 || (group
->extra_data_free_func
!= extra_data_free_func
)
215 || (group
->extra_data_clear_free_func
!= extra_data_clear_free_func
))
217 ECerr(EC_F_EC_GROUP_GET_EXTRA_DATA
, EC_R_NO_SUCH_EXTRA_DATA
);
221 return group
->extra_data
;
225 /* this has 'package' visibility */
226 void EC_GROUP_free_extra_data(EC_GROUP
*group
)
228 if (group
->extra_data_free_func
)
229 group
->extra_data_free_func(group
->extra_data
);
230 group
->extra_data
= NULL
;
231 group
->extra_data_dup_func
= 0;
232 group
->extra_data_free_func
= 0;
233 group
->extra_data_clear_free_func
= 0;
237 /* this has 'package' visibility */
238 void EC_GROUP_clear_free_extra_data(EC_GROUP
*group
)
240 if (group
->extra_data_clear_free_func
)
241 group
->extra_data_clear_free_func(group
->extra_data
);
242 else if (group
->extra_data_free_func
)
243 group
->extra_data_free_func(group
->extra_data
);
244 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;
252 /* functions for EC_POINT objects */
254 EC_POINT
*EC_POINT_new(const EC_GROUP
*group
)
260 ECerr(EC_F_EC_POINT_NEW
, ERR_R_PASSED_NULL_PARAMETER
);
263 if (group
->meth
->point_init
== 0)
265 ECerr(EC_F_EC_POINT_NEW
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
269 ret
= OPENSSL_malloc(sizeof *ret
);
272 ECerr(EC_F_EC_POINT_NEW
, ERR_R_MALLOC_FAILURE
);
276 ret
->meth
= group
->meth
;
278 if (!ret
->meth
->point_init(ret
))
288 void EC_POINT_free(EC_POINT
*point
)
290 if (point
->meth
->point_finish
!= 0)
291 point
->meth
->point_finish(point
);
296 void EC_POINT_clear_free(EC_POINT
*point
)
298 if (point
->meth
->point_clear_finish
!= 0)
299 point
->meth
->point_clear_finish(point
);
300 else if (point
->meth
!= NULL
&& point
->meth
->point_finish
!= 0)
301 point
->meth
->point_finish(point
);
302 memset(point
, 0, sizeof *point
);
307 int EC_POINT_copy(EC_POINT
*dest
, const EC_POINT
*src
)
309 if (dest
->meth
->point_copy
== 0)
311 ECerr(EC_F_EC_POINT_COPY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
314 if (dest
->meth
!= src
->meth
)
316 ECerr(EC_F_EC_POINT_COPY
, EC_R_INCOMPATIBLE_OBJECTS
);
319 return dest
->meth
->point_copy(dest
, src
);
323 int EC_POINT_set_to_infinity(const EC_GROUP
*group
, EC_POINT
*point
)
325 if (group
->meth
->point_set_to_infinity
== 0)
327 ECerr(EC_F_EC_POINT_SET_TO_INFINITY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
330 if (group
->meth
!= point
->meth
)
332 ECerr(EC_F_EC_POINT_SET_TO_INFINITY
, EC_R_INCOMPATIBLE_OBJECTS
);
335 return group
->meth
->point_set_to_infinity(group
, point
);
339 int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
340 const BIGNUM
*x
, const BIGNUM
*y
, const BIGNUM
*z
, BN_CTX
*ctx
)
342 if (group
->meth
->point_set_Jprojective_coordinates_GFp
== 0)
344 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
347 if (group
->meth
!= point
->meth
)
349 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
352 return group
->meth
->point_set_Jprojective_coordinates_GFp(group
, point
, x
, y
, z
, ctx
);
356 int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP
*group
, const EC_POINT
*point
,
357 BIGNUM
*x
, BIGNUM
*y
, BIGNUM
*z
, BN_CTX
*ctx
)
359 if (group
->meth
->point_get_Jprojective_coordinates_GFp
== 0)
361 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
364 if (group
->meth
!= point
->meth
)
366 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
369 return group
->meth
->point_get_Jprojective_coordinates_GFp(group
, point
, x
, y
, z
, ctx
);
373 int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
374 const BIGNUM
*x
, const BIGNUM
*y
, BN_CTX
*ctx
)
376 if (group
->meth
->point_set_affine_coordinates_GFp
== 0)
378 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
381 if (group
->meth
!= point
->meth
)
383 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
386 return group
->meth
->point_set_affine_coordinates_GFp(group
, point
, x
, y
, ctx
);
390 int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP
*group
, const EC_POINT
*point
,
391 BIGNUM
*x
, BIGNUM
*y
, BN_CTX
*ctx
)
393 if (group
->meth
->point_get_affine_coordinates_GFp
== 0)
395 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
398 if (group
->meth
!= point
->meth
)
400 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
403 return group
->meth
->point_get_affine_coordinates_GFp(group
, point
, x
, y
, ctx
);
407 int EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP
*group
, EC_POINT
*point
,
408 const BIGNUM
*x
, int y_bit
, BN_CTX
*ctx
)
410 if (group
->meth
->point_set_compressed_coordinates_GFp
== 0)
412 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
415 if (group
->meth
!= point
->meth
)
417 ECerr(EC_F_EC_POINT_SET_COMPRESSED_COORDINATES_GFP
, EC_R_INCOMPATIBLE_OBJECTS
);
420 return group
->meth
->point_set_compressed_coordinates_GFp(group
, point
, x
, y_bit
, ctx
);
424 size_t EC_POINT_point2oct(const EC_GROUP
*group
, const EC_POINT
*point
, point_conversion_form_t form
,
425 unsigned char *buf
, size_t len
, BN_CTX
*ctx
)
427 if (group
->meth
->point2oct
== 0)
429 ECerr(EC_F_EC_POINT_POINT2OCT
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
432 if (group
->meth
!= point
->meth
)
434 ECerr(EC_F_EC_POINT_POINT2OCT
, EC_R_INCOMPATIBLE_OBJECTS
);
437 return group
->meth
->point2oct(group
, point
, form
, buf
, len
, ctx
);
441 int EC_POINT_oct2point(const EC_GROUP
*group
, EC_POINT
*point
,
442 const unsigned char *buf
, size_t len
, BN_CTX
*ctx
)
444 if (group
->meth
->oct2point
== 0)
446 ECerr(EC_F_EC_POINT_OCT2POINT
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
449 if (group
->meth
!= point
->meth
)
451 ECerr(EC_F_EC_POINT_OCT2POINT
, EC_R_INCOMPATIBLE_OBJECTS
);
454 return group
->meth
->oct2point(group
, point
, buf
, len
, ctx
);
458 int EC_POINT_add(const EC_GROUP
*group
, EC_POINT
*r
, const EC_POINT
*a
, const EC_POINT
*b
, BN_CTX
*ctx
)
460 if (group
->meth
->add
== 0)
462 ECerr(EC_F_EC_POINT_ADD
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
465 if ((group
->meth
!= r
->meth
) || (r
->meth
!= a
->meth
) || (a
->meth
!= b
->meth
))
467 ECerr(EC_F_EC_POINT_ADD
, EC_R_INCOMPATIBLE_OBJECTS
);
470 return group
->meth
->add(group
, r
, a
, b
, ctx
);
474 int EC_POINT_dbl(const EC_GROUP
*group
, EC_POINT
*r
, const EC_POINT
*a
, BN_CTX
*ctx
)
476 if (group
->meth
->dbl
== 0)
478 ECerr(EC_F_EC_POINT_DBL
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
481 if ((group
->meth
!= r
->meth
) || (r
->meth
!= a
->meth
))
483 ECerr(EC_F_EC_POINT_DBL
, EC_R_INCOMPATIBLE_OBJECTS
);
486 return group
->meth
->dbl(group
, r
, a
, ctx
);
490 int EC_POINT_invert(const EC_GROUP
*group
, EC_POINT
*a
, BN_CTX
*ctx
)
492 if (group
->meth
->dbl
== 0)
494 ECerr(EC_F_EC_POINT_DBL
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
497 if (group
->meth
!= a
->meth
)
499 ECerr(EC_F_EC_POINT_DBL
, EC_R_INCOMPATIBLE_OBJECTS
);
502 return group
->meth
->invert(group
, a
, ctx
);
506 int EC_POINT_is_at_infinity(const EC_GROUP
*group
, const EC_POINT
*point
)
508 if (group
->meth
->is_at_infinity
== 0)
510 ECerr(EC_F_EC_POINT_IS_AT_INFINITY
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
513 if (group
->meth
!= point
->meth
)
515 ECerr(EC_F_EC_POINT_IS_AT_INFINITY
, EC_R_INCOMPATIBLE_OBJECTS
);
518 return group
->meth
->is_at_infinity(group
, point
);
522 int EC_POINT_is_on_curve(const EC_GROUP
*group
, const EC_POINT
*point
, BN_CTX
*ctx
)
524 if (group
->meth
->is_on_curve
== 0)
526 ECerr(EC_F_EC_POINT_IS_ON_CURVE
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
529 if (group
->meth
!= point
->meth
)
531 ECerr(EC_F_EC_POINT_IS_ON_CURVE
, EC_R_INCOMPATIBLE_OBJECTS
);
534 return group
->meth
->is_on_curve(group
, point
, ctx
);
538 int EC_POINT_cmp(const EC_GROUP
*group
, const EC_POINT
*a
, const EC_POINT
*b
, BN_CTX
*ctx
)
540 if (group
->meth
->point_cmp
== 0)
542 ECerr(EC_F_EC_POINT_CMP
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
545 if ((group
->meth
!= a
->meth
) || (a
->meth
!= b
->meth
))
547 ECerr(EC_F_EC_POINT_CMP
, EC_R_INCOMPATIBLE_OBJECTS
);
550 return group
->meth
->point_cmp(group
, a
, b
, ctx
);
554 int EC_POINT_make_affine(const EC_GROUP
*group
, EC_POINT
*point
, BN_CTX
*ctx
)
556 if (group
->meth
->make_affine
== 0)
558 ECerr(EC_F_EC_POINT_MAKE_AFFINE
, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED
);
561 if (group
->meth
!= point
->meth
)
563 ECerr(EC_F_EC_POINT_MAKE_AFFINE
, EC_R_INCOMPATIBLE_OBJECTS
);
566 return group
->meth
->make_affine(group
, point
, ctx
);