1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * Low level APIs related to EC_KEY are deprecated for public use,
12e1051a39Sopenharmony_ci * but still ok for internal use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <openssl/core_names.h>
17e1051a39Sopenharmony_ci#include <openssl/objects.h>
18e1051a39Sopenharmony_ci#include <openssl/params.h>
19e1051a39Sopenharmony_ci#include <openssl/err.h>
20e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
21e1051a39Sopenharmony_ci# include <openssl/engine.h>
22e1051a39Sopenharmony_ci# include <openssl/x509.h>
23e1051a39Sopenharmony_ci#endif
24e1051a39Sopenharmony_ci#include "crypto/bn.h"
25e1051a39Sopenharmony_ci#include "crypto/ec.h"
26e1051a39Sopenharmony_ci#include "ec_local.h"
27e1051a39Sopenharmony_ci#include "e_os.h"
28e1051a39Sopenharmony_ci#include "internal/param_build_set.h"
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_ci/* Mapping between a flag and a name */
31e1051a39Sopenharmony_cistatic const OSSL_ITEM encoding_nameid_map[] = {
32e1051a39Sopenharmony_ci    { OPENSSL_EC_EXPLICIT_CURVE, OSSL_PKEY_EC_ENCODING_EXPLICIT },
33e1051a39Sopenharmony_ci    { OPENSSL_EC_NAMED_CURVE, OSSL_PKEY_EC_ENCODING_GROUP },
34e1051a39Sopenharmony_ci};
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_cistatic const OSSL_ITEM check_group_type_nameid_map[] = {
37e1051a39Sopenharmony_ci    { 0, OSSL_PKEY_EC_GROUP_CHECK_DEFAULT },
38e1051a39Sopenharmony_ci    { EC_FLAG_CHECK_NAMED_GROUP, OSSL_PKEY_EC_GROUP_CHECK_NAMED },
39e1051a39Sopenharmony_ci    { EC_FLAG_CHECK_NAMED_GROUP_NIST, OSSL_PKEY_EC_GROUP_CHECK_NAMED_NIST },
40e1051a39Sopenharmony_ci};
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_cistatic const OSSL_ITEM format_nameid_map[] = {
43e1051a39Sopenharmony_ci    { (int)POINT_CONVERSION_UNCOMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_UNCOMPRESSED },
44e1051a39Sopenharmony_ci    { (int)POINT_CONVERSION_COMPRESSED, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_COMPRESSED },
45e1051a39Sopenharmony_ci    { (int)POINT_CONVERSION_HYBRID, OSSL_PKEY_EC_POINT_CONVERSION_FORMAT_HYBRID },
46e1051a39Sopenharmony_ci};
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_ciint ossl_ec_encoding_name2id(const char *name)
49e1051a39Sopenharmony_ci{
50e1051a39Sopenharmony_ci    size_t i, sz;
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci    /* Return the default value if there is no name */
53e1051a39Sopenharmony_ci    if (name == NULL)
54e1051a39Sopenharmony_ci        return OPENSSL_EC_NAMED_CURVE;
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
57e1051a39Sopenharmony_ci        if (OPENSSL_strcasecmp(name, encoding_nameid_map[i].ptr) == 0)
58e1051a39Sopenharmony_ci            return encoding_nameid_map[i].id;
59e1051a39Sopenharmony_ci    }
60e1051a39Sopenharmony_ci    return -1;
61e1051a39Sopenharmony_ci}
62e1051a39Sopenharmony_ci
63e1051a39Sopenharmony_cistatic char *ec_param_encoding_id2name(int id)
64e1051a39Sopenharmony_ci{
65e1051a39Sopenharmony_ci    size_t i, sz;
66e1051a39Sopenharmony_ci
67e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(encoding_nameid_map); i < sz; i++) {
68e1051a39Sopenharmony_ci        if (id == (int)encoding_nameid_map[i].id)
69e1051a39Sopenharmony_ci            return encoding_nameid_map[i].ptr;
70e1051a39Sopenharmony_ci    }
71e1051a39Sopenharmony_ci    return NULL;
72e1051a39Sopenharmony_ci}
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cichar *ossl_ec_check_group_type_id2name(int id)
75e1051a39Sopenharmony_ci{
76e1051a39Sopenharmony_ci    size_t i, sz;
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
79e1051a39Sopenharmony_ci        if (id == (int)check_group_type_nameid_map[i].id)
80e1051a39Sopenharmony_ci            return check_group_type_nameid_map[i].ptr;
81e1051a39Sopenharmony_ci    }
82e1051a39Sopenharmony_ci    return NULL;
83e1051a39Sopenharmony_ci}
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_cistatic int ec_check_group_type_name2id(const char *name)
86e1051a39Sopenharmony_ci{
87e1051a39Sopenharmony_ci    size_t i, sz;
88e1051a39Sopenharmony_ci
89e1051a39Sopenharmony_ci    /* Return the default value if there is no name */
90e1051a39Sopenharmony_ci    if (name == NULL)
91e1051a39Sopenharmony_ci        return 0;
92e1051a39Sopenharmony_ci
93e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(check_group_type_nameid_map); i < sz; i++) {
94e1051a39Sopenharmony_ci        if (OPENSSL_strcasecmp(name, check_group_type_nameid_map[i].ptr) == 0)
95e1051a39Sopenharmony_ci            return check_group_type_nameid_map[i].id;
96e1051a39Sopenharmony_ci    }
97e1051a39Sopenharmony_ci    return -1;
98e1051a39Sopenharmony_ci}
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ciint ossl_ec_set_check_group_type_from_name(EC_KEY *ec, const char *name)
101e1051a39Sopenharmony_ci{
102e1051a39Sopenharmony_ci    int flags = ec_check_group_type_name2id(name);
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci    if (flags == -1)
105e1051a39Sopenharmony_ci        return 0;
106e1051a39Sopenharmony_ci    EC_KEY_clear_flags(ec, EC_FLAG_CHECK_NAMED_GROUP_MASK);
107e1051a39Sopenharmony_ci    EC_KEY_set_flags(ec, flags);
108e1051a39Sopenharmony_ci    return 1;
109e1051a39Sopenharmony_ci}
110e1051a39Sopenharmony_ci
111e1051a39Sopenharmony_cistatic int ec_set_check_group_type_from_param(EC_KEY *ec, const OSSL_PARAM *p)
112e1051a39Sopenharmony_ci{
113e1051a39Sopenharmony_ci    const char *name = NULL;
114e1051a39Sopenharmony_ci    int status = 0;
115e1051a39Sopenharmony_ci
116e1051a39Sopenharmony_ci    switch (p->data_type) {
117e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_STRING:
118e1051a39Sopenharmony_ci        name = p->data;
119e1051a39Sopenharmony_ci        status = (name != NULL);
120e1051a39Sopenharmony_ci        break;
121e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_PTR:
122e1051a39Sopenharmony_ci        status = OSSL_PARAM_get_utf8_ptr(p, &name);
123e1051a39Sopenharmony_ci        break;
124e1051a39Sopenharmony_ci    }
125e1051a39Sopenharmony_ci    if (status)
126e1051a39Sopenharmony_ci        return ossl_ec_set_check_group_type_from_name(ec, name);
127e1051a39Sopenharmony_ci    return 0;
128e1051a39Sopenharmony_ci}
129e1051a39Sopenharmony_ci
130e1051a39Sopenharmony_ciint ossl_ec_pt_format_name2id(const char *name)
131e1051a39Sopenharmony_ci{
132e1051a39Sopenharmony_ci    size_t i, sz;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci    /* Return the default value if there is no name */
135e1051a39Sopenharmony_ci    if (name == NULL)
136e1051a39Sopenharmony_ci        return (int)POINT_CONVERSION_UNCOMPRESSED;
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
139e1051a39Sopenharmony_ci        if (OPENSSL_strcasecmp(name, format_nameid_map[i].ptr) == 0)
140e1051a39Sopenharmony_ci            return format_nameid_map[i].id;
141e1051a39Sopenharmony_ci    }
142e1051a39Sopenharmony_ci    return -1;
143e1051a39Sopenharmony_ci}
144e1051a39Sopenharmony_ci
145e1051a39Sopenharmony_cichar *ossl_ec_pt_format_id2name(int id)
146e1051a39Sopenharmony_ci{
147e1051a39Sopenharmony_ci    size_t i, sz;
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    for (i = 0, sz = OSSL_NELEM(format_nameid_map); i < sz; i++) {
150e1051a39Sopenharmony_ci        if (id == (int)format_nameid_map[i].id)
151e1051a39Sopenharmony_ci            return format_nameid_map[i].ptr;
152e1051a39Sopenharmony_ci    }
153e1051a39Sopenharmony_ci    return NULL;
154e1051a39Sopenharmony_ci}
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_cistatic int ec_group_explicit_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
157e1051a39Sopenharmony_ci                                    OSSL_PARAM params[], BN_CTX *bnctx,
158e1051a39Sopenharmony_ci                                    unsigned char **genbuf)
159e1051a39Sopenharmony_ci{
160e1051a39Sopenharmony_ci    int ret = 0, fid;
161e1051a39Sopenharmony_ci    const char *field_type;
162e1051a39Sopenharmony_ci    const OSSL_PARAM *param = NULL;
163e1051a39Sopenharmony_ci    const OSSL_PARAM *param_p = NULL;
164e1051a39Sopenharmony_ci    const OSSL_PARAM *param_a = NULL;
165e1051a39Sopenharmony_ci    const OSSL_PARAM *param_b = NULL;
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci    fid = EC_GROUP_get_field_type(group);
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci    if (fid == NID_X9_62_prime_field) {
170e1051a39Sopenharmony_ci        field_type = SN_X9_62_prime_field;
171e1051a39Sopenharmony_ci    } else if (fid == NID_X9_62_characteristic_two_field) {
172e1051a39Sopenharmony_ci#ifdef OPENSSL_NO_EC2M
173e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_GF2M_NOT_SUPPORTED);
174e1051a39Sopenharmony_ci        goto err;
175e1051a39Sopenharmony_ci#else
176e1051a39Sopenharmony_ci        field_type = SN_X9_62_characteristic_two_field;
177e1051a39Sopenharmony_ci#endif
178e1051a39Sopenharmony_ci    } else {
179e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_FIELD);
180e1051a39Sopenharmony_ci        return 0;
181e1051a39Sopenharmony_ci    }
182e1051a39Sopenharmony_ci
183e1051a39Sopenharmony_ci    param_p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_P);
184e1051a39Sopenharmony_ci    param_a = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_A);
185e1051a39Sopenharmony_ci    param_b = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_B);
186e1051a39Sopenharmony_ci    if (tmpl != NULL || param_p != NULL || param_a != NULL || param_b != NULL)
187e1051a39Sopenharmony_ci    {
188e1051a39Sopenharmony_ci        BIGNUM *p = BN_CTX_get(bnctx);
189e1051a39Sopenharmony_ci        BIGNUM *a = BN_CTX_get(bnctx);
190e1051a39Sopenharmony_ci        BIGNUM *b = BN_CTX_get(bnctx);
191e1051a39Sopenharmony_ci
192e1051a39Sopenharmony_ci        if (b == NULL) {
193e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
194e1051a39Sopenharmony_ci            goto err;
195e1051a39Sopenharmony_ci        }
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci        if (!EC_GROUP_get_curve(group, p, a, b, bnctx)) {
198e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
199e1051a39Sopenharmony_ci            goto err;
200e1051a39Sopenharmony_ci        }
201e1051a39Sopenharmony_ci        if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_P, p)
202e1051a39Sopenharmony_ci            || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_A, a)
203e1051a39Sopenharmony_ci            || !ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_B, b)) {
204e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
205e1051a39Sopenharmony_ci            goto err;
206e1051a39Sopenharmony_ci        }
207e1051a39Sopenharmony_ci    }
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_ci    param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_ORDER);
210e1051a39Sopenharmony_ci    if (tmpl != NULL || param != NULL) {
211e1051a39Sopenharmony_ci        const BIGNUM *order = EC_GROUP_get0_order(group);
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci        if (order == NULL) {
214e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_GROUP_ORDER);
215e1051a39Sopenharmony_ci            goto err;
216e1051a39Sopenharmony_ci        }
217e1051a39Sopenharmony_ci        if (!ossl_param_build_set_bn(tmpl, params, OSSL_PKEY_PARAM_EC_ORDER,
218e1051a39Sopenharmony_ci                                    order)) {
219e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
220e1051a39Sopenharmony_ci            goto err;
221e1051a39Sopenharmony_ci        }
222e1051a39Sopenharmony_ci    }
223e1051a39Sopenharmony_ci
224e1051a39Sopenharmony_ci    param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_FIELD_TYPE);
225e1051a39Sopenharmony_ci    if (tmpl != NULL || param != NULL) {
226e1051a39Sopenharmony_ci        if (!ossl_param_build_set_utf8_string(tmpl, params,
227e1051a39Sopenharmony_ci                                              OSSL_PKEY_PARAM_EC_FIELD_TYPE,
228e1051a39Sopenharmony_ci                                              field_type)) {
229e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
230e1051a39Sopenharmony_ci            goto err;
231e1051a39Sopenharmony_ci        }
232e1051a39Sopenharmony_ci    }
233e1051a39Sopenharmony_ci
234e1051a39Sopenharmony_ci    param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GENERATOR);
235e1051a39Sopenharmony_ci    if (tmpl != NULL || param != NULL) {
236e1051a39Sopenharmony_ci        size_t genbuf_len;
237e1051a39Sopenharmony_ci        const EC_POINT *genpt = EC_GROUP_get0_generator(group);
238e1051a39Sopenharmony_ci        point_conversion_form_t genform = EC_GROUP_get_point_conversion_form(group);
239e1051a39Sopenharmony_ci
240e1051a39Sopenharmony_ci        if (genpt == NULL) {
241e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
242e1051a39Sopenharmony_ci            goto err;
243e1051a39Sopenharmony_ci        }
244e1051a39Sopenharmony_ci        genbuf_len = EC_POINT_point2buf(group, genpt, genform, genbuf, bnctx);
245e1051a39Sopenharmony_ci        if (genbuf_len == 0) {
246e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_GENERATOR);
247e1051a39Sopenharmony_ci            goto err;
248e1051a39Sopenharmony_ci        }
249e1051a39Sopenharmony_ci        if (!ossl_param_build_set_octet_string(tmpl, params,
250e1051a39Sopenharmony_ci                                               OSSL_PKEY_PARAM_EC_GENERATOR,
251e1051a39Sopenharmony_ci                                               *genbuf, genbuf_len)) {
252e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
253e1051a39Sopenharmony_ci            goto err;
254e1051a39Sopenharmony_ci        }
255e1051a39Sopenharmony_ci    }
256e1051a39Sopenharmony_ci
257e1051a39Sopenharmony_ci    param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_COFACTOR);
258e1051a39Sopenharmony_ci    if (tmpl != NULL || param != NULL) {
259e1051a39Sopenharmony_ci        const BIGNUM *cofactor = EC_GROUP_get0_cofactor(group);
260e1051a39Sopenharmony_ci
261e1051a39Sopenharmony_ci        if (cofactor != NULL
262e1051a39Sopenharmony_ci            && !ossl_param_build_set_bn(tmpl, params,
263e1051a39Sopenharmony_ci                                        OSSL_PKEY_PARAM_EC_COFACTOR, cofactor)) {
264e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
265e1051a39Sopenharmony_ci            goto err;
266e1051a39Sopenharmony_ci        }
267e1051a39Sopenharmony_ci    }
268e1051a39Sopenharmony_ci
269e1051a39Sopenharmony_ci    param = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_SEED);
270e1051a39Sopenharmony_ci    if (tmpl != NULL || param != NULL) {
271e1051a39Sopenharmony_ci        unsigned char *seed = EC_GROUP_get0_seed(group);
272e1051a39Sopenharmony_ci        size_t seed_len = EC_GROUP_get_seed_len(group);
273e1051a39Sopenharmony_ci
274e1051a39Sopenharmony_ci        if (seed != NULL
275e1051a39Sopenharmony_ci            && seed_len > 0
276e1051a39Sopenharmony_ci            && !ossl_param_build_set_octet_string(tmpl, params,
277e1051a39Sopenharmony_ci                                                  OSSL_PKEY_PARAM_EC_SEED,
278e1051a39Sopenharmony_ci                                                  seed, seed_len)) {
279e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
280e1051a39Sopenharmony_ci            goto err;
281e1051a39Sopenharmony_ci        }
282e1051a39Sopenharmony_ci    }
283e1051a39Sopenharmony_ci    ret = 1;
284e1051a39Sopenharmony_cierr:
285e1051a39Sopenharmony_ci    return ret;
286e1051a39Sopenharmony_ci}
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ciint ossl_ec_group_todata(const EC_GROUP *group, OSSL_PARAM_BLD *tmpl,
289e1051a39Sopenharmony_ci                         OSSL_PARAM params[], OSSL_LIB_CTX *libctx,
290e1051a39Sopenharmony_ci                         const char *propq,
291e1051a39Sopenharmony_ci                         BN_CTX *bnctx, unsigned char **genbuf)
292e1051a39Sopenharmony_ci{
293e1051a39Sopenharmony_ci    int ret = 0, curve_nid, encoding_flag;
294e1051a39Sopenharmony_ci    const char *encoding_name, *pt_form_name;
295e1051a39Sopenharmony_ci    point_conversion_form_t genform;
296e1051a39Sopenharmony_ci
297e1051a39Sopenharmony_ci    if (group == NULL) {
298e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC,EC_R_PASSED_NULL_PARAMETER);
299e1051a39Sopenharmony_ci        return 0;
300e1051a39Sopenharmony_ci    }
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ci    genform = EC_GROUP_get_point_conversion_form(group);
303e1051a39Sopenharmony_ci    pt_form_name = ossl_ec_pt_format_id2name(genform);
304e1051a39Sopenharmony_ci    if (pt_form_name == NULL
305e1051a39Sopenharmony_ci        || !ossl_param_build_set_utf8_string(
306e1051a39Sopenharmony_ci                tmpl, params,
307e1051a39Sopenharmony_ci                OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, pt_form_name)) {
308e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_FORM);
309e1051a39Sopenharmony_ci        return 0;
310e1051a39Sopenharmony_ci    }
311e1051a39Sopenharmony_ci    encoding_flag = EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE;
312e1051a39Sopenharmony_ci    encoding_name = ec_param_encoding_id2name(encoding_flag);
313e1051a39Sopenharmony_ci    if (encoding_name == NULL
314e1051a39Sopenharmony_ci        || !ossl_param_build_set_utf8_string(tmpl, params,
315e1051a39Sopenharmony_ci                                             OSSL_PKEY_PARAM_EC_ENCODING,
316e1051a39Sopenharmony_ci                                             encoding_name)) {
317e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
318e1051a39Sopenharmony_ci        return 0;
319e1051a39Sopenharmony_ci    }
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_ci    if (!ossl_param_build_set_int(tmpl, params,
322e1051a39Sopenharmony_ci                                  OSSL_PKEY_PARAM_EC_DECODED_FROM_EXPLICIT_PARAMS,
323e1051a39Sopenharmony_ci                                  group->decoded_from_explicit_params))
324e1051a39Sopenharmony_ci        return 0;
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_ci    curve_nid = EC_GROUP_get_curve_name(group);
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    /*
329e1051a39Sopenharmony_ci     * Get the explicit parameters in these two cases:
330e1051a39Sopenharmony_ci     * - We do not have a template, i.e. specific parameters are requested
331e1051a39Sopenharmony_ci     * - The curve is not a named curve
332e1051a39Sopenharmony_ci     */
333e1051a39Sopenharmony_ci    if (tmpl == NULL || curve_nid == NID_undef)
334e1051a39Sopenharmony_ci        if (!ec_group_explicit_todata(group, tmpl, params, bnctx, genbuf))
335e1051a39Sopenharmony_ci            goto err;
336e1051a39Sopenharmony_ci
337e1051a39Sopenharmony_ci    if (curve_nid != NID_undef) {
338e1051a39Sopenharmony_ci        /* Named curve */
339e1051a39Sopenharmony_ci        const char *curve_name = OSSL_EC_curve_nid2name(curve_nid);
340e1051a39Sopenharmony_ci
341e1051a39Sopenharmony_ci        if (curve_name == NULL
342e1051a39Sopenharmony_ci            || !ossl_param_build_set_utf8_string(tmpl, params,
343e1051a39Sopenharmony_ci                                                 OSSL_PKEY_PARAM_GROUP_NAME,
344e1051a39Sopenharmony_ci                                                 curve_name)) {
345e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
346e1051a39Sopenharmony_ci            goto err;
347e1051a39Sopenharmony_ci        }
348e1051a39Sopenharmony_ci    }
349e1051a39Sopenharmony_ci    ret = 1;
350e1051a39Sopenharmony_cierr:
351e1051a39Sopenharmony_ci    return ret;
352e1051a39Sopenharmony_ci}
353e1051a39Sopenharmony_ci
354e1051a39Sopenharmony_ci/*
355e1051a39Sopenharmony_ci * The intention with the "backend" source file is to offer backend support
356e1051a39Sopenharmony_ci * for legacy backends (EVP_PKEY_ASN1_METHOD and EVP_PKEY_METHOD) and provider
357e1051a39Sopenharmony_ci * implementations alike.
358e1051a39Sopenharmony_ci */
359e1051a39Sopenharmony_ciint ossl_ec_set_ecdh_cofactor_mode(EC_KEY *ec, int mode)
360e1051a39Sopenharmony_ci{
361e1051a39Sopenharmony_ci    const EC_GROUP *ecg = EC_KEY_get0_group(ec);
362e1051a39Sopenharmony_ci    const BIGNUM *cofactor;
363e1051a39Sopenharmony_ci    /*
364e1051a39Sopenharmony_ci     * mode can be only 0 for disable, or 1 for enable here.
365e1051a39Sopenharmony_ci     *
366e1051a39Sopenharmony_ci     * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
367e1051a39Sopenharmony_ci     * also supports mode == -1 with the meaning of "reset to the default for
368e1051a39Sopenharmony_ci     * the associated key".
369e1051a39Sopenharmony_ci     */
370e1051a39Sopenharmony_ci    if (mode < 0 || mode > 1)
371e1051a39Sopenharmony_ci        return 0;
372e1051a39Sopenharmony_ci
373e1051a39Sopenharmony_ci    if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
374e1051a39Sopenharmony_ci        return 0;
375e1051a39Sopenharmony_ci
376e1051a39Sopenharmony_ci    /* ECDH cofactor mode has no effect if cofactor is 1 */
377e1051a39Sopenharmony_ci    if (BN_is_one(cofactor))
378e1051a39Sopenharmony_ci        return 1;
379e1051a39Sopenharmony_ci
380e1051a39Sopenharmony_ci    if (mode == 1)
381e1051a39Sopenharmony_ci        EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
382e1051a39Sopenharmony_ci    else if (mode == 0)
383e1051a39Sopenharmony_ci        EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
384e1051a39Sopenharmony_ci
385e1051a39Sopenharmony_ci    return 1;
386e1051a39Sopenharmony_ci}
387e1051a39Sopenharmony_ci
388e1051a39Sopenharmony_ci/*
389e1051a39Sopenharmony_ci * Callers of ossl_ec_key_fromdata MUST make sure that ec_key_params_fromdata has
390e1051a39Sopenharmony_ci * been called before!
391e1051a39Sopenharmony_ci *
392e1051a39Sopenharmony_ci * This function only gets the bare keypair, domain parameters and other
393e1051a39Sopenharmony_ci * parameters are treated separately, and domain parameters are required to
394e1051a39Sopenharmony_ci * define a keypair.
395e1051a39Sopenharmony_ci */
396e1051a39Sopenharmony_ciint ossl_ec_key_fromdata(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
397e1051a39Sopenharmony_ci{
398e1051a39Sopenharmony_ci    const OSSL_PARAM *param_priv_key = NULL, *param_pub_key = NULL;
399e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
400e1051a39Sopenharmony_ci    BIGNUM *priv_key = NULL;
401e1051a39Sopenharmony_ci    unsigned char *pub_key = NULL;
402e1051a39Sopenharmony_ci    size_t pub_key_len;
403e1051a39Sopenharmony_ci    const EC_GROUP *ecg = NULL;
404e1051a39Sopenharmony_ci    EC_POINT *pub_point = NULL;
405e1051a39Sopenharmony_ci    int ok = 0;
406e1051a39Sopenharmony_ci
407e1051a39Sopenharmony_ci    ecg = EC_KEY_get0_group(ec);
408e1051a39Sopenharmony_ci    if (ecg == NULL)
409e1051a39Sopenharmony_ci        return 0;
410e1051a39Sopenharmony_ci
411e1051a39Sopenharmony_ci    param_pub_key =
412e1051a39Sopenharmony_ci        OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
413e1051a39Sopenharmony_ci    if (include_private)
414e1051a39Sopenharmony_ci        param_priv_key =
415e1051a39Sopenharmony_ci            OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
416e1051a39Sopenharmony_ci
417e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(ossl_ec_key_get_libctx(ec));
418e1051a39Sopenharmony_ci    if (ctx == NULL)
419e1051a39Sopenharmony_ci        goto err;
420e1051a39Sopenharmony_ci
421e1051a39Sopenharmony_ci    if (param_pub_key != NULL)
422e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_octet_string(param_pub_key,
423e1051a39Sopenharmony_ci                                         (void **)&pub_key, 0, &pub_key_len)
424e1051a39Sopenharmony_ci            || (pub_point = EC_POINT_new(ecg)) == NULL
425e1051a39Sopenharmony_ci            || !EC_POINT_oct2point(ecg, pub_point, pub_key, pub_key_len, ctx))
426e1051a39Sopenharmony_ci        goto err;
427e1051a39Sopenharmony_ci
428e1051a39Sopenharmony_ci    if (param_priv_key != NULL && include_private) {
429e1051a39Sopenharmony_ci        int fixed_words;
430e1051a39Sopenharmony_ci        const BIGNUM *order;
431e1051a39Sopenharmony_ci
432e1051a39Sopenharmony_ci        /*
433e1051a39Sopenharmony_ci         * Key import/export should never leak the bit length of the secret
434e1051a39Sopenharmony_ci         * scalar in the key.
435e1051a39Sopenharmony_ci         *
436e1051a39Sopenharmony_ci         * For this reason, on export we use padded BIGNUMs with fixed length.
437e1051a39Sopenharmony_ci         *
438e1051a39Sopenharmony_ci         * When importing we also should make sure that, even if short lived,
439e1051a39Sopenharmony_ci         * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
440e1051a39Sopenharmony_ci         * soon as possible, so that any processing of this BIGNUM might opt for
441e1051a39Sopenharmony_ci         * constant time implementations in the backend.
442e1051a39Sopenharmony_ci         *
443e1051a39Sopenharmony_ci         * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
444e1051a39Sopenharmony_ci         * to preallocate the BIGNUM internal buffer to a fixed public size big
445e1051a39Sopenharmony_ci         * enough that operations performed during the processing never trigger
446e1051a39Sopenharmony_ci         * a realloc which would leak the size of the scalar through memory
447e1051a39Sopenharmony_ci         * accesses.
448e1051a39Sopenharmony_ci         *
449e1051a39Sopenharmony_ci         * Fixed Length
450e1051a39Sopenharmony_ci         * ------------
451e1051a39Sopenharmony_ci         *
452e1051a39Sopenharmony_ci         * The order of the large prime subgroup of the curve is our choice for
453e1051a39Sopenharmony_ci         * a fixed public size, as that is generally the upper bound for
454e1051a39Sopenharmony_ci         * generating a private key in EC cryptosystems and should fit all valid
455e1051a39Sopenharmony_ci         * secret scalars.
456e1051a39Sopenharmony_ci         *
457e1051a39Sopenharmony_ci         * For padding on export we just use the bit length of the order
458e1051a39Sopenharmony_ci         * converted to bytes (rounding up).
459e1051a39Sopenharmony_ci         *
460e1051a39Sopenharmony_ci         * For preallocating the BIGNUM storage we look at the number of "words"
461e1051a39Sopenharmony_ci         * required for the internal representation of the order, and we
462e1051a39Sopenharmony_ci         * preallocate 2 extra "words" in case any of the subsequent processing
463e1051a39Sopenharmony_ci         * might temporarily overflow the order length.
464e1051a39Sopenharmony_ci         */
465e1051a39Sopenharmony_ci        order = EC_GROUP_get0_order(ecg);
466e1051a39Sopenharmony_ci        if (order == NULL || BN_is_zero(order))
467e1051a39Sopenharmony_ci            goto err;
468e1051a39Sopenharmony_ci
469e1051a39Sopenharmony_ci        fixed_words = bn_get_top(order) + 2;
470e1051a39Sopenharmony_ci
471e1051a39Sopenharmony_ci        if ((priv_key = BN_secure_new()) == NULL)
472e1051a39Sopenharmony_ci            goto err;
473e1051a39Sopenharmony_ci        if (bn_wexpand(priv_key, fixed_words) == NULL)
474e1051a39Sopenharmony_ci            goto err;
475e1051a39Sopenharmony_ci        BN_set_flags(priv_key, BN_FLG_CONSTTIME);
476e1051a39Sopenharmony_ci
477e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_BN(param_priv_key, &priv_key))
478e1051a39Sopenharmony_ci            goto err;
479e1051a39Sopenharmony_ci    }
480e1051a39Sopenharmony_ci
481e1051a39Sopenharmony_ci    if (priv_key != NULL
482e1051a39Sopenharmony_ci        && !EC_KEY_set_private_key(ec, priv_key))
483e1051a39Sopenharmony_ci        goto err;
484e1051a39Sopenharmony_ci
485e1051a39Sopenharmony_ci    if (pub_point != NULL
486e1051a39Sopenharmony_ci        && !EC_KEY_set_public_key(ec, pub_point))
487e1051a39Sopenharmony_ci        goto err;
488e1051a39Sopenharmony_ci
489e1051a39Sopenharmony_ci    ok = 1;
490e1051a39Sopenharmony_ci
491e1051a39Sopenharmony_ci err:
492e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
493e1051a39Sopenharmony_ci    BN_clear_free(priv_key);
494e1051a39Sopenharmony_ci    OPENSSL_free(pub_key);
495e1051a39Sopenharmony_ci    EC_POINT_free(pub_point);
496e1051a39Sopenharmony_ci    return ok;
497e1051a39Sopenharmony_ci}
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_ciint ossl_ec_group_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
500e1051a39Sopenharmony_ci{
501e1051a39Sopenharmony_ci    int ok = 0;
502e1051a39Sopenharmony_ci    EC_GROUP *group = NULL;
503e1051a39Sopenharmony_ci
504e1051a39Sopenharmony_ci    if (ec == NULL)
505e1051a39Sopenharmony_ci        return 0;
506e1051a39Sopenharmony_ci
507e1051a39Sopenharmony_ci     group = EC_GROUP_new_from_params(params, ossl_ec_key_get_libctx(ec),
508e1051a39Sopenharmony_ci                                      ossl_ec_key_get0_propq(ec));
509e1051a39Sopenharmony_ci
510e1051a39Sopenharmony_ci    if (!EC_KEY_set_group(ec, group))
511e1051a39Sopenharmony_ci        goto err;
512e1051a39Sopenharmony_ci    ok = 1;
513e1051a39Sopenharmony_cierr:
514e1051a39Sopenharmony_ci    EC_GROUP_free(group);
515e1051a39Sopenharmony_ci    return ok;
516e1051a39Sopenharmony_ci}
517e1051a39Sopenharmony_ci
518e1051a39Sopenharmony_cistatic int ec_key_point_format_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
519e1051a39Sopenharmony_ci{
520e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
521e1051a39Sopenharmony_ci    int format = -1;
522e1051a39Sopenharmony_ci
523e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT);
524e1051a39Sopenharmony_ci    if (p != NULL) {
525e1051a39Sopenharmony_ci        if (!ossl_ec_pt_format_param2id(p, &format)) {
526e1051a39Sopenharmony_ci            ECerr(0, EC_R_INVALID_FORM);
527e1051a39Sopenharmony_ci            return 0;
528e1051a39Sopenharmony_ci        }
529e1051a39Sopenharmony_ci        EC_KEY_set_conv_form(ec, format);
530e1051a39Sopenharmony_ci    }
531e1051a39Sopenharmony_ci    return 1;
532e1051a39Sopenharmony_ci}
533e1051a39Sopenharmony_ci
534e1051a39Sopenharmony_cistatic int ec_key_group_check_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
535e1051a39Sopenharmony_ci{
536e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
537e1051a39Sopenharmony_ci
538e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE);
539e1051a39Sopenharmony_ci    if (p != NULL)
540e1051a39Sopenharmony_ci        return ec_set_check_group_type_from_param(ec, p);
541e1051a39Sopenharmony_ci    return 1;
542e1051a39Sopenharmony_ci}
543e1051a39Sopenharmony_ci
544e1051a39Sopenharmony_cistatic int ec_set_include_public(EC_KEY *ec, int include)
545e1051a39Sopenharmony_ci{
546e1051a39Sopenharmony_ci    int flags = EC_KEY_get_enc_flags(ec);
547e1051a39Sopenharmony_ci
548e1051a39Sopenharmony_ci    if (!include)
549e1051a39Sopenharmony_ci        flags |= EC_PKEY_NO_PUBKEY;
550e1051a39Sopenharmony_ci    else
551e1051a39Sopenharmony_ci        flags &= ~EC_PKEY_NO_PUBKEY;
552e1051a39Sopenharmony_ci    EC_KEY_set_enc_flags(ec, flags);
553e1051a39Sopenharmony_ci    return 1;
554e1051a39Sopenharmony_ci}
555e1051a39Sopenharmony_ci
556e1051a39Sopenharmony_ciint ossl_ec_key_otherparams_fromdata(EC_KEY *ec, const OSSL_PARAM params[])
557e1051a39Sopenharmony_ci{
558e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
559e1051a39Sopenharmony_ci
560e1051a39Sopenharmony_ci    if (ec == NULL)
561e1051a39Sopenharmony_ci        return 0;
562e1051a39Sopenharmony_ci
563e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
564e1051a39Sopenharmony_ci    if (p != NULL) {
565e1051a39Sopenharmony_ci        int mode;
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_int(p, &mode)
568e1051a39Sopenharmony_ci            || !ossl_ec_set_ecdh_cofactor_mode(ec, mode))
569e1051a39Sopenharmony_ci            return 0;
570e1051a39Sopenharmony_ci    }
571e1051a39Sopenharmony_ci
572e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_INCLUDE_PUBLIC);
573e1051a39Sopenharmony_ci    if (p != NULL) {
574e1051a39Sopenharmony_ci        int include = 1;
575e1051a39Sopenharmony_ci
576e1051a39Sopenharmony_ci        if (!OSSL_PARAM_get_int(p, &include)
577e1051a39Sopenharmony_ci            || !ec_set_include_public(ec, include))
578e1051a39Sopenharmony_ci            return 0;
579e1051a39Sopenharmony_ci    }
580e1051a39Sopenharmony_ci    if (!ec_key_point_format_fromdata(ec, params))
581e1051a39Sopenharmony_ci        return 0;
582e1051a39Sopenharmony_ci    if (!ec_key_group_check_fromdata(ec, params))
583e1051a39Sopenharmony_ci        return 0;
584e1051a39Sopenharmony_ci    return 1;
585e1051a39Sopenharmony_ci}
586e1051a39Sopenharmony_ci
587e1051a39Sopenharmony_ciint ossl_ec_key_is_foreign(const EC_KEY *ec)
588e1051a39Sopenharmony_ci{
589e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
590e1051a39Sopenharmony_ci    if (ec->engine != NULL || EC_KEY_get_method(ec) != EC_KEY_OpenSSL())
591e1051a39Sopenharmony_ci        return 1;
592e1051a39Sopenharmony_ci#endif
593e1051a39Sopenharmony_ci    return 0;
594e1051a39Sopenharmony_ci
595e1051a39Sopenharmony_ci}
596e1051a39Sopenharmony_ci
597e1051a39Sopenharmony_ciEC_KEY *ossl_ec_key_dup(const EC_KEY *src, int selection)
598e1051a39Sopenharmony_ci{
599e1051a39Sopenharmony_ci    EC_KEY *ret;
600e1051a39Sopenharmony_ci
601e1051a39Sopenharmony_ci    if (src == NULL) {
602e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
603e1051a39Sopenharmony_ci        return NULL;
604e1051a39Sopenharmony_ci    }
605e1051a39Sopenharmony_ci
606e1051a39Sopenharmony_ci    if ((ret = ossl_ec_key_new_method_int(src->libctx, src->propq,
607e1051a39Sopenharmony_ci                                          src->engine)) == NULL)
608e1051a39Sopenharmony_ci        return NULL;
609e1051a39Sopenharmony_ci
610e1051a39Sopenharmony_ci    /* copy the parameters */
611e1051a39Sopenharmony_ci    if (src->group != NULL
612e1051a39Sopenharmony_ci        && (selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
613e1051a39Sopenharmony_ci        ret->group = ossl_ec_group_new_ex(src->libctx, src->propq,
614e1051a39Sopenharmony_ci                                          src->group->meth);
615e1051a39Sopenharmony_ci        if (ret->group == NULL
616e1051a39Sopenharmony_ci            || !EC_GROUP_copy(ret->group, src->group))
617e1051a39Sopenharmony_ci            goto err;
618e1051a39Sopenharmony_ci
619e1051a39Sopenharmony_ci        if (src->meth != NULL) {
620e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE)
621e1051a39Sopenharmony_ci            if (src->engine != NULL && ENGINE_init(src->engine) == 0)
622e1051a39Sopenharmony_ci                goto err;
623e1051a39Sopenharmony_ci            ret->engine = src->engine;
624e1051a39Sopenharmony_ci#endif
625e1051a39Sopenharmony_ci            ret->meth = src->meth;
626e1051a39Sopenharmony_ci        }
627e1051a39Sopenharmony_ci    }
628e1051a39Sopenharmony_ci
629e1051a39Sopenharmony_ci    /*  copy the public key */
630e1051a39Sopenharmony_ci    if (src->pub_key != NULL
631e1051a39Sopenharmony_ci        && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
632e1051a39Sopenharmony_ci        if (ret->group == NULL)
633e1051a39Sopenharmony_ci            /* no parameter-less keys allowed */
634e1051a39Sopenharmony_ci            goto err;
635e1051a39Sopenharmony_ci        ret->pub_key = EC_POINT_new(ret->group);
636e1051a39Sopenharmony_ci        if (ret->pub_key == NULL
637e1051a39Sopenharmony_ci            || !EC_POINT_copy(ret->pub_key, src->pub_key))
638e1051a39Sopenharmony_ci                goto err;
639e1051a39Sopenharmony_ci    }
640e1051a39Sopenharmony_ci
641e1051a39Sopenharmony_ci    /* copy the private key */
642e1051a39Sopenharmony_ci    if (src->priv_key != NULL
643e1051a39Sopenharmony_ci        && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
644e1051a39Sopenharmony_ci        if (ret->group == NULL)
645e1051a39Sopenharmony_ci            /* no parameter-less keys allowed */
646e1051a39Sopenharmony_ci            goto err;
647e1051a39Sopenharmony_ci        ret->priv_key = BN_new();
648e1051a39Sopenharmony_ci        if (ret->priv_key == NULL || !BN_copy(ret->priv_key, src->priv_key))
649e1051a39Sopenharmony_ci            goto err;
650e1051a39Sopenharmony_ci        if (ret->group->meth->keycopy
651e1051a39Sopenharmony_ci            && ret->group->meth->keycopy(ret, src) == 0)
652e1051a39Sopenharmony_ci            goto err;
653e1051a39Sopenharmony_ci    }
654e1051a39Sopenharmony_ci
655e1051a39Sopenharmony_ci    /* copy the rest */
656e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
657e1051a39Sopenharmony_ci        ret->enc_flag = src->enc_flag;
658e1051a39Sopenharmony_ci        ret->conv_form = src->conv_form;
659e1051a39Sopenharmony_ci    }
660e1051a39Sopenharmony_ci
661e1051a39Sopenharmony_ci    ret->version = src->version;
662e1051a39Sopenharmony_ci    ret->flags = src->flags;
663e1051a39Sopenharmony_ci
664e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
665e1051a39Sopenharmony_ci    if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_EC_KEY,
666e1051a39Sopenharmony_ci                            &ret->ex_data, &src->ex_data))
667e1051a39Sopenharmony_ci        goto err;
668e1051a39Sopenharmony_ci#endif
669e1051a39Sopenharmony_ci
670e1051a39Sopenharmony_ci    if (ret->meth != NULL && ret->meth->copy != NULL) {
671e1051a39Sopenharmony_ci        if ((selection
672e1051a39Sopenharmony_ci             & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
673e1051a39Sopenharmony_ci            goto err;
674e1051a39Sopenharmony_ci        if (ret->meth->copy(ret, src) == 0)
675e1051a39Sopenharmony_ci            goto err;
676e1051a39Sopenharmony_ci    }
677e1051a39Sopenharmony_ci
678e1051a39Sopenharmony_ci    return ret;
679e1051a39Sopenharmony_ci err:
680e1051a39Sopenharmony_ci    EC_KEY_free(ret);
681e1051a39Sopenharmony_ci    return NULL;
682e1051a39Sopenharmony_ci}
683e1051a39Sopenharmony_ci
684e1051a39Sopenharmony_ciint ossl_ec_encoding_param2id(const OSSL_PARAM *p, int *id)
685e1051a39Sopenharmony_ci{
686e1051a39Sopenharmony_ci    const char *name = NULL;
687e1051a39Sopenharmony_ci    int status = 0;
688e1051a39Sopenharmony_ci
689e1051a39Sopenharmony_ci    switch (p->data_type) {
690e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_STRING:
691e1051a39Sopenharmony_ci        /* The OSSL_PARAM functions have no support for this */
692e1051a39Sopenharmony_ci        name = p->data;
693e1051a39Sopenharmony_ci        status = (name != NULL);
694e1051a39Sopenharmony_ci        break;
695e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_PTR:
696e1051a39Sopenharmony_ci        status = OSSL_PARAM_get_utf8_ptr(p, &name);
697e1051a39Sopenharmony_ci        break;
698e1051a39Sopenharmony_ci    }
699e1051a39Sopenharmony_ci    if (status) {
700e1051a39Sopenharmony_ci        int i = ossl_ec_encoding_name2id(name);
701e1051a39Sopenharmony_ci
702e1051a39Sopenharmony_ci        if (i >= 0) {
703e1051a39Sopenharmony_ci            *id = i;
704e1051a39Sopenharmony_ci            return 1;
705e1051a39Sopenharmony_ci        }
706e1051a39Sopenharmony_ci    }
707e1051a39Sopenharmony_ci    return 0;
708e1051a39Sopenharmony_ci}
709e1051a39Sopenharmony_ci
710e1051a39Sopenharmony_ciint ossl_ec_pt_format_param2id(const OSSL_PARAM *p, int *id)
711e1051a39Sopenharmony_ci{
712e1051a39Sopenharmony_ci    const char *name = NULL;
713e1051a39Sopenharmony_ci    int status = 0;
714e1051a39Sopenharmony_ci
715e1051a39Sopenharmony_ci    switch (p->data_type) {
716e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_STRING:
717e1051a39Sopenharmony_ci        /* The OSSL_PARAM functions have no support for this */
718e1051a39Sopenharmony_ci        name = p->data;
719e1051a39Sopenharmony_ci        status = (name != NULL);
720e1051a39Sopenharmony_ci        break;
721e1051a39Sopenharmony_ci    case OSSL_PARAM_UTF8_PTR:
722e1051a39Sopenharmony_ci        status = OSSL_PARAM_get_utf8_ptr(p, &name);
723e1051a39Sopenharmony_ci        break;
724e1051a39Sopenharmony_ci    }
725e1051a39Sopenharmony_ci    if (status) {
726e1051a39Sopenharmony_ci        int i = ossl_ec_pt_format_name2id(name);
727e1051a39Sopenharmony_ci
728e1051a39Sopenharmony_ci        if (i >= 0) {
729e1051a39Sopenharmony_ci            *id = i;
730e1051a39Sopenharmony_ci            return 1;
731e1051a39Sopenharmony_ci        }
732e1051a39Sopenharmony_ci    }
733e1051a39Sopenharmony_ci    return 0;
734e1051a39Sopenharmony_ci}
735e1051a39Sopenharmony_ci
736e1051a39Sopenharmony_ci#ifndef FIPS_MODULE
737e1051a39Sopenharmony_ciint ossl_x509_algor_is_sm2(const X509_ALGOR *palg)
738e1051a39Sopenharmony_ci{
739e1051a39Sopenharmony_ci    int ptype = 0;
740e1051a39Sopenharmony_ci    const void *pval = NULL;
741e1051a39Sopenharmony_ci
742e1051a39Sopenharmony_ci    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
743e1051a39Sopenharmony_ci
744e1051a39Sopenharmony_ci    if (ptype == V_ASN1_OBJECT)
745e1051a39Sopenharmony_ci        return OBJ_obj2nid((ASN1_OBJECT *)pval) == NID_sm2;
746e1051a39Sopenharmony_ci
747e1051a39Sopenharmony_ci    if (ptype == V_ASN1_SEQUENCE) {
748e1051a39Sopenharmony_ci        const ASN1_STRING *str = pval;
749e1051a39Sopenharmony_ci        const unsigned char *der = str->data;
750e1051a39Sopenharmony_ci        int derlen = str->length;
751e1051a39Sopenharmony_ci        EC_GROUP *group;
752e1051a39Sopenharmony_ci        int ret;
753e1051a39Sopenharmony_ci
754e1051a39Sopenharmony_ci        if ((group = d2i_ECPKParameters(NULL, &der, derlen)) == NULL)
755e1051a39Sopenharmony_ci            ret = 0;
756e1051a39Sopenharmony_ci        else
757e1051a39Sopenharmony_ci            ret = (EC_GROUP_get_curve_name(group) == NID_sm2);
758e1051a39Sopenharmony_ci
759e1051a39Sopenharmony_ci        EC_GROUP_free(group);
760e1051a39Sopenharmony_ci        return ret;
761e1051a39Sopenharmony_ci    }
762e1051a39Sopenharmony_ci
763e1051a39Sopenharmony_ci    return 0;
764e1051a39Sopenharmony_ci}
765e1051a39Sopenharmony_ci
766e1051a39Sopenharmony_ciEC_KEY *ossl_ec_key_param_from_x509_algor(const X509_ALGOR *palg,
767e1051a39Sopenharmony_ci                                     OSSL_LIB_CTX *libctx, const char *propq)
768e1051a39Sopenharmony_ci{
769e1051a39Sopenharmony_ci    int ptype = 0;
770e1051a39Sopenharmony_ci    const void *pval = NULL;
771e1051a39Sopenharmony_ci    EC_KEY *eckey = NULL;
772e1051a39Sopenharmony_ci    EC_GROUP *group = NULL;
773e1051a39Sopenharmony_ci
774e1051a39Sopenharmony_ci    X509_ALGOR_get0(NULL, &ptype, &pval, palg);
775e1051a39Sopenharmony_ci    if ((eckey = EC_KEY_new_ex(libctx, propq)) == NULL) {
776e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
777e1051a39Sopenharmony_ci        goto ecerr;
778e1051a39Sopenharmony_ci    }
779e1051a39Sopenharmony_ci
780e1051a39Sopenharmony_ci    if (ptype == V_ASN1_SEQUENCE) {
781e1051a39Sopenharmony_ci        const ASN1_STRING *pstr = pval;
782e1051a39Sopenharmony_ci        const unsigned char *pm = pstr->data;
783e1051a39Sopenharmony_ci        int pmlen = pstr->length;
784e1051a39Sopenharmony_ci
785e1051a39Sopenharmony_ci
786e1051a39Sopenharmony_ci        if (d2i_ECParameters(&eckey, &pm, pmlen) == NULL) {
787e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
788e1051a39Sopenharmony_ci            goto ecerr;
789e1051a39Sopenharmony_ci        }
790e1051a39Sopenharmony_ci    } else if (ptype == V_ASN1_OBJECT) {
791e1051a39Sopenharmony_ci        const ASN1_OBJECT *poid = pval;
792e1051a39Sopenharmony_ci
793e1051a39Sopenharmony_ci        /*
794e1051a39Sopenharmony_ci         * type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
795e1051a39Sopenharmony_ci         */
796e1051a39Sopenharmony_ci
797e1051a39Sopenharmony_ci        group = EC_GROUP_new_by_curve_name_ex(libctx, propq, OBJ_obj2nid(poid));
798e1051a39Sopenharmony_ci        if (group == NULL)
799e1051a39Sopenharmony_ci            goto ecerr;
800e1051a39Sopenharmony_ci        EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
801e1051a39Sopenharmony_ci        if (EC_KEY_set_group(eckey, group) == 0)
802e1051a39Sopenharmony_ci            goto ecerr;
803e1051a39Sopenharmony_ci        EC_GROUP_free(group);
804e1051a39Sopenharmony_ci    } else {
805e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
806e1051a39Sopenharmony_ci        goto ecerr;
807e1051a39Sopenharmony_ci    }
808e1051a39Sopenharmony_ci
809e1051a39Sopenharmony_ci    return eckey;
810e1051a39Sopenharmony_ci
811e1051a39Sopenharmony_ci ecerr:
812e1051a39Sopenharmony_ci    EC_KEY_free(eckey);
813e1051a39Sopenharmony_ci    EC_GROUP_free(group);
814e1051a39Sopenharmony_ci    return NULL;
815e1051a39Sopenharmony_ci}
816e1051a39Sopenharmony_ci
817e1051a39Sopenharmony_ciEC_KEY *ossl_ec_key_from_pkcs8(const PKCS8_PRIV_KEY_INFO *p8inf,
818e1051a39Sopenharmony_ci                               OSSL_LIB_CTX *libctx, const char *propq)
819e1051a39Sopenharmony_ci{
820e1051a39Sopenharmony_ci    const unsigned char *p = NULL;
821e1051a39Sopenharmony_ci    int pklen;
822e1051a39Sopenharmony_ci    EC_KEY *eckey = NULL;
823e1051a39Sopenharmony_ci    const X509_ALGOR *palg;
824e1051a39Sopenharmony_ci
825e1051a39Sopenharmony_ci    if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8inf))
826e1051a39Sopenharmony_ci        return 0;
827e1051a39Sopenharmony_ci    eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
828e1051a39Sopenharmony_ci    if (eckey == NULL)
829e1051a39Sopenharmony_ci        goto err;
830e1051a39Sopenharmony_ci
831e1051a39Sopenharmony_ci    /* We have parameters now set private key */
832e1051a39Sopenharmony_ci    if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
833e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
834e1051a39Sopenharmony_ci        goto err;
835e1051a39Sopenharmony_ci    }
836e1051a39Sopenharmony_ci
837e1051a39Sopenharmony_ci    return eckey;
838e1051a39Sopenharmony_ci err:
839e1051a39Sopenharmony_ci    EC_KEY_free(eckey);
840e1051a39Sopenharmony_ci    return NULL;
841e1051a39Sopenharmony_ci}
842e1051a39Sopenharmony_ci#endif
843