]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_lib.c
Clean away some declarations
[thirdparty/openssl.git] / crypto / ec / ec_lib.c
CommitLineData
35b73a1f 1/*
33388b44 2 * Copyright 2001-2020 The OpenSSL Project Authors. All Rights Reserved.
aa8f3d76 3 * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
65e81670 4 *
a7f182b7 5 * Licensed under the Apache License 2.0 (the "License"). You may not use
aa6bb135
RS
6 * this file except in compliance with the License. You can obtain a copy
7 * in the file LICENSE in the source distribution or at
8 * https://www.openssl.org/source/license.html
65e81670 9 */
aa6bb135 10
579422c8
P
11/*
12 * ECDSA low level APIs are deprecated for public use, but still ok for
13 * internal use.
14 */
15#include "internal/deprecated.h"
16
c4b36ff4
BM
17#include <string.h>
18
0657bf9c 19#include <openssl/err.h>
bb62a8b0 20#include <openssl/opensslv.h>
0657bf9c 21
706457b7 22#include "ec_local.h"
0657bf9c 23
0657bf9c
BM
24/* functions for EC_GROUP objects */
25
2da8d4eb
MC
26EC_GROUP *ec_group_new_with_libctx(OPENSSL_CTX *libctx, const char *propq,
27 const EC_METHOD *meth)
0f113f3e
MC
28{
29 EC_GROUP *ret;
30
31 if (meth == NULL) {
2da8d4eb 32 ECerr(0, EC_R_SLOT_FULL);
0f113f3e
MC
33 return NULL;
34 }
35 if (meth->group_init == 0) {
2da8d4eb 36 ECerr(0, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
0f113f3e
MC
37 return NULL;
38 }
39
64b25758 40 ret = OPENSSL_zalloc(sizeof(*ret));
0f113f3e 41 if (ret == NULL) {
2da8d4eb 42 ECerr(0, ERR_R_MALLOC_FAILURE);
0f113f3e
MC
43 return NULL;
44 }
45
a9612d6c 46 ret->libctx = libctx;
2da8d4eb
MC
47 if (propq != NULL) {
48 ret->propq = OPENSSL_strdup(propq);
49 if (ret->propq == NULL) {
50 ECerr(0, ERR_R_MALLOC_FAILURE);
51 goto err;
52 }
53 }
0f113f3e 54 ret->meth = meth;
6903e2e7
DSH
55 if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
56 ret->order = BN_new();
57 if (ret->order == NULL)
58 goto err;
59 ret->cofactor = BN_new();
60 if (ret->cofactor == NULL)
61 goto err;
62 }
86f300d3 63 ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
0f113f3e 64 ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
0f113f3e
MC
65 if (!meth->group_init(ret))
66 goto err;
0f113f3e 67 return ret;
64b25758 68
0f113f3e 69 err:
23a1d5e9
RS
70 BN_free(ret->order);
71 BN_free(ret->cofactor);
2da8d4eb 72 OPENSSL_free(ret->propq);
0f113f3e
MC
73 OPENSSL_free(ret);
74 return NULL;
75}
0657bf9c 76
23ccae80
BB
77#ifndef OPENSSL_NO_DEPRECATED_3_0
78# ifndef FIPS_MODULE
a9612d6c
MC
79EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
80{
2da8d4eb 81 return ec_group_new_with_libctx(NULL, NULL, meth);
a9612d6c 82}
23ccae80 83# endif
a9612d6c
MC
84#endif
85
2c52ac9b 86void EC_pre_comp_free(EC_GROUP *group)
3aef36ff
RS
87{
88 switch (group->pre_comp_type) {
f3b3d7f0 89 case PCT_none:
3aef36ff 90 break;
66117ab0 91 case PCT_nistz256:
f3b3d7f0 92#ifdef ECP_NISTZ256_ASM
3aef36ff 93 EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
e69aa800 94#endif
f3b3d7f0 95 break;
3aef36ff 96#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
66117ab0 97 case PCT_nistp224:
3aef36ff
RS
98 EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
99 break;
66117ab0 100 case PCT_nistp256:
3aef36ff
RS
101 EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
102 break;
66117ab0 103 case PCT_nistp521:
3aef36ff
RS
104 EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
105 break;
f3b3d7f0
RS
106#else
107 case PCT_nistp224:
108 case PCT_nistp256:
109 case PCT_nistp521:
110 break;
3aef36ff 111#endif
66117ab0 112 case PCT_ec:
3aef36ff
RS
113 EC_ec_pre_comp_free(group->pre_comp.ec);
114 break;
115 }
116 group->pre_comp.ec = NULL;
117}
118
0657bf9c 119void EC_GROUP_free(EC_GROUP *group)
0f113f3e
MC
120{
121 if (!group)
122 return;
7711de24 123
0f113f3e
MC
124 if (group->meth->group_finish != 0)
125 group->meth->group_finish(group);
df9cc153 126
2c52ac9b 127 EC_pre_comp_free(group);
23a1d5e9 128 BN_MONT_CTX_free(group->mont_data);
8fdc3734 129 EC_POINT_free(group->generator);
0f113f3e
MC
130 BN_free(group->order);
131 BN_free(group->cofactor);
25aaa98a 132 OPENSSL_free(group->seed);
2da8d4eb 133 OPENSSL_free(group->propq);
0f113f3e
MC
134 OPENSSL_free(group);
135}
0657bf9c 136
936c2b9e 137#ifndef OPENSSL_NO_DEPRECATED_3_0
0657bf9c 138void EC_GROUP_clear_free(EC_GROUP *group)
0f113f3e
MC
139{
140 if (!group)
141 return;
df9cc153 142
0f113f3e
MC
143 if (group->meth->group_clear_finish != 0)
144 group->meth->group_clear_finish(group);
145 else if (group->meth->group_finish != 0)
146 group->meth->group_finish(group);
df9cc153 147
2c52ac9b 148 EC_pre_comp_free(group);
23a1d5e9 149 BN_MONT_CTX_free(group->mont_data);
8fdc3734 150 EC_POINT_clear_free(group->generator);
0f113f3e
MC
151 BN_clear_free(group->order);
152 BN_clear_free(group->cofactor);
4b45c6e5 153 OPENSSL_clear_free(group->seed, group->seed_len);
b4faea50 154 OPENSSL_clear_free(group, sizeof(*group));
0f113f3e 155}
4a7a4972 156#endif
0657bf9c
BM
157
158int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
0f113f3e 159{
0f113f3e
MC
160 if (dest->meth->group_copy == 0) {
161 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
162 return 0;
163 }
164 if (dest->meth != src->meth) {
165 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
166 return 0;
167 }
168 if (dest == src)
169 return 1;
170
a9612d6c 171 dest->libctx = src->libctx;
b14e6015
MC
172 dest->curve_name = src->curve_name;
173
3aef36ff
RS
174 /* Copy precomputed */
175 dest->pre_comp_type = src->pre_comp_type;
176 switch (src->pre_comp_type) {
f3b3d7f0 177 case PCT_none:
3aef36ff
RS
178 dest->pre_comp.ec = NULL;
179 break;
66117ab0 180 case PCT_nistz256:
f3b3d7f0 181#ifdef ECP_NISTZ256_ASM
3aef36ff 182 dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
e69aa800 183#endif
f3b3d7f0 184 break;
3aef36ff 185#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
66117ab0 186 case PCT_nistp224:
3aef36ff
RS
187 dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
188 break;
66117ab0 189 case PCT_nistp256:
3aef36ff
RS
190 dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
191 break;
66117ab0 192 case PCT_nistp521:
3aef36ff
RS
193 dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
194 break;
f3b3d7f0
RS
195#else
196 case PCT_nistp224:
197 case PCT_nistp256:
198 case PCT_nistp521:
199 break;
3aef36ff 200#endif
66117ab0 201 case PCT_ec:
3aef36ff
RS
202 dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
203 break;
0f113f3e
MC
204 }
205
206 if (src->mont_data != NULL) {
207 if (dest->mont_data == NULL) {
208 dest->mont_data = BN_MONT_CTX_new();
209 if (dest->mont_data == NULL)
210 return 0;
211 }
212 if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
213 return 0;
214 } else {
215 /* src->generator == NULL */
23a1d5e9
RS
216 BN_MONT_CTX_free(dest->mont_data);
217 dest->mont_data = NULL;
0f113f3e 218 }
0657bf9c 219
0f113f3e
MC
220 if (src->generator != NULL) {
221 if (dest->generator == NULL) {
222 dest->generator = EC_POINT_new(dest);
223 if (dest->generator == NULL)
224 return 0;
225 }
226 if (!EC_POINT_copy(dest->generator, src->generator))
227 return 0;
228 } else {
229 /* src->generator == NULL */
8fdc3734
RS
230 EC_POINT_clear_free(dest->generator);
231 dest->generator = NULL;
0f113f3e
MC
232 }
233
6903e2e7
DSH
234 if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
235 if (!BN_copy(dest->order, src->order))
236 return 0;
237 if (!BN_copy(dest->cofactor, src->cofactor))
238 return 0;
239 }
0f113f3e 240
0f113f3e
MC
241 dest->asn1_flag = src->asn1_flag;
242 dest->asn1_form = src->asn1_form;
243
244 if (src->seed) {
b548a1f1 245 OPENSSL_free(dest->seed);
cdb10bae
RS
246 if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
247 ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE);
0f113f3e 248 return 0;
cdb10bae 249 }
0f113f3e
MC
250 if (!memcpy(dest->seed, src->seed, src->seed_len))
251 return 0;
252 dest->seed_len = src->seed_len;
253 } else {
b548a1f1 254 OPENSSL_free(dest->seed);
0f113f3e
MC
255 dest->seed = NULL;
256 dest->seed_len = 0;
257 }
258
259 return dest->meth->group_copy(dest, src);
260}
0657bf9c 261
7793f30e 262EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
0f113f3e
MC
263{
264 EC_GROUP *t = NULL;
265 int ok = 0;
7793f30e 266
0f113f3e
MC
267 if (a == NULL)
268 return NULL;
7793f30e 269
2da8d4eb 270 if ((t = ec_group_new_with_libctx(a->libctx, a->propq, a->meth)) == NULL)
26a7d938 271 return NULL;
0f113f3e
MC
272 if (!EC_GROUP_copy(t, a))
273 goto err;
7793f30e 274
0f113f3e 275 ok = 1;
7793f30e 276
0f113f3e
MC
277 err:
278 if (!ok) {
8fdc3734 279 EC_GROUP_free(t);
0f113f3e 280 return NULL;
8fdc3734 281 }
0f113f3e
MC
282 return t;
283}
7793f30e 284
23ccae80 285#ifndef OPENSSL_NO_DEPRECATED_3_0
48fe4d62 286const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
0f113f3e
MC
287{
288 return group->meth;
289}
48fe4d62 290
458c2917 291int EC_METHOD_get_field_type(const EC_METHOD *meth)
0f113f3e
MC
292{
293 return meth->field_type;
294}
23ccae80 295#endif
0f113f3e 296
eb791696
AP
297static int ec_precompute_mont_data(EC_GROUP *);
298
b783beea
BB
299/*-
300 * Try computing cofactor from the generator order (n) and field cardinality (q).
301 * This works for all curves of cryptographic interest.
302 *
303 * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
304 * h_min = (q + 1 - 2*sqrt(q))/n
305 * h_max = (q + 1 + 2*sqrt(q))/n
306 * h_max - h_min = 4*sqrt(q)/n
307 * So if n > 4*sqrt(q) holds, there is only one possible value for h:
308 * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
309 *
310 * Otherwise, zero cofactor and return success.
311 */
312static int ec_guess_cofactor(EC_GROUP *group) {
313 int ret = 0;
314 BN_CTX *ctx = NULL;
315 BIGNUM *q = NULL;
316
317 /*-
318 * If the cofactor is too large, we cannot guess it.
319 * The RHS of below is a strict overestimate of lg(4 * sqrt(q))
320 */
321 if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
322 /* default to 0 */
323 BN_zero(group->cofactor);
324 /* return success */
325 return 1;
326 }
327
328 if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL)
329 return 0;
330
331 BN_CTX_start(ctx);
332 if ((q = BN_CTX_get(ctx)) == NULL)
333 goto err;
334
335 /* set q = 2**m for binary fields; q = p otherwise */
336 if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
337 BN_zero(q);
338 if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
339 goto err;
340 } else {
341 if (!BN_copy(q, group->field))
342 goto err;
343 }
344
345 /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
346 if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
347 || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
348 /* q + 1 + n/2 */
349 || !BN_add(group->cofactor, group->cofactor, BN_value_one())
350 /* (q + 1 + n/2)/n */
351 || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
352 goto err;
353 ret = 1;
354 err:
355 BN_CTX_end(ctx);
356 BN_CTX_free(ctx);
357 return ret;
358}
359
0f113f3e
MC
360int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
361 const BIGNUM *order, const BIGNUM *cofactor)
362{
363 if (generator == NULL) {
364 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
365 return 0;
366 }
367
b783beea
BB
368 /* require group->field >= 1 */
369 if (group->field == NULL || BN_is_zero(group->field)
370 || BN_is_negative(group->field)) {
371 ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_FIELD);
372 return 0;
373 }
374
375 /*-
376 * - require order >= 1
377 * - enforce upper bound due to Hasse thm: order can be no more than one bit
378 * longer than field cardinality
379 */
380 if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
381 || BN_num_bits(order) > BN_num_bits(group->field) + 1) {
382 ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_INVALID_GROUP_ORDER);
383 return 0;
384 }
385
386 /*-
387 * Unfortunately the cofactor is an optional field in many standards.
388 * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
389 * So accept cofactor == NULL or cofactor >= 0.
390 */
391 if (cofactor != NULL && BN_is_negative(cofactor)) {
392 ECerr(EC_F_EC_GROUP_SET_GENERATOR, EC_R_UNKNOWN_COFACTOR);
393 return 0;
394 }
395
0f113f3e
MC
396 if (group->generator == NULL) {
397 group->generator = EC_POINT_new(group);
398 if (group->generator == NULL)
399 return 0;
400 }
401 if (!EC_POINT_copy(group->generator, generator))
402 return 0;
403
b783beea
BB
404 if (!BN_copy(group->order, order))
405 return 0;
0f113f3e 406
b783beea
BB
407 /* Either take the provided positive cofactor, or try to compute it */
408 if (cofactor != NULL && !BN_is_zero(cofactor)) {
0f113f3e
MC
409 if (!BN_copy(group->cofactor, cofactor))
410 return 0;
b783beea 411 } else if (!ec_guess_cofactor(group)) {
0f113f3e 412 BN_zero(group->cofactor);
b783beea 413 return 0;
8402cd5f 414 }
b783beea 415
0f113f3e 416 /*
3a6a4a93 417 * Some groups have an order with
0f113f3e
MC
418 * factors of two, which makes the Montgomery setup fail.
419 * |group->mont_data| will be NULL in this case.
420 */
3a6a4a93
BB
421 if (BN_is_odd(group->order)) {
422 return ec_precompute_mont_data(group);
423 }
0f113f3e 424
3a6a4a93
BB
425 BN_MONT_CTX_free(group->mont_data);
426 group->mont_data = NULL;
0f113f3e
MC
427 return 1;
428}
bb62a8b0 429
9dd84053 430const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
0f113f3e
MC
431{
432 return group->generator;
433}
bb62a8b0 434
f54be179 435BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
0f113f3e
MC
436{
437 return group->mont_data;
438}
bb62a8b0 439
b6db386f 440int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
0f113f3e 441{
be2e334f
DSH
442 if (group->order == NULL)
443 return 0;
0f113f3e
MC
444 if (!BN_copy(order, group->order))
445 return 0;
0657bf9c 446
0f113f3e
MC
447 return !BN_is_zero(order);
448}
0657bf9c 449
be2e334f
DSH
450const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
451{
452 return group->order;
453}
454
455int EC_GROUP_order_bits(const EC_GROUP *group)
456{
77470e98 457 return group->meth->group_order_bits(group);
be2e334f
DSH
458}
459
0f113f3e
MC
460int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
461 BN_CTX *ctx)
462{
be2e334f
DSH
463
464 if (group->cofactor == NULL)
465 return 0;
0f113f3e
MC
466 if (!BN_copy(cofactor, group->cofactor))
467 return 0;
48fe4d62 468
0f113f3e
MC
469 return !BN_is_zero(group->cofactor);
470}
48fe4d62 471
be2e334f
DSH
472const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
473{
474 return group->cofactor;
475}
476
7dc17a6c 477void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
0f113f3e
MC
478{
479 group->curve_name = nid;
480}
b6db386f 481
7dc17a6c 482int EC_GROUP_get_curve_name(const EC_GROUP *group)
0f113f3e
MC
483{
484 return group->curve_name;
485}
b6db386f 486
fa1f0306
DA
487const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
488{
489 return group->field;
490}
491
23ccae80
BB
492int EC_GROUP_get_field_type(const EC_GROUP *group)
493{
494 return group->meth->field_type;
495}
496
458c2917 497void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
0f113f3e
MC
498{
499 group->asn1_flag = flag;
500}
458c2917
BM
501
502int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
0f113f3e
MC
503{
504 return group->asn1_flag;
505}
458c2917 506
0f113f3e 507void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
254ef80d 508 point_conversion_form_t form)
0f113f3e
MC
509{
510 group->asn1_form = form;
511}
254ef80d 512
0f113f3e
MC
513point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
514 *group)
515{
516 return group->asn1_form;
517}
254ef80d 518
5f3d6f70 519size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
0f113f3e 520{
b548a1f1
RS
521 OPENSSL_free(group->seed);
522 group->seed = NULL;
523 group->seed_len = 0;
5f3d6f70 524
0f113f3e
MC
525 if (!len || !p)
526 return 1;
5f3d6f70 527
f06080cb
F
528 if ((group->seed = OPENSSL_malloc(len)) == NULL) {
529 ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE);
0f113f3e 530 return 0;
f06080cb 531 }
0f113f3e
MC
532 memcpy(group->seed, p, len);
533 group->seed_len = len;
5f3d6f70 534
0f113f3e
MC
535 return len;
536}
5f3d6f70
BM
537
538unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
0f113f3e
MC
539{
540 return group->seed;
541}
5f3d6f70
BM
542
543size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
0f113f3e
MC
544{
545 return group->seed_len;
546}
547
8e3cced7
MC
548int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
549 const BIGNUM *b, BN_CTX *ctx)
0f113f3e
MC
550{
551 if (group->meth->group_set_curve == 0) {
8e3cced7 552 ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
0f113f3e
MC
553 return 0;
554 }
555 return group->meth->group_set_curve(group, p, a, b, ctx);
556}
557
8e3cced7
MC
558int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
559 BN_CTX *ctx)
0f113f3e 560{
8e3cced7
MC
561 if (group->meth->group_get_curve == NULL) {
562 ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
0f113f3e
MC
563 return 0;
564 }
565 return group->meth->group_get_curve(group, p, a, b, ctx);
566}
7793f30e 567
936c2b9e 568#ifndef OPENSSL_NO_DEPRECATED_3_0
8e3cced7
MC
569int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
570 const BIGNUM *b, BN_CTX *ctx)
571{
572 return EC_GROUP_set_curve(group, p, a, b, ctx);
573}
574
575int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
576 BIGNUM *b, BN_CTX *ctx)
577{
578 return EC_GROUP_get_curve(group, p, a, b, ctx);
579}
580
50db8163 581# ifndef OPENSSL_NO_EC2M
0f113f3e
MC
582int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
583 const BIGNUM *b, BN_CTX *ctx)
584{
8e3cced7 585 return EC_GROUP_set_curve(group, p, a, b, ctx);
0f113f3e
MC
586}
587
588int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
589 BIGNUM *b, BN_CTX *ctx)
590{
8e3cced7 591 return EC_GROUP_get_curve(group, p, a, b, ctx);
0f113f3e 592}
50db8163 593# endif
b3310161 594#endif
7793f30e
BM
595
596int EC_GROUP_get_degree(const EC_GROUP *group)
0f113f3e
MC
597{
598 if (group->meth->group_get_degree == 0) {
599 ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
600 return 0;
601 }
602 return group->meth->group_get_degree(group);
603}
48fe4d62 604
17d6bb81 605int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
0f113f3e
MC
606{
607 if (group->meth->group_check_discriminant == 0) {
608 ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
609 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
610 return 0;
611 }
612 return group->meth->group_check_discriminant(group, ctx);
613}
af28dd6c 614
ada0e717 615int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
0f113f3e
MC
616{
617 int r = 0;
618 BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
f844f9eb 619#ifndef FIPS_MODULE
0f113f3e 620 BN_CTX *ctx_new = NULL;
a9612d6c 621#endif
a9612d6c 622
0f113f3e 623 /* compare the field types */
23ccae80 624 if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b))
0f113f3e
MC
625 return 1;
626 /* compare the curve name (if present in both) */
627 if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
628 EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
629 return 1;
6903e2e7
DSH
630 if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
631 return 0;
0f113f3e 632
f844f9eb 633#ifndef FIPS_MODULE
0e8b6c97
AT
634 if (ctx == NULL)
635 ctx_new = ctx = BN_CTX_new();
636#endif
637 if (ctx == NULL)
638 return -1;
639
0f113f3e
MC
640 BN_CTX_start(ctx);
641 a1 = BN_CTX_get(ctx);
642 a2 = BN_CTX_get(ctx);
643 a3 = BN_CTX_get(ctx);
644 b1 = BN_CTX_get(ctx);
645 b2 = BN_CTX_get(ctx);
646 b3 = BN_CTX_get(ctx);
90945fa3 647 if (b3 == NULL) {
0f113f3e 648 BN_CTX_end(ctx);
f844f9eb 649#ifndef FIPS_MODULE
23a1d5e9 650 BN_CTX_free(ctx_new);
a9612d6c 651#endif
0f113f3e
MC
652 return -1;
653 }
654
655 /*
656 * XXX This approach assumes that the external representation of curves
657 * over the same field type is the same.
658 */
659 if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
660 !b->meth->group_get_curve(b, b1, b2, b3, ctx))
661 r = 1;
662
8402cd5f
SL
663 /* return 1 if the curve parameters are different */
664 if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
0f113f3e
MC
665 r = 1;
666
ac2b52c6 667 /* XXX EC_POINT_cmp() assumes that the methods are equal */
8402cd5f 668 /* return 1 if the generators are different */
0f113f3e 669 if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
8402cd5f 670 EC_GROUP_get0_generator(b), ctx) != 0)
0f113f3e
MC
671 r = 1;
672
673 if (!r) {
be2e334f 674 const BIGNUM *ao, *bo, *ac, *bc;
ac2b52c6 675 /* compare the orders */
be2e334f
DSH
676 ao = EC_GROUP_get0_order(a);
677 bo = EC_GROUP_get0_order(b);
be2e334f 678 if (ao == NULL || bo == NULL) {
8402cd5f
SL
679 /* return an error if either order is NULL */
680 r = -1;
681 goto end;
682 }
683 if (BN_cmp(ao, bo) != 0) {
684 /* return 1 if orders are different */
685 r = 1;
686 goto end;
0f113f3e 687 }
8402cd5f
SL
688 /*
689 * It gets here if the curve parameters and generator matched.
690 * Now check the optional cofactors (if both are present).
691 */
692 ac = EC_GROUP_get0_cofactor(a);
693 bc = EC_GROUP_get0_cofactor(b);
694 /* Returns 1 (mismatch) if both cofactors are specified and different */
695 if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0)
0f113f3e 696 r = 1;
8402cd5f 697 /* Returns 0 if the parameters matched */
0f113f3e 698 }
8402cd5f 699end:
0f113f3e 700 BN_CTX_end(ctx);
f844f9eb 701#ifndef FIPS_MODULE
23a1d5e9 702 BN_CTX_free(ctx_new);
a9612d6c 703#endif
0f113f3e
MC
704 return r;
705}
ada0e717 706
0657bf9c
BM
707/* functions for EC_POINT objects */
708
709EC_POINT *EC_POINT_new(const EC_GROUP *group)
0f113f3e
MC
710{
711 EC_POINT *ret;
712
713 if (group == NULL) {
714 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
715 return NULL;
716 }
f06080cb 717 if (group->meth->point_init == NULL) {
0f113f3e
MC
718 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
719 return NULL;
720 }
721
1b4cf96f 722 ret = OPENSSL_zalloc(sizeof(*ret));
0f113f3e
MC
723 if (ret == NULL) {
724 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
725 return NULL;
726 }
727
728 ret->meth = group->meth;
b14e6015 729 ret->curve_name = group->curve_name;
0f113f3e
MC
730
731 if (!ret->meth->point_init(ret)) {
732 OPENSSL_free(ret);
733 return NULL;
734 }
735
736 return ret;
737}
0657bf9c
BM
738
739void EC_POINT_free(EC_POINT *point)
0f113f3e 740{
12a765a5 741 if (point == NULL)
0f113f3e 742 return;
7711de24 743
0f113f3e
MC
744 if (point->meth->point_finish != 0)
745 point->meth->point_finish(point);
746 OPENSSL_free(point);
747}
0657bf9c
BM
748
749void EC_POINT_clear_free(EC_POINT *point)
0f113f3e 750{
12a765a5 751 if (point == NULL)
0f113f3e
MC
752 return;
753
754 if (point->meth->point_clear_finish != 0)
755 point->meth->point_clear_finish(point);
756 else if (point->meth->point_finish != 0)
757 point->meth->point_finish(point);
b4faea50 758 OPENSSL_clear_free(point, sizeof(*point));
0f113f3e 759}
0657bf9c
BM
760
761int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
0f113f3e
MC
762{
763 if (dest->meth->point_copy == 0) {
764 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
765 return 0;
766 }
b14e6015
MC
767 if (dest->meth != src->meth
768 || (dest->curve_name != src->curve_name
8402cd5f
SL
769 && dest->curve_name != 0
770 && src->curve_name != 0)) {
0f113f3e
MC
771 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
772 return 0;
773 }
774 if (dest == src)
775 return 1;
776 return dest->meth->point_copy(dest, src);
777}
0657bf9c 778
7793f30e 779EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
0f113f3e
MC
780{
781 EC_POINT *t;
782 int r;
783
784 if (a == NULL)
785 return NULL;
786
787 t = EC_POINT_new(group);
788 if (t == NULL)
26a7d938 789 return NULL;
0f113f3e
MC
790 r = EC_POINT_copy(t, a);
791 if (!r) {
792 EC_POINT_free(t);
793 return NULL;
8fdc3734
RS
794 }
795 return t;
0f113f3e 796}
7793f30e 797
23ccae80 798#ifndef OPENSSL_NO_DEPRECATED_3_0
48fe4d62 799const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
0f113f3e
MC
800{
801 return point->meth;
802}
23ccae80 803#endif
48fe4d62 804
226cc7de 805int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
0f113f3e
MC
806{
807 if (group->meth->point_set_to_infinity == 0) {
808 ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
809 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
810 return 0;
811 }
812 if (group->meth != point->meth) {
813 ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
814 return 0;
815 }
816 return group->meth->point_set_to_infinity(group, point);
817}
818
07caec83 819#ifndef OPENSSL_NO_DEPRECATED_3_0
0f113f3e
MC
820int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
821 EC_POINT *point, const BIGNUM *x,
822 const BIGNUM *y, const BIGNUM *z,
823 BN_CTX *ctx)
824{
07caec83 825 if (group->meth->field_type != NID_X9_62_prime_field) {
0f113f3e
MC
826 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
827 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
828 return 0;
829 }
b14e6015 830 if (!ec_point_is_compat(point, group)) {
0f113f3e
MC
831 ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
832 EC_R_INCOMPATIBLE_OBJECTS);
833 return 0;
834 }
07caec83 835 return ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
0f113f3e
MC
836}
837
838int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
839 const EC_POINT *point, BIGNUM *x,
840 BIGNUM *y, BIGNUM *z,
841 BN_CTX *ctx)
842{
07caec83 843 if (group->meth->field_type != NID_X9_62_prime_field) {
0f113f3e
MC
844 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
845 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
846 return 0;
847 }
b14e6015 848 if (!ec_point_is_compat(point, group)) {
0f113f3e
MC
849 ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
850 EC_R_INCOMPATIBLE_OBJECTS);
851 return 0;
852 }
07caec83 853 return ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point, x, y, z, ctx);
0f113f3e 854}
07caec83 855#endif
0f113f3e 856
8e3cced7
MC
857int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
858 const BIGNUM *x, const BIGNUM *y,
859 BN_CTX *ctx)
0f113f3e 860{
8e3cced7
MC
861 if (group->meth->point_set_affine_coordinates == NULL) {
862 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES,
0f113f3e
MC
863 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
864 return 0;
865 }
b14e6015 866 if (!ec_point_is_compat(point, group)) {
8e3cced7 867 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
0f113f3e
MC
868 return 0;
869 }
1e2012b7
EK
870 if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
871 return 0;
872
873 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
8e3cced7 874 ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE);
1e2012b7
EK
875 return 0;
876 }
877 return 1;
0f113f3e 878}
226cc7de 879
936c2b9e 880#ifndef OPENSSL_NO_DEPRECATED_3_0
8e3cced7
MC
881int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
882 EC_POINT *point, const BIGNUM *x,
883 const BIGNUM *y, BN_CTX *ctx)
884{
885 return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
886}
887
50db8163 888# ifndef OPENSSL_NO_EC2M
0f113f3e
MC
889int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
890 EC_POINT *point, const BIGNUM *x,
891 const BIGNUM *y, BN_CTX *ctx)
892{
8e3cced7
MC
893 return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
894}
50db8163 895# endif
8e3cced7
MC
896#endif
897
898int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
899 const EC_POINT *point, BIGNUM *x, BIGNUM *y,
900 BN_CTX *ctx)
901{
902 if (group->meth->point_get_affine_coordinates == NULL) {
903 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES,
0f113f3e
MC
904 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
905 return 0;
906 }
b14e6015 907 if (!ec_point_is_compat(point, group)) {
8e3cced7 908 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
1e2012b7
EK
909 return 0;
910 }
bfb10b97
BB
911 if (EC_POINT_is_at_infinity(group, point)) {
912 ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
913 return 0;
914 }
8e3cced7 915 return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
0f113f3e 916}
7793f30e 917
936c2b9e 918#ifndef OPENSSL_NO_DEPRECATED_3_0
0f113f3e
MC
919int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
920 const EC_POINT *point, BIGNUM *x,
921 BIGNUM *y, BN_CTX *ctx)
922{
8e3cced7 923 return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
0f113f3e 924}
7793f30e 925
50db8163 926# ifndef OPENSSL_NO_EC2M
0f113f3e
MC
927int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
928 const EC_POINT *point, BIGNUM *x,
929 BIGNUM *y, BN_CTX *ctx)
930{
8e3cced7 931 return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
0f113f3e 932}
50db8163 933# endif
b3310161 934#endif
7793f30e 935
0f113f3e
MC
936int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
937 const EC_POINT *b, BN_CTX *ctx)
938{
939 if (group->meth->add == 0) {
940 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
941 return 0;
942 }
b14e6015
MC
943 if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
944 || !ec_point_is_compat(b, group)) {
0f113f3e
MC
945 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
946 return 0;
947 }
948 return group->meth->add(group, r, a, b, ctx);
949}
950
951int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
952 BN_CTX *ctx)
953{
954 if (group->meth->dbl == 0) {
955 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
956 return 0;
957 }
b14e6015 958 if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
0f113f3e
MC
959 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
960 return 0;
961 }
962 return group->meth->dbl(group, r, a, ctx);
963}
0657bf9c 964
1d5bd6cf 965int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
0f113f3e
MC
966{
967 if (group->meth->invert == 0) {
968 ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
969 return 0;
970 }
b14e6015 971 if (!ec_point_is_compat(a, group)) {
0f113f3e
MC
972 ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
973 return 0;
974 }
975 return group->meth->invert(group, a, ctx);
976}
1d5bd6cf 977
0657bf9c 978int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
0f113f3e
MC
979{
980 if (group->meth->is_at_infinity == 0) {
981 ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
982 ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
983 return 0;
984 }
b14e6015 985 if (!ec_point_is_compat(point, group)) {
0f113f3e
MC
986 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
987 return 0;
988 }
989 return group->meth->is_at_infinity(group, point);
990}
991
68886be7
MC
992/*
993 * Check whether an EC_POINT is on the curve or not. Note that the return
994 * value for this function should NOT be treated as a boolean. Return values:
995 * 1: The point is on the curve
996 * 0: The point is not on the curve
997 * -1: An error occurred
998 */
0f113f3e
MC
999int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
1000 BN_CTX *ctx)
1001{
1002 if (group->meth->is_on_curve == 0) {
1003 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1004 return 0;
1005 }
b14e6015 1006 if (!ec_point_is_compat(point, group)) {
0f113f3e
MC
1007 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
1008 return 0;
1009 }
1010 return group->meth->is_on_curve(group, point, ctx);
1011}
1012
1013int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
1014 BN_CTX *ctx)
1015{
1016 if (group->meth->point_cmp == 0) {
1017 ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1018 return -1;
1019 }
b14e6015 1020 if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
0f113f3e
MC
1021 ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
1022 return -1;
1023 }
1024 return group->meth->point_cmp(group, a, b, ctx);
1025}
1d5bd6cf 1026
c2f2db9b 1027#ifndef OPENSSL_NO_DEPRECATED_3_0
e869d4bd 1028int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
0f113f3e
MC
1029{
1030 if (group->meth->make_affine == 0) {
1031 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1032 return 0;
1033 }
b14e6015 1034 if (!ec_point_is_compat(point, group)) {
0f113f3e
MC
1035 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1036 return 0;
1037 }
1038 return group->meth->make_affine(group, point, ctx);
1039}
1040
1041int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1042 EC_POINT *points[], BN_CTX *ctx)
1043{
1044 size_t i;
1045
1046 if (group->meth->points_make_affine == 0) {
1047 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1048 return 0;
1049 }
1050 for (i = 0; i < num; i++) {
b14e6015 1051 if (!ec_point_is_compat(points[i], group)) {
0f113f3e
MC
1052 ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
1053 return 0;
1054 }
1055 }
1056 return group->meth->points_make_affine(group, num, points, ctx);
1057}
c2f2db9b 1058#endif
0f113f3e
MC
1059
1060/*
1061 * Functions for point multiplication. If group->meth->mul is 0, we use the
1062 * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1063 * methods.
37c660ff
BM
1064 */
1065
4fcd15c1 1066#ifndef OPENSSL_NO_DEPRECATED_3_0
37c660ff 1067int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
0f113f3e
MC
1068 size_t num, const EC_POINT *points[],
1069 const BIGNUM *scalars[], BN_CTX *ctx)
1070{
01ad66f8
NT
1071 int ret = 0;
1072 size_t i = 0;
f844f9eb 1073#ifndef FIPS_MODULE
01ad66f8 1074 BN_CTX *new_ctx = NULL;
a9612d6c 1075#endif
a9612d6c 1076
01ad66f8
NT
1077 if (!ec_point_is_compat(r, group)) {
1078 ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
1079 return 0;
1080 }
1eb9b54a
BE
1081
1082 if (scalar == NULL && num == 0)
1083 return EC_POINT_set_to_infinity(group, r);
1084
01ad66f8
NT
1085 for (i = 0; i < num; i++) {
1086 if (!ec_point_is_compat(points[i], group)) {
1087 ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
1088 return 0;
1089 }
1090 }
1091
f844f9eb 1092#ifndef FIPS_MODULE
0e8b6c97
AT
1093 if (ctx == NULL)
1094 ctx = new_ctx = BN_CTX_secure_new();
1095#endif
1096 if (ctx == NULL) {
1097 ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
1098 return 0;
1099 }
1100
01ad66f8
NT
1101 if (group->meth->mul != NULL)
1102 ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1103 else
0f113f3e 1104 /* use default */
01ad66f8 1105 ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
37c660ff 1106
f844f9eb 1107#ifndef FIPS_MODULE
01ad66f8 1108 BN_CTX_free(new_ctx);
a9612d6c 1109#endif
01ad66f8 1110 return ret;
0f113f3e 1111}
4fcd15c1 1112#endif
37c660ff
BM
1113
1114int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
0f113f3e
MC
1115 const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1116{
4fcd15c1 1117 int ret = 0;
9c47a338 1118 size_t num;
4fcd15c1
BB
1119#ifndef FIPS_MODULE
1120 BN_CTX *new_ctx = NULL;
1121#endif
37c660ff 1122
4fcd15c1
BB
1123 if (!ec_point_is_compat(r, group)
1124 || (point != NULL && !ec_point_is_compat(point, group))) {
1125 ECerr(EC_F_EC_POINT_MUL, EC_R_INCOMPATIBLE_OBJECTS);
1126 return 0;
1127 }
37c660ff 1128
4fcd15c1
BB
1129 if (g_scalar == NULL && p_scalar == NULL)
1130 return EC_POINT_set_to_infinity(group, r);
37c660ff 1131
4fcd15c1
BB
1132#ifndef FIPS_MODULE
1133 if (ctx == NULL)
1134 ctx = new_ctx = BN_CTX_secure_new();
1135#endif
1136 if (ctx == NULL) {
1137 ECerr(EC_F_EC_POINT_MUL, ERR_R_INTERNAL_ERROR);
1138 return 0;
1139 }
1140
9c47a338 1141 num = (point != NULL && p_scalar != NULL) ? 1 : 0;
4fcd15c1 1142 if (group->meth->mul != NULL)
9c47a338 1143 ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
4fcd15c1
BB
1144 else
1145 /* use default */
9c47a338 1146 ret = ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
4fcd15c1
BB
1147
1148#ifndef FIPS_MODULE
1149 BN_CTX_free(new_ctx);
1150#endif
1151 return ret;
0f113f3e 1152}
37c660ff 1153
6b4eb933 1154#ifndef OPENSSL_NO_DEPRECATED_3_0
37c660ff 1155int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
0f113f3e
MC
1156{
1157 if (group->meth->mul == 0)
1158 /* use default */
1159 return ec_wNAF_precompute_mult(group, ctx);
37c660ff 1160
0f113f3e
MC
1161 if (group->meth->precompute_mult != 0)
1162 return group->meth->precompute_mult(group, ctx);
1163 else
1164 return 1; /* nothing to do, so report success */
1165}
37c660ff
BM
1166
1167int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
0f113f3e
MC
1168{
1169 if (group->meth->mul == 0)
1170 /* use default */
1171 return ec_wNAF_have_precompute_mult(group);
1172
1173 if (group->meth->have_precompute_mult != 0)
1174 return group->meth->have_precompute_mult(group);
1175 else
1176 return 0; /* cannot tell whether precomputation has
1177 * been performed */
1178}
6b4eb933 1179#endif
0f113f3e
MC
1180
1181/*
1182 * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
1183 * returns one on success. On error it returns zero.
1184 */
eb791696 1185static int ec_precompute_mont_data(EC_GROUP *group)
0f113f3e 1186{
a9612d6c 1187 BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
0f113f3e
MC
1188 int ret = 0;
1189
23a1d5e9
RS
1190 BN_MONT_CTX_free(group->mont_data);
1191 group->mont_data = NULL;
0f113f3e
MC
1192
1193 if (ctx == NULL)
1194 goto err;
1195
1196 group->mont_data = BN_MONT_CTX_new();
90945fa3 1197 if (group->mont_data == NULL)
0f113f3e
MC
1198 goto err;
1199
1200 if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
1201 BN_MONT_CTX_free(group->mont_data);
1202 group->mont_data = NULL;
1203 goto err;
1204 }
1205
1206 ret = 1;
1207
1208 err:
1209
23a1d5e9 1210 BN_CTX_free(ctx);
0f113f3e
MC
1211 return ret;
1212}
3aef36ff 1213
f844f9eb 1214#ifndef FIPS_MODULE
3aef36ff
RS
1215int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
1216{
1217 return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
1218}
1219
1220void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
1221{
1222 return CRYPTO_get_ex_data(&key->ex_data, idx);
1223}
a9612d6c 1224#endif
77470e98
DSH
1225
1226int ec_group_simple_order_bits(const EC_GROUP *group)
1227{
1228 if (group->order == NULL)
1229 return 0;
1230 return BN_num_bits(group->order);
1231}
eb791696 1232
c11d372b 1233static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
792546eb 1234 const BIGNUM *x, BN_CTX *ctx)
c11d372b 1235{
262dccc0 1236 BIGNUM *e = NULL;
c11d372b 1237 int ret = 0;
f844f9eb 1238#ifndef FIPS_MODULE
a9612d6c 1239 BN_CTX *new_ctx = NULL;
0e8b6c97
AT
1240#endif
1241
1242 if (group->mont_data == NULL)
1243 return 0;
c11d372b 1244
f844f9eb 1245#ifndef FIPS_MODULE
a9612d6c
MC
1246 if (ctx == NULL)
1247 ctx = new_ctx = BN_CTX_secure_new();
1248#endif
1249 if (ctx == NULL)
792546eb
BB
1250 return 0;
1251
c11d372b 1252 BN_CTX_start(ctx);
262dccc0 1253 if ((e = BN_CTX_get(ctx)) == NULL)
c11d372b
BB
1254 goto err;
1255
792546eb
BB
1256 /*-
1257 * We want inverse in constant time, therefore we utilize the fact
1258 * order must be prime and use Fermats Little Theorem instead.
1259 */
1260 if (!BN_set_word(e, 2))
1261 goto err;
1262 if (!BN_sub(e, group->order, e))
1263 goto err;
1264 /*-
1265 * Exponent e is public.
1266 * No need for scatter-gather or BN_FLG_CONSTTIME.
1267 */
1268 if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
1269 goto err;
c11d372b 1270
792546eb 1271 ret = 1;
c11d372b
BB
1272
1273 err:
ce1415ed 1274 BN_CTX_end(ctx);
f844f9eb 1275#ifndef FIPS_MODULE
c11d372b 1276 BN_CTX_free(new_ctx);
a9612d6c 1277#endif
c11d372b
BB
1278 return ret;
1279}
1280
792546eb
BB
1281/*-
1282 * Default behavior, if group->meth->field_inverse_mod_ord is NULL:
1283 * - When group->order is even, this function returns an error.
1284 * - When group->order is otherwise composite, the correctness
1285 * of the output is not guaranteed.
1286 * - When x is outside the range [1, group->order), the correctness
1287 * of the output is not guaranteed.
1288 * - Otherwise, this function returns the multiplicative inverse in the
1289 * range [1, group->order).
1290 *
1291 * EC_METHODs must implement their own field_inverse_mod_ord for
1292 * other functionality.
1293 */
1294int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
1295 const BIGNUM *x, BN_CTX *ctx)
eb791696
AP
1296{
1297 if (group->meth->field_inverse_mod_ord != NULL)
1298 return group->meth->field_inverse_mod_ord(group, res, x, ctx);
1299 else
c11d372b 1300 return ec_field_inverse_mod_ord(group, res, x, ctx);
eb791696 1301}
f667820c
SH
1302
1303/*-
1304 * Coordinate blinding for EC_POINT.
1305 *
1306 * The underlying EC_METHOD can optionally implement this function:
1307 * underlying implementations should return 0 on errors, or 1 on
1308 * success.
1309 *
1310 * This wrapper returns 1 in case the underlying EC_METHOD does not
1311 * support coordinate blinding.
1312 */
1313int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
1314{
1315 if (group->meth->blind_coordinates == NULL)
1316 return 1; /* ignore if not implemented */
1317
1318 return group->meth->blind_coordinates(group, p, ctx);
1319}