Line data Source code
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 : const char EC_version[] = "EC" OPENSSL_VERSION_PTEXT;
72 :
73 : /* functions for EC_GROUP objects */
74 :
75 4344 : EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
76 : {
77 : EC_GROUP *ret;
78 :
79 4344 : if (meth == NULL) {
80 0 : ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
81 0 : return NULL;
82 : }
83 4344 : if (meth->group_init == 0) {
84 0 : ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
85 0 : return NULL;
86 : }
87 :
88 4344 : ret = OPENSSL_malloc(sizeof *ret);
89 4344 : if (ret == NULL) {
90 0 : ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
91 0 : return NULL;
92 : }
93 :
94 4344 : ret->meth = meth;
95 :
96 4344 : ret->extra_data = NULL;
97 4344 : ret->mont_data = NULL;
98 :
99 4344 : ret->generator = NULL;
100 4344 : BN_init(&ret->order);
101 4344 : BN_init(&ret->cofactor);
102 :
103 4344 : ret->curve_name = 0;
104 4344 : ret->asn1_flag = ~EC_GROUP_ASN1_FLAG_MASK;
105 4344 : ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
106 :
107 4344 : ret->seed = NULL;
108 4344 : ret->seed_len = 0;
109 :
110 4344 : if (!meth->group_init(ret)) {
111 0 : OPENSSL_free(ret);
112 0 : return NULL;
113 : }
114 :
115 : return ret;
116 : }
117 :
118 4344 : void EC_GROUP_free(EC_GROUP *group)
119 : {
120 4344 : if (!group)
121 4344 : return;
122 :
123 4344 : if (group->meth->group_finish != 0)
124 4344 : group->meth->group_finish(group);
125 :
126 4344 : EC_EX_DATA_free_all_data(&group->extra_data);
127 :
128 4344 : if (EC_GROUP_VERSION(group) && group->mont_data)
129 4344 : BN_MONT_CTX_free(group->mont_data);
130 :
131 4344 : if (group->generator != NULL)
132 4344 : EC_POINT_free(group->generator);
133 4344 : BN_free(&group->order);
134 4344 : BN_free(&group->cofactor);
135 :
136 4344 : if (group->seed)
137 4344 : OPENSSL_free(group->seed);
138 :
139 4344 : OPENSSL_free(group);
140 : }
141 :
142 0 : void EC_GROUP_clear_free(EC_GROUP *group)
143 : {
144 0 : if (!group)
145 0 : return;
146 :
147 0 : if (group->meth->group_clear_finish != 0)
148 0 : group->meth->group_clear_finish(group);
149 0 : else if (group->meth->group_finish != 0)
150 0 : group->meth->group_finish(group);
151 :
152 0 : EC_EX_DATA_clear_free_all_data(&group->extra_data);
153 :
154 0 : if (EC_GROUP_VERSION(group) && group->mont_data)
155 0 : BN_MONT_CTX_free(group->mont_data);
156 :
157 0 : if (group->generator != NULL)
158 0 : EC_POINT_clear_free(group->generator);
159 0 : BN_clear_free(&group->order);
160 0 : BN_clear_free(&group->cofactor);
161 :
162 0 : if (group->seed) {
163 0 : OPENSSL_cleanse(group->seed, group->seed_len);
164 0 : OPENSSL_free(group->seed);
165 : }
166 :
167 0 : OPENSSL_cleanse(group, sizeof *group);
168 0 : OPENSSL_free(group);
169 : }
170 :
171 3102 : int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
172 : {
173 : EC_EXTRA_DATA *d;
174 :
175 3102 : if (dest->meth->group_copy == 0) {
176 0 : ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
177 0 : return 0;
178 : }
179 3102 : if (dest->meth != src->meth) {
180 0 : ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
181 0 : return 0;
182 : }
183 3102 : if (dest == src)
184 : return 1;
185 :
186 3102 : EC_EX_DATA_free_all_data(&dest->extra_data);
187 :
188 3102 : for (d = src->extra_data; d != NULL; d = d->next) {
189 0 : void *t = d->dup_func(d->data);
190 :
191 0 : if (t == NULL)
192 : return 0;
193 0 : if (!EC_EX_DATA_set_data
194 0 : (&dest->extra_data, t, d->dup_func, d->free_func,
195 : d->clear_free_func))
196 : return 0;
197 : }
198 :
199 3102 : if (EC_GROUP_VERSION(src) && src->mont_data != NULL) {
200 3102 : if (dest->mont_data == NULL) {
201 3102 : dest->mont_data = BN_MONT_CTX_new();
202 3102 : if (dest->mont_data == NULL)
203 : return 0;
204 : }
205 3102 : if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
206 : return 0;
207 : } else {
208 : /* src->generator == NULL */
209 0 : if (EC_GROUP_VERSION(dest) && dest->mont_data != NULL) {
210 0 : BN_MONT_CTX_free(dest->mont_data);
211 0 : dest->mont_data = NULL;
212 : }
213 : }
214 :
215 3102 : if (src->generator != NULL) {
216 3102 : if (dest->generator == NULL) {
217 3102 : dest->generator = EC_POINT_new(dest);
218 3102 : if (dest->generator == NULL)
219 : return 0;
220 : }
221 3102 : if (!EC_POINT_copy(dest->generator, src->generator))
222 : return 0;
223 : } else {
224 : /* src->generator == NULL */
225 0 : if (dest->generator != NULL) {
226 0 : EC_POINT_clear_free(dest->generator);
227 0 : dest->generator = NULL;
228 : }
229 : }
230 :
231 3102 : if (!BN_copy(&dest->order, &src->order))
232 : return 0;
233 3102 : if (!BN_copy(&dest->cofactor, &src->cofactor))
234 : return 0;
235 :
236 3102 : dest->curve_name = src->curve_name;
237 3102 : dest->asn1_flag = src->asn1_flag;
238 3102 : dest->asn1_form = src->asn1_form;
239 :
240 3102 : if (src->seed) {
241 3102 : if (dest->seed)
242 0 : OPENSSL_free(dest->seed);
243 3102 : dest->seed = OPENSSL_malloc(src->seed_len);
244 3102 : if (dest->seed == NULL)
245 : return 0;
246 6204 : if (!memcpy(dest->seed, src->seed, src->seed_len))
247 : return 0;
248 3102 : dest->seed_len = src->seed_len;
249 : } else {
250 0 : if (dest->seed)
251 0 : OPENSSL_free(dest->seed);
252 0 : dest->seed = NULL;
253 0 : dest->seed_len = 0;
254 : }
255 :
256 3102 : return dest->meth->group_copy(dest, src);
257 : }
258 :
259 1107 : EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
260 : {
261 : EC_GROUP *t = NULL;
262 : int ok = 0;
263 :
264 1107 : if (a == NULL)
265 : return NULL;
266 :
267 1107 : if ((t = EC_GROUP_new(a->meth)) == NULL)
268 : return (NULL);
269 1107 : if (!EC_GROUP_copy(t, a))
270 : goto err;
271 :
272 : ok = 1;
273 :
274 : err:
275 1107 : if (!ok) {
276 0 : if (t)
277 0 : EC_GROUP_free(t);
278 : return NULL;
279 : } else
280 : return t;
281 : }
282 :
283 3105 : const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
284 : {
285 3105 : return group->meth;
286 : }
287 :
288 1110 : int EC_METHOD_get_field_type(const EC_METHOD *meth)
289 : {
290 1110 : return meth->field_type;
291 : }
292 :
293 1242 : int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
294 : const BIGNUM *order, const BIGNUM *cofactor)
295 : {
296 1242 : if (generator == NULL) {
297 0 : ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
298 0 : return 0;
299 : }
300 :
301 1242 : if (group->generator == NULL) {
302 1242 : group->generator = EC_POINT_new(group);
303 1242 : if (group->generator == NULL)
304 : return 0;
305 : }
306 1242 : if (!EC_POINT_copy(group->generator, generator))
307 : return 0;
308 :
309 1242 : if (order != NULL) {
310 1242 : if (!BN_copy(&group->order, order))
311 : return 0;
312 : } else
313 0 : BN_zero(&group->order);
314 :
315 1242 : if (cofactor != NULL) {
316 1242 : if (!BN_copy(&group->cofactor, cofactor))
317 : return 0;
318 : } else
319 0 : BN_zero(&group->cofactor);
320 :
321 : /*
322 : * We ignore the return value because some groups have an order with
323 : * factors of two, which makes the Montgomery setup fail.
324 : * |group->mont_data| will be NULL in this case.
325 : */
326 1242 : ec_precompute_mont_data(group);
327 :
328 1242 : return 1;
329 : }
330 :
331 1615 : const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
332 : {
333 1615 : return group->generator;
334 : }
335 :
336 0 : BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
337 : {
338 0 : return EC_GROUP_VERSION(group) ? group->mont_data : NULL;
339 : }
340 :
341 1615 : int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
342 : {
343 1615 : if (!BN_copy(order, &group->order))
344 : return 0;
345 :
346 1615 : return !BN_is_zero(order);
347 : }
348 :
349 0 : int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
350 : BN_CTX *ctx)
351 : {
352 0 : if (!BN_copy(cofactor, &group->cofactor))
353 : return 0;
354 :
355 0 : return !BN_is_zero(&group->cofactor);
356 : }
357 :
358 1242 : void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
359 : {
360 1242 : group->curve_name = nid;
361 1242 : }
362 :
363 746 : int EC_GROUP_get_curve_name(const EC_GROUP *group)
364 : {
365 746 : return group->curve_name;
366 : }
367 :
368 0 : void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
369 : {
370 0 : group->asn1_flag &= ~EC_GROUP_ASN1_FLAG_MASK;
371 0 : group->asn1_flag |= flag & EC_GROUP_ASN1_FLAG_MASK;
372 0 : }
373 :
374 0 : int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
375 : {
376 0 : return group->asn1_flag & EC_GROUP_ASN1_FLAG_MASK;
377 : }
378 :
379 0 : void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
380 : point_conversion_form_t form)
381 : {
382 0 : group->asn1_form = form;
383 0 : }
384 :
385 0 : point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
386 : *group)
387 : {
388 0 : return group->asn1_form;
389 : }
390 :
391 1242 : size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
392 : {
393 1242 : if (group->seed) {
394 0 : OPENSSL_free(group->seed);
395 0 : group->seed = NULL;
396 0 : group->seed_len = 0;
397 : }
398 :
399 1242 : if (!len || !p)
400 : return 1;
401 :
402 1242 : if ((group->seed = OPENSSL_malloc(len)) == NULL)
403 : return 0;
404 : memcpy(group->seed, p, len);
405 1242 : group->seed_len = len;
406 :
407 1242 : return len;
408 : }
409 :
410 0 : unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
411 : {
412 0 : return group->seed;
413 : }
414 :
415 0 : size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
416 : {
417 0 : return group->seed_len;
418 : }
419 :
420 1242 : int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
421 : const BIGNUM *b, BN_CTX *ctx)
422 : {
423 1242 : if (group->meth->group_set_curve == 0) {
424 0 : ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
425 0 : return 0;
426 : }
427 1242 : return group->meth->group_set_curve(group, p, a, b, ctx);
428 : }
429 :
430 0 : int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
431 : BIGNUM *b, BN_CTX *ctx)
432 : {
433 0 : if (group->meth->group_get_curve == 0) {
434 0 : ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
435 0 : return 0;
436 : }
437 0 : return group->meth->group_get_curve(group, p, a, b, ctx);
438 : }
439 :
440 : #ifndef OPENSSL_NO_EC2M
441 0 : int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
442 : const BIGNUM *b, BN_CTX *ctx)
443 : {
444 0 : if (group->meth->group_set_curve == 0) {
445 0 : ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
446 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
447 0 : return 0;
448 : }
449 0 : return group->meth->group_set_curve(group, p, a, b, ctx);
450 : }
451 :
452 0 : int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
453 : BIGNUM *b, BN_CTX *ctx)
454 : {
455 0 : if (group->meth->group_get_curve == 0) {
456 0 : ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
457 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
458 0 : return 0;
459 : }
460 0 : return group->meth->group_get_curve(group, p, a, b, ctx);
461 : }
462 : #endif
463 :
464 1474 : int EC_GROUP_get_degree(const EC_GROUP *group)
465 : {
466 1474 : if (group->meth->group_get_degree == 0) {
467 0 : ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
468 0 : return 0;
469 : }
470 1474 : return group->meth->group_get_degree(group);
471 : }
472 :
473 0 : int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
474 : {
475 0 : if (group->meth->group_check_discriminant == 0) {
476 0 : ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
477 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
478 0 : return 0;
479 : }
480 0 : return group->meth->group_check_discriminant(group, ctx);
481 : }
482 :
483 0 : int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
484 : {
485 : int r = 0;
486 : BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
487 : BN_CTX *ctx_new = NULL;
488 :
489 : /* compare the field types */
490 0 : if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
491 : EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
492 : return 1;
493 : /* compare the curve name (if present in both) */
494 0 : if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
495 : EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
496 : return 1;
497 :
498 0 : if (!ctx)
499 0 : ctx_new = ctx = BN_CTX_new();
500 0 : if (!ctx)
501 : return -1;
502 :
503 0 : BN_CTX_start(ctx);
504 0 : a1 = BN_CTX_get(ctx);
505 0 : a2 = BN_CTX_get(ctx);
506 0 : a3 = BN_CTX_get(ctx);
507 0 : b1 = BN_CTX_get(ctx);
508 0 : b2 = BN_CTX_get(ctx);
509 0 : b3 = BN_CTX_get(ctx);
510 0 : if (!b3) {
511 0 : BN_CTX_end(ctx);
512 0 : if (ctx_new)
513 0 : BN_CTX_free(ctx);
514 : return -1;
515 : }
516 :
517 : /*
518 : * XXX This approach assumes that the external representation of curves
519 : * over the same field type is the same.
520 : */
521 0 : if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
522 0 : !b->meth->group_get_curve(b, b1, b2, b3, ctx))
523 : r = 1;
524 :
525 0 : if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
526 : r = 1;
527 :
528 : /* XXX EC_POINT_cmp() assumes that the methods are equal */
529 0 : if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
530 : EC_GROUP_get0_generator(b), ctx))
531 : r = 1;
532 :
533 0 : if (!r) {
534 : /* compare the order and cofactor */
535 0 : if (!EC_GROUP_get_order(a, a1, ctx) ||
536 0 : !EC_GROUP_get_order(b, b1, ctx) ||
537 0 : !EC_GROUP_get_cofactor(a, a2, ctx) ||
538 : !EC_GROUP_get_cofactor(b, b2, ctx)) {
539 0 : BN_CTX_end(ctx);
540 0 : if (ctx_new)
541 0 : BN_CTX_free(ctx);
542 : return -1;
543 : }
544 0 : if (BN_cmp(a1, b1) || BN_cmp(a2, b2))
545 : r = 1;
546 : }
547 :
548 0 : BN_CTX_end(ctx);
549 0 : if (ctx_new)
550 0 : BN_CTX_free(ctx);
551 :
552 0 : return r;
553 : }
554 :
555 : /* this has 'package' visibility */
556 737 : int EC_EX_DATA_set_data(EC_EXTRA_DATA **ex_data, void *data,
557 : void *(*dup_func) (void *),
558 : void (*free_func) (void *),
559 : void (*clear_free_func) (void *))
560 : {
561 : EC_EXTRA_DATA *d;
562 :
563 737 : if (ex_data == NULL)
564 : return 0;
565 :
566 737 : for (d = *ex_data; d != NULL; d = d->next) {
567 0 : if (d->dup_func == dup_func && d->free_func == free_func
568 0 : && d->clear_free_func == clear_free_func) {
569 0 : ECerr(EC_F_EC_EX_DATA_SET_DATA, EC_R_SLOT_FULL);
570 0 : return 0;
571 : }
572 : }
573 :
574 737 : if (data == NULL)
575 : /* no explicit entry needed */
576 : return 1;
577 :
578 737 : d = OPENSSL_malloc(sizeof *d);
579 737 : if (d == NULL)
580 : return 0;
581 :
582 737 : d->data = data;
583 737 : d->dup_func = dup_func;
584 737 : d->free_func = free_func;
585 737 : d->clear_free_func = clear_free_func;
586 :
587 737 : d->next = *ex_data;
588 737 : *ex_data = d;
589 :
590 737 : return 1;
591 : }
592 :
593 : /* this has 'package' visibility */
594 3089 : void *EC_EX_DATA_get_data(const EC_EXTRA_DATA *ex_data,
595 : void *(*dup_func) (void *),
596 : void (*free_func) (void *),
597 : void (*clear_free_func) (void *))
598 : {
599 : const EC_EXTRA_DATA *d;
600 :
601 3089 : for (d = ex_data; d != NULL; d = d->next) {
602 0 : if (d->dup_func == dup_func && d->free_func == free_func
603 0 : && d->clear_free_func == clear_free_func)
604 0 : return d->data;
605 : }
606 :
607 : return NULL;
608 : }
609 :
610 : /* this has 'package' visibility */
611 0 : void EC_EX_DATA_free_data(EC_EXTRA_DATA **ex_data,
612 : void *(*dup_func) (void *),
613 : void (*free_func) (void *),
614 : void (*clear_free_func) (void *))
615 : {
616 : EC_EXTRA_DATA **p;
617 :
618 0 : if (ex_data == NULL)
619 : return;
620 :
621 0 : for (p = ex_data; *p != NULL; p = &((*p)->next)) {
622 0 : if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
623 0 : && (*p)->clear_free_func == clear_free_func) {
624 0 : EC_EXTRA_DATA *next = (*p)->next;
625 :
626 0 : (*p)->free_func((*p)->data);
627 0 : OPENSSL_free(*p);
628 :
629 0 : *p = next;
630 0 : return;
631 : }
632 : }
633 : }
634 :
635 : /* this has 'package' visibility */
636 0 : void EC_EX_DATA_clear_free_data(EC_EXTRA_DATA **ex_data,
637 : void *(*dup_func) (void *),
638 : void (*free_func) (void *),
639 : void (*clear_free_func) (void *))
640 : {
641 : EC_EXTRA_DATA **p;
642 :
643 0 : if (ex_data == NULL)
644 : return;
645 :
646 0 : for (p = ex_data; *p != NULL; p = &((*p)->next)) {
647 0 : if ((*p)->dup_func == dup_func && (*p)->free_func == free_func
648 0 : && (*p)->clear_free_func == clear_free_func) {
649 0 : EC_EXTRA_DATA *next = (*p)->next;
650 :
651 0 : (*p)->clear_free_func((*p)->data);
652 0 : OPENSSL_free(*p);
653 :
654 0 : *p = next;
655 0 : return;
656 : }
657 : }
658 : }
659 :
660 : /* this has 'package' visibility */
661 13415 : void EC_EX_DATA_free_all_data(EC_EXTRA_DATA **ex_data)
662 : {
663 : EC_EXTRA_DATA *d;
664 :
665 13415 : if (ex_data == NULL)
666 13415 : return;
667 :
668 13415 : d = *ex_data;
669 27567 : while (d) {
670 737 : EC_EXTRA_DATA *next = d->next;
671 :
672 737 : d->free_func(d->data);
673 737 : OPENSSL_free(d);
674 :
675 : d = next;
676 : }
677 13415 : *ex_data = NULL;
678 : }
679 :
680 : /* this has 'package' visibility */
681 0 : void EC_EX_DATA_clear_free_all_data(EC_EXTRA_DATA **ex_data)
682 : {
683 : EC_EXTRA_DATA *d;
684 :
685 0 : if (ex_data == NULL)
686 0 : return;
687 :
688 0 : d = *ex_data;
689 0 : while (d) {
690 0 : EC_EXTRA_DATA *next = d->next;
691 :
692 0 : d->clear_free_func(d->data);
693 0 : OPENSSL_free(d);
694 :
695 : d = next;
696 : }
697 0 : *ex_data = NULL;
698 : }
699 :
700 : /* functions for EC_POINT objects */
701 :
702 21555 : EC_POINT *EC_POINT_new(const EC_GROUP *group)
703 : {
704 : EC_POINT *ret;
705 :
706 21555 : if (group == NULL) {
707 0 : ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
708 0 : return NULL;
709 : }
710 21555 : if (group->meth->point_init == 0) {
711 0 : ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
712 0 : return NULL;
713 : }
714 :
715 21555 : ret = OPENSSL_malloc(sizeof *ret);
716 21555 : if (ret == NULL) {
717 0 : ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
718 0 : return NULL;
719 : }
720 :
721 21555 : ret->meth = group->meth;
722 :
723 21555 : if (!ret->meth->point_init(ret)) {
724 0 : OPENSSL_free(ret);
725 0 : return NULL;
726 : }
727 :
728 : return ret;
729 : }
730 :
731 12147 : void EC_POINT_free(EC_POINT *point)
732 : {
733 12147 : if (!point)
734 12147 : return;
735 :
736 12147 : if (point->meth->point_finish != 0)
737 12147 : point->meth->point_finish(point);
738 12147 : OPENSSL_free(point);
739 : }
740 :
741 9408 : void EC_POINT_clear_free(EC_POINT *point)
742 : {
743 9408 : if (!point)
744 9408 : return;
745 :
746 9408 : if (point->meth->point_clear_finish != 0)
747 9408 : point->meth->point_clear_finish(point);
748 0 : else if (point->meth->point_finish != 0)
749 0 : point->meth->point_finish(point);
750 9408 : OPENSSL_cleanse(point, sizeof *point);
751 9408 : OPENSSL_free(point);
752 : }
753 :
754 10541 : int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
755 : {
756 10541 : if (dest->meth->point_copy == 0) {
757 0 : ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
758 0 : return 0;
759 : }
760 10541 : if (dest->meth != src->meth) {
761 0 : ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
762 0 : return 0;
763 : }
764 10541 : if (dest == src)
765 : return 1;
766 10541 : return dest->meth->point_copy(dest, src);
767 : }
768 :
769 370 : EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
770 : {
771 : EC_POINT *t;
772 : int r;
773 :
774 370 : if (a == NULL)
775 : return NULL;
776 :
777 370 : t = EC_POINT_new(group);
778 370 : if (t == NULL)
779 : return (NULL);
780 370 : r = EC_POINT_copy(t, a);
781 370 : if (!r) {
782 0 : EC_POINT_free(t);
783 0 : return NULL;
784 : } else
785 : return t;
786 : }
787 :
788 0 : const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
789 : {
790 0 : return point->meth;
791 : }
792 :
793 0 : int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
794 : {
795 0 : if (group->meth->point_set_to_infinity == 0) {
796 0 : ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
797 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
798 0 : return 0;
799 : }
800 0 : if (group->meth != point->meth) {
801 0 : ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
802 0 : return 0;
803 : }
804 0 : return group->meth->point_set_to_infinity(group, point);
805 : }
806 :
807 1979 : int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
808 : EC_POINT *point, const BIGNUM *x,
809 : const BIGNUM *y, const BIGNUM *z,
810 : BN_CTX *ctx)
811 : {
812 1979 : if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
813 0 : ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
814 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
815 0 : return 0;
816 : }
817 1979 : if (group->meth != point->meth) {
818 0 : ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
819 : EC_R_INCOMPATIBLE_OBJECTS);
820 0 : return 0;
821 : }
822 1979 : return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
823 : y, z, ctx);
824 : }
825 :
826 0 : int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
827 : const EC_POINT *point, BIGNUM *x,
828 : BIGNUM *y, BIGNUM *z,
829 : BN_CTX *ctx)
830 : {
831 0 : if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
832 0 : ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
833 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
834 0 : return 0;
835 : }
836 0 : if (group->meth != point->meth) {
837 0 : ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
838 : EC_R_INCOMPATIBLE_OBJECTS);
839 0 : return 0;
840 : }
841 0 : return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
842 : y, z, ctx);
843 : }
844 :
845 1979 : int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
846 : EC_POINT *point, const BIGNUM *x,
847 : const BIGNUM *y, BN_CTX *ctx)
848 : {
849 1979 : if (group->meth->point_set_affine_coordinates == 0) {
850 0 : ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
851 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
852 0 : return 0;
853 : }
854 1979 : if (group->meth != point->meth) {
855 0 : ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
856 : EC_R_INCOMPATIBLE_OBJECTS);
857 0 : return 0;
858 : }
859 1979 : return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
860 : }
861 :
862 : #ifndef OPENSSL_NO_EC2M
863 0 : int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
864 : EC_POINT *point, const BIGNUM *x,
865 : const BIGNUM *y, BN_CTX *ctx)
866 : {
867 0 : if (group->meth->point_set_affine_coordinates == 0) {
868 0 : ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
869 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
870 0 : return 0;
871 : }
872 0 : if (group->meth != point->meth) {
873 0 : ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
874 : EC_R_INCOMPATIBLE_OBJECTS);
875 0 : return 0;
876 : }
877 0 : return group->meth->point_set_affine_coordinates(group, point, x, y, ctx);
878 : }
879 : #endif
880 :
881 1480 : int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
882 : const EC_POINT *point, BIGNUM *x,
883 : BIGNUM *y, BN_CTX *ctx)
884 : {
885 1480 : if (group->meth->point_get_affine_coordinates == 0) {
886 0 : ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
887 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
888 0 : return 0;
889 : }
890 1480 : if (group->meth != point->meth) {
891 0 : ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
892 : EC_R_INCOMPATIBLE_OBJECTS);
893 0 : return 0;
894 : }
895 1480 : return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
896 : }
897 :
898 : #ifndef OPENSSL_NO_EC2M
899 0 : int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
900 : const EC_POINT *point, BIGNUM *x,
901 : BIGNUM *y, BN_CTX *ctx)
902 : {
903 0 : if (group->meth->point_get_affine_coordinates == 0) {
904 0 : ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
905 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
906 0 : return 0;
907 : }
908 0 : if (group->meth != point->meth) {
909 0 : ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
910 : EC_R_INCOMPATIBLE_OBJECTS);
911 0 : return 0;
912 : }
913 0 : return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
914 : }
915 : #endif
916 :
917 126147 : int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
918 : const EC_POINT *b, BN_CTX *ctx)
919 : {
920 126147 : if (group->meth->add == 0) {
921 0 : ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
922 0 : return 0;
923 : }
924 126147 : if ((group->meth != r->meth) || (r->meth != a->meth)
925 126147 : || (a->meth != b->meth)) {
926 0 : ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
927 0 : return 0;
928 : }
929 126147 : return group->meth->add(group, r, a, b, ctx);
930 : }
931 :
932 598791 : int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
933 : BN_CTX *ctx)
934 : {
935 598791 : if (group->meth->dbl == 0) {
936 0 : ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
937 0 : return 0;
938 : }
939 598791 : if ((group->meth != r->meth) || (r->meth != a->meth)) {
940 0 : ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
941 0 : return 0;
942 : }
943 598791 : return group->meth->dbl(group, r, a, ctx);
944 : }
945 :
946 60674 : int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
947 : {
948 60674 : if (group->meth->invert == 0) {
949 0 : ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
950 0 : return 0;
951 : }
952 60674 : if (group->meth != a->meth) {
953 0 : ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
954 0 : return 0;
955 : }
956 60674 : return group->meth->invert(group, a, ctx);
957 : }
958 :
959 915462 : int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
960 : {
961 915462 : if (group->meth->is_at_infinity == 0) {
962 0 : ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
963 : ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
964 0 : return 0;
965 : }
966 915462 : if (group->meth != point->meth) {
967 0 : ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
968 0 : return 0;
969 : }
970 915462 : return group->meth->is_at_infinity(group, point);
971 : }
972 :
973 : /*
974 : * Check whether an EC_POINT is on the curve or not. Note that the return
975 : * value for this function should NOT be treated as a boolean. Return values:
976 : * 1: The point is on the curve
977 : * 0: The point is not on the curve
978 : * -1: An error occurred
979 : */
980 737 : int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
981 : BN_CTX *ctx)
982 : {
983 737 : if (group->meth->is_on_curve == 0) {
984 0 : ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
985 0 : return 0;
986 : }
987 737 : if (group->meth != point->meth) {
988 0 : ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
989 0 : return 0;
990 : }
991 737 : return group->meth->is_on_curve(group, point, ctx);
992 : }
993 :
994 0 : int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
995 : BN_CTX *ctx)
996 : {
997 0 : if (group->meth->point_cmp == 0) {
998 0 : ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
999 0 : return -1;
1000 : }
1001 0 : if ((group->meth != a->meth) || (a->meth != b->meth)) {
1002 0 : ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1003 0 : return -1;
1004 : }
1005 0 : return group->meth->point_cmp(group, a, b, ctx);
1006 : }
1007 :
1008 0 : int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1009 : {
1010 0 : if (group->meth->make_affine == 0) {
1011 0 : ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1012 0 : return 0;
1013 : }
1014 0 : if (group->meth != point->meth) {
1015 0 : ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1016 0 : return 0;
1017 : }
1018 0 : return group->meth->make_affine(group, point, ctx);
1019 : }
1020 :
1021 2352 : int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1022 : EC_POINT *points[], BN_CTX *ctx)
1023 : {
1024 : size_t i;
1025 :
1026 2352 : if (group->meth->points_make_affine == 0) {
1027 0 : ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1028 0 : return 0;
1029 : }
1030 9408 : for (i = 0; i < num; i++) {
1031 9408 : if (group->meth != points[i]->meth) {
1032 0 : ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1033 0 : return 0;
1034 : }
1035 : }
1036 2352 : return group->meth->points_make_affine(group, num, points, ctx);
1037 : }
1038 :
1039 : /*
1040 : * Functions for point multiplication. If group->meth->mul is 0, we use the
1041 : * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1042 : * methods.
1043 : */
1044 :
1045 2352 : int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1046 : size_t num, const EC_POINT *points[],
1047 : const BIGNUM *scalars[], BN_CTX *ctx)
1048 : {
1049 2352 : if (group->meth->mul == 0)
1050 : /* use default */
1051 2352 : return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1052 :
1053 0 : return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1054 : }
1055 :
1056 2352 : int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1057 : const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1058 : {
1059 : /* just a convenient interface to EC_POINTs_mul() */
1060 :
1061 : const EC_POINT *points[1];
1062 : const BIGNUM *scalars[1];
1063 :
1064 2352 : points[0] = point;
1065 2352 : scalars[0] = p_scalar;
1066 :
1067 2352 : return EC_POINTs_mul(group, r, g_scalar,
1068 2352 : (point != NULL
1069 2352 : && p_scalar != NULL), points, scalars, ctx);
1070 : }
1071 :
1072 0 : int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1073 : {
1074 0 : if (group->meth->mul == 0)
1075 : /* use default */
1076 0 : return ec_wNAF_precompute_mult(group, ctx);
1077 :
1078 0 : if (group->meth->precompute_mult != 0)
1079 0 : return group->meth->precompute_mult(group, ctx);
1080 : else
1081 : return 1; /* nothing to do, so report success */
1082 : }
1083 :
1084 0 : int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1085 : {
1086 0 : if (group->meth->mul == 0)
1087 : /* use default */
1088 0 : return ec_wNAF_have_precompute_mult(group);
1089 :
1090 0 : if (group->meth->have_precompute_mult != 0)
1091 0 : return group->meth->have_precompute_mult(group);
1092 : else
1093 : return 0; /* cannot tell whether precomputation has
1094 : * been performed */
1095 : }
1096 :
1097 : /*
1098 : * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1099 : * returns one on success. On error it returns zero.
1100 : */
1101 1242 : int ec_precompute_mont_data(EC_GROUP *group)
1102 : {
1103 1242 : BN_CTX *ctx = BN_CTX_new();
1104 : int ret = 0;
1105 :
1106 1242 : if (!EC_GROUP_VERSION(group))
1107 : goto err;
1108 :
1109 1242 : if (group->mont_data) {
1110 0 : BN_MONT_CTX_free(group->mont_data);
1111 0 : group->mont_data = NULL;
1112 : }
1113 :
1114 1242 : if (ctx == NULL)
1115 : goto err;
1116 :
1117 1242 : group->mont_data = BN_MONT_CTX_new();
1118 1242 : if (!group->mont_data)
1119 : goto err;
1120 :
1121 1242 : if (!BN_MONT_CTX_set(group->mont_data, &group->order, ctx)) {
1122 0 : BN_MONT_CTX_free(group->mont_data);
1123 0 : group->mont_data = NULL;
1124 0 : goto err;
1125 : }
1126 :
1127 : ret = 1;
1128 :
1129 : err:
1130 :
1131 1242 : if (ctx)
1132 1242 : BN_CTX_free(ctx);
1133 1242 : return ret;
1134 : }
|