]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_lib.c
More tweaks for comments due indent issues
[thirdparty/openssl.git] / crypto / ec / ec_lib.c
CommitLineData
65e81670 1/* crypto/ec/ec_lib.c */
35b73a1f
BM
2/*
3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */
65e81670 5/* ====================================================================
37c660ff 6 * Copyright (c) 1998-2003 The OpenSSL Project. All rights reserved.
65e81670
BM
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 */
7793f30e
BM
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 */
65e81670 63
73e45b2d 64
84b08eee 65
c4b36ff4
BM
66#include <string.h>
67
0657bf9c 68#include <openssl/err.h>
bb62a8b0 69#include <openssl/opensslv.h>
0657bf9c 70
65e81670 71#include "ec_lcl.h"
0657bf9c 72
b597aab8 73const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
bb62a8b0 74
0657bf9c
BM
75
76/* functions for EC_GROUP objects */
77
78EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
79 {
80 EC_GROUP *ret;
81
82 if (meth == NULL)
83 {
739a543e 84 ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
0657bf9c
BM
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;
df9cc153
BM
101
102 ret->extra_data = NULL;
f54be179 103 ret->mont_data = NULL;
945e15a2 104
b6db386f 105 ret->generator = NULL;
5784a521
MC
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;
b6db386f 111
254ef80d
BM
112 ret->curve_name = 0;
113 ret->asn1_flag = 0;
5f3d6f70 114 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
458c2917
BM
115
116 ret->seed = NULL;
117 ret->seed_len = 0;
945e15a2 118
5784a521 119 if (!meth->group_init(ret)) goto err;
0657bf9c
BM
120
121 return ret;
5784a521
MC
122err:
123 if(ret->order) BN_free(ret->order);
124 if(ret->cofactor) BN_free(ret->cofactor);
125 OPENSSL_free(ret);
126 return NULL;
0657bf9c
BM
127 }
128
129
0657bf9c
BM
130void EC_GROUP_free(EC_GROUP *group)
131 {
7711de24
BM
132 if (!group) return;
133
0657bf9c
BM
134 if (group->meth->group_finish != 0)
135 group->meth->group_finish(group);
df9cc153 136
9dd84053 137 EC_EX_DATA_free_all_data(&group->extra_data);
df9cc153 138
f54be179
AP
139 if (group->mont_data)
140 BN_MONT_CTX_free(group->mont_data);
141
b6db386f
BM
142 if (group->generator != NULL)
143 EC_POINT_free(group->generator);
5784a521
MC
144 BN_free(group->order);
145 BN_free(group->cofactor);
b6db386f 146
458c2917
BM
147 if (group->seed)
148 OPENSSL_free(group->seed);
149
0657bf9c
BM
150 OPENSSL_free(group);
151 }
152
153
154void EC_GROUP_clear_free(EC_GROUP *group)
155 {
7711de24
BM
156 if (!group) return;
157
0657bf9c
BM
158 if (group->meth->group_clear_finish != 0)
159 group->meth->group_clear_finish(group);
bbab9b61 160 else if (group->meth->group_finish != 0)
0657bf9c 161 group->meth->group_finish(group);
df9cc153 162
9dd84053 163 EC_EX_DATA_clear_free_all_data(&group->extra_data);
df9cc153 164
f54be179
AP
165 if (group->mont_data)
166 BN_MONT_CTX_free(group->mont_data);
167
b6db386f
BM
168 if (group->generator != NULL)
169 EC_POINT_clear_free(group->generator);
5784a521
MC
170 BN_clear_free(group->order);
171 BN_clear_free(group->cofactor);
b6db386f 172
458c2917
BM
173 if (group->seed)
174 {
4579924b 175 OPENSSL_cleanse(group->seed, group->seed_len);
458c2917
BM
176 OPENSSL_free(group->seed);
177 }
178
4579924b 179 OPENSSL_cleanse(group, sizeof *group);
0657bf9c
BM
180 OPENSSL_free(group);
181 }
182
183
184int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
185 {
ba729265
BM
186 EC_EXTRA_DATA *d;
187
0657bf9c
BM
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 }
1d5bd6cf
BM
198 if (dest == src)
199 return 1;
0657bf9c 200
9dd84053 201 EC_EX_DATA_free_all_data(&dest->extra_data);
df9cc153 202
ba729265
BM
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;
9dd84053 209 if (!EC_EX_DATA_set_data(&dest->extra_data, t, d->dup_func, d->free_func, d->clear_free_func))
ba729265 210 return 0;
df9cc153
BM
211 }
212
f54be179
AP
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
b6db386f
BM
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
5784a521
MC
251 if (!BN_copy(dest->order, src->order)) return 0;
252 if (!BN_copy(dest->cofactor, src->cofactor)) return 0;
b6db386f 253
254ef80d
BM
254 dest->curve_name = src->curve_name;
255 dest->asn1_flag = src->asn1_flag;
256 dest->asn1_form = src->asn1_form;
458c2917
BM
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
b6db386f 277
0657bf9c
BM
278 return dest->meth->group_copy(dest, src);
279 }
280
281
7793f30e
BM
282EC_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
48fe4d62
BM
304const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
305 {
306 return group->meth;
307 }
308
309
458c2917
BM
310int EC_METHOD_get_field_type(const EC_METHOD *meth)
311 {
312 return meth->field_type;
313 }
314
315
b6db386f 316int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
bb62a8b0 317 {
b6db386f 318 if (generator == NULL)
bb62a8b0 319 {
b6db386f
BM
320 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
321 return 0 ;
bb62a8b0 322 }
b6db386f
BM
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)
5784a521 332 { if (!BN_copy(group->order, order)) return 0; }
b6db386f 333 else
5784a521 334 BN_zero(group->order);
b6db386f
BM
335
336 if (cofactor != NULL)
5784a521 337 { if (!BN_copy(group->cofactor, cofactor)) return 0; }
b6db386f 338 else
5784a521 339 BN_zero(group->cofactor);
b6db386f 340
f54be179
AP
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
b6db386f 346 return 1;
bb62a8b0
BM
347 }
348
349
9dd84053 350const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
bb62a8b0 351 {
b6db386f 352 return group->generator;
bb62a8b0
BM
353 }
354
f54be179
AP
355BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
356 {
357 return group->mont_data;
358 }
bb62a8b0 359
b6db386f 360int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
0657bf9c 361 {
5784a521 362 if (!BN_copy(order, group->order))
0657bf9c 363 return 0;
b6db386f
BM
364
365 return !BN_is_zero(order);
0657bf9c
BM
366 }
367
368
b6db386f 369int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor, BN_CTX *ctx)
48fe4d62 370 {
5784a521 371 if (!BN_copy(cofactor, group->cofactor))
48fe4d62 372 return 0;
b6db386f 373
5784a521 374 return !BN_is_zero(group->cofactor);
48fe4d62
BM
375 }
376
377
7dc17a6c 378void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
b6db386f 379 {
254ef80d 380 group->curve_name = nid;
b6db386f
BM
381 }
382
383
7dc17a6c 384int EC_GROUP_get_curve_name(const EC_GROUP *group)
b6db386f 385 {
254ef80d 386 return group->curve_name;
b6db386f
BM
387 }
388
389
458c2917
BM
390void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
391 {
392 group->asn1_flag = flag;
393 }
394
395
396int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
397 {
398 return group->asn1_flag;
399 }
400
401
254ef80d
BM
402void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
403 point_conversion_form_t form)
404 {
405 group->asn1_form = form;
406 }
407
408
409point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP *group)
410 {
411 return group->asn1_form;
412 }
413
414
5f3d6f70
BM
415size_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
436unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
437 {
438 return group->seed;
439 }
440
441
442size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
443 {
444 return group->seed_len;
445 }
446
447
b6db386f 448int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
48fe4d62 449 {
7793f30e 450 if (group->meth->group_set_curve == 0)
48fe4d62 451 {
b6db386f 452 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
48fe4d62
BM
453 return 0;
454 }
7793f30e 455 return group->meth->group_set_curve(group, p, a, b, ctx);
48fe4d62
BM
456 }
457
458
b6db386f 459int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
48fe4d62 460 {
7793f30e 461 if (group->meth->group_get_curve == 0)
48fe4d62 462 {
b6db386f 463 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
48fe4d62
BM
464 return 0;
465 }
7793f30e
BM
466 return group->meth->group_get_curve(group, p, a, b, ctx);
467 }
468
b3310161 469#ifndef OPENSSL_NO_EC2M
7793f30e
BM
470int 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
481int 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 }
b3310161 490#endif
7793f30e
BM
491
492int 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);
48fe4d62
BM
500 }
501
502
17d6bb81 503int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
af28dd6c 504 {
17d6bb81 505 if (group->meth->group_check_discriminant == 0)
af28dd6c 506 {
17d6bb81 507 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
af28dd6c
BM
508 return 0;
509 }
17d6bb81 510 return group->meth->group_check_discriminant(group, ctx);
af28dd6c
BM
511 }
512
513
ada0e717
BM
514int 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;
ca567a03 524 /* compare the curve name (if present in both) */
7dc17a6c 525 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
ca567a03
BM
526 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
527 return 1;
ada0e717
BM
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
80c808b9 556 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
ada0e717
BM
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
df9cc153 589/* this has 'package' visibility */
9dd84053 590int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
ba729265 591 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
df9cc153 592 {
ba729265
BM
593 EC_EXTRA_DATA *d;
594
9dd84053 595 if (ex_data == NULL)
df9cc153 596 return 0;
ba729265 597
9dd84053 598 for (d = *ex_data; d != NULL; d = d->next)
ba729265
BM
599 {
600 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
601 {
137023dd 602 ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
ba729265
BM
603 return 0;
604 }
df9cc153
BM
605 }
606
ba729265
BM
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
9dd84053
NL
620 d->next = *ex_data;
621 *ex_data = d;
ba729265 622
df9cc153
BM
623 return 1;
624 }
625
df9cc153 626/* this has 'package' visibility */
9dd84053 627void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
ba729265 628 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
df9cc153 629 {
9dd84053 630 const EC_EXTRA_DATA *d;
ba729265 631
9dd84053 632 for (d = ex_data; d != NULL; d = d->next)
ba729265
BM
633 {
634 if (d->dup_func == dup_func && d->free_func == free_func && d->clear_free_func == clear_free_func)
635 return d->data;
df9cc153 636 }
ba729265
BM
637
638 return NULL;
639 }
df9cc153 640
ba729265 641/* this has 'package' visibility */
9dd84053 642void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
ba729265
BM
643 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
644 {
645 EC_EXTRA_DATA **p;
646
9dd84053 647 if (ex_data == NULL)
ba729265
BM
648 return;
649
9dd84053 650 for (p = ex_data; *p != NULL; p = &((*p)->next))
ba729265
BM
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 }
df9cc153
BM
663 }
664
ba729265 665/* this has 'package' visibility */
bbbd6710 666void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
ba729265
BM
667 void *(*dup_func)(void *), void (*free_func)(void *), void (*clear_free_func)(void *))
668 {
669 EC_EXTRA_DATA **p;
670
9dd84053 671 if (ex_data == NULL)
ba729265
BM
672 return;
673
9dd84053 674 for (p = ex_data; *p != NULL; p = &((*p)->next))
ba729265
BM
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 }
df9cc153
BM
688
689/* this has 'package' visibility */
9dd84053 690void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
df9cc153 691 {
ba729265
BM
692 EC_EXTRA_DATA *d;
693
9dd84053 694 if (ex_data == NULL)
ba729265
BM
695 return;
696
9dd84053 697 d = *ex_data;
ba729265
BM
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 }
9dd84053 707 *ex_data = NULL;
df9cc153
BM
708 }
709
df9cc153 710/* this has 'package' visibility */
9dd84053 711void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
df9cc153 712 {
ba729265
BM
713 EC_EXTRA_DATA *d;
714
9dd84053 715 if (ex_data == NULL)
ba729265
BM
716 return;
717
9dd84053 718 d = *ex_data;
ba729265
BM
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 }
9dd84053 728 *ex_data = NULL;
df9cc153
BM
729 }
730
0657bf9c
BM
731
732/* functions for EC_POINT objects */
733
734EC_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
768void EC_POINT_free(EC_POINT *point)
769 {
7711de24
BM
770 if (!point) return;
771
0657bf9c
BM
772 if (point->meth->point_finish != 0)
773 point->meth->point_finish(point);
774 OPENSSL_free(point);
775 }
776
777
778void EC_POINT_clear_free(EC_POINT *point)
779 {
7711de24
BM
780 if (!point) return;
781
0657bf9c
BM
782 if (point->meth->point_clear_finish != 0)
783 point->meth->point_clear_finish(point);
67b6f1ca 784 else if (point->meth->point_finish != 0)
0657bf9c 785 point->meth->point_finish(point);
4579924b 786 OPENSSL_cleanse(point, sizeof *point);
0657bf9c
BM
787 OPENSSL_free(point);
788 }
789
790
791int 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 }
91f29a38
BM
803 if (dest == src)
804 return 1;
0657bf9c
BM
805 return dest->meth->point_copy(dest, src);
806 }
807
808
7793f30e
BM
809EC_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
48fe4d62
BM
828const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
829 {
830 return point->meth;
831 }
832
833
226cc7de
BM
834int 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
1d5bd6cf
BM
850int 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 {
35b73a1f 853 if (group->meth->point_set_Jprojective_coordinates_GFp == 0)
1d5bd6cf
BM
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 }
35b73a1f 863 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
1d5bd6cf
BM
864 }
865
866
867int 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 {
35b73a1f 870 if (group->meth->point_get_Jprojective_coordinates_GFp == 0)
1d5bd6cf
BM
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 }
35b73a1f 880 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
1d5bd6cf
BM
881 }
882
883
226cc7de
BM
884int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group, EC_POINT *point,
885 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
886 {
7793f30e 887 if (group->meth->point_set_affine_coordinates == 0)
226cc7de
BM
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 }
7793f30e 897 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
226cc7de
BM
898 }
899
b3310161 900#ifndef OPENSSL_NO_EC2M
35b73a1f
BM
901int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group, EC_POINT *point,
902 const BIGNUM *x, const BIGNUM *y, BN_CTX *ctx)
7793f30e 903 {
35b73a1f 904 if (group->meth->point_set_affine_coordinates == 0)
7793f30e 905 {
35b73a1f 906 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7793f30e
BM
907 return 0;
908 }
909 if (group->meth != point->meth)
910 {
35b73a1f 911 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
7793f30e
BM
912 return 0;
913 }
35b73a1f 914 return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
7793f30e 915 }
b3310161 916#endif
7793f30e 917
35b73a1f
BM
918int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group, const EC_POINT *point,
919 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
7793f30e 920 {
35b73a1f 921 if (group->meth->point_get_affine_coordinates == 0)
7793f30e 922 {
35b73a1f 923 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7793f30e
BM
924 return 0;
925 }
926 if (group->meth != point->meth)
927 {
35b73a1f 928 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP, EC_R_INCOMPATIBLE_OBJECTS);
7793f30e
BM
929 return 0;
930 }
35b73a1f 931 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
7793f30e
BM
932 }
933
b3310161 934#ifndef OPENSSL_NO_EC2M
35b73a1f
BM
935int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group, const EC_POINT *point,
936 BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
7793f30e 937 {
35b73a1f 938 if (group->meth->point_get_affine_coordinates == 0)
7793f30e 939 {
35b73a1f 940 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
7793f30e
BM
941 return 0;
942 }
943 if (group->meth != point->meth)
944 {
35b73a1f 945 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M, EC_R_INCOMPATIBLE_OBJECTS);
7793f30e
BM
946 return 0;
947 }
35b73a1f 948 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
7793f30e 949 }
b3310161 950#endif
7793f30e 951
0657bf9c
BM
952int 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
968int 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
1d5bd6cf
BM
984int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
985 {
cba11f57 986 if (group->meth->invert == 0)
1d5bd6cf 987 {
aa4ce731 988 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1d5bd6cf
BM
989 return 0;
990 }
991 if (group->meth != a->meth)
992 {
aa4ce731 993 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
1d5bd6cf
BM
994 return 0;
995 }
996 return group->meth->invert(group, a, ctx);
997 }
998
999
0657bf9c
BM
1000int 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
1016int 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
1d5bd6cf
BM
1032int 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);
ca567a03 1037 return -1;
1d5bd6cf
BM
1038 }
1039 if ((group->meth != a->meth) || (a->meth != b->meth))
1040 {
1041 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
ca567a03 1042 return -1;
1d5bd6cf
BM
1043 }
1044 return group->meth->point_cmp(group, a, b, ctx);
1045 }
1046
1047
e869d4bd 1048int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
0657bf9c
BM
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 }
48fe4d62
BM
1062
1063
1064int 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 }
37c660ff
BM
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
1091int 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
1101int 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
1115int 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
1127int 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 }
f54be179
AP
1138
1139/* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1140 * returns one on success. On error it returns zero. */
1141int 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
5784a521 1159 if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx))
f54be179
AP
1160 {
1161 BN_MONT_CTX_free(group->mont_data);
1162 group->mont_data = NULL;
1163 goto err;
1164 }
1165
1166 ret = 1;
1167
1168err:
1169
1170 if (ctx)
1171 BN_CTX_free(ctx);
1172 return ret;
1173 }