1a89c9211Schristos /*
2*5b10f583Schristos  * Copyright 2001-2022 The OpenSSL Project Authors. All Rights Reserved.
3e7ccb6d1Schristos  * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
44ec2eca9Schristos  *
5*5b10f583Schristos  * Licensed under the Apache License 2.0 (the "License").  You may not use
64ec2eca9Schristos  * this file except in compliance with the License.  You can obtain a copy
74ec2eca9Schristos  * in the file LICENSE in the source distribution or at
84ec2eca9Schristos  * https://www.openssl.org/source/license.html
9a89c9211Schristos  */
104ec2eca9Schristos 
11*5b10f583Schristos /*
12*5b10f583Schristos  * EC_GROUP low level APIs are deprecated for public use, but still ok for
13*5b10f583Schristos  * internal use.
14*5b10f583Schristos  */
15*5b10f583Schristos #include "internal/deprecated.h"
16a89c9211Schristos 
17*5b10f583Schristos #include <string.h>
18*5b10f583Schristos #include <openssl/params.h>
19*5b10f583Schristos #include <openssl/core_names.h>
20a89c9211Schristos #include <openssl/err.h>
21a89c9211Schristos #include <openssl/opensslv.h>
22*5b10f583Schristos #include "crypto/ec.h"
23*5b10f583Schristos #include "internal/nelem.h"
24cb006352Schristos #include "ec_local.h"
25a89c9211Schristos 
26a89c9211Schristos /* functions for EC_GROUP objects */
27a89c9211Schristos 
ossl_ec_group_new_ex(OSSL_LIB_CTX * libctx,const char * propq,const EC_METHOD * meth)28*5b10f583Schristos EC_GROUP *ossl_ec_group_new_ex(OSSL_LIB_CTX *libctx, const char *propq,
29*5b10f583Schristos                                const EC_METHOD *meth)
30a89c9211Schristos {
31a89c9211Schristos     EC_GROUP *ret;
32a89c9211Schristos 
33ac65d4acSspz     if (meth == NULL) {
34*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_SLOT_FULL);
35a89c9211Schristos         return NULL;
36a89c9211Schristos     }
37ac65d4acSspz     if (meth->group_init == 0) {
38*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
39a89c9211Schristos         return NULL;
40a89c9211Schristos     }
41a89c9211Schristos 
424ec2eca9Schristos     ret = OPENSSL_zalloc(sizeof(*ret));
43ac65d4acSspz     if (ret == NULL) {
44*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
45a89c9211Schristos         return NULL;
46a89c9211Schristos     }
47a89c9211Schristos 
48*5b10f583Schristos     ret->libctx = libctx;
49*5b10f583Schristos     if (propq != NULL) {
50*5b10f583Schristos         ret->propq = OPENSSL_strdup(propq);
51*5b10f583Schristos         if (ret->propq == NULL) {
52*5b10f583Schristos             ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
53*5b10f583Schristos             goto err;
54*5b10f583Schristos         }
55*5b10f583Schristos     }
56a89c9211Schristos     ret->meth = meth;
574ec2eca9Schristos     if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
584ec2eca9Schristos         ret->order = BN_new();
594ec2eca9Schristos         if (ret->order == NULL)
604ec2eca9Schristos             goto err;
614ec2eca9Schristos         ret->cofactor = BN_new();
624ec2eca9Schristos         if (ret->cofactor == NULL)
634ec2eca9Schristos             goto err;
644ec2eca9Schristos     }
65*5b10f583Schristos     ret->asn1_flag = OPENSSL_EC_EXPLICIT_CURVE;
66a89c9211Schristos     ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
674ec2eca9Schristos     if (!meth->group_init(ret))
684ec2eca9Schristos         goto err;
694ec2eca9Schristos     return ret;
70a89c9211Schristos 
714ec2eca9Schristos  err:
724ec2eca9Schristos     BN_free(ret->order);
734ec2eca9Schristos     BN_free(ret->cofactor);
74*5b10f583Schristos     OPENSSL_free(ret->propq);
75a89c9211Schristos     OPENSSL_free(ret);
76a89c9211Schristos     return NULL;
77a89c9211Schristos }
78a89c9211Schristos 
79*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
80*5b10f583Schristos # ifndef FIPS_MODULE
EC_GROUP_new(const EC_METHOD * meth)81*5b10f583Schristos EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
82*5b10f583Schristos {
83*5b10f583Schristos     return ossl_ec_group_new_ex(NULL, NULL, meth);
84*5b10f583Schristos }
85*5b10f583Schristos # endif
86*5b10f583Schristos #endif
87*5b10f583Schristos 
EC_pre_comp_free(EC_GROUP * group)884ec2eca9Schristos void EC_pre_comp_free(EC_GROUP *group)
894ec2eca9Schristos {
904ec2eca9Schristos     switch (group->pre_comp_type) {
91e7ccb6d1Schristos     case PCT_none:
924ec2eca9Schristos         break;
934ec2eca9Schristos     case PCT_nistz256:
94e7ccb6d1Schristos #ifdef ECP_NISTZ256_ASM
954ec2eca9Schristos         EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
964ec2eca9Schristos #endif
97e7ccb6d1Schristos         break;
984ec2eca9Schristos #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
994ec2eca9Schristos     case PCT_nistp224:
1004ec2eca9Schristos         EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
1014ec2eca9Schristos         break;
1024ec2eca9Schristos     case PCT_nistp256:
1034ec2eca9Schristos         EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
1044ec2eca9Schristos         break;
1054ec2eca9Schristos     case PCT_nistp521:
1064ec2eca9Schristos         EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
1074ec2eca9Schristos         break;
108e7ccb6d1Schristos #else
109e7ccb6d1Schristos     case PCT_nistp224:
110e7ccb6d1Schristos     case PCT_nistp256:
111e7ccb6d1Schristos     case PCT_nistp521:
112e7ccb6d1Schristos         break;
1134ec2eca9Schristos #endif
1144ec2eca9Schristos     case PCT_ec:
1154ec2eca9Schristos         EC_ec_pre_comp_free(group->pre_comp.ec);
1164ec2eca9Schristos         break;
1174ec2eca9Schristos     }
1184ec2eca9Schristos     group->pre_comp.ec = NULL;
119a89c9211Schristos }
120a89c9211Schristos 
EC_GROUP_free(EC_GROUP * group)121a89c9211Schristos void EC_GROUP_free(EC_GROUP *group)
122a89c9211Schristos {
123ac65d4acSspz     if (!group)
124ac65d4acSspz         return;
125a89c9211Schristos 
126a89c9211Schristos     if (group->meth->group_finish != 0)
127a89c9211Schristos         group->meth->group_finish(group);
128a89c9211Schristos 
1294ec2eca9Schristos     EC_pre_comp_free(group);
1301440100dSspz     BN_MONT_CTX_free(group->mont_data);
131a89c9211Schristos     EC_POINT_free(group->generator);
1324ec2eca9Schristos     BN_free(group->order);
1334ec2eca9Schristos     BN_free(group->cofactor);
134a89c9211Schristos     OPENSSL_free(group->seed);
135*5b10f583Schristos     OPENSSL_free(group->propq);
136a89c9211Schristos     OPENSSL_free(group);
137a89c9211Schristos }
138a89c9211Schristos 
139*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_GROUP_clear_free(EC_GROUP * group)140a89c9211Schristos void EC_GROUP_clear_free(EC_GROUP *group)
141a89c9211Schristos {
142ac65d4acSspz     if (!group)
143ac65d4acSspz         return;
144a89c9211Schristos 
145a89c9211Schristos     if (group->meth->group_clear_finish != 0)
146a89c9211Schristos         group->meth->group_clear_finish(group);
147a89c9211Schristos     else if (group->meth->group_finish != 0)
148a89c9211Schristos         group->meth->group_finish(group);
149a89c9211Schristos 
1504ec2eca9Schristos     EC_pre_comp_free(group);
1511440100dSspz     BN_MONT_CTX_free(group->mont_data);
152a89c9211Schristos     EC_POINT_clear_free(group->generator);
1534ec2eca9Schristos     BN_clear_free(group->order);
1544ec2eca9Schristos     BN_clear_free(group->cofactor);
1554ec2eca9Schristos     OPENSSL_clear_free(group->seed, group->seed_len);
1564ec2eca9Schristos     OPENSSL_clear_free(group, sizeof(*group));
157a89c9211Schristos }
158*5b10f583Schristos #endif
159a89c9211Schristos 
EC_GROUP_copy(EC_GROUP * dest,const EC_GROUP * src)160a89c9211Schristos int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
161a89c9211Schristos {
162ac65d4acSspz     if (dest->meth->group_copy == 0) {
163*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
164a89c9211Schristos         return 0;
165a89c9211Schristos     }
166ac65d4acSspz     if (dest->meth != src->meth) {
167*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
168a89c9211Schristos         return 0;
169a89c9211Schristos     }
170a89c9211Schristos     if (dest == src)
171a89c9211Schristos         return 1;
172a89c9211Schristos 
173*5b10f583Schristos     dest->libctx = src->libctx;
17495661423Schristos     dest->curve_name = src->curve_name;
17595661423Schristos 
1764ec2eca9Schristos     /* Copy precomputed */
1774ec2eca9Schristos     dest->pre_comp_type = src->pre_comp_type;
1784ec2eca9Schristos     switch (src->pre_comp_type) {
179e7ccb6d1Schristos     case PCT_none:
1804ec2eca9Schristos         dest->pre_comp.ec = NULL;
1814ec2eca9Schristos         break;
1824ec2eca9Schristos     case PCT_nistz256:
183e7ccb6d1Schristos #ifdef ECP_NISTZ256_ASM
1844ec2eca9Schristos         dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
1854ec2eca9Schristos #endif
186e7ccb6d1Schristos         break;
1874ec2eca9Schristos #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1884ec2eca9Schristos     case PCT_nistp224:
1894ec2eca9Schristos         dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
1904ec2eca9Schristos         break;
1914ec2eca9Schristos     case PCT_nistp256:
1924ec2eca9Schristos         dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
1934ec2eca9Schristos         break;
1944ec2eca9Schristos     case PCT_nistp521:
1954ec2eca9Schristos         dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
1964ec2eca9Schristos         break;
197e7ccb6d1Schristos #else
198e7ccb6d1Schristos     case PCT_nistp224:
199e7ccb6d1Schristos     case PCT_nistp256:
200e7ccb6d1Schristos     case PCT_nistp521:
201e7ccb6d1Schristos         break;
2024ec2eca9Schristos #endif
2034ec2eca9Schristos     case PCT_ec:
2044ec2eca9Schristos         dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
2054ec2eca9Schristos         break;
206a89c9211Schristos     }
207a89c9211Schristos 
2084ec2eca9Schristos     if (src->mont_data != NULL) {
2091440100dSspz         if (dest->mont_data == NULL) {
2101440100dSspz             dest->mont_data = BN_MONT_CTX_new();
2111440100dSspz             if (dest->mont_data == NULL)
2121440100dSspz                 return 0;
2131440100dSspz         }
2141440100dSspz         if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
2151440100dSspz             return 0;
2161440100dSspz     } else {
2171440100dSspz         /* src->generator == NULL */
2181440100dSspz         BN_MONT_CTX_free(dest->mont_data);
2191440100dSspz         dest->mont_data = NULL;
2201440100dSspz     }
2211440100dSspz 
222ac65d4acSspz     if (src->generator != NULL) {
223ac65d4acSspz         if (dest->generator == NULL) {
224a89c9211Schristos             dest->generator = EC_POINT_new(dest);
225ac65d4acSspz             if (dest->generator == NULL)
226ac65d4acSspz                 return 0;
227a89c9211Schristos         }
228ac65d4acSspz         if (!EC_POINT_copy(dest->generator, src->generator))
229ac65d4acSspz             return 0;
230ac65d4acSspz     } else {
231a89c9211Schristos         /* src->generator == NULL */
232a89c9211Schristos         EC_POINT_clear_free(dest->generator);
233a89c9211Schristos         dest->generator = NULL;
234a89c9211Schristos     }
235a89c9211Schristos 
2364ec2eca9Schristos     if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
2374ec2eca9Schristos         if (!BN_copy(dest->order, src->order))
238ac65d4acSspz             return 0;
2394ec2eca9Schristos         if (!BN_copy(dest->cofactor, src->cofactor))
240ac65d4acSspz             return 0;
2414ec2eca9Schristos     }
242a89c9211Schristos 
243a89c9211Schristos     dest->asn1_flag = src->asn1_flag;
244a89c9211Schristos     dest->asn1_form = src->asn1_form;
245986ce643Schristos     dest->decoded_from_explicit_params = src->decoded_from_explicit_params;
246a89c9211Schristos 
247ac65d4acSspz     if (src->seed) {
248a89c9211Schristos         OPENSSL_free(dest->seed);
249e7ccb6d1Schristos         if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
250*5b10f583Schristos             ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
251a89c9211Schristos             return 0;
252e7ccb6d1Schristos         }
253a89c9211Schristos         if (!memcpy(dest->seed, src->seed, src->seed_len))
254a89c9211Schristos             return 0;
255a89c9211Schristos         dest->seed_len = src->seed_len;
256ac65d4acSspz     } else {
257a89c9211Schristos         OPENSSL_free(dest->seed);
258a89c9211Schristos         dest->seed = NULL;
259a89c9211Schristos         dest->seed_len = 0;
260a89c9211Schristos     }
261a89c9211Schristos 
262a89c9211Schristos     return dest->meth->group_copy(dest, src);
263a89c9211Schristos }
264a89c9211Schristos 
EC_GROUP_dup(const EC_GROUP * a)265a89c9211Schristos EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
266a89c9211Schristos {
267a89c9211Schristos     EC_GROUP *t = NULL;
268a89c9211Schristos     int ok = 0;
269a89c9211Schristos 
270ac65d4acSspz     if (a == NULL)
271ac65d4acSspz         return NULL;
272a89c9211Schristos 
273*5b10f583Schristos     if ((t = ossl_ec_group_new_ex(a->libctx, a->propq, a->meth)) == NULL)
274e7ccb6d1Schristos         return NULL;
275ac65d4acSspz     if (!EC_GROUP_copy(t, a))
276ac65d4acSspz         goto err;
277a89c9211Schristos 
278a89c9211Schristos     ok = 1;
279a89c9211Schristos 
280a89c9211Schristos  err:
281ac65d4acSspz     if (!ok) {
282ac65d4acSspz         EC_GROUP_free(t);
283a89c9211Schristos         return NULL;
2844ec2eca9Schristos     }
285ac65d4acSspz         return t;
286a89c9211Schristos }
287a89c9211Schristos 
288*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_GROUP_method_of(const EC_GROUP * group)289a89c9211Schristos const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
290a89c9211Schristos {
291a89c9211Schristos     return group->meth;
292a89c9211Schristos }
293a89c9211Schristos 
EC_METHOD_get_field_type(const EC_METHOD * meth)294a89c9211Schristos int EC_METHOD_get_field_type(const EC_METHOD *meth)
295a89c9211Schristos {
296a89c9211Schristos     return meth->field_type;
297a89c9211Schristos }
298*5b10f583Schristos #endif
299a89c9211Schristos 
300e7ccb6d1Schristos static int ec_precompute_mont_data(EC_GROUP *);
301e7ccb6d1Schristos 
302f23d01f8Schristos /*-
303f23d01f8Schristos  * Try computing cofactor from the generator order (n) and field cardinality (q).
304f23d01f8Schristos  * This works for all curves of cryptographic interest.
305f23d01f8Schristos  *
306f23d01f8Schristos  * Hasse thm: q + 1 - 2*sqrt(q) <= n*h <= q + 1 + 2*sqrt(q)
307f23d01f8Schristos  * h_min = (q + 1 - 2*sqrt(q))/n
308f23d01f8Schristos  * h_max = (q + 1 + 2*sqrt(q))/n
309f23d01f8Schristos  * h_max - h_min = 4*sqrt(q)/n
310f23d01f8Schristos  * So if n > 4*sqrt(q) holds, there is only one possible value for h:
311f23d01f8Schristos  * h = \lfloor (h_min + h_max)/2 \rceil = \lfloor (q + 1)/n \rceil
312f23d01f8Schristos  *
313f23d01f8Schristos  * Otherwise, zero cofactor and return success.
314f23d01f8Schristos  */
ec_guess_cofactor(EC_GROUP * group)315f23d01f8Schristos static int ec_guess_cofactor(EC_GROUP *group) {
316f23d01f8Schristos     int ret = 0;
317f23d01f8Schristos     BN_CTX *ctx = NULL;
318f23d01f8Schristos     BIGNUM *q = NULL;
319f23d01f8Schristos 
320f23d01f8Schristos     /*-
321f23d01f8Schristos      * If the cofactor is too large, we cannot guess it.
322f23d01f8Schristos      * The RHS of below is a strict overestimate of lg(4 * sqrt(q))
323f23d01f8Schristos      */
324f23d01f8Schristos     if (BN_num_bits(group->order) <= (BN_num_bits(group->field) + 1) / 2 + 3) {
325f23d01f8Schristos         /* default to 0 */
326f23d01f8Schristos         BN_zero(group->cofactor);
327f23d01f8Schristos         /* return success */
328f23d01f8Schristos         return 1;
329f23d01f8Schristos     }
330f23d01f8Schristos 
331*5b10f583Schristos     if ((ctx = BN_CTX_new_ex(group->libctx)) == NULL)
332f23d01f8Schristos         return 0;
333f23d01f8Schristos 
334f23d01f8Schristos     BN_CTX_start(ctx);
335f23d01f8Schristos     if ((q = BN_CTX_get(ctx)) == NULL)
336f23d01f8Schristos         goto err;
337f23d01f8Schristos 
338f23d01f8Schristos     /* set q = 2**m for binary fields; q = p otherwise */
339f23d01f8Schristos     if (group->meth->field_type == NID_X9_62_characteristic_two_field) {
340f23d01f8Schristos         BN_zero(q);
341f23d01f8Schristos         if (!BN_set_bit(q, BN_num_bits(group->field) - 1))
342f23d01f8Schristos             goto err;
343f23d01f8Schristos     } else {
344f23d01f8Schristos         if (!BN_copy(q, group->field))
345f23d01f8Schristos             goto err;
346f23d01f8Schristos     }
347f23d01f8Schristos 
348f23d01f8Schristos     /* compute h = \lfloor (q + 1)/n \rceil = \lfloor (q + 1 + n/2)/n \rfloor */
349f23d01f8Schristos     if (!BN_rshift1(group->cofactor, group->order) /* n/2 */
350f23d01f8Schristos         || !BN_add(group->cofactor, group->cofactor, q) /* q + n/2 */
351f23d01f8Schristos         /* q + 1 + n/2 */
352f23d01f8Schristos         || !BN_add(group->cofactor, group->cofactor, BN_value_one())
353f23d01f8Schristos         /* (q + 1 + n/2)/n */
354f23d01f8Schristos         || !BN_div(group->cofactor, NULL, group->cofactor, group->order, ctx))
355f23d01f8Schristos         goto err;
356f23d01f8Schristos     ret = 1;
357f23d01f8Schristos  err:
358f23d01f8Schristos     BN_CTX_end(ctx);
359f23d01f8Schristos     BN_CTX_free(ctx);
360f23d01f8Schristos     return ret;
361f23d01f8Schristos }
362f23d01f8Schristos 
EC_GROUP_set_generator(EC_GROUP * group,const EC_POINT * generator,const BIGNUM * order,const BIGNUM * cofactor)363ac65d4acSspz int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
364ac65d4acSspz                            const BIGNUM *order, const BIGNUM *cofactor)
365a89c9211Schristos {
366ac65d4acSspz     if (generator == NULL) {
367*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
368a89c9211Schristos         return 0;
369a89c9211Schristos     }
370a89c9211Schristos 
371f23d01f8Schristos     /* require group->field >= 1 */
372f23d01f8Schristos     if (group->field == NULL || BN_is_zero(group->field)
373f23d01f8Schristos         || BN_is_negative(group->field)) {
374*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
375f23d01f8Schristos         return 0;
376f23d01f8Schristos     }
377f23d01f8Schristos 
378f23d01f8Schristos     /*-
379f23d01f8Schristos      * - require order >= 1
380f23d01f8Schristos      * - enforce upper bound due to Hasse thm: order can be no more than one bit
381f23d01f8Schristos      *   longer than field cardinality
382f23d01f8Schristos      */
383f23d01f8Schristos     if (order == NULL || BN_is_zero(order) || BN_is_negative(order)
384f23d01f8Schristos         || BN_num_bits(order) > BN_num_bits(group->field) + 1) {
385*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
386f23d01f8Schristos         return 0;
387f23d01f8Schristos     }
388f23d01f8Schristos 
389f23d01f8Schristos     /*-
390f23d01f8Schristos      * Unfortunately the cofactor is an optional field in many standards.
391f23d01f8Schristos      * Internally, the lib uses 0 cofactor as a marker for "unknown cofactor".
392f23d01f8Schristos      * So accept cofactor == NULL or cofactor >= 0.
393f23d01f8Schristos      */
394f23d01f8Schristos     if (cofactor != NULL && BN_is_negative(cofactor)) {
395*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_UNKNOWN_COFACTOR);
396f23d01f8Schristos         return 0;
397f23d01f8Schristos     }
398f23d01f8Schristos 
399ac65d4acSspz     if (group->generator == NULL) {
400a89c9211Schristos         group->generator = EC_POINT_new(group);
401ac65d4acSspz         if (group->generator == NULL)
402ac65d4acSspz             return 0;
403a89c9211Schristos     }
404ac65d4acSspz     if (!EC_POINT_copy(group->generator, generator))
405ac65d4acSspz         return 0;
406a89c9211Schristos 
4074ec2eca9Schristos     if (!BN_copy(group->order, order))
408ac65d4acSspz         return 0;
409a89c9211Schristos 
410f23d01f8Schristos     /* Either take the provided positive cofactor, or try to compute it */
411f23d01f8Schristos     if (cofactor != NULL && !BN_is_zero(cofactor)) {
4124ec2eca9Schristos         if (!BN_copy(group->cofactor, cofactor))
413ac65d4acSspz             return 0;
414f23d01f8Schristos     } else if (!ec_guess_cofactor(group)) {
4154ec2eca9Schristos         BN_zero(group->cofactor);
416f23d01f8Schristos         return 0;
417f23d01f8Schristos     }
418a89c9211Schristos 
4191440100dSspz     /*
4204ec2eca9Schristos      * Some groups have an order with
4211440100dSspz      * factors of two, which makes the Montgomery setup fail.
4221440100dSspz      * |group->mont_data| will be NULL in this case.
4231440100dSspz      */
4244ec2eca9Schristos     if (BN_is_odd(group->order)) {
4254ec2eca9Schristos         return ec_precompute_mont_data(group);
4264ec2eca9Schristos     }
4271440100dSspz 
4284ec2eca9Schristos     BN_MONT_CTX_free(group->mont_data);
4294ec2eca9Schristos     group->mont_data = NULL;
430a89c9211Schristos     return 1;
431a89c9211Schristos }
432a89c9211Schristos 
EC_GROUP_get0_generator(const EC_GROUP * group)433a89c9211Schristos const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
434a89c9211Schristos {
435a89c9211Schristos     return group->generator;
436a89c9211Schristos }
437a89c9211Schristos 
EC_GROUP_get_mont_data(const EC_GROUP * group)4381440100dSspz BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
4391440100dSspz {
4404ec2eca9Schristos     return group->mont_data;
4411440100dSspz }
4421440100dSspz 
EC_GROUP_get_order(const EC_GROUP * group,BIGNUM * order,BN_CTX * ctx)443a89c9211Schristos int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
444a89c9211Schristos {
4454ec2eca9Schristos     if (group->order == NULL)
4464ec2eca9Schristos         return 0;
4474ec2eca9Schristos     if (!BN_copy(order, group->order))
448a89c9211Schristos         return 0;
449a89c9211Schristos 
450a89c9211Schristos     return !BN_is_zero(order);
451a89c9211Schristos }
452a89c9211Schristos 
EC_GROUP_get0_order(const EC_GROUP * group)4534ec2eca9Schristos const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
4544ec2eca9Schristos {
4554ec2eca9Schristos     return group->order;
4564ec2eca9Schristos }
4574ec2eca9Schristos 
EC_GROUP_order_bits(const EC_GROUP * group)4584ec2eca9Schristos int EC_GROUP_order_bits(const EC_GROUP *group)
4594ec2eca9Schristos {
4604ec2eca9Schristos     return group->meth->group_order_bits(group);
4614ec2eca9Schristos }
4624ec2eca9Schristos 
EC_GROUP_get_cofactor(const EC_GROUP * group,BIGNUM * cofactor,BN_CTX * ctx)463ac65d4acSspz int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
464ac65d4acSspz                           BN_CTX *ctx)
465a89c9211Schristos {
4664ec2eca9Schristos 
4674ec2eca9Schristos     if (group->cofactor == NULL)
4684ec2eca9Schristos         return 0;
4694ec2eca9Schristos     if (!BN_copy(cofactor, group->cofactor))
470a89c9211Schristos         return 0;
471a89c9211Schristos 
4724ec2eca9Schristos     return !BN_is_zero(group->cofactor);
4734ec2eca9Schristos }
4744ec2eca9Schristos 
EC_GROUP_get0_cofactor(const EC_GROUP * group)4754ec2eca9Schristos const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
4764ec2eca9Schristos {
4774ec2eca9Schristos     return group->cofactor;
478a89c9211Schristos }
479a89c9211Schristos 
EC_GROUP_set_curve_name(EC_GROUP * group,int nid)480a89c9211Schristos void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
481a89c9211Schristos {
482a89c9211Schristos     group->curve_name = nid;
483*5b10f583Schristos     group->asn1_flag =
484*5b10f583Schristos         (nid != NID_undef)
485*5b10f583Schristos         ? OPENSSL_EC_NAMED_CURVE
486*5b10f583Schristos         : OPENSSL_EC_EXPLICIT_CURVE;
487a89c9211Schristos }
488a89c9211Schristos 
EC_GROUP_get_curve_name(const EC_GROUP * group)489a89c9211Schristos int EC_GROUP_get_curve_name(const EC_GROUP *group)
490a89c9211Schristos {
491a89c9211Schristos     return group->curve_name;
492a89c9211Schristos }
493a89c9211Schristos 
EC_GROUP_get0_field(const EC_GROUP * group)494*5b10f583Schristos const BIGNUM *EC_GROUP_get0_field(const EC_GROUP *group)
495*5b10f583Schristos {
496*5b10f583Schristos     return group->field;
497*5b10f583Schristos }
498*5b10f583Schristos 
EC_GROUP_get_field_type(const EC_GROUP * group)499*5b10f583Schristos int EC_GROUP_get_field_type(const EC_GROUP *group)
500*5b10f583Schristos {
501*5b10f583Schristos     return group->meth->field_type;
502*5b10f583Schristos }
503*5b10f583Schristos 
EC_GROUP_set_asn1_flag(EC_GROUP * group,int flag)504a89c9211Schristos void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
505a89c9211Schristos {
5064ec2eca9Schristos     group->asn1_flag = flag;
507a89c9211Schristos }
508a89c9211Schristos 
EC_GROUP_get_asn1_flag(const EC_GROUP * group)509a89c9211Schristos int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
510a89c9211Schristos {
5114ec2eca9Schristos     return group->asn1_flag;
512a89c9211Schristos }
513a89c9211Schristos 
EC_GROUP_set_point_conversion_form(EC_GROUP * group,point_conversion_form_t form)514a89c9211Schristos void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
515a89c9211Schristos                                         point_conversion_form_t form)
516a89c9211Schristos {
517a89c9211Schristos     group->asn1_form = form;
518a89c9211Schristos }
519a89c9211Schristos 
EC_GROUP_get_point_conversion_form(const EC_GROUP * group)520ac65d4acSspz point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
521ac65d4acSspz                                                            *group)
522a89c9211Schristos {
523a89c9211Schristos     return group->asn1_form;
524a89c9211Schristos }
525a89c9211Schristos 
EC_GROUP_set_seed(EC_GROUP * group,const unsigned char * p,size_t len)526a89c9211Schristos size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
527a89c9211Schristos {
528a89c9211Schristos     OPENSSL_free(group->seed);
529a89c9211Schristos     group->seed = NULL;
530a89c9211Schristos     group->seed_len = 0;
531a89c9211Schristos 
532a89c9211Schristos     if (!len || !p)
533a89c9211Schristos         return 1;
534a89c9211Schristos 
535e7ccb6d1Schristos     if ((group->seed = OPENSSL_malloc(len)) == NULL) {
536*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
537a89c9211Schristos         return 0;
538e7ccb6d1Schristos     }
539a89c9211Schristos     memcpy(group->seed, p, len);
540a89c9211Schristos     group->seed_len = len;
541a89c9211Schristos 
542a89c9211Schristos     return len;
543a89c9211Schristos }
544a89c9211Schristos 
EC_GROUP_get0_seed(const EC_GROUP * group)545a89c9211Schristos unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
546a89c9211Schristos {
547a89c9211Schristos     return group->seed;
548a89c9211Schristos }
549a89c9211Schristos 
EC_GROUP_get_seed_len(const EC_GROUP * group)550a89c9211Schristos size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
551a89c9211Schristos {
552a89c9211Schristos     return group->seed_len;
553a89c9211Schristos }
554a89c9211Schristos 
EC_GROUP_set_curve(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)555e7ccb6d1Schristos int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
556ac65d4acSspz                        const BIGNUM *b, BN_CTX *ctx)
557a89c9211Schristos {
558ac65d4acSspz     if (group->meth->group_set_curve == 0) {
559*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
560a89c9211Schristos         return 0;
561a89c9211Schristos     }
562a89c9211Schristos     return group->meth->group_set_curve(group, p, a, b, ctx);
563a89c9211Schristos }
564a89c9211Schristos 
EC_GROUP_get_curve(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)565e7ccb6d1Schristos int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
566e7ccb6d1Schristos                        BN_CTX *ctx)
567a89c9211Schristos {
568e7ccb6d1Schristos     if (group->meth->group_get_curve == NULL) {
569*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
570a89c9211Schristos         return 0;
571a89c9211Schristos     }
572a89c9211Schristos     return group->meth->group_get_curve(group, p, a, b, ctx);
573a89c9211Schristos }
574a89c9211Schristos 
575*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_GROUP_set_curve_GFp(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)576e7ccb6d1Schristos int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
577e7ccb6d1Schristos                            const BIGNUM *b, BN_CTX *ctx)
578e7ccb6d1Schristos {
579e7ccb6d1Schristos     return EC_GROUP_set_curve(group, p, a, b, ctx);
580e7ccb6d1Schristos }
581e7ccb6d1Schristos 
EC_GROUP_get_curve_GFp(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)582e7ccb6d1Schristos int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
583e7ccb6d1Schristos                            BIGNUM *b, BN_CTX *ctx)
584e7ccb6d1Schristos {
585e7ccb6d1Schristos     return EC_GROUP_get_curve(group, p, a, b, ctx);
586e7ccb6d1Schristos }
587e7ccb6d1Schristos 
58813ce5681Schristos # ifndef OPENSSL_NO_EC2M
EC_GROUP_set_curve_GF2m(EC_GROUP * group,const BIGNUM * p,const BIGNUM * a,const BIGNUM * b,BN_CTX * ctx)589ac65d4acSspz int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
590ac65d4acSspz                             const BIGNUM *b, BN_CTX *ctx)
591a89c9211Schristos {
592e7ccb6d1Schristos     return EC_GROUP_set_curve(group, p, a, b, ctx);
593a89c9211Schristos }
594a89c9211Schristos 
EC_GROUP_get_curve_GF2m(const EC_GROUP * group,BIGNUM * p,BIGNUM * a,BIGNUM * b,BN_CTX * ctx)595ac65d4acSspz int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
596ac65d4acSspz                             BIGNUM *b, BN_CTX *ctx)
597a89c9211Schristos {
598e7ccb6d1Schristos     return EC_GROUP_get_curve(group, p, a, b, ctx);
599a89c9211Schristos }
600e7ccb6d1Schristos # endif
60113ce5681Schristos #endif
602a89c9211Schristos 
EC_GROUP_get_degree(const EC_GROUP * group)603a89c9211Schristos int EC_GROUP_get_degree(const EC_GROUP *group)
604a89c9211Schristos {
605ac65d4acSspz     if (group->meth->group_get_degree == 0) {
606*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
607a89c9211Schristos         return 0;
608a89c9211Schristos     }
609a89c9211Schristos     return group->meth->group_get_degree(group);
610a89c9211Schristos }
611a89c9211Schristos 
EC_GROUP_check_discriminant(const EC_GROUP * group,BN_CTX * ctx)612a89c9211Schristos int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
613a89c9211Schristos {
614ac65d4acSspz     if (group->meth->group_check_discriminant == 0) {
615*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
616a89c9211Schristos         return 0;
617a89c9211Schristos     }
618a89c9211Schristos     return group->meth->group_check_discriminant(group, ctx);
619a89c9211Schristos }
620a89c9211Schristos 
EC_GROUP_cmp(const EC_GROUP * a,const EC_GROUP * b,BN_CTX * ctx)621a89c9211Schristos int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
622a89c9211Schristos {
623a89c9211Schristos     int r = 0;
624a89c9211Schristos     BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
625*5b10f583Schristos #ifndef FIPS_MODULE
626a89c9211Schristos     BN_CTX *ctx_new = NULL;
627*5b10f583Schristos #endif
628a89c9211Schristos 
629a89c9211Schristos     /* compare the field types */
630*5b10f583Schristos     if (EC_GROUP_get_field_type(a) != EC_GROUP_get_field_type(b))
631a89c9211Schristos         return 1;
63267270043Schristos     /* compare the curve name (if present in both) */
633a89c9211Schristos     if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
63467270043Schristos         EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
63567270043Schristos         return 1;
6364ec2eca9Schristos     if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
6374ec2eca9Schristos         return 0;
638a89c9211Schristos 
639*5b10f583Schristos #ifndef FIPS_MODULE
6404ec2eca9Schristos     if (ctx == NULL)
641a89c9211Schristos         ctx_new = ctx = BN_CTX_new();
642*5b10f583Schristos #endif
6434ec2eca9Schristos     if (ctx == NULL)
644a89c9211Schristos         return -1;
645a89c9211Schristos 
646a89c9211Schristos     BN_CTX_start(ctx);
647a89c9211Schristos     a1 = BN_CTX_get(ctx);
648a89c9211Schristos     a2 = BN_CTX_get(ctx);
649a89c9211Schristos     a3 = BN_CTX_get(ctx);
650a89c9211Schristos     b1 = BN_CTX_get(ctx);
651a89c9211Schristos     b2 = BN_CTX_get(ctx);
652a89c9211Schristos     b3 = BN_CTX_get(ctx);
6534ec2eca9Schristos     if (b3 == NULL) {
654a89c9211Schristos         BN_CTX_end(ctx);
655*5b10f583Schristos #ifndef FIPS_MODULE
6564ec2eca9Schristos         BN_CTX_free(ctx_new);
657*5b10f583Schristos #endif
658a89c9211Schristos         return -1;
659a89c9211Schristos     }
660a89c9211Schristos 
661ac65d4acSspz     /*
662ac65d4acSspz      * XXX This approach assumes that the external representation of curves
663ac65d4acSspz      * over the same field type is the same.
664a89c9211Schristos      */
665a89c9211Schristos     if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
666a89c9211Schristos         !b->meth->group_get_curve(b, b1, b2, b3, ctx))
667a89c9211Schristos         r = 1;
668a89c9211Schristos 
669*5b10f583Schristos     /* return 1 if the curve parameters are different */
670*5b10f583Schristos     if (r || BN_cmp(a1, b1) != 0 || BN_cmp(a2, b2) != 0 || BN_cmp(a3, b3) != 0)
671a89c9211Schristos         r = 1;
672a89c9211Schristos 
673a89c9211Schristos     /* XXX EC_POINT_cmp() assumes that the methods are equal */
674*5b10f583Schristos     /* return 1 if the generators are different */
675a89c9211Schristos     if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
676*5b10f583Schristos                           EC_GROUP_get0_generator(b), ctx) != 0)
677a89c9211Schristos         r = 1;
678a89c9211Schristos 
679ac65d4acSspz     if (!r) {
6804ec2eca9Schristos         const BIGNUM *ao, *bo, *ac, *bc;
681*5b10f583Schristos         /* compare the orders */
6824ec2eca9Schristos         ao = EC_GROUP_get0_order(a);
6834ec2eca9Schristos         bo = EC_GROUP_get0_order(b);
684*5b10f583Schristos         if (ao == NULL || bo == NULL) {
685*5b10f583Schristos             /* return an error if either order is NULL */
686*5b10f583Schristos             r = -1;
687*5b10f583Schristos             goto end;
688*5b10f583Schristos         }
689*5b10f583Schristos         if (BN_cmp(ao, bo) != 0) {
690*5b10f583Schristos             /* return 1 if orders are different */
691*5b10f583Schristos             r = 1;
692*5b10f583Schristos             goto end;
693*5b10f583Schristos         }
694*5b10f583Schristos         /*
695*5b10f583Schristos          * It gets here if the curve parameters and generator matched.
696*5b10f583Schristos          * Now check the optional cofactors (if both are present).
697*5b10f583Schristos          */
6984ec2eca9Schristos         ac = EC_GROUP_get0_cofactor(a);
6994ec2eca9Schristos         bc = EC_GROUP_get0_cofactor(b);
700*5b10f583Schristos         /* Returns 1 (mismatch) if both cofactors are specified and different */
701*5b10f583Schristos         if (!BN_is_zero(ac) && !BN_is_zero(bc) && BN_cmp(ac, bc) != 0)
702a89c9211Schristos             r = 1;
703*5b10f583Schristos         /* Returns 0 if the parameters matched */
704a89c9211Schristos     }
705*5b10f583Schristos end:
706a89c9211Schristos     BN_CTX_end(ctx);
707*5b10f583Schristos #ifndef FIPS_MODULE
7084ec2eca9Schristos     BN_CTX_free(ctx_new);
709*5b10f583Schristos #endif
710a89c9211Schristos     return r;
711a89c9211Schristos }
712a89c9211Schristos 
713a89c9211Schristos /* functions for EC_POINT objects */
714a89c9211Schristos 
EC_POINT_new(const EC_GROUP * group)715a89c9211Schristos EC_POINT *EC_POINT_new(const EC_GROUP *group)
716a89c9211Schristos {
717a89c9211Schristos     EC_POINT *ret;
718a89c9211Schristos 
719ac65d4acSspz     if (group == NULL) {
720*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
721a89c9211Schristos         return NULL;
722a89c9211Schristos     }
723e7ccb6d1Schristos     if (group->meth->point_init == NULL) {
724*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
725a89c9211Schristos         return NULL;
726a89c9211Schristos     }
727a89c9211Schristos 
7284ec2eca9Schristos     ret = OPENSSL_zalloc(sizeof(*ret));
729ac65d4acSspz     if (ret == NULL) {
730*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
731a89c9211Schristos         return NULL;
732a89c9211Schristos     }
733a89c9211Schristos 
734a89c9211Schristos     ret->meth = group->meth;
73595661423Schristos     ret->curve_name = group->curve_name;
736a89c9211Schristos 
737ac65d4acSspz     if (!ret->meth->point_init(ret)) {
738a89c9211Schristos         OPENSSL_free(ret);
739a89c9211Schristos         return NULL;
740a89c9211Schristos     }
741a89c9211Schristos 
742a89c9211Schristos     return ret;
743a89c9211Schristos }
744a89c9211Schristos 
EC_POINT_free(EC_POINT * point)745a89c9211Schristos void EC_POINT_free(EC_POINT *point)
746a89c9211Schristos {
747*5b10f583Schristos     if (point == NULL)
748ac65d4acSspz         return;
749a89c9211Schristos 
750a89c9211Schristos     if (point->meth->point_finish != 0)
751a89c9211Schristos         point->meth->point_finish(point);
752a89c9211Schristos     OPENSSL_free(point);
753a89c9211Schristos }
754a89c9211Schristos 
EC_POINT_clear_free(EC_POINT * point)755a89c9211Schristos void EC_POINT_clear_free(EC_POINT *point)
756a89c9211Schristos {
757*5b10f583Schristos     if (point == NULL)
758ac65d4acSspz         return;
759a89c9211Schristos 
760a89c9211Schristos     if (point->meth->point_clear_finish != 0)
761a89c9211Schristos         point->meth->point_clear_finish(point);
762a89c9211Schristos     else if (point->meth->point_finish != 0)
763a89c9211Schristos         point->meth->point_finish(point);
7644ec2eca9Schristos     OPENSSL_clear_free(point, sizeof(*point));
765a89c9211Schristos }
766a89c9211Schristos 
EC_POINT_copy(EC_POINT * dest,const EC_POINT * src)767a89c9211Schristos int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
768a89c9211Schristos {
769ac65d4acSspz     if (dest->meth->point_copy == 0) {
770*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
771a89c9211Schristos         return 0;
772a89c9211Schristos     }
77395661423Schristos     if (dest->meth != src->meth
77495661423Schristos             || (dest->curve_name != src->curve_name
77595661423Schristos                  && dest->curve_name != 0
77695661423Schristos                  && src->curve_name != 0)) {
777*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
778a89c9211Schristos         return 0;
779a89c9211Schristos     }
780a89c9211Schristos     if (dest == src)
781a89c9211Schristos         return 1;
782a89c9211Schristos     return dest->meth->point_copy(dest, src);
783a89c9211Schristos }
784a89c9211Schristos 
EC_POINT_dup(const EC_POINT * a,const EC_GROUP * group)785a89c9211Schristos EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
786a89c9211Schristos {
787a89c9211Schristos     EC_POINT *t;
788a89c9211Schristos     int r;
789a89c9211Schristos 
790ac65d4acSspz     if (a == NULL)
791ac65d4acSspz         return NULL;
792a89c9211Schristos 
793a89c9211Schristos     t = EC_POINT_new(group);
794ac65d4acSspz     if (t == NULL)
795e7ccb6d1Schristos         return NULL;
796a89c9211Schristos     r = EC_POINT_copy(t, a);
797ac65d4acSspz     if (!r) {
798a89c9211Schristos         EC_POINT_free(t);
799a89c9211Schristos         return NULL;
8004ec2eca9Schristos     }
801ac65d4acSspz     return t;
802a89c9211Schristos }
803a89c9211Schristos 
804*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINT_method_of(const EC_POINT * point)805a89c9211Schristos const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
806a89c9211Schristos {
807a89c9211Schristos     return point->meth;
808a89c9211Schristos }
809*5b10f583Schristos #endif
810a89c9211Schristos 
EC_POINT_set_to_infinity(const EC_GROUP * group,EC_POINT * point)811a89c9211Schristos int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
812a89c9211Schristos {
813ac65d4acSspz     if (group->meth->point_set_to_infinity == 0) {
814*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
815a89c9211Schristos         return 0;
816a89c9211Schristos     }
817ac65d4acSspz     if (group->meth != point->meth) {
818*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
819a89c9211Schristos         return 0;
820a89c9211Schristos     }
821a89c9211Schristos     return group->meth->point_set_to_infinity(group, point);
822a89c9211Schristos }
823a89c9211Schristos 
824*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,const BIGNUM * z,BN_CTX * ctx)825ac65d4acSspz int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
826ac65d4acSspz                                              EC_POINT *point, const BIGNUM *x,
827ac65d4acSspz                                              const BIGNUM *y, const BIGNUM *z,
828ac65d4acSspz                                              BN_CTX *ctx)
829a89c9211Schristos {
830*5b10f583Schristos     if (group->meth->field_type != NID_X9_62_prime_field) {
831*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
832a89c9211Schristos         return 0;
833a89c9211Schristos     }
83495661423Schristos     if (!ec_point_is_compat(point, group)) {
835*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
836a89c9211Schristos         return 0;
837a89c9211Schristos     }
838*5b10f583Schristos     return ossl_ec_GFp_simple_set_Jprojective_coordinates_GFp(group, point,
839*5b10f583Schristos                                                               x, y, z, ctx);
840a89c9211Schristos }
841a89c9211Schristos 
EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BIGNUM * z,BN_CTX * ctx)842ac65d4acSspz int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
843ac65d4acSspz                                              const EC_POINT *point, BIGNUM *x,
844ac65d4acSspz                                              BIGNUM *y, BIGNUM *z,
845ac65d4acSspz                                              BN_CTX *ctx)
846a89c9211Schristos {
847*5b10f583Schristos     if (group->meth->field_type != NID_X9_62_prime_field) {
848*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
849a89c9211Schristos         return 0;
850a89c9211Schristos     }
85195661423Schristos     if (!ec_point_is_compat(point, group)) {
852*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
853a89c9211Schristos         return 0;
854a89c9211Schristos     }
855*5b10f583Schristos     return ossl_ec_GFp_simple_get_Jprojective_coordinates_GFp(group, point,
856*5b10f583Schristos                                                               x, y, z, ctx);
857a89c9211Schristos }
858*5b10f583Schristos #endif
859a89c9211Schristos 
EC_POINT_set_affine_coordinates(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)860e7ccb6d1Schristos int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
861e7ccb6d1Schristos                                     const BIGNUM *x, const BIGNUM *y,
862e7ccb6d1Schristos                                     BN_CTX *ctx)
863a89c9211Schristos {
864e7ccb6d1Schristos     if (group->meth->point_set_affine_coordinates == NULL) {
865*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
866a89c9211Schristos         return 0;
867a89c9211Schristos     }
86895661423Schristos     if (!ec_point_is_compat(point, group)) {
869*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
870a89c9211Schristos         return 0;
871a89c9211Schristos     }
8724ec2eca9Schristos     if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
8734ec2eca9Schristos         return 0;
8744ec2eca9Schristos 
8754ec2eca9Schristos     if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
876*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_POINT_IS_NOT_ON_CURVE);
8774ec2eca9Schristos         return 0;
8784ec2eca9Schristos     }
8794ec2eca9Schristos     return 1;
880a89c9211Schristos }
881a89c9211Schristos 
882*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINT_set_affine_coordinates_GFp(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)883e7ccb6d1Schristos int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
884e7ccb6d1Schristos                                         EC_POINT *point, const BIGNUM *x,
885e7ccb6d1Schristos                                         const BIGNUM *y, BN_CTX *ctx)
886e7ccb6d1Schristos {
887e7ccb6d1Schristos     return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
888e7ccb6d1Schristos }
889e7ccb6d1Schristos 
89013ce5681Schristos # ifndef OPENSSL_NO_EC2M
EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP * group,EC_POINT * point,const BIGNUM * x,const BIGNUM * y,BN_CTX * ctx)891ac65d4acSspz int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
892ac65d4acSspz                                          EC_POINT *point, const BIGNUM *x,
893ac65d4acSspz                                          const BIGNUM *y, BN_CTX *ctx)
894a89c9211Schristos {
895e7ccb6d1Schristos     return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
896e7ccb6d1Schristos }
897e7ccb6d1Schristos # endif
898e7ccb6d1Schristos #endif
899e7ccb6d1Schristos 
EC_POINT_get_affine_coordinates(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)900e7ccb6d1Schristos int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
901e7ccb6d1Schristos                                     const EC_POINT *point, BIGNUM *x, BIGNUM *y,
902e7ccb6d1Schristos                                     BN_CTX *ctx)
903e7ccb6d1Schristos {
904e7ccb6d1Schristos     if (group->meth->point_get_affine_coordinates == NULL) {
905*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
906a89c9211Schristos         return 0;
907a89c9211Schristos     }
90895661423Schristos     if (!ec_point_is_compat(point, group)) {
909*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
910a89c9211Schristos         return 0;
911a89c9211Schristos     }
912e7ccb6d1Schristos     if (EC_POINT_is_at_infinity(group, point)) {
913*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_POINT_AT_INFINITY);
9144ec2eca9Schristos         return 0;
915e7ccb6d1Schristos     }
916e7ccb6d1Schristos     return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
917e7ccb6d1Schristos }
9184ec2eca9Schristos 
919*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINT_get_affine_coordinates_GFp(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)920ac65d4acSspz int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
921ac65d4acSspz                                         const EC_POINT *point, BIGNUM *x,
922ac65d4acSspz                                         BIGNUM *y, BN_CTX *ctx)
923a89c9211Schristos {
924e7ccb6d1Schristos     return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
925a89c9211Schristos }
926a89c9211Schristos 
92713ce5681Schristos # ifndef OPENSSL_NO_EC2M
EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP * group,const EC_POINT * point,BIGNUM * x,BIGNUM * y,BN_CTX * ctx)928ac65d4acSspz int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
929ac65d4acSspz                                          const EC_POINT *point, BIGNUM *x,
930ac65d4acSspz                                          BIGNUM *y, BN_CTX *ctx)
931a89c9211Schristos {
932e7ccb6d1Schristos     return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
933a89c9211Schristos }
934e7ccb6d1Schristos # endif
93513ce5681Schristos #endif
936a89c9211Schristos 
EC_POINT_add(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)937ac65d4acSspz int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
938ac65d4acSspz                  const EC_POINT *b, BN_CTX *ctx)
939a89c9211Schristos {
940ac65d4acSspz     if (group->meth->add == 0) {
941*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
942a89c9211Schristos         return 0;
943a89c9211Schristos     }
94495661423Schristos     if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
94595661423Schristos         || !ec_point_is_compat(b, group)) {
946*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
947a89c9211Schristos         return 0;
948a89c9211Schristos     }
949a89c9211Schristos     return group->meth->add(group, r, a, b, ctx);
950a89c9211Schristos }
951a89c9211Schristos 
EC_POINT_dbl(const EC_GROUP * group,EC_POINT * r,const EC_POINT * a,BN_CTX * ctx)952ac65d4acSspz int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
953ac65d4acSspz                  BN_CTX *ctx)
954a89c9211Schristos {
955ac65d4acSspz     if (group->meth->dbl == 0) {
956*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
957a89c9211Schristos         return 0;
958a89c9211Schristos     }
95995661423Schristos     if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
960*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
961a89c9211Schristos         return 0;
962a89c9211Schristos     }
963a89c9211Schristos     return group->meth->dbl(group, r, a, ctx);
964a89c9211Schristos }
965a89c9211Schristos 
EC_POINT_invert(const EC_GROUP * group,EC_POINT * a,BN_CTX * ctx)966a89c9211Schristos int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
967a89c9211Schristos {
968ac65d4acSspz     if (group->meth->invert == 0) {
969*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
970a89c9211Schristos         return 0;
971a89c9211Schristos     }
97295661423Schristos     if (!ec_point_is_compat(a, group)) {
973*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
974a89c9211Schristos         return 0;
975a89c9211Schristos     }
976a89c9211Schristos     return group->meth->invert(group, a, ctx);
977a89c9211Schristos }
978a89c9211Schristos 
EC_POINT_is_at_infinity(const EC_GROUP * group,const EC_POINT * point)979a89c9211Schristos int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
980a89c9211Schristos {
981ac65d4acSspz     if (group->meth->is_at_infinity == 0) {
982*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
983a89c9211Schristos         return 0;
984a89c9211Schristos     }
98595661423Schristos     if (!ec_point_is_compat(point, group)) {
986*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
987a89c9211Schristos         return 0;
988a89c9211Schristos     }
989a89c9211Schristos     return group->meth->is_at_infinity(group, point);
990a89c9211Schristos }
991a89c9211Schristos 
992db3fdf78Schristos /*
993db3fdf78Schristos  * Check whether an EC_POINT is on the curve or not. Note that the return
994db3fdf78Schristos  * value for this function should NOT be treated as a boolean. Return values:
995db3fdf78Schristos  *  1: The point is on the curve
996db3fdf78Schristos  *  0: The point is not on the curve
997db3fdf78Schristos  * -1: An error occurred
998db3fdf78Schristos  */
EC_POINT_is_on_curve(const EC_GROUP * group,const EC_POINT * point,BN_CTX * ctx)999ac65d4acSspz int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
1000ac65d4acSspz                          BN_CTX *ctx)
1001a89c9211Schristos {
1002ac65d4acSspz     if (group->meth->is_on_curve == 0) {
1003*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1004a89c9211Schristos         return 0;
1005a89c9211Schristos     }
100695661423Schristos     if (!ec_point_is_compat(point, group)) {
1007*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1008a89c9211Schristos         return 0;
1009a89c9211Schristos     }
1010a89c9211Schristos     return group->meth->is_on_curve(group, point, ctx);
1011a89c9211Schristos }
1012a89c9211Schristos 
EC_POINT_cmp(const EC_GROUP * group,const EC_POINT * a,const EC_POINT * b,BN_CTX * ctx)1013ac65d4acSspz int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
1014ac65d4acSspz                  BN_CTX *ctx)
1015a89c9211Schristos {
1016ac65d4acSspz     if (group->meth->point_cmp == 0) {
1017*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
101867270043Schristos         return -1;
1019a89c9211Schristos     }
102095661423Schristos     if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
1021*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
102267270043Schristos         return -1;
1023a89c9211Schristos     }
1024a89c9211Schristos     return group->meth->point_cmp(group, a, b, ctx);
1025a89c9211Schristos }
1026a89c9211Schristos 
1027*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINT_make_affine(const EC_GROUP * group,EC_POINT * point,BN_CTX * ctx)1028a89c9211Schristos int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
1029a89c9211Schristos {
1030ac65d4acSspz     if (group->meth->make_affine == 0) {
1031*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1032a89c9211Schristos         return 0;
1033a89c9211Schristos     }
103495661423Schristos     if (!ec_point_is_compat(point, group)) {
1035*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1036a89c9211Schristos         return 0;
1037a89c9211Schristos     }
1038a89c9211Schristos     return group->meth->make_affine(group, point, ctx);
1039a89c9211Schristos }
1040a89c9211Schristos 
EC_POINTs_make_affine(const EC_GROUP * group,size_t num,EC_POINT * points[],BN_CTX * ctx)1041ac65d4acSspz int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
1042ac65d4acSspz                           EC_POINT *points[], BN_CTX *ctx)
1043a89c9211Schristos {
1044a89c9211Schristos     size_t i;
1045a89c9211Schristos 
1046ac65d4acSspz     if (group->meth->points_make_affine == 0) {
1047*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1048a89c9211Schristos         return 0;
1049a89c9211Schristos     }
1050ac65d4acSspz     for (i = 0; i < num; i++) {
105195661423Schristos         if (!ec_point_is_compat(points[i], group)) {
1052*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1053a89c9211Schristos             return 0;
1054a89c9211Schristos         }
1055a89c9211Schristos     }
1056a89c9211Schristos     return group->meth->points_make_affine(group, num, points, ctx);
1057a89c9211Schristos }
1058*5b10f583Schristos #endif
1059a89c9211Schristos 
1060ac65d4acSspz /*
1061ac65d4acSspz  * Functions for point multiplication. If group->meth->mul is 0, we use the
1062ac65d4acSspz  * wNAF-based implementations in ec_mult.c; otherwise we dispatch through
1063ac65d4acSspz  * methods.
1064a89c9211Schristos  */
1065a89c9211Schristos 
1066*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_POINTs_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * scalar,size_t num,const EC_POINT * points[],const BIGNUM * scalars[],BN_CTX * ctx)1067a89c9211Schristos int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
1068ac65d4acSspz                   size_t num, const EC_POINT *points[],
1069ac65d4acSspz                   const BIGNUM *scalars[], BN_CTX *ctx)
1070a89c9211Schristos {
1071e7ccb6d1Schristos     int ret = 0;
1072e7ccb6d1Schristos     size_t i = 0;
1073*5b10f583Schristos #ifndef FIPS_MODULE
1074e7ccb6d1Schristos     BN_CTX *new_ctx = NULL;
1075*5b10f583Schristos #endif
1076a89c9211Schristos 
1077e7ccb6d1Schristos     if (!ec_point_is_compat(r, group)) {
1078*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1079e7ccb6d1Schristos         return 0;
1080e7ccb6d1Schristos     }
1081003b39c1Schristos 
1082003b39c1Schristos     if (scalar == NULL && num == 0)
1083003b39c1Schristos         return EC_POINT_set_to_infinity(group, r);
1084003b39c1Schristos 
1085e7ccb6d1Schristos     for (i = 0; i < num; i++) {
1086e7ccb6d1Schristos         if (!ec_point_is_compat(points[i], group)) {
1087*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1088e7ccb6d1Schristos             return 0;
1089e7ccb6d1Schristos         }
1090e7ccb6d1Schristos     }
1091e7ccb6d1Schristos 
1092*5b10f583Schristos #ifndef FIPS_MODULE
1093*5b10f583Schristos     if (ctx == NULL)
1094*5b10f583Schristos         ctx = new_ctx = BN_CTX_secure_new();
1095*5b10f583Schristos #endif
1096*5b10f583Schristos     if (ctx == NULL) {
1097*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
1098e7ccb6d1Schristos         return 0;
1099e7ccb6d1Schristos     }
1100e7ccb6d1Schristos 
1101e7ccb6d1Schristos     if (group->meth->mul != NULL)
1102e7ccb6d1Schristos         ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
1103e7ccb6d1Schristos     else
1104e7ccb6d1Schristos         /* use default */
1105*5b10f583Schristos         ret = ossl_ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
1106e7ccb6d1Schristos 
1107*5b10f583Schristos #ifndef FIPS_MODULE
1108e7ccb6d1Schristos     BN_CTX_free(new_ctx);
1109*5b10f583Schristos #endif
1110e7ccb6d1Schristos     return ret;
1111a89c9211Schristos }
1112*5b10f583Schristos #endif
1113a89c9211Schristos 
EC_POINT_mul(const EC_GROUP * group,EC_POINT * r,const BIGNUM * g_scalar,const EC_POINT * point,const BIGNUM * p_scalar,BN_CTX * ctx)1114a89c9211Schristos int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
1115a89c9211Schristos                  const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
1116a89c9211Schristos {
1117*5b10f583Schristos     int ret = 0;
1118*5b10f583Schristos     size_t num;
1119*5b10f583Schristos #ifndef FIPS_MODULE
1120*5b10f583Schristos     BN_CTX *new_ctx = NULL;
1121*5b10f583Schristos #endif
1122a89c9211Schristos 
1123*5b10f583Schristos     if (!ec_point_is_compat(r, group)
1124*5b10f583Schristos         || (point != NULL && !ec_point_is_compat(point, group))) {
1125*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INCOMPATIBLE_OBJECTS);
1126*5b10f583Schristos         return 0;
1127a89c9211Schristos     }
1128a89c9211Schristos 
1129*5b10f583Schristos     if (g_scalar == NULL && p_scalar == NULL)
1130*5b10f583Schristos         return EC_POINT_set_to_infinity(group, r);
1131*5b10f583Schristos 
1132*5b10f583Schristos #ifndef FIPS_MODULE
1133*5b10f583Schristos     if (ctx == NULL)
1134*5b10f583Schristos         ctx = new_ctx = BN_CTX_secure_new();
1135*5b10f583Schristos #endif
1136*5b10f583Schristos     if (ctx == NULL) {
1137*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_INTERNAL_ERROR);
1138*5b10f583Schristos         return 0;
1139*5b10f583Schristos     }
1140*5b10f583Schristos 
1141*5b10f583Schristos     num = (point != NULL && p_scalar != NULL) ? 1 : 0;
1142*5b10f583Schristos     if (group->meth->mul != NULL)
1143*5b10f583Schristos         ret = group->meth->mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
1144*5b10f583Schristos     else
1145*5b10f583Schristos         /* use default */
1146*5b10f583Schristos         ret = ossl_ec_wNAF_mul(group, r, g_scalar, num, &point, &p_scalar, ctx);
1147*5b10f583Schristos 
1148*5b10f583Schristos #ifndef FIPS_MODULE
1149*5b10f583Schristos     BN_CTX_free(new_ctx);
1150*5b10f583Schristos #endif
1151*5b10f583Schristos     return ret;
1152*5b10f583Schristos }
1153*5b10f583Schristos 
1154*5b10f583Schristos #ifndef OPENSSL_NO_DEPRECATED_3_0
EC_GROUP_precompute_mult(EC_GROUP * group,BN_CTX * ctx)1155a89c9211Schristos int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
1156a89c9211Schristos {
1157a89c9211Schristos     if (group->meth->mul == 0)
1158a89c9211Schristos         /* use default */
1159*5b10f583Schristos         return ossl_ec_wNAF_precompute_mult(group, ctx);
1160a89c9211Schristos 
1161a89c9211Schristos     if (group->meth->precompute_mult != 0)
1162a89c9211Schristos         return group->meth->precompute_mult(group, ctx);
1163a89c9211Schristos     else
1164a89c9211Schristos         return 1;               /* nothing to do, so report success */
1165a89c9211Schristos }
1166a89c9211Schristos 
EC_GROUP_have_precompute_mult(const EC_GROUP * group)1167a89c9211Schristos int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
1168a89c9211Schristos {
1169a89c9211Schristos     if (group->meth->mul == 0)
1170a89c9211Schristos         /* use default */
1171*5b10f583Schristos         return ossl_ec_wNAF_have_precompute_mult(group);
1172a89c9211Schristos 
1173a89c9211Schristos     if (group->meth->have_precompute_mult != 0)
1174a89c9211Schristos         return group->meth->have_precompute_mult(group);
1175a89c9211Schristos     else
1176ac65d4acSspz         return 0;               /* cannot tell whether precomputation has
1177ac65d4acSspz                                  * been performed */
1178a89c9211Schristos }
1179*5b10f583Schristos #endif
11801440100dSspz 
11811440100dSspz /*
11821440100dSspz  * ec_precompute_mont_data sets |group->mont_data| from |group->order| and
11831440100dSspz  * returns one on success. On error it returns zero.
11841440100dSspz  */
ec_precompute_mont_data(EC_GROUP * group)1185e7ccb6d1Schristos static int ec_precompute_mont_data(EC_GROUP *group)
11861440100dSspz {
1187*5b10f583Schristos     BN_CTX *ctx = BN_CTX_new_ex(group->libctx);
11881440100dSspz     int ret = 0;
11891440100dSspz 
11901440100dSspz     BN_MONT_CTX_free(group->mont_data);
11911440100dSspz     group->mont_data = NULL;
11921440100dSspz 
11931440100dSspz     if (ctx == NULL)
11941440100dSspz         goto err;
11951440100dSspz 
11961440100dSspz     group->mont_data = BN_MONT_CTX_new();
11974ec2eca9Schristos     if (group->mont_data == NULL)
11981440100dSspz         goto err;
11991440100dSspz 
12004ec2eca9Schristos     if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
12011440100dSspz         BN_MONT_CTX_free(group->mont_data);
12021440100dSspz         group->mont_data = NULL;
12031440100dSspz         goto err;
12041440100dSspz     }
12051440100dSspz 
12061440100dSspz     ret = 1;
12071440100dSspz 
12081440100dSspz  err:
12091440100dSspz 
12101440100dSspz     BN_CTX_free(ctx);
12111440100dSspz     return ret;
12121440100dSspz }
12134ec2eca9Schristos 
1214*5b10f583Schristos #ifndef FIPS_MODULE
EC_KEY_set_ex_data(EC_KEY * key,int idx,void * arg)12154ec2eca9Schristos int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
12164ec2eca9Schristos {
12174ec2eca9Schristos     return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
12184ec2eca9Schristos }
12194ec2eca9Schristos 
EC_KEY_get_ex_data(const EC_KEY * key,int idx)12204ec2eca9Schristos void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
12214ec2eca9Schristos {
12224ec2eca9Schristos     return CRYPTO_get_ex_data(&key->ex_data, idx);
12234ec2eca9Schristos }
1224*5b10f583Schristos #endif
12254ec2eca9Schristos 
ossl_ec_group_simple_order_bits(const EC_GROUP * group)1226*5b10f583Schristos int ossl_ec_group_simple_order_bits(const EC_GROUP *group)
12274ec2eca9Schristos {
12284ec2eca9Schristos     if (group->order == NULL)
12294ec2eca9Schristos         return 0;
12304ec2eca9Schristos     return BN_num_bits(group->order);
12314ec2eca9Schristos }
1232e7ccb6d1Schristos 
ec_field_inverse_mod_ord(const EC_GROUP * group,BIGNUM * r,const BIGNUM * x,BN_CTX * ctx)1233e7ccb6d1Schristos static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
1234e7ccb6d1Schristos                                     const BIGNUM *x, BN_CTX *ctx)
1235e7ccb6d1Schristos {
1236e7ccb6d1Schristos     BIGNUM *e = NULL;
1237e7ccb6d1Schristos     int ret = 0;
1238*5b10f583Schristos #ifndef FIPS_MODULE
1239*5b10f583Schristos     BN_CTX *new_ctx = NULL;
1240*5b10f583Schristos #endif
1241e7ccb6d1Schristos 
1242e7ccb6d1Schristos     if (group->mont_data == NULL)
1243e7ccb6d1Schristos         return 0;
1244e7ccb6d1Schristos 
1245*5b10f583Schristos #ifndef FIPS_MODULE
1246*5b10f583Schristos     if (ctx == NULL)
1247*5b10f583Schristos         ctx = new_ctx = BN_CTX_secure_new();
1248*5b10f583Schristos #endif
1249*5b10f583Schristos     if (ctx == NULL)
1250e7ccb6d1Schristos         return 0;
1251e7ccb6d1Schristos 
1252e7ccb6d1Schristos     BN_CTX_start(ctx);
1253e7ccb6d1Schristos     if ((e = BN_CTX_get(ctx)) == NULL)
1254e7ccb6d1Schristos         goto err;
1255e7ccb6d1Schristos 
1256e7ccb6d1Schristos     /*-
1257e7ccb6d1Schristos      * We want inverse in constant time, therefore we utilize the fact
1258e7ccb6d1Schristos      * order must be prime and use Fermats Little Theorem instead.
1259e7ccb6d1Schristos      */
1260e7ccb6d1Schristos     if (!BN_set_word(e, 2))
1261e7ccb6d1Schristos         goto err;
1262e7ccb6d1Schristos     if (!BN_sub(e, group->order, e))
1263e7ccb6d1Schristos         goto err;
1264e7ccb6d1Schristos     /*-
1265e7ccb6d1Schristos      * Exponent e is public.
1266e7ccb6d1Schristos      * No need for scatter-gather or BN_FLG_CONSTTIME.
1267e7ccb6d1Schristos      */
1268e7ccb6d1Schristos     if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
1269e7ccb6d1Schristos         goto err;
1270e7ccb6d1Schristos 
1271e7ccb6d1Schristos     ret = 1;
1272e7ccb6d1Schristos 
1273e7ccb6d1Schristos  err:
1274e7ccb6d1Schristos     BN_CTX_end(ctx);
1275*5b10f583Schristos #ifndef FIPS_MODULE
1276e7ccb6d1Schristos     BN_CTX_free(new_ctx);
1277*5b10f583Schristos #endif
1278e7ccb6d1Schristos     return ret;
1279e7ccb6d1Schristos }
1280e7ccb6d1Schristos 
1281e7ccb6d1Schristos /*-
1282e7ccb6d1Schristos  * Default behavior, if group->meth->field_inverse_mod_ord is NULL:
1283e7ccb6d1Schristos  * - When group->order is even, this function returns an error.
1284e7ccb6d1Schristos  * - When group->order is otherwise composite, the correctness
1285e7ccb6d1Schristos  *   of the output is not guaranteed.
1286e7ccb6d1Schristos  * - When x is outside the range [1, group->order), the correctness
1287e7ccb6d1Schristos  *   of the output is not guaranteed.
1288e7ccb6d1Schristos  * - Otherwise, this function returns the multiplicative inverse in the
1289e7ccb6d1Schristos  *   range [1, group->order).
1290e7ccb6d1Schristos  *
1291e7ccb6d1Schristos  * EC_METHODs must implement their own field_inverse_mod_ord for
1292e7ccb6d1Schristos  * other functionality.
1293e7ccb6d1Schristos  */
ossl_ec_group_do_inverse_ord(const EC_GROUP * group,BIGNUM * res,const BIGNUM * x,BN_CTX * ctx)1294*5b10f583Schristos int ossl_ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
1295e7ccb6d1Schristos                                  const BIGNUM *x, BN_CTX *ctx)
1296e7ccb6d1Schristos {
1297e7ccb6d1Schristos     if (group->meth->field_inverse_mod_ord != NULL)
1298e7ccb6d1Schristos         return group->meth->field_inverse_mod_ord(group, res, x, ctx);
1299e7ccb6d1Schristos     else
1300e7ccb6d1Schristos         return ec_field_inverse_mod_ord(group, res, x, ctx);
1301e7ccb6d1Schristos }
1302e7ccb6d1Schristos 
1303e7ccb6d1Schristos /*-
1304e7ccb6d1Schristos  * Coordinate blinding for EC_POINT.
1305e7ccb6d1Schristos  *
1306e7ccb6d1Schristos  * The underlying EC_METHOD can optionally implement this function:
1307e7ccb6d1Schristos  * underlying implementations should return 0 on errors, or 1 on
1308e7ccb6d1Schristos  * success.
1309e7ccb6d1Schristos  *
1310e7ccb6d1Schristos  * This wrapper returns 1 in case the underlying EC_METHOD does not
1311e7ccb6d1Schristos  * support coordinate blinding.
1312e7ccb6d1Schristos  */
ossl_ec_point_blind_coordinates(const EC_GROUP * group,EC_POINT * p,BN_CTX * ctx)1313*5b10f583Schristos int ossl_ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
1314*5b10f583Schristos                                     BN_CTX *ctx)
1315e7ccb6d1Schristos {
1316e7ccb6d1Schristos     if (group->meth->blind_coordinates == NULL)
1317e7ccb6d1Schristos         return 1; /* ignore if not implemented */
1318e7ccb6d1Schristos 
1319e7ccb6d1Schristos     return group->meth->blind_coordinates(group, p, ctx);
1320e7ccb6d1Schristos }
1321*5b10f583Schristos 
EC_GROUP_get_basis_type(const EC_GROUP * group)1322*5b10f583Schristos int EC_GROUP_get_basis_type(const EC_GROUP *group)
1323*5b10f583Schristos {
1324*5b10f583Schristos     int i;
1325*5b10f583Schristos 
1326*5b10f583Schristos     if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field)
1327*5b10f583Schristos         /* everything else is currently not supported */
1328*5b10f583Schristos         return 0;
1329*5b10f583Schristos 
1330*5b10f583Schristos     /* Find the last non-zero element of group->poly[] */
1331*5b10f583Schristos     for (i = 0;
1332*5b10f583Schristos          i < (int)OSSL_NELEM(group->poly) && group->poly[i] != 0;
1333*5b10f583Schristos          i++)
1334*5b10f583Schristos         continue;
1335*5b10f583Schristos 
1336*5b10f583Schristos     if (i == 4)
1337*5b10f583Schristos         return NID_X9_62_ppBasis;
1338*5b10f583Schristos     else if (i == 2)
1339*5b10f583Schristos         return NID_X9_62_tpBasis;
1340*5b10f583Schristos     else
1341*5b10f583Schristos         /* everything else is currently not supported */
1342*5b10f583Schristos         return 0;
1343*5b10f583Schristos }
1344*5b10f583Schristos 
1345*5b10f583Schristos #ifndef OPENSSL_NO_EC2M
EC_GROUP_get_trinomial_basis(const EC_GROUP * group,unsigned int * k)1346*5b10f583Schristos int EC_GROUP_get_trinomial_basis(const EC_GROUP *group, unsigned int *k)
1347*5b10f583Schristos {
1348*5b10f583Schristos     if (group == NULL)
1349*5b10f583Schristos         return 0;
1350*5b10f583Schristos 
1351*5b10f583Schristos     if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
1352*5b10f583Schristos         || !((group->poly[0] != 0) && (group->poly[1] != 0)
1353*5b10f583Schristos              && (group->poly[2] == 0))) {
1354*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1355*5b10f583Schristos         return 0;
1356*5b10f583Schristos     }
1357*5b10f583Schristos 
1358*5b10f583Schristos     if (k)
1359*5b10f583Schristos         *k = group->poly[1];
1360*5b10f583Schristos 
1361*5b10f583Schristos     return 1;
1362*5b10f583Schristos }
1363*5b10f583Schristos 
EC_GROUP_get_pentanomial_basis(const EC_GROUP * group,unsigned int * k1,unsigned int * k2,unsigned int * k3)1364*5b10f583Schristos int EC_GROUP_get_pentanomial_basis(const EC_GROUP *group, unsigned int *k1,
1365*5b10f583Schristos                                    unsigned int *k2, unsigned int *k3)
1366*5b10f583Schristos {
1367*5b10f583Schristos     if (group == NULL)
1368*5b10f583Schristos         return 0;
1369*5b10f583Schristos 
1370*5b10f583Schristos     if (EC_GROUP_get_field_type(group) != NID_X9_62_characteristic_two_field
1371*5b10f583Schristos         || !((group->poly[0] != 0) && (group->poly[1] != 0)
1372*5b10f583Schristos              && (group->poly[2] != 0) && (group->poly[3] != 0)
1373*5b10f583Schristos              && (group->poly[4] == 0))) {
1374*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
1375*5b10f583Schristos         return 0;
1376*5b10f583Schristos     }
1377*5b10f583Schristos 
1378*5b10f583Schristos     if (k1)
1379*5b10f583Schristos         *k1 = group->poly[3];
1380*5b10f583Schristos     if (k2)
1381*5b10f583Schristos         *k2 = group->poly[2];
1382*5b10f583Schristos     if (k3)
1383*5b10f583Schristos         *k3 = group->poly[1];
1384*5b10f583Schristos 
1385*5b10f583Schristos     return 1;
1386*5b10f583Schristos }
1387*5b10f583Schristos #endif
1388*5b10f583Schristos 
1389*5b10f583Schristos #ifndef FIPS_MODULE
1390*5b10f583Schristos /*
1391*5b10f583Schristos  * Check if the explicit parameters group matches any built-in curves.
1392*5b10f583Schristos  *
1393*5b10f583Schristos  * We create a copy of the group just built, so that we can remove optional
1394*5b10f583Schristos  * fields for the lookup: we do this to avoid the possibility that one of
1395*5b10f583Schristos  * the optional parameters is used to force the library into using a less
1396*5b10f583Schristos  * performant and less secure EC_METHOD instead of the specialized one.
1397*5b10f583Schristos  * In any case, `seed` is not really used in any computation, while a
1398*5b10f583Schristos  * cofactor different from the one in the built-in table is just
1399*5b10f583Schristos  * mathematically wrong anyway and should not be used.
1400*5b10f583Schristos  */
ec_group_explicit_to_named(const EC_GROUP * group,OSSL_LIB_CTX * libctx,const char * propq,BN_CTX * ctx)1401*5b10f583Schristos static EC_GROUP *ec_group_explicit_to_named(const EC_GROUP *group,
1402*5b10f583Schristos                                             OSSL_LIB_CTX *libctx,
1403*5b10f583Schristos                                             const char *propq,
1404*5b10f583Schristos                                             BN_CTX *ctx)
1405*5b10f583Schristos {
1406*5b10f583Schristos     EC_GROUP *ret_group = NULL, *dup = NULL;
1407*5b10f583Schristos     int curve_name_nid;
1408*5b10f583Schristos 
1409*5b10f583Schristos     const EC_POINT *point = EC_GROUP_get0_generator(group);
1410*5b10f583Schristos     const BIGNUM *order = EC_GROUP_get0_order(group);
1411*5b10f583Schristos     int no_seed = (EC_GROUP_get0_seed(group) == NULL);
1412*5b10f583Schristos 
1413*5b10f583Schristos     if ((dup = EC_GROUP_dup(group)) == NULL
1414*5b10f583Schristos             || EC_GROUP_set_seed(dup, NULL, 0) != 1
1415*5b10f583Schristos             || !EC_GROUP_set_generator(dup, point, order, NULL))
1416*5b10f583Schristos         goto err;
1417*5b10f583Schristos     if ((curve_name_nid = ossl_ec_curve_nid_from_params(dup, ctx)) != NID_undef) {
1418*5b10f583Schristos         /*
1419*5b10f583Schristos          * The input explicit parameters successfully matched one of the
1420*5b10f583Schristos          * built-in curves: often for built-in curves we have specialized
1421*5b10f583Schristos          * methods with better performance and hardening.
1422*5b10f583Schristos          *
1423*5b10f583Schristos          * In this case we replace the `EC_GROUP` created through explicit
1424*5b10f583Schristos          * parameters with one created from a named group.
1425*5b10f583Schristos          */
1426*5b10f583Schristos 
1427*5b10f583Schristos # ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
1428*5b10f583Schristos         /*
1429*5b10f583Schristos          * NID_wap_wsg_idm_ecid_wtls12 and NID_secp224r1 are both aliases for
1430*5b10f583Schristos          * the same curve, we prefer the SECP nid when matching explicit
1431*5b10f583Schristos          * parameters as that is associated with a specialized EC_METHOD.
1432*5b10f583Schristos          */
1433*5b10f583Schristos         if (curve_name_nid == NID_wap_wsg_idm_ecid_wtls12)
1434*5b10f583Schristos             curve_name_nid = NID_secp224r1;
1435*5b10f583Schristos # endif /* !def(OPENSSL_NO_EC_NISTP_64_GCC_128) */
1436*5b10f583Schristos 
1437*5b10f583Schristos         ret_group = EC_GROUP_new_by_curve_name_ex(libctx, propq, curve_name_nid);
1438*5b10f583Schristos         if (ret_group == NULL)
1439*5b10f583Schristos             goto err;
1440*5b10f583Schristos 
1441*5b10f583Schristos         /*
1442*5b10f583Schristos          * Set the flag so that EC_GROUPs created from explicit parameters are
1443*5b10f583Schristos          * serialized using explicit parameters by default.
1444*5b10f583Schristos          */
1445*5b10f583Schristos         EC_GROUP_set_asn1_flag(ret_group, OPENSSL_EC_EXPLICIT_CURVE);
1446*5b10f583Schristos 
1447*5b10f583Schristos         /*
1448*5b10f583Schristos          * If the input params do not contain the optional seed field we make
1449*5b10f583Schristos          * sure it is not added to the returned group.
1450*5b10f583Schristos          *
1451*5b10f583Schristos          * The seed field is not really used inside libcrypto anyway, and
1452*5b10f583Schristos          * adding it to parsed explicit parameter keys would alter their DER
1453*5b10f583Schristos          * encoding output (because of the extra field) which could impact
1454*5b10f583Schristos          * applications fingerprinting keys by their DER encoding.
1455*5b10f583Schristos          */
1456*5b10f583Schristos         if (no_seed) {
1457*5b10f583Schristos             if (EC_GROUP_set_seed(ret_group, NULL, 0) != 1)
1458*5b10f583Schristos                 goto err;
1459*5b10f583Schristos         }
1460*5b10f583Schristos     } else {
1461*5b10f583Schristos         ret_group = (EC_GROUP *)group;
1462*5b10f583Schristos     }
1463*5b10f583Schristos     EC_GROUP_free(dup);
1464*5b10f583Schristos     return ret_group;
1465*5b10f583Schristos err:
1466*5b10f583Schristos     EC_GROUP_free(dup);
1467*5b10f583Schristos     EC_GROUP_free(ret_group);
1468*5b10f583Schristos     return NULL;
1469*5b10f583Schristos }
1470*5b10f583Schristos #endif /* FIPS_MODULE */
1471*5b10f583Schristos 
group_new_from_name(const OSSL_PARAM * p,OSSL_LIB_CTX * libctx,const char * propq)1472*5b10f583Schristos static EC_GROUP *group_new_from_name(const OSSL_PARAM *p,
1473*5b10f583Schristos                                      OSSL_LIB_CTX *libctx, const char *propq)
1474*5b10f583Schristos {
1475*5b10f583Schristos     int ok = 0, nid;
1476*5b10f583Schristos     const char *curve_name = NULL;
1477*5b10f583Schristos 
1478*5b10f583Schristos     switch (p->data_type) {
1479*5b10f583Schristos     case OSSL_PARAM_UTF8_STRING:
1480*5b10f583Schristos         /* The OSSL_PARAM functions have no support for this */
1481*5b10f583Schristos         curve_name = p->data;
1482*5b10f583Schristos         ok = (curve_name != NULL);
1483*5b10f583Schristos         break;
1484*5b10f583Schristos     case OSSL_PARAM_UTF8_PTR:
1485*5b10f583Schristos         ok = OSSL_PARAM_get_utf8_ptr(p, &curve_name);
1486*5b10f583Schristos         break;
1487*5b10f583Schristos     }
1488*5b10f583Schristos 
1489*5b10f583Schristos     if (ok) {
1490*5b10f583Schristos         nid = ossl_ec_curve_name2nid(curve_name);
1491*5b10f583Schristos         if (nid == NID_undef) {
1492*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
1493*5b10f583Schristos             return NULL;
1494*5b10f583Schristos         } else {
1495*5b10f583Schristos             return EC_GROUP_new_by_curve_name_ex(libctx, propq, nid);
1496*5b10f583Schristos         }
1497*5b10f583Schristos     }
1498*5b10f583Schristos     return NULL;
1499*5b10f583Schristos }
1500*5b10f583Schristos 
1501*5b10f583Schristos /* These parameters can be set directly into an EC_GROUP */
ossl_ec_group_set_params(EC_GROUP * group,const OSSL_PARAM params[])1502*5b10f583Schristos int ossl_ec_group_set_params(EC_GROUP *group, const OSSL_PARAM params[])
1503*5b10f583Schristos {
1504*5b10f583Schristos     int encoding_flag = -1, format = -1;
1505*5b10f583Schristos     const OSSL_PARAM *p;
1506*5b10f583Schristos 
1507*5b10f583Schristos     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
1508*5b10f583Schristos     if (p != NULL) {
1509*5b10f583Schristos         if (!ossl_ec_pt_format_param2id(p, &format)) {
1510*5b10f583Schristos             ECerr(0, EC_R_INVALID_FORM);
1511*5b10f583Schristos             return 0;
1512*5b10f583Schristos         }
1513*5b10f583Schristos         EC_GROUP_set_point_conversion_form(group, format);
1514*5b10f583Schristos     }
1515*5b10f583Schristos 
1516*5b10f583Schristos     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
1517*5b10f583Schristos     if (p != NULL) {
1518*5b10f583Schristos         if (!ossl_ec_encoding_param2id(p, &encoding_flag)) {
1519*5b10f583Schristos             ECerr(0, EC_R_INVALID_FORM);
1520*5b10f583Schristos             return 0;
1521*5b10f583Schristos         }
1522*5b10f583Schristos         EC_GROUP_set_asn1_flag(group, encoding_flag);
1523*5b10f583Schristos     }
1524*5b10f583Schristos     /* Optional seed */
1525*5b10f583Schristos     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
1526*5b10f583Schristos     if (p != NULL) {
1527*5b10f583Schristos         /* The seed is allowed to be NULL */
1528*5b10f583Schristos         if (p->data_type != OSSL_PARAM_OCTET_STRING
1529*5b10f583Schristos             || !EC_GROUP_set_seed(group, p->data, p->data_size)) {
1530*5b10f583Schristos             ECerr(0, EC_R_INVALID_SEED);
1531*5b10f583Schristos             return 0;
1532*5b10f583Schristos         }
1533*5b10f583Schristos     }
1534*5b10f583Schristos     return 1;
1535*5b10f583Schristos }
1536*5b10f583Schristos 
EC_GROUP_new_from_params(const OSSL_PARAM params[],OSSL_LIB_CTX * libctx,const char * propq)1537*5b10f583Schristos EC_GROUP *EC_GROUP_new_from_params(const OSSL_PARAM params[],
1538*5b10f583Schristos                                    OSSL_LIB_CTX *libctx, const char *propq)
1539*5b10f583Schristos {
1540*5b10f583Schristos     const OSSL_PARAM *ptmp;
1541*5b10f583Schristos     EC_GROUP *group = NULL;
1542*5b10f583Schristos 
1543*5b10f583Schristos #ifndef FIPS_MODULE
1544*5b10f583Schristos     const OSSL_PARAM *pa, *pb;
1545*5b10f583Schristos     int ok = 0;
1546*5b10f583Schristos     EC_GROUP *named_group = NULL;
1547*5b10f583Schristos     BIGNUM *p = NULL, *a = NULL, *b = NULL, *order = NULL, *cofactor = NULL;
1548*5b10f583Schristos     EC_POINT *point = NULL;
1549*5b10f583Schristos     int field_bits = 0;
1550*5b10f583Schristos     int is_prime_field = 1;
1551*5b10f583Schristos     BN_CTX *bnctx = NULL;
1552*5b10f583Schristos     const unsigned char *buf = NULL;
1553*5b10f583Schristos     int encoding_flag = -1;
1554*5b10f583Schristos #endif
1555*5b10f583Schristos 
1556*5b10f583Schristos     /* This is the simple named group case */
1557*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
1558*5b10f583Schristos     if (ptmp != NULL) {
1559*5b10f583Schristos         int decoded = 0;
1560*5b10f583Schristos 
1561*5b10f583Schristos         if ((group = group_new_from_name(ptmp, libctx, propq)) == NULL)
1562*5b10f583Schristos             return NULL;
1563*5b10f583Schristos         if (!ossl_ec_group_set_params(group, params)) {
1564*5b10f583Schristos             EC_GROUP_free(group);
1565*5b10f583Schristos             return NULL;
1566*5b10f583Schristos         }
1567*5b10f583Schristos 
1568*5b10f583Schristos         ptmp = OSSL_PARAM_locate_const(params,
1569*5b10f583Schristos                                        OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS);
1570*5b10f583Schristos         if (ptmp != NULL && !OSSL_PARAM_get_int(ptmp, &decoded)) {
1571*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_WRONG_CURVE_PARAMETERS);
1572*5b10f583Schristos             EC_GROUP_free(group);
1573*5b10f583Schristos             return NULL;
1574*5b10f583Schristos         }
1575*5b10f583Schristos         group->decoded_from_explicit_params = decoded > 0;
1576*5b10f583Schristos         return group;
1577*5b10f583Schristos     }
1578*5b10f583Schristos #ifdef FIPS_MODULE
1579*5b10f583Schristos     ERR_raise(ERR_LIB_EC, EC_R_EXPLICIT_PARAMS_NOT_SUPPORTED);
1580*5b10f583Schristos     return NULL;
1581*5b10f583Schristos #else
1582*5b10f583Schristos     /* If it gets here then we are trying explicit parameters */
1583*5b10f583Schristos     bnctx = BN_CTX_new_ex(libctx);
1584*5b10f583Schristos     if (bnctx == NULL) {
1585*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1586*5b10f583Schristos         return 0;
1587*5b10f583Schristos     }
1588*5b10f583Schristos     BN_CTX_start(bnctx);
1589*5b10f583Schristos 
1590*5b10f583Schristos     p = BN_CTX_get(bnctx);
1591*5b10f583Schristos     a = BN_CTX_get(bnctx);
1592*5b10f583Schristos     b = BN_CTX_get(bnctx);
1593*5b10f583Schristos     order = BN_CTX_get(bnctx);
1594*5b10f583Schristos     if (order == NULL) {
1595*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1596*5b10f583Schristos         goto err;
1597*5b10f583Schristos     }
1598*5b10f583Schristos 
1599*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
1600*5b10f583Schristos     if (ptmp == NULL || ptmp->data_type != OSSL_PARAM_UTF8_STRING) {
1601*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
1602*5b10f583Schristos         goto err;
1603*5b10f583Schristos     }
1604*5b10f583Schristos     if (OPENSSL_strcasecmp(ptmp->data, SN_X9_62_prime_field) == 0) {
1605*5b10f583Schristos         is_prime_field = 1;
1606*5b10f583Schristos     } else if (OPENSSL_strcasecmp(ptmp->data,
1607*5b10f583Schristos                                   SN_X9_62_characteristic_two_field) == 0) {
1608*5b10f583Schristos         is_prime_field = 0;
1609*5b10f583Schristos     } else {
1610*5b10f583Schristos         /* Invalid field */
1611*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_UNSUPPORTED_FIELD);
1612*5b10f583Schristos         goto err;
1613*5b10f583Schristos     }
1614*5b10f583Schristos 
1615*5b10f583Schristos     pa = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
1616*5b10f583Schristos     if (!OSSL_PARAM_get_BN(pa, &a)) {
1617*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_A);
1618*5b10f583Schristos         goto err;
1619*5b10f583Schristos     }
1620*5b10f583Schristos     pb = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
1621*5b10f583Schristos     if (!OSSL_PARAM_get_BN(pb, &b)) {
1622*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_B);
1623*5b10f583Schristos         goto err;
1624*5b10f583Schristos     }
1625*5b10f583Schristos 
1626*5b10f583Schristos     /* extract the prime number or irreducible polynomial */
1627*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
1628*5b10f583Schristos     if (!OSSL_PARAM_get_BN(ptmp, &p)) {
1629*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
1630*5b10f583Schristos         goto err;
1631*5b10f583Schristos     }
1632*5b10f583Schristos 
1633*5b10f583Schristos     if (is_prime_field) {
1634*5b10f583Schristos         if (BN_is_negative(p) || BN_is_zero(p)) {
1635*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_P);
1636*5b10f583Schristos             goto err;
1637*5b10f583Schristos         }
1638*5b10f583Schristos         field_bits = BN_num_bits(p);
1639*5b10f583Schristos         if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
1640*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
1641*5b10f583Schristos             goto err;
1642*5b10f583Schristos         }
1643*5b10f583Schristos 
1644*5b10f583Schristos         /* create the EC_GROUP structure */
1645*5b10f583Schristos         group = EC_GROUP_new_curve_GFp(p, a, b, bnctx);
1646*5b10f583Schristos     } else {
1647*5b10f583Schristos # ifdef OPENSSL_NO_EC2M
1648*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
1649*5b10f583Schristos         goto err;
1650*5b10f583Schristos # else
1651*5b10f583Schristos         /* create the EC_GROUP structure */
1652*5b10f583Schristos         group = EC_GROUP_new_curve_GF2m(p, a, b, NULL);
1653*5b10f583Schristos         if (group != NULL) {
1654*5b10f583Schristos             field_bits = EC_GROUP_get_degree(group);
1655*5b10f583Schristos             if (field_bits > OPENSSL_ECC_MAX_FIELD_BITS) {
1656*5b10f583Schristos                 ERR_raise(ERR_LIB_EC, EC_R_FIELD_TOO_LARGE);
1657*5b10f583Schristos                 goto err;
1658*5b10f583Schristos             }
1659*5b10f583Schristos         }
1660*5b10f583Schristos # endif /* OPENSSL_NO_EC2M */
1661*5b10f583Schristos     }
1662*5b10f583Schristos 
1663*5b10f583Schristos     if (group == NULL) {
1664*5b10f583Schristos         ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1665*5b10f583Schristos         goto err;
1666*5b10f583Schristos     }
1667*5b10f583Schristos 
1668*5b10f583Schristos     /* Optional seed */
1669*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
1670*5b10f583Schristos     if (ptmp != NULL) {
1671*5b10f583Schristos         if (ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
1672*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_SEED);
1673*5b10f583Schristos             goto err;
1674*5b10f583Schristos         }
1675*5b10f583Schristos         if (!EC_GROUP_set_seed(group, ptmp->data, ptmp->data_size))
1676*5b10f583Schristos             goto err;
1677*5b10f583Schristos     }
1678*5b10f583Schristos 
1679*5b10f583Schristos     /* generator base point */
1680*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
1681*5b10f583Schristos     if (ptmp == NULL
1682*5b10f583Schristos         || ptmp->data_type != OSSL_PARAM_OCTET_STRING) {
1683*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
1684*5b10f583Schristos         goto err;
1685*5b10f583Schristos     }
1686*5b10f583Schristos     buf = (const unsigned char *)(ptmp->data);
1687*5b10f583Schristos     if ((point = EC_POINT_new(group)) == NULL)
1688*5b10f583Schristos         goto err;
1689*5b10f583Schristos     EC_GROUP_set_point_conversion_form(group,
1690*5b10f583Schristos                                        (point_conversion_form_t)buf[0] & ~0x01);
1691*5b10f583Schristos     if (!EC_POINT_oct2point(group, point, buf, ptmp->data_size, bnctx)) {
1692*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
1693*5b10f583Schristos         goto err;
1694*5b10f583Schristos     }
1695*5b10f583Schristos 
1696*5b10f583Schristos     /* order */
1697*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
1698*5b10f583Schristos     if (!OSSL_PARAM_get_BN(ptmp, &order)
1699*5b10f583Schristos         || (BN_is_negative(order) || BN_is_zero(order))
1700*5b10f583Schristos         || (BN_num_bits(order) > (int)field_bits + 1)) { /* Hasse bound */
1701*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
1702*5b10f583Schristos         goto err;
1703*5b10f583Schristos     }
1704*5b10f583Schristos 
1705*5b10f583Schristos     /* Optional cofactor */
1706*5b10f583Schristos     ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
1707*5b10f583Schristos     if (ptmp != NULL) {
1708*5b10f583Schristos         cofactor = BN_CTX_get(bnctx);
1709*5b10f583Schristos         if (cofactor == NULL || !OSSL_PARAM_get_BN(ptmp, &cofactor)) {
1710*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_COFACTOR);
1711*5b10f583Schristos             goto err;
1712*5b10f583Schristos         }
1713*5b10f583Schristos     }
1714*5b10f583Schristos 
1715*5b10f583Schristos     /* set the generator, order and cofactor (if present) */
1716*5b10f583Schristos     if (!EC_GROUP_set_generator(group, point, order, cofactor)) {
1717*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
1718*5b10f583Schristos         goto err;
1719*5b10f583Schristos     }
1720*5b10f583Schristos 
1721*5b10f583Schristos     named_group = ec_group_explicit_to_named(group, libctx, propq, bnctx);
1722*5b10f583Schristos     if (named_group == NULL) {
1723*5b10f583Schristos         ERR_raise(ERR_LIB_EC, EC_R_INVALID_NAMED_GROUP_CONVERSION);
1724*5b10f583Schristos         goto err;
1725*5b10f583Schristos     }
1726*5b10f583Schristos     if (named_group == group) {
1727*5b10f583Schristos         /*
1728*5b10f583Schristos          * If we did not find a named group then the encoding should be explicit
1729*5b10f583Schristos          * if it was specified
1730*5b10f583Schristos          */
1731*5b10f583Schristos         ptmp = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ENCODING);
1732*5b10f583Schristos         if (ptmp != NULL
1733*5b10f583Schristos             && !ossl_ec_encoding_param2id(ptmp, &encoding_flag)) {
1734*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
1735*5b10f583Schristos             goto err;
1736*5b10f583Schristos         }
1737*5b10f583Schristos         if (encoding_flag == OPENSSL_EC_NAMED_CURVE) {
1738*5b10f583Schristos             ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
1739*5b10f583Schristos             goto err;
1740*5b10f583Schristos         }
1741*5b10f583Schristos         EC_GROUP_set_asn1_flag(group, OPENSSL_EC_EXPLICIT_CURVE);
1742*5b10f583Schristos     } else {
1743*5b10f583Schristos         EC_GROUP_free(group);
1744*5b10f583Schristos         group = named_group;
1745*5b10f583Schristos     }
1746*5b10f583Schristos     /* We've imported the group from explicit parameters, set it so. */
1747*5b10f583Schristos     group->decoded_from_explicit_params = 1;
1748*5b10f583Schristos     ok = 1;
1749*5b10f583Schristos  err:
1750*5b10f583Schristos     if (!ok) {
1751*5b10f583Schristos         EC_GROUP_free(group);
1752*5b10f583Schristos         group = NULL;
1753*5b10f583Schristos     }
1754*5b10f583Schristos     EC_POINT_free(point);
1755*5b10f583Schristos     BN_CTX_end(bnctx);
1756*5b10f583Schristos     BN_CTX_free(bnctx);
1757*5b10f583Schristos 
1758*5b10f583Schristos     return group;
1759*5b10f583Schristos #endif /* FIPS_MODULE */
1760*5b10f583Schristos }
1761