]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_lib.c
Declare a new x509v3 extension: x509ExtAdmission
[thirdparty/openssl.git] / crypto / ec / ec_lib.c
CommitLineData
35b73a1f 1/*
aa6bb135 2 * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
65e81670 3 *
aa6bb135
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
65e81670 8 */
aa6bb135 9
7793f30e
BM
10/* ====================================================================
11 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
0f113f3e 12 * Binary polynomial ECC support in OpenSSL originally developed by
7793f30e
BM
13 * SUN MICROSYSTEMS, INC., and contributed to the OpenSSL project.
14 */
65e81670 15
c4b36ff4
BM
16#include <string.h>
17
0657bf9c 18#include <openssl/err.h>
bb62a8b0 19#include <openssl/opensslv.h>
0657bf9c 20
65e81670 21#include "ec_lcl.h"
0657bf9c 22
0657bf9c
BM
23/* functions for EC_GROUP objects */
24
25EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
0f113f3e
MC
26{
27 EC_GROUP *ret;
28
29 if (meth == NULL) {
30 ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
31 return NULL;
32 }
33 if (meth->group_init == 0) {
34 ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
35 return NULL;
36 }
37
64b25758 38 ret = OPENSSL_zalloc(sizeof(*ret));
0f113f3e
MC
39 if (ret == NULL) {
40 ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
41 return NULL;
42 }
43
44 ret->meth = meth;
6903e2e7
DSH
45 if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
46 ret->order = BN_new();
47 if (ret->order == NULL)
48 goto err;
49 ret->cofactor = BN_new();
50 if (ret->cofactor == NULL)
51 goto err;
52 }
86f300d3 53 ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
0f113f3e 54 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
0f113f3e
MC
55 if (!meth->group_init(ret))
56 goto err;
0f113f3e 57 return ret;
64b25758 58
0f113f3e 59 err:
23a1d5e9
RS
60 BN_free(ret->order);
61 BN_free(ret->cofactor);
0f113f3e
MC
62 OPENSSL_free(ret);
63 return NULL;
64}
0657bf9c 65
2c52ac9b 66void EC_pre_comp_free(EC_GROUP *group)
3aef36ff
RS
67{
68 switch (group->pre_comp_type) {
f3b3d7f0 69 case PCT_none:
3aef36ff 70 break;
66117ab0 71 case PCT_nistz256:
f3b3d7f0 72#ifdef ECP_NISTZ256_ASM
3aef36ff 73 EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
e69aa800 74#endif
f3b3d7f0 75 break;
3aef36ff 76#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
66117ab0 77 case PCT_nistp224:
3aef36ff
RS
78 EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
79 break;
66117ab0 80 case PCT_nistp256:
3aef36ff
RS
81 EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
82 break;
66117ab0 83 case PCT_nistp521:
3aef36ff
RS
84 EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
85 break;
f3b3d7f0
RS
86#else
87 case PCT_nistp224:
88 case PCT_nistp256:
89 case PCT_nistp521:
90 break;
3aef36ff 91#endif
66117ab0 92 case PCT_ec:
3aef36ff
RS
93 EC_ec_pre_comp_free(group->pre_comp.ec);
94 break;
95 }
96 group->pre_comp.ec = NULL;
97}
98
0657bf9c 99void EC_GROUP_free(EC_GROUP *group)
0f113f3e
MC
100{
101 if (!group)
102 return;
7711de24 103
0f113f3e
MC
104 if (group->meth->group_finish != 0)
105 group->meth->group_finish(group);
df9cc153 106
2c52ac9b 107 EC_pre_comp_free(group);
23a1d5e9 108 BN_MONT_CTX_free(group->mont_data);
8fdc3734 109 EC_POINT_free(group->generator);
0f113f3e
MC
110 BN_free(group->order);
111 BN_free(group->cofactor);
25aaa98a 112 OPENSSL_free(group->seed);
0f113f3e
MC
113 OPENSSL_free(group);
114}
0657bf9c
BM
115
116void EC_GROUP_clear_free(EC_GROUP *group)
0f113f3e
MC
117{
118 if (!group)
119 return;
df9cc153 120
0f113f3e
MC
121 if (group->meth->group_clear_finish != 0)
122 group->meth->group_clear_finish(group);
123 else if (group->meth->group_finish != 0)
124 group->meth->group_finish(group);
df9cc153 125
2c52ac9b 126 EC_pre_comp_free(group);
23a1d5e9 127 BN_MONT_CTX_free(group->mont_data);
8fdc3734 128 EC_POINT_clear_free(group->generator);
0f113f3e
MC
129 BN_clear_free(group->order);
130 BN_clear_free(group->cofactor);
4b45c6e5 131 OPENSSL_clear_free(group->seed, group->seed_len);
b4faea50 132 OPENSSL_clear_free(group, sizeof(*group));
0f113f3e 133}
0657bf9c
BM
134
135int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
0f113f3e 136{
0f113f3e
MC
137 if (dest->meth->group_copy == 0) {
138 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
139 return 0;
140 }
141 if (dest->meth != src->meth) {
142 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
143 return 0;
144 }
145 if (dest == src)
146 return 1;
147
3aef36ff
RS
148 /* Copy precomputed */
149 dest->pre_comp_type = src->pre_comp_type;
150 switch (src->pre_comp_type) {
f3b3d7f0 151 case PCT_none:
3aef36ff
RS
152 dest->pre_comp.ec = NULL;
153 break;
66117ab0 154 case PCT_nistz256:
f3b3d7f0 155#ifdef ECP_NISTZ256_ASM
3aef36ff 156 dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
e69aa800 157#endif
f3b3d7f0 158 break;
3aef36ff 159#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
66117ab0 160 case PCT_nistp224:
3aef36ff
RS
161 dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
162 break;
66117ab0 163 case PCT_nistp256:
3aef36ff
RS
164 dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
165 break;
66117ab0 166 case PCT_nistp521:
3aef36ff
RS
167 dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
168 break;
f3b3d7f0
RS
169#else
170 case PCT_nistp224:
171 case PCT_nistp256:
172 case PCT_nistp521:
173 break;
3aef36ff 174#endif
66117ab0 175 case PCT_ec:
3aef36ff
RS
176 dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
177 break;
0f113f3e
MC
178 }
179
180 if (src->mont_data != NULL) {
181 if (dest->mont_data == NULL) {
182 dest->mont_data = BN_MONT_CTX_new();
183 if (dest->mont_data == NULL)
184 return 0;
185 }
186 if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
187 return 0;
188 } else {
189 /* src->generator == NULL */
23a1d5e9
RS
190 BN_MONT_CTX_free(dest->mont_data);
191 dest->mont_data = NULL;
0f113f3e 192 }
0657bf9c 193
0f113f3e
MC
194 if (src->generator != NULL) {
195 if (dest->generator == NULL) {
196 dest->generator = EC_POINT_new(dest);
197 if (dest->generator == NULL)
198 return 0;
199 }
200 if (!EC_POINT_copy(dest->generator, src->generator))
201 return 0;
202 } else {
203 /* src->generator == NULL */
8fdc3734
RS
204 EC_POINT_clear_free(dest->generator);
205 dest->generator = NULL;
0f113f3e
MC
206 }
207
6903e2e7
DSH
208 if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
209 if (!BN_copy(dest->order, src->order))
210 return 0;
211 if (!BN_copy(dest->cofactor, src->cofactor))
212 return 0;
213 }
0f113f3e
MC
214
215 dest->curve_name = src->curve_name;
216 dest->asn1_flag = src->asn1_flag;
217 dest->asn1_form = src->asn1_form;
218
219 if (src->seed) {
b548a1f1 220 OPENSSL_free(dest->seed);
0f113f3e
MC
221 dest->seed = OPENSSL_malloc(src->seed_len);
222 if (dest->seed == NULL)
223 return 0;
224 if (!memcpy(dest->seed, src->seed, src->seed_len))
225 return 0;
226 dest->seed_len = src->seed_len;
227 } else {
b548a1f1 228 OPENSSL_free(dest->seed);
0f113f3e
MC
229 dest->seed = NULL;
230 dest->seed_len = 0;
231 }
232
233 return dest->meth->group_copy(dest, src);
234}
0657bf9c 235
7793f30e 236EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
0f113f3e
MC
237{
238 EC_GROUP *t = NULL;
239 int ok = 0;
7793f30e 240
0f113f3e
MC
241 if (a == NULL)
242 return NULL;
7793f30e 243
0f113f3e
MC
244 if ((t = EC_GROUP_new(a->meth)) == NULL)
245 return (NULL);
246 if (!EC_GROUP_copy(t, a))
247 goto err;
7793f30e 248
0f113f3e 249 ok = 1;
7793f30e 250
0f113f3e
MC
251 err:
252 if (!ok) {
8fdc3734 253 EC_GROUP_free(t);
0f113f3e 254 return NULL;
8fdc3734 255 }
0f113f3e
MC
256 return t;
257}
7793f30e 258
48fe4d62 259const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
0f113f3e
MC
260{
261 return group->meth;
262}
48fe4d62 263
458c2917 264int EC_METHOD_get_field_type(const EC_METHOD *meth)
0f113f3e
MC
265{
266 return meth->field_type;
267}
268
269int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
270 const BIGNUM *order, const BIGNUM *cofactor)
271{
272 if (generator == NULL) {
273 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
274 return 0;
275 }
276
277 if (group->generator == NULL) {
278 group->generator = EC_POINT_new(group);
279 if (group->generator == NULL)
280 return 0;
281 }
282 if (!EC_POINT_copy(group->generator, generator))
283 return 0;
284
285 if (order != NULL) {
286 if (!BN_copy(group->order, order))
287 return 0;
288 } else
289 BN_zero(group->order);
290
291 if (cofactor != NULL) {
292 if (!BN_copy(group->cofactor, cofactor))
293 return 0;
294 } else
295 BN_zero(group->cofactor);
296
297 /*
3a6a4a93 298 * Some groups have an order with
0f113f3e
MC
299 * factors of two, which makes the Montgomery setup fail.
300 * |group->mont_data| will be NULL in this case.
301 */
3a6a4a93
BB
302 if (BN_is_odd(group->order)) {
303 return ec_precompute_mont_data(group);
304 }
0f113f3e 305
3a6a4a93
BB
306 BN_MONT_CTX_free(group->mont_data);
307 group->mont_data = NULL;
0f113f3e
MC
308 return 1;
309}
bb62a8b0 310
9dd84053 311const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
0f113f3e
MC
312{
313 return group->generator;
314}
bb62a8b0 315
f54be179 316BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
0f113f3e
MC
317{
318 return group->mont_data;
319}
bb62a8b0 320
b6db386f 321int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
0f113f3e 322{
be2e334f
DSH
323 if (group->order == NULL)
324 return 0;
0f113f3e
MC
325 if (!BN_copy(order, group->order))
326 return 0;
0657bf9c 327
0f113f3e
MC
328 return !BN_is_zero(order);
329}
0657bf9c 330
be2e334f
DSH
331const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
332{
333 return group->order;
334}
335
336int EC_GROUP_order_bits(const EC_GROUP *group)
337{
9ff9bccc 338 OPENSSL_assert(group->meth->group_order_bits != NULL);
77470e98 339 return group->meth->group_order_bits(group);
be2e334f
DSH
340}
341
0f113f3e
MC
342int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
343 BN_CTX *ctx)
344{
be2e334f
DSH
345
346 if (group->cofactor == NULL)
347 return 0;
0f113f3e
MC
348 if (!BN_copy(cofactor, group->cofactor))
349 return 0;
48fe4d62 350
0f113f3e
MC
351 return !BN_is_zero(group->cofactor);
352}
48fe4d62 353
be2e334f
DSH
354const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
355{
356 return group->cofactor;
357}
358
7dc17a6c 359void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
0f113f3e
MC
360{
361 group->curve_name = nid;
362}
b6db386f 363
7dc17a6c 364int EC_GROUP_get_curve_name(const EC_GROUP *group)
0f113f3e
MC
365{
366 return group->curve_name;
367}
b6db386f 368
458c2917 369void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
0f113f3e
MC
370{
371 group->asn1_flag = flag;
372}
458c2917
BM
373
374int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
0f113f3e
MC
375{
376 return group->asn1_flag;
377}
458c2917 378
0f113f3e 379void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
254ef80d 380 point_conversion_form_t form)
0f113f3e
MC
381{
382 group->asn1_form = form;
383}
254ef80d 384
0f113f3e
MC
385point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
386 *group)
387{
388 return group->asn1_form;
389}
254ef80d 390
5f3d6f70 391size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
0f113f3e 392{
b548a1f1
RS
393 OPENSSL_free(group->seed);
394 group->seed = NULL;
395 group->seed_len = 0;
5f3d6f70 396
0f113f3e
MC
397 if (!len || !p)
398 return 1;
5f3d6f70 399
0f113f3e
MC
400 if ((group->seed = OPENSSL_malloc(len)) == NULL)
401 return 0;
402 memcpy(group->seed, p, len);
403 group->seed_len = len;
5f3d6f70 404
0f113f3e
MC
405 return len;
406}
5f3d6f70
BM
407
408unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
0f113f3e
MC
409{
410 return group->seed;
411}
5f3d6f70
BM
412
413size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
0f113f3e
MC
414{
415 return group->seed_len;
416}
417
418int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
419 const BIGNUM *b, BN_CTX *ctx)
420{
421 if (group->meth->group_set_curve == 0) {
422 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
423 return 0;
424 }
425 return group->meth->group_set_curve(group, p, a, b, ctx);
426}
427
428int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
429 BIGNUM *b, BN_CTX *ctx)
430{
431 if (group->meth->group_get_curve == 0) {
432 ECerr(EC_F_EC_GROUP_GET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
433 return 0;
434 }
435 return group->meth->group_get_curve(group, p, a, b, ctx);
436}
7793f30e 437
b3310161 438#ifndef OPENSSL_NO_EC2M
0f113f3e
MC
439int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
440 const BIGNUM *b, BN_CTX *ctx)
441{
442 if (group->meth->group_set_curve == 0) {
443 ECerr(EC_F_EC_GROUP_SET_CURVE_GF2M,
444 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
445 return 0;
446 }
447 return group->meth->group_set_curve(group, p, a, b, ctx);
448}
449
450int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
451 BIGNUM *b, BN_CTX *ctx)
452{
453 if (group->meth->group_get_curve == 0) {
454 ECerr(EC_F_EC_GROUP_GET_CURVE_GF2M,
455 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
456 return 0;
457 }
458 return group->meth->group_get_curve(group, p, a, b, ctx);
459}
b3310161 460#endif
7793f30e
BM
461
462int EC_GROUP_get_degree(const EC_GROUP *group)
0f113f3e
MC
463{
464 if (group->meth->group_get_degree == 0) {
465 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
466 return 0;
467 }
468 return group->meth->group_get_degree(group);
469}
48fe4d62 470
17d6bb81 471int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
0f113f3e
MC
472{
473 if (group->meth->group_check_discriminant == 0) {
474 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
475 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
476 return 0;
477 }
478 return group->meth->group_check_discriminant(group, ctx);
479}
af28dd6c 480
ada0e717 481int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
0f113f3e
MC
482{
483 int r = 0;
484 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
485 BN_CTX *ctx_new = NULL;
486
487 /* compare the field types */
488 if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
489 EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
490 return 1;
491 /* compare the curve name (if present in both) */
492 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
493 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
494 return 1;
6903e2e7
DSH
495 if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
496 return 0;
0f113f3e 497
90945fa3 498 if (ctx == NULL)
0f113f3e 499 ctx_new = ctx = BN_CTX_new();
90945fa3 500 if (ctx == NULL)
0f113f3e
MC
501 return -1;
502
503 BN_CTX_start(ctx);
504 a1 = BN_CTX_get(ctx);
505 a2 = BN_CTX_get(ctx);
506 a3 = BN_CTX_get(ctx);
507 b1 = BN_CTX_get(ctx);
508 b2 = BN_CTX_get(ctx);
509 b3 = BN_CTX_get(ctx);
90945fa3 510 if (b3 == NULL) {
0f113f3e 511 BN_CTX_end(ctx);
23a1d5e9 512 BN_CTX_free(ctx_new);
0f113f3e
MC
513 return -1;
514 }
515
516 /*
517 * XXX This approach assumes that the external representation of curves
518 * over the same field type is the same.
519 */
520 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
521 !b->meth->group_get_curve(b, b1, b2, b3, ctx))
522 r = 1;
523
524 if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
525 r = 1;
526
527 /* XXX EC_POINT_cmp() assumes that the methods are equal */
528 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
529 EC_GROUP_get0_generator(b), ctx))
530 r = 1;
531
532 if (!r) {
be2e334f 533 const BIGNUM *ao, *bo, *ac, *bc;
0f113f3e 534 /* compare the order and cofactor */
be2e334f
DSH
535 ao = EC_GROUP_get0_order(a);
536 bo = EC_GROUP_get0_order(b);
537 ac = EC_GROUP_get0_cofactor(a);
538 bc = EC_GROUP_get0_cofactor(b);
539 if (ao == NULL || bo == NULL) {
0f113f3e 540 BN_CTX_end(ctx);
23a1d5e9 541 BN_CTX_free(ctx_new);
0f113f3e
MC
542 return -1;
543 }
be2e334f 544 if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
0f113f3e
MC
545 r = 1;
546 }
547
548 BN_CTX_end(ctx);
23a1d5e9 549 BN_CTX_free(ctx_new);
ada0e717 550
0f113f3e
MC
551 return r;
552}
ada0e717 553
0657bf9c
BM
554/* functions for EC_POINT objects */
555
556EC_POINT *EC_POINT_new(const EC_GROUP *group)
0f113f3e
MC
557{
558 EC_POINT *ret;
559
560 if (group == NULL) {
561 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
562 return NULL;
563 }
564 if (group->meth->point_init == 0) {
565 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
566 return NULL;
567 }
568
1b4cf96f 569 ret = OPENSSL_zalloc(sizeof(*ret));
0f113f3e
MC
570 if (ret == NULL) {
571 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
572 return NULL;
573 }
574
575 ret->meth = group->meth;
576
577 if (!ret->meth->point_init(ret)) {
578 OPENSSL_free(ret);
579 return NULL;
580 }
581
582 return ret;
583}
0657bf9c
BM
584
585void EC_POINT_free(EC_POINT *point)
0f113f3e
MC
586{
587 if (!point)
588 return;
7711de24 589
0f113f3e
MC
590 if (point->meth->point_finish != 0)
591 point->meth->point_finish(point);
592 OPENSSL_free(point);
593}
0657bf9c
BM
594
595void EC_POINT_clear_free(EC_POINT *point)
0f113f3e
MC
596{
597 if (!point)
598 return;
599
600 if (point->meth->point_clear_finish != 0)
601 point->meth->point_clear_finish(point);
602 else if (point->meth->point_finish != 0)
603 point->meth->point_finish(point);
b4faea50 604 OPENSSL_clear_free(point, sizeof(*point));
0f113f3e 605}
0657bf9c
BM
606
607int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
0f113f3e
MC
608{
609 if (dest->meth->point_copy == 0) {
610 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
611 return 0;
612 }
613 if (dest->meth != src->meth) {
614 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
615 return 0;
616 }
617 if (dest == src)
618 return 1;
619 return dest->meth->point_copy(dest, src);
620}
0657bf9c 621
7793f30e 622EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
0f113f3e
MC
623{
624 EC_POINT *t;
625 int r;
626
627 if (a == NULL)
628 return NULL;
629
630 t = EC_POINT_new(group);
631 if (t == NULL)
632 return (NULL);
633 r = EC_POINT_copy(t, a);
634 if (!r) {
635 EC_POINT_free(t);
636 return NULL;
8fdc3734
RS
637 }
638 return t;
0f113f3e 639}
7793f30e 640
48fe4d62 641const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
0f113f3e
MC
642{
643 return point->meth;
644}
48fe4d62 645
226cc7de 646int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
0f113f3e
MC
647{
648 if (group->meth->point_set_to_infinity == 0) {
649 ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
650 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
651 return 0;
652 }
653 if (group->meth != point->meth) {
654 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
655 return 0;
656 }
657 return group->meth->point_set_to_infinity(group, point);
658}
659
660int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
661 EC_POINT *point, const BIGNUM *x,
662 const BIGNUM *y, const BIGNUM *z,
663 BN_CTX *ctx)
664{
665 if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
666 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
667 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
668 return 0;
669 }
670 if (group->meth != point->meth) {
671 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
672 EC_R_INCOMPATIBLE_OBJECTS);
673 return 0;
674 }
675 return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
676 y, z, ctx);
677}
678
679int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
680 const EC_POINT *point, BIGNUM *x,
681 BIGNUM *y, BIGNUM *z,
682 BN_CTX *ctx)
683{
684 if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
685 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
686 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
687 return 0;
688 }
689 if (group->meth != point->meth) {
690 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
691 EC_R_INCOMPATIBLE_OBJECTS);
692 return 0;
693 }
694 return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
695 y, z, ctx);
696}
697
698int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
699 EC_POINT *point, const BIGNUM *x,
700 const BIGNUM *y, BN_CTX *ctx)
701{
702 if (group->meth->point_set_affine_coordinates == 0) {
703 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
704 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
705 return 0;
706 }
707 if (group->meth != point->meth) {
708 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
709 EC_R_INCOMPATIBLE_OBJECTS);
710 return 0;
711 }
1e2012b7
EK
712 if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
713 return 0;
714
715 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
716 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GFP,
717 EC_R_POINT_IS_NOT_ON_CURVE);
718 return 0;
719 }
720 return 1;
0f113f3e 721}
226cc7de 722
b3310161 723#ifndef OPENSSL_NO_EC2M
0f113f3e
MC
724int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
725 EC_POINT *point, const BIGNUM *x,
726 const BIGNUM *y, BN_CTX *ctx)
727{
728 if (group->meth->point_set_affine_coordinates == 0) {
729 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
730 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
731 return 0;
732 }
733 if (group->meth != point->meth) {
734 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
735 EC_R_INCOMPATIBLE_OBJECTS);
736 return 0;
737 }
1e2012b7
EK
738 if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
739 return 0;
740
741 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
742 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES_GF2M,
743 EC_R_POINT_IS_NOT_ON_CURVE);
744 return 0;
745 }
746 return 1;
0f113f3e 747}
b3310161 748#endif
7793f30e 749
0f113f3e
MC
750int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
751 const EC_POINT *point, BIGNUM *x,
752 BIGNUM *y, BN_CTX *ctx)
753{
754 if (group->meth->point_get_affine_coordinates == 0) {
755 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
756 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
757 return 0;
758 }
759 if (group->meth != point->meth) {
760 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GFP,
761 EC_R_INCOMPATIBLE_OBJECTS);
762 return 0;
763 }
764 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
765}
7793f30e 766
b3310161 767#ifndef OPENSSL_NO_EC2M
0f113f3e
MC
768int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
769 const EC_POINT *point, BIGNUM *x,
770 BIGNUM *y, BN_CTX *ctx)
771{
772 if (group->meth->point_get_affine_coordinates == 0) {
773 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
774 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
775 return 0;
776 }
777 if (group->meth != point->meth) {
778 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES_GF2M,
779 EC_R_INCOMPATIBLE_OBJECTS);
780 return 0;
781 }
782 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
783}
b3310161 784#endif
7793f30e 785
0f113f3e
MC
786int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
787 const EC_POINT *b, BN_CTX *ctx)
788{
789 if (group->meth->add == 0) {
790 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
791 return 0;
792 }
793 if ((group->meth != r->meth) || (r->meth != a->meth)
794 || (a->meth != b->meth)) {
795 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
796 return 0;
797 }
798 return group->meth->add(group, r, a, b, ctx);
799}
800
801int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
802 BN_CTX *ctx)
803{
804 if (group->meth->dbl == 0) {
805 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
806 return 0;
807 }
808 if ((group->meth != r->meth) || (r->meth != a->meth)) {
809 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
810 return 0;
811 }
812 return group->meth->dbl(group, r, a, ctx);
813}
0657bf9c 814
1d5bd6cf 815int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
0f113f3e
MC
816{
817 if (group->meth->invert == 0) {
818 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
819 return 0;
820 }
821 if (group->meth != a->meth) {
822 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
823 return 0;
824 }
825 return group->meth->invert(group, a, ctx);
826}
1d5bd6cf 827
0657bf9c 828int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
0f113f3e
MC
829{
830 if (group->meth->is_at_infinity == 0) {
831 ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
832 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
833 return 0;
834 }
835 if (group->meth != point->meth) {
836 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
837 return 0;
838 }
839 return group->meth->is_at_infinity(group, point);
840}
841
68886be7
MC
842/*
843 * Check whether an EC_POINT is on the curve or not. Note that the return
844 * value for this function should NOT be treated as a boolean. Return values:
845 * 1: The point is on the curve
846 * 0: The point is not on the curve
847 * -1: An error occurred
848 */
0f113f3e
MC
849int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
850 BN_CTX *ctx)
851{
852 if (group->meth->is_on_curve == 0) {
853 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
854 return 0;
855 }
856 if (group->meth != point->meth) {
857 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
858 return 0;
859 }
860 return group->meth->is_on_curve(group, point, ctx);
861}
862
863int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
864 BN_CTX *ctx)
865{
866 if (group->meth->point_cmp == 0) {
867 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
868 return -1;
869 }
870 if ((group->meth != a->meth) || (a->meth != b->meth)) {
871 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
872 return -1;
873 }
874 return group->meth->point_cmp(group, a, b, ctx);
875}
1d5bd6cf 876
e869d4bd 877int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
0f113f3e
MC
878{
879 if (group->meth->make_affine == 0) {
880 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
881 return 0;
882 }
883 if (group->meth != point->meth) {
884 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
885 return 0;
886 }
887 return group->meth->make_affine(group, point, ctx);
888}
889
890int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
891 EC_POINT *points[], BN_CTX *ctx)
892{
893 size_t i;
894
895 if (group->meth->points_make_affine == 0) {
896 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
897 return 0;
898 }
899 for (i = 0; i < num; i++) {
900 if (group->meth != points[i]->meth) {
901 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
902 return 0;
903 }
904 }
905 return group->meth->points_make_affine(group, num, points, ctx);
906}
907
908/*
909 * Functions for point multiplication. If group->meth->mul is 0, we use the
910 * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
911 * methods.
37c660ff
BM
912 */
913
914int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
0f113f3e
MC
915 size_t num, const EC_POINT *points[],
916 const BIGNUM *scalars[], BN_CTX *ctx)
917{
918 if (group->meth->mul == 0)
919 /* use default */
920 return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
37c660ff 921
0f113f3e
MC
922 return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
923}
37c660ff
BM
924
925int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
0f113f3e
MC
926 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
927{
928 /* just a convenient interface to EC_POINTs_mul() */
37c660ff 929
0f113f3e
MC
930 const EC_POINT *points[1];
931 const BIGNUM *scalars[1];
37c660ff 932
0f113f3e
MC
933 points[0] = point;
934 scalars[0] = p_scalar;
37c660ff 935
0f113f3e
MC
936 return EC_POINTs_mul(group, r, g_scalar,
937 (point != NULL
938 && p_scalar != NULL), points, scalars, ctx);
939}
37c660ff
BM
940
941int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
0f113f3e
MC
942{
943 if (group->meth->mul == 0)
944 /* use default */
945 return ec_wNAF_precompute_mult(group, ctx);
37c660ff 946
0f113f3e
MC
947 if (group->meth->precompute_mult != 0)
948 return group->meth->precompute_mult(group, ctx);
949 else
950 return 1; /* nothing to do, so report success */
951}
37c660ff
BM
952
953int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
0f113f3e
MC
954{
955 if (group->meth->mul == 0)
956 /* use default */
957 return ec_wNAF_have_precompute_mult(group);
958
959 if (group->meth->have_precompute_mult != 0)
960 return group->meth->have_precompute_mult(group);
961 else
962 return 0; /* cannot tell whether precomputation has
963 * been performed */
964}
965
966/*
967 * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
968 * returns one on success. On error it returns zero.
969 */
f54be179 970int ec_precompute_mont_data(EC_GROUP *group)
0f113f3e
MC
971{
972 BN_CTX *ctx = BN_CTX_new();
973 int ret = 0;
974
23a1d5e9
RS
975 BN_MONT_CTX_free(group->mont_data);
976 group->mont_data = NULL;
0f113f3e
MC
977
978 if (ctx == NULL)
979 goto err;
980
981 group->mont_data = BN_MONT_CTX_new();
90945fa3 982 if (group->mont_data == NULL)
0f113f3e
MC
983 goto err;
984
985 if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
986 BN_MONT_CTX_free(group->mont_data);
987 group->mont_data = NULL;
988 goto err;
989 }
990
991 ret = 1;
992
993 err:
994
23a1d5e9 995 BN_CTX_free(ctx);
0f113f3e
MC
996 return ret;
997}
3aef36ff
RS
998
999int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
1000{
1001 return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
1002}
1003
1004void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
1005{
1006 return CRYPTO_get_ex_data(&key->ex_data, idx);
1007}
77470e98
DSH
1008
1009int ec_group_simple_order_bits(const EC_GROUP *group)
1010{
1011 if (group->order == NULL)
1012 return 0;
1013 return BN_num_bits(group->order);
1014}