1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2006-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 * ECDH and ECDSA low level APIs are deprecated for public use, but still ok
12e1051a39Sopenharmony_ci * for internal use.
13e1051a39Sopenharmony_ci */
14e1051a39Sopenharmony_ci#include "internal/deprecated.h"
15e1051a39Sopenharmony_ci
16e1051a39Sopenharmony_ci#include <stdio.h>
17e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
18e1051a39Sopenharmony_ci#include <openssl/x509.h>
19e1051a39Sopenharmony_ci#include <openssl/ec.h>
20e1051a39Sopenharmony_ci#include <openssl/bn.h>
21e1051a39Sopenharmony_ci#include <openssl/asn1t.h>
22e1051a39Sopenharmony_ci#include "crypto/asn1.h"
23e1051a39Sopenharmony_ci#include "crypto/evp.h"
24e1051a39Sopenharmony_ci#include "crypto/x509.h"
25e1051a39Sopenharmony_ci#include <openssl/core_names.h>
26e1051a39Sopenharmony_ci#include <openssl/param_build.h>
27e1051a39Sopenharmony_ci#include "ec_local.h"
28e1051a39Sopenharmony_ci
29e1051a39Sopenharmony_cistatic int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
30e1051a39Sopenharmony_ci{
31e1051a39Sopenharmony_ci    const EC_GROUP *group;
32e1051a39Sopenharmony_ci    int nid;
33e1051a39Sopenharmony_ci
34e1051a39Sopenharmony_ci    if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
35e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
36e1051a39Sopenharmony_ci        return 0;
37e1051a39Sopenharmony_ci    }
38e1051a39Sopenharmony_ci    if (EC_GROUP_get_asn1_flag(group)
39e1051a39Sopenharmony_ci        && (nid = EC_GROUP_get_curve_name(group)))
40e1051a39Sopenharmony_ci        /* we have a 'named curve' => just set the OID */
41e1051a39Sopenharmony_ci    {
42e1051a39Sopenharmony_ci        ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid);
43e1051a39Sopenharmony_ci
44e1051a39Sopenharmony_ci        if (asn1obj == NULL || OBJ_length(asn1obj) == 0) {
45e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID);
46e1051a39Sopenharmony_ci            return 0;
47e1051a39Sopenharmony_ci        }
48e1051a39Sopenharmony_ci        *ppval = asn1obj;
49e1051a39Sopenharmony_ci        *pptype = V_ASN1_OBJECT;
50e1051a39Sopenharmony_ci    } else {                    /* explicit parameters */
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_ci        ASN1_STRING *pstr = NULL;
53e1051a39Sopenharmony_ci        pstr = ASN1_STRING_new();
54e1051a39Sopenharmony_ci        if (pstr == NULL)
55e1051a39Sopenharmony_ci            return 0;
56e1051a39Sopenharmony_ci        pstr->length = i2d_ECParameters(ec_key, &pstr->data);
57e1051a39Sopenharmony_ci        if (pstr->length <= 0) {
58e1051a39Sopenharmony_ci            ASN1_STRING_free(pstr);
59e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
60e1051a39Sopenharmony_ci            return 0;
61e1051a39Sopenharmony_ci        }
62e1051a39Sopenharmony_ci        *ppval = pstr;
63e1051a39Sopenharmony_ci        *pptype = V_ASN1_SEQUENCE;
64e1051a39Sopenharmony_ci    }
65e1051a39Sopenharmony_ci    return 1;
66e1051a39Sopenharmony_ci}
67e1051a39Sopenharmony_ci
68e1051a39Sopenharmony_cistatic int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
69e1051a39Sopenharmony_ci{
70e1051a39Sopenharmony_ci    const EC_KEY *ec_key = pkey->pkey.ec;
71e1051a39Sopenharmony_ci    void *pval = NULL;
72e1051a39Sopenharmony_ci    int ptype;
73e1051a39Sopenharmony_ci    unsigned char *penc = NULL, *p;
74e1051a39Sopenharmony_ci    int penclen;
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_ci    if (!eckey_param2type(&ptype, &pval, ec_key)) {
77e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
78e1051a39Sopenharmony_ci        return 0;
79e1051a39Sopenharmony_ci    }
80e1051a39Sopenharmony_ci    penclen = i2o_ECPublicKey(ec_key, NULL);
81e1051a39Sopenharmony_ci    if (penclen <= 0)
82e1051a39Sopenharmony_ci        goto err;
83e1051a39Sopenharmony_ci    penc = OPENSSL_malloc(penclen);
84e1051a39Sopenharmony_ci    if (penc == NULL)
85e1051a39Sopenharmony_ci        goto err;
86e1051a39Sopenharmony_ci    p = penc;
87e1051a39Sopenharmony_ci    penclen = i2o_ECPublicKey(ec_key, &p);
88e1051a39Sopenharmony_ci    if (penclen <= 0)
89e1051a39Sopenharmony_ci        goto err;
90e1051a39Sopenharmony_ci    if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
91e1051a39Sopenharmony_ci                               ptype, pval, penc, penclen))
92e1051a39Sopenharmony_ci        return 1;
93e1051a39Sopenharmony_ci err:
94e1051a39Sopenharmony_ci    if (ptype == V_ASN1_SEQUENCE)
95e1051a39Sopenharmony_ci        ASN1_STRING_free(pval);
96e1051a39Sopenharmony_ci    OPENSSL_free(penc);
97e1051a39Sopenharmony_ci    return 0;
98e1051a39Sopenharmony_ci}
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_cistatic int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
101e1051a39Sopenharmony_ci{
102e1051a39Sopenharmony_ci    const unsigned char *p = NULL;
103e1051a39Sopenharmony_ci    int pklen;
104e1051a39Sopenharmony_ci    EC_KEY *eckey = NULL;
105e1051a39Sopenharmony_ci    X509_ALGOR *palg;
106e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = NULL;
107e1051a39Sopenharmony_ci    const char *propq = NULL;
108e1051a39Sopenharmony_ci
109e1051a39Sopenharmony_ci    if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)
110e1051a39Sopenharmony_ci        || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
111e1051a39Sopenharmony_ci        return 0;
112e1051a39Sopenharmony_ci    eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_ci    if (!eckey)
115e1051a39Sopenharmony_ci        return 0;
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci    /* We have parameters now set public key */
118e1051a39Sopenharmony_ci    if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
119e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
120e1051a39Sopenharmony_ci        goto ecerr;
121e1051a39Sopenharmony_ci    }
122e1051a39Sopenharmony_ci
123e1051a39Sopenharmony_ci    EVP_PKEY_assign_EC_KEY(pkey, eckey);
124e1051a39Sopenharmony_ci    return 1;
125e1051a39Sopenharmony_ci
126e1051a39Sopenharmony_ci ecerr:
127e1051a39Sopenharmony_ci    EC_KEY_free(eckey);
128e1051a39Sopenharmony_ci    return 0;
129e1051a39Sopenharmony_ci}
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_cistatic int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
132e1051a39Sopenharmony_ci{
133e1051a39Sopenharmony_ci    int r;
134e1051a39Sopenharmony_ci    const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
135e1051a39Sopenharmony_ci    const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
136e1051a39Sopenharmony_ci        *pb = EC_KEY_get0_public_key(b->pkey.ec);
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci    if (group == NULL || pa == NULL || pb == NULL)
139e1051a39Sopenharmony_ci        return -2;
140e1051a39Sopenharmony_ci    r = EC_POINT_cmp(group, pa, pb, NULL);
141e1051a39Sopenharmony_ci    if (r == 0)
142e1051a39Sopenharmony_ci        return 1;
143e1051a39Sopenharmony_ci    if (r == 1)
144e1051a39Sopenharmony_ci        return 0;
145e1051a39Sopenharmony_ci    return -2;
146e1051a39Sopenharmony_ci}
147e1051a39Sopenharmony_ci
148e1051a39Sopenharmony_cistatic int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
149e1051a39Sopenharmony_ci                                OSSL_LIB_CTX *libctx, const char *propq)
150e1051a39Sopenharmony_ci{
151e1051a39Sopenharmony_ci    int ret = 0;
152e1051a39Sopenharmony_ci    EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq);
153e1051a39Sopenharmony_ci
154e1051a39Sopenharmony_ci    if (eckey != NULL) {
155e1051a39Sopenharmony_ci        ret = 1;
156e1051a39Sopenharmony_ci        EVP_PKEY_assign_EC_KEY(pkey, eckey);
157e1051a39Sopenharmony_ci    }
158e1051a39Sopenharmony_ci
159e1051a39Sopenharmony_ci    return ret;
160e1051a39Sopenharmony_ci}
161e1051a39Sopenharmony_ci
162e1051a39Sopenharmony_cistatic int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
163e1051a39Sopenharmony_ci{
164e1051a39Sopenharmony_ci    EC_KEY ec_key = *(pkey->pkey.ec);
165e1051a39Sopenharmony_ci    unsigned char *ep = NULL;
166e1051a39Sopenharmony_ci    int eplen, ptype;
167e1051a39Sopenharmony_ci    void *pval;
168e1051a39Sopenharmony_ci    unsigned int old_flags;
169e1051a39Sopenharmony_ci
170e1051a39Sopenharmony_ci    if (!eckey_param2type(&ptype, &pval, &ec_key)) {
171e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
172e1051a39Sopenharmony_ci        return 0;
173e1051a39Sopenharmony_ci    }
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci    /* set the private key */
176e1051a39Sopenharmony_ci
177e1051a39Sopenharmony_ci    /*
178e1051a39Sopenharmony_ci     * do not include the parameters in the SEC1 private key see PKCS#11
179e1051a39Sopenharmony_ci     * 12.11
180e1051a39Sopenharmony_ci     */
181e1051a39Sopenharmony_ci    old_flags = EC_KEY_get_enc_flags(&ec_key);
182e1051a39Sopenharmony_ci    EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS);
183e1051a39Sopenharmony_ci
184e1051a39Sopenharmony_ci    eplen = i2d_ECPrivateKey(&ec_key, &ep);
185e1051a39Sopenharmony_ci    if (eplen <= 0) {
186e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
187e1051a39Sopenharmony_ci        goto err;
188e1051a39Sopenharmony_ci    }
189e1051a39Sopenharmony_ci
190e1051a39Sopenharmony_ci    if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
191e1051a39Sopenharmony_ci                         ptype, pval, ep, eplen)) {
192e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
193e1051a39Sopenharmony_ci        OPENSSL_clear_free(ep, eplen);
194e1051a39Sopenharmony_ci        goto err;
195e1051a39Sopenharmony_ci    }
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    return 1;
198e1051a39Sopenharmony_ci
199e1051a39Sopenharmony_ci err:
200e1051a39Sopenharmony_ci    if (ptype == V_ASN1_SEQUENCE)
201e1051a39Sopenharmony_ci        ASN1_STRING_free(pval);
202e1051a39Sopenharmony_ci    return 0;
203e1051a39Sopenharmony_ci}
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_cistatic int int_ec_size(const EVP_PKEY *pkey)
206e1051a39Sopenharmony_ci{
207e1051a39Sopenharmony_ci    return ECDSA_size(pkey->pkey.ec);
208e1051a39Sopenharmony_ci}
209e1051a39Sopenharmony_ci
210e1051a39Sopenharmony_cistatic int ec_bits(const EVP_PKEY *pkey)
211e1051a39Sopenharmony_ci{
212e1051a39Sopenharmony_ci    return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec));
213e1051a39Sopenharmony_ci}
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_cistatic int ec_security_bits(const EVP_PKEY *pkey)
216e1051a39Sopenharmony_ci{
217e1051a39Sopenharmony_ci    int ecbits = ec_bits(pkey);
218e1051a39Sopenharmony_ci
219e1051a39Sopenharmony_ci    if (ecbits >= 512)
220e1051a39Sopenharmony_ci        return 256;
221e1051a39Sopenharmony_ci    if (ecbits >= 384)
222e1051a39Sopenharmony_ci        return 192;
223e1051a39Sopenharmony_ci    if (ecbits >= 256)
224e1051a39Sopenharmony_ci        return 128;
225e1051a39Sopenharmony_ci    if (ecbits >= 224)
226e1051a39Sopenharmony_ci        return 112;
227e1051a39Sopenharmony_ci    if (ecbits >= 160)
228e1051a39Sopenharmony_ci        return 80;
229e1051a39Sopenharmony_ci    return ecbits / 2;
230e1051a39Sopenharmony_ci}
231e1051a39Sopenharmony_ci
232e1051a39Sopenharmony_cistatic int ec_missing_parameters(const EVP_PKEY *pkey)
233e1051a39Sopenharmony_ci{
234e1051a39Sopenharmony_ci    if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL)
235e1051a39Sopenharmony_ci        return 1;
236e1051a39Sopenharmony_ci    return 0;
237e1051a39Sopenharmony_ci}
238e1051a39Sopenharmony_ci
239e1051a39Sopenharmony_cistatic int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ci    if (group == NULL)
244e1051a39Sopenharmony_ci        return 0;
245e1051a39Sopenharmony_ci    if (to->pkey.ec == NULL) {
246e1051a39Sopenharmony_ci        to->pkey.ec = EC_KEY_new();
247e1051a39Sopenharmony_ci        if (to->pkey.ec == NULL)
248e1051a39Sopenharmony_ci            goto err;
249e1051a39Sopenharmony_ci    }
250e1051a39Sopenharmony_ci    if (EC_KEY_set_group(to->pkey.ec, group) == 0)
251e1051a39Sopenharmony_ci        goto err;
252e1051a39Sopenharmony_ci    EC_GROUP_free(group);
253e1051a39Sopenharmony_ci    return 1;
254e1051a39Sopenharmony_ci err:
255e1051a39Sopenharmony_ci    EC_GROUP_free(group);
256e1051a39Sopenharmony_ci    return 0;
257e1051a39Sopenharmony_ci}
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_cistatic int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
260e1051a39Sopenharmony_ci{
261e1051a39Sopenharmony_ci    const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
262e1051a39Sopenharmony_ci        *group_b = EC_KEY_get0_group(b->pkey.ec);
263e1051a39Sopenharmony_ci
264e1051a39Sopenharmony_ci    if (group_a == NULL || group_b == NULL)
265e1051a39Sopenharmony_ci        return -2;
266e1051a39Sopenharmony_ci    if (EC_GROUP_cmp(group_a, group_b, NULL))
267e1051a39Sopenharmony_ci        return 0;
268e1051a39Sopenharmony_ci    else
269e1051a39Sopenharmony_ci        return 1;
270e1051a39Sopenharmony_ci}
271e1051a39Sopenharmony_ci
272e1051a39Sopenharmony_cistatic void int_ec_free(EVP_PKEY *pkey)
273e1051a39Sopenharmony_ci{
274e1051a39Sopenharmony_ci    EC_KEY_free(pkey->pkey.ec);
275e1051a39Sopenharmony_ci}
276e1051a39Sopenharmony_ci
277e1051a39Sopenharmony_citypedef enum {
278e1051a39Sopenharmony_ci    EC_KEY_PRINT_PRIVATE,
279e1051a39Sopenharmony_ci    EC_KEY_PRINT_PUBLIC,
280e1051a39Sopenharmony_ci    EC_KEY_PRINT_PARAM
281e1051a39Sopenharmony_ci} ec_print_t;
282e1051a39Sopenharmony_ci
283e1051a39Sopenharmony_cistatic int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
284e1051a39Sopenharmony_ci{
285e1051a39Sopenharmony_ci    const char *ecstr;
286e1051a39Sopenharmony_ci    unsigned char *priv = NULL, *pub = NULL;
287e1051a39Sopenharmony_ci    size_t privlen = 0, publen = 0;
288e1051a39Sopenharmony_ci    int ret = 0;
289e1051a39Sopenharmony_ci    const EC_GROUP *group;
290e1051a39Sopenharmony_ci
291e1051a39Sopenharmony_ci    if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
292e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
293e1051a39Sopenharmony_ci        return 0;
294e1051a39Sopenharmony_ci    }
295e1051a39Sopenharmony_ci
296e1051a39Sopenharmony_ci    if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) {
297e1051a39Sopenharmony_ci        publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
298e1051a39Sopenharmony_ci        if (publen == 0)
299e1051a39Sopenharmony_ci            goto err;
300e1051a39Sopenharmony_ci    }
301e1051a39Sopenharmony_ci
302e1051a39Sopenharmony_ci    if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
303e1051a39Sopenharmony_ci        privlen = EC_KEY_priv2buf(x, &priv);
304e1051a39Sopenharmony_ci        if (privlen == 0)
305e1051a39Sopenharmony_ci            goto err;
306e1051a39Sopenharmony_ci    }
307e1051a39Sopenharmony_ci
308e1051a39Sopenharmony_ci    if (ktype == EC_KEY_PRINT_PRIVATE)
309e1051a39Sopenharmony_ci        ecstr = "Private-Key";
310e1051a39Sopenharmony_ci    else if (ktype == EC_KEY_PRINT_PUBLIC)
311e1051a39Sopenharmony_ci        ecstr = "Public-Key";
312e1051a39Sopenharmony_ci    else
313e1051a39Sopenharmony_ci        ecstr = "ECDSA-Parameters";
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci    if (!BIO_indent(bp, off, 128))
316e1051a39Sopenharmony_ci        goto err;
317e1051a39Sopenharmony_ci    if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
318e1051a39Sopenharmony_ci                   EC_GROUP_order_bits(group)) <= 0)
319e1051a39Sopenharmony_ci        goto err;
320e1051a39Sopenharmony_ci
321e1051a39Sopenharmony_ci    if (privlen != 0) {
322e1051a39Sopenharmony_ci        if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
323e1051a39Sopenharmony_ci            goto err;
324e1051a39Sopenharmony_ci        if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
325e1051a39Sopenharmony_ci            goto err;
326e1051a39Sopenharmony_ci    }
327e1051a39Sopenharmony_ci
328e1051a39Sopenharmony_ci    if (publen != 0) {
329e1051a39Sopenharmony_ci        if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
330e1051a39Sopenharmony_ci            goto err;
331e1051a39Sopenharmony_ci        if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
332e1051a39Sopenharmony_ci            goto err;
333e1051a39Sopenharmony_ci    }
334e1051a39Sopenharmony_ci
335e1051a39Sopenharmony_ci    if (!ECPKParameters_print(bp, group, off))
336e1051a39Sopenharmony_ci        goto err;
337e1051a39Sopenharmony_ci    ret = 1;
338e1051a39Sopenharmony_ci err:
339e1051a39Sopenharmony_ci    if (!ret)
340e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
341e1051a39Sopenharmony_ci    OPENSSL_clear_free(priv, privlen);
342e1051a39Sopenharmony_ci    OPENSSL_free(pub);
343e1051a39Sopenharmony_ci    return ret;
344e1051a39Sopenharmony_ci}
345e1051a39Sopenharmony_ci
346e1051a39Sopenharmony_cistatic int eckey_param_decode(EVP_PKEY *pkey,
347e1051a39Sopenharmony_ci                              const unsigned char **pder, int derlen)
348e1051a39Sopenharmony_ci{
349e1051a39Sopenharmony_ci    EC_KEY *eckey;
350e1051a39Sopenharmony_ci
351e1051a39Sopenharmony_ci    if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL)
352e1051a39Sopenharmony_ci        return 0;
353e1051a39Sopenharmony_ci    EVP_PKEY_assign_EC_KEY(pkey, eckey);
354e1051a39Sopenharmony_ci    return 1;
355e1051a39Sopenharmony_ci}
356e1051a39Sopenharmony_ci
357e1051a39Sopenharmony_cistatic int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
358e1051a39Sopenharmony_ci{
359e1051a39Sopenharmony_ci    return i2d_ECParameters(pkey->pkey.ec, pder);
360e1051a39Sopenharmony_ci}
361e1051a39Sopenharmony_ci
362e1051a39Sopenharmony_cistatic int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
363e1051a39Sopenharmony_ci                             ASN1_PCTX *ctx)
364e1051a39Sopenharmony_ci{
365e1051a39Sopenharmony_ci    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM);
366e1051a39Sopenharmony_ci}
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_cistatic int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
369e1051a39Sopenharmony_ci                           ASN1_PCTX *ctx)
370e1051a39Sopenharmony_ci{
371e1051a39Sopenharmony_ci    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC);
372e1051a39Sopenharmony_ci}
373e1051a39Sopenharmony_ci
374e1051a39Sopenharmony_cistatic int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
375e1051a39Sopenharmony_ci                            ASN1_PCTX *ctx)
376e1051a39Sopenharmony_ci{
377e1051a39Sopenharmony_ci    return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE);
378e1051a39Sopenharmony_ci}
379e1051a39Sopenharmony_ci
380e1051a39Sopenharmony_cistatic int old_ec_priv_decode(EVP_PKEY *pkey,
381e1051a39Sopenharmony_ci                              const unsigned char **pder, int derlen)
382e1051a39Sopenharmony_ci{
383e1051a39Sopenharmony_ci    EC_KEY *ec;
384e1051a39Sopenharmony_ci
385e1051a39Sopenharmony_ci    if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL)
386e1051a39Sopenharmony_ci        return 0;
387e1051a39Sopenharmony_ci    EVP_PKEY_assign_EC_KEY(pkey, ec);
388e1051a39Sopenharmony_ci    return 1;
389e1051a39Sopenharmony_ci}
390e1051a39Sopenharmony_ci
391e1051a39Sopenharmony_cistatic int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
392e1051a39Sopenharmony_ci{
393e1051a39Sopenharmony_ci    return i2d_ECPrivateKey(pkey->pkey.ec, pder);
394e1051a39Sopenharmony_ci}
395e1051a39Sopenharmony_ci
396e1051a39Sopenharmony_cistatic int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
397e1051a39Sopenharmony_ci{
398e1051a39Sopenharmony_ci    switch (op) {
399e1051a39Sopenharmony_ci    case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
400e1051a39Sopenharmony_ci        if (EVP_PKEY_get_id(pkey) == EVP_PKEY_SM2) {
401e1051a39Sopenharmony_ci            /* For SM2, the only valid digest-alg is SM3 */
402e1051a39Sopenharmony_ci            *(int *)arg2 = NID_sm3;
403e1051a39Sopenharmony_ci            return 2;            /* Make it mandatory */
404e1051a39Sopenharmony_ci        }
405e1051a39Sopenharmony_ci        *(int *)arg2 = NID_sha256;
406e1051a39Sopenharmony_ci        return 1;
407e1051a39Sopenharmony_ci
408e1051a39Sopenharmony_ci    case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
409e1051a39Sopenharmony_ci        /* We should only be here if we have a legacy key */
410e1051a39Sopenharmony_ci        if (!ossl_assert(evp_pkey_is_legacy(pkey)))
411e1051a39Sopenharmony_ci            return 0;
412e1051a39Sopenharmony_ci        return EC_KEY_oct2key(evp_pkey_get0_EC_KEY_int(pkey), arg2, arg1, NULL);
413e1051a39Sopenharmony_ci
414e1051a39Sopenharmony_ci    case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
415e1051a39Sopenharmony_ci        return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey),
416e1051a39Sopenharmony_ci                              POINT_CONVERSION_UNCOMPRESSED, arg2, NULL);
417e1051a39Sopenharmony_ci
418e1051a39Sopenharmony_ci    default:
419e1051a39Sopenharmony_ci        return -2;
420e1051a39Sopenharmony_ci    }
421e1051a39Sopenharmony_ci}
422e1051a39Sopenharmony_ci
423e1051a39Sopenharmony_cistatic int ec_pkey_check(const EVP_PKEY *pkey)
424e1051a39Sopenharmony_ci{
425e1051a39Sopenharmony_ci    EC_KEY *eckey = pkey->pkey.ec;
426e1051a39Sopenharmony_ci
427e1051a39Sopenharmony_ci    /* stay consistent to what EVP_PKEY_check demands */
428e1051a39Sopenharmony_ci    if (eckey->priv_key == NULL) {
429e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
430e1051a39Sopenharmony_ci        return 0;
431e1051a39Sopenharmony_ci    }
432e1051a39Sopenharmony_ci
433e1051a39Sopenharmony_ci    return EC_KEY_check_key(eckey);
434e1051a39Sopenharmony_ci}
435e1051a39Sopenharmony_ci
436e1051a39Sopenharmony_cistatic int ec_pkey_public_check(const EVP_PKEY *pkey)
437e1051a39Sopenharmony_ci{
438e1051a39Sopenharmony_ci    EC_KEY *eckey = pkey->pkey.ec;
439e1051a39Sopenharmony_ci
440e1051a39Sopenharmony_ci    /*
441e1051a39Sopenharmony_ci     * Note: it unnecessary to check eckey->pub_key here since
442e1051a39Sopenharmony_ci     * it will be checked in EC_KEY_check_key(). In fact, the
443e1051a39Sopenharmony_ci     * EC_KEY_check_key() mainly checks the public key, and checks
444e1051a39Sopenharmony_ci     * the private key optionally (only if there is one). So if
445e1051a39Sopenharmony_ci     * someone passes a whole EC key (public + private), this
446e1051a39Sopenharmony_ci     * will also work...
447e1051a39Sopenharmony_ci     */
448e1051a39Sopenharmony_ci
449e1051a39Sopenharmony_ci    return EC_KEY_check_key(eckey);
450e1051a39Sopenharmony_ci}
451e1051a39Sopenharmony_ci
452e1051a39Sopenharmony_cistatic int ec_pkey_param_check(const EVP_PKEY *pkey)
453e1051a39Sopenharmony_ci{
454e1051a39Sopenharmony_ci    EC_KEY *eckey = pkey->pkey.ec;
455e1051a39Sopenharmony_ci
456e1051a39Sopenharmony_ci    /* stay consistent to what EVP_PKEY_check demands */
457e1051a39Sopenharmony_ci    if (eckey->group == NULL) {
458e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
459e1051a39Sopenharmony_ci        return 0;
460e1051a39Sopenharmony_ci    }
461e1051a39Sopenharmony_ci
462e1051a39Sopenharmony_ci    return EC_GROUP_check(eckey->group, NULL);
463e1051a39Sopenharmony_ci}
464e1051a39Sopenharmony_ci
465e1051a39Sopenharmony_cistatic
466e1051a39Sopenharmony_cisize_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey)
467e1051a39Sopenharmony_ci{
468e1051a39Sopenharmony_ci    return pkey->pkey.ec->dirty_cnt;
469e1051a39Sopenharmony_ci}
470e1051a39Sopenharmony_ci
471e1051a39Sopenharmony_cistatic
472e1051a39Sopenharmony_ciint ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
473e1051a39Sopenharmony_ci                      OSSL_FUNC_keymgmt_import_fn *importer,
474e1051a39Sopenharmony_ci                      OSSL_LIB_CTX *libctx, const char *propq)
475e1051a39Sopenharmony_ci{
476e1051a39Sopenharmony_ci    const EC_KEY *eckey = NULL;
477e1051a39Sopenharmony_ci    const EC_GROUP *ecg = NULL;
478e1051a39Sopenharmony_ci    unsigned char *pub_key_buf = NULL, *gen_buf = NULL;
479e1051a39Sopenharmony_ci    size_t pub_key_buflen;
480e1051a39Sopenharmony_ci    OSSL_PARAM_BLD *tmpl;
481e1051a39Sopenharmony_ci    OSSL_PARAM *params = NULL;
482e1051a39Sopenharmony_ci    const BIGNUM *priv_key = NULL;
483e1051a39Sopenharmony_ci    const EC_POINT *pub_point = NULL;
484e1051a39Sopenharmony_ci    int selection = 0;
485e1051a39Sopenharmony_ci    int rv = 0;
486e1051a39Sopenharmony_ci    BN_CTX *bnctx = NULL;
487e1051a39Sopenharmony_ci
488e1051a39Sopenharmony_ci    if (from == NULL
489e1051a39Sopenharmony_ci            || (eckey = from->pkey.ec) == NULL
490e1051a39Sopenharmony_ci            || (ecg = EC_KEY_get0_group(eckey)) == NULL)
491e1051a39Sopenharmony_ci        return 0;
492e1051a39Sopenharmony_ci
493e1051a39Sopenharmony_ci    tmpl = OSSL_PARAM_BLD_new();
494e1051a39Sopenharmony_ci    if (tmpl == NULL)
495e1051a39Sopenharmony_ci        return 0;
496e1051a39Sopenharmony_ci
497e1051a39Sopenharmony_ci    /*
498e1051a39Sopenharmony_ci     * EC_POINT_point2buf() can generate random numbers in some
499e1051a39Sopenharmony_ci     * implementations so we need to ensure we use the correct libctx.
500e1051a39Sopenharmony_ci     */
501e1051a39Sopenharmony_ci    bnctx = BN_CTX_new_ex(libctx);
502e1051a39Sopenharmony_ci    if (bnctx == NULL)
503e1051a39Sopenharmony_ci        goto err;
504e1051a39Sopenharmony_ci    BN_CTX_start(bnctx);
505e1051a39Sopenharmony_ci
506e1051a39Sopenharmony_ci    /* export the domain parameters */
507e1051a39Sopenharmony_ci    if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf))
508e1051a39Sopenharmony_ci        goto err;
509e1051a39Sopenharmony_ci    selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_ci    priv_key = EC_KEY_get0_private_key(eckey);
512e1051a39Sopenharmony_ci    pub_point = EC_KEY_get0_public_key(eckey);
513e1051a39Sopenharmony_ci
514e1051a39Sopenharmony_ci    if (pub_point != NULL) {
515e1051a39Sopenharmony_ci        /* convert pub_point to a octet string according to the SECG standard */
516e1051a39Sopenharmony_ci        point_conversion_form_t format = EC_KEY_get_conv_form(eckey);
517e1051a39Sopenharmony_ci
518e1051a39Sopenharmony_ci        if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
519e1051a39Sopenharmony_ci                                                 format,
520e1051a39Sopenharmony_ci                                                 &pub_key_buf, bnctx)) == 0
521e1051a39Sopenharmony_ci            || !OSSL_PARAM_BLD_push_octet_string(tmpl,
522e1051a39Sopenharmony_ci                                                 OSSL_PKEY_PARAM_PUB_KEY,
523e1051a39Sopenharmony_ci                                                 pub_key_buf,
524e1051a39Sopenharmony_ci                                                 pub_key_buflen))
525e1051a39Sopenharmony_ci            goto err;
526e1051a39Sopenharmony_ci        selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
527e1051a39Sopenharmony_ci    }
528e1051a39Sopenharmony_ci
529e1051a39Sopenharmony_ci    if (priv_key != NULL) {
530e1051a39Sopenharmony_ci        size_t sz;
531e1051a39Sopenharmony_ci        int ecbits;
532e1051a39Sopenharmony_ci        int ecdh_cofactor_mode;
533e1051a39Sopenharmony_ci
534e1051a39Sopenharmony_ci        /*
535e1051a39Sopenharmony_ci         * Key import/export should never leak the bit length of the secret
536e1051a39Sopenharmony_ci         * scalar in the key.
537e1051a39Sopenharmony_ci         *
538e1051a39Sopenharmony_ci         * For this reason, on export we use padded BIGNUMs with fixed length.
539e1051a39Sopenharmony_ci         *
540e1051a39Sopenharmony_ci         * When importing we also should make sure that, even if short lived,
541e1051a39Sopenharmony_ci         * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
542e1051a39Sopenharmony_ci         * soon as possible, so that any processing of this BIGNUM might opt for
543e1051a39Sopenharmony_ci         * constant time implementations in the backend.
544e1051a39Sopenharmony_ci         *
545e1051a39Sopenharmony_ci         * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
546e1051a39Sopenharmony_ci         * to preallocate the BIGNUM internal buffer to a fixed public size big
547e1051a39Sopenharmony_ci         * enough that operations performed during the processing never trigger
548e1051a39Sopenharmony_ci         * a realloc which would leak the size of the scalar through memory
549e1051a39Sopenharmony_ci         * accesses.
550e1051a39Sopenharmony_ci         *
551e1051a39Sopenharmony_ci         * Fixed Length
552e1051a39Sopenharmony_ci         * ------------
553e1051a39Sopenharmony_ci         *
554e1051a39Sopenharmony_ci         * The order of the large prime subgroup of the curve is our choice for
555e1051a39Sopenharmony_ci         * a fixed public size, as that is generally the upper bound for
556e1051a39Sopenharmony_ci         * generating a private key in EC cryptosystems and should fit all valid
557e1051a39Sopenharmony_ci         * secret scalars.
558e1051a39Sopenharmony_ci         *
559e1051a39Sopenharmony_ci         * For padding on export we just use the bit length of the order
560e1051a39Sopenharmony_ci         * converted to bytes (rounding up).
561e1051a39Sopenharmony_ci         *
562e1051a39Sopenharmony_ci         * For preallocating the BIGNUM storage we look at the number of "words"
563e1051a39Sopenharmony_ci         * required for the internal representation of the order, and we
564e1051a39Sopenharmony_ci         * preallocate 2 extra "words" in case any of the subsequent processing
565e1051a39Sopenharmony_ci         * might temporarily overflow the order length.
566e1051a39Sopenharmony_ci         */
567e1051a39Sopenharmony_ci        ecbits = EC_GROUP_order_bits(ecg);
568e1051a39Sopenharmony_ci        if (ecbits <= 0)
569e1051a39Sopenharmony_ci            goto err;
570e1051a39Sopenharmony_ci
571e1051a39Sopenharmony_ci        sz = (ecbits + 7 ) / 8;
572e1051a39Sopenharmony_ci        if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
573e1051a39Sopenharmony_ci                                        OSSL_PKEY_PARAM_PRIV_KEY,
574e1051a39Sopenharmony_ci                                        priv_key, sz))
575e1051a39Sopenharmony_ci            goto err;
576e1051a39Sopenharmony_ci        selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
577e1051a39Sopenharmony_ci
578e1051a39Sopenharmony_ci        /*
579e1051a39Sopenharmony_ci         * The ECDH Cofactor Mode is defined only if the EC_KEY actually
580e1051a39Sopenharmony_ci         * contains a private key, so we check for the flag and export it only
581e1051a39Sopenharmony_ci         * in this case.
582e1051a39Sopenharmony_ci         */
583e1051a39Sopenharmony_ci        ecdh_cofactor_mode =
584e1051a39Sopenharmony_ci            (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
585e1051a39Sopenharmony_ci
586e1051a39Sopenharmony_ci        /* Export the ECDH_COFACTOR_MODE parameter */
587e1051a39Sopenharmony_ci        if (!OSSL_PARAM_BLD_push_int(tmpl,
588e1051a39Sopenharmony_ci                                     OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
589e1051a39Sopenharmony_ci                                     ecdh_cofactor_mode))
590e1051a39Sopenharmony_ci            goto err;
591e1051a39Sopenharmony_ci        selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
592e1051a39Sopenharmony_ci    }
593e1051a39Sopenharmony_ci
594e1051a39Sopenharmony_ci    params = OSSL_PARAM_BLD_to_param(tmpl);
595e1051a39Sopenharmony_ci
596e1051a39Sopenharmony_ci    /* We export, the provider imports */
597e1051a39Sopenharmony_ci    rv = importer(to_keydata, selection, params);
598e1051a39Sopenharmony_ci
599e1051a39Sopenharmony_ci err:
600e1051a39Sopenharmony_ci    OSSL_PARAM_BLD_free(tmpl);
601e1051a39Sopenharmony_ci    OSSL_PARAM_free(params);
602e1051a39Sopenharmony_ci    OPENSSL_free(pub_key_buf);
603e1051a39Sopenharmony_ci    OPENSSL_free(gen_buf);
604e1051a39Sopenharmony_ci    BN_CTX_end(bnctx);
605e1051a39Sopenharmony_ci    BN_CTX_free(bnctx);
606e1051a39Sopenharmony_ci    return rv;
607e1051a39Sopenharmony_ci}
608e1051a39Sopenharmony_ci
609e1051a39Sopenharmony_cistatic int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
610e1051a39Sopenharmony_ci{
611e1051a39Sopenharmony_ci    EVP_PKEY_CTX *pctx = vpctx;
612e1051a39Sopenharmony_ci    EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
613e1051a39Sopenharmony_ci    EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery);
614e1051a39Sopenharmony_ci
615e1051a39Sopenharmony_ci    if (ec == NULL) {
616e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
617e1051a39Sopenharmony_ci        return 0;
618e1051a39Sopenharmony_ci    }
619e1051a39Sopenharmony_ci
620e1051a39Sopenharmony_ci    if (!ossl_ec_group_fromdata(ec, params)
621e1051a39Sopenharmony_ci        || !ossl_ec_key_otherparams_fromdata(ec, params)
622e1051a39Sopenharmony_ci        || !ossl_ec_key_fromdata(ec, params, 1)
623e1051a39Sopenharmony_ci        || !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
624e1051a39Sopenharmony_ci        EC_KEY_free(ec);
625e1051a39Sopenharmony_ci        return 0;
626e1051a39Sopenharmony_ci    }
627e1051a39Sopenharmony_ci    return 1;
628e1051a39Sopenharmony_ci}
629e1051a39Sopenharmony_ci
630e1051a39Sopenharmony_cistatic int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
631e1051a39Sopenharmony_ci{
632e1051a39Sopenharmony_ci    EC_KEY *eckey = from->pkey.ec;
633e1051a39Sopenharmony_ci    EC_KEY *dupkey = NULL;
634e1051a39Sopenharmony_ci    int ret;
635e1051a39Sopenharmony_ci
636e1051a39Sopenharmony_ci    if (eckey != NULL) {
637e1051a39Sopenharmony_ci        dupkey = EC_KEY_dup(eckey);
638e1051a39Sopenharmony_ci        if (dupkey == NULL)
639e1051a39Sopenharmony_ci            return 0;
640e1051a39Sopenharmony_ci    } else {
641e1051a39Sopenharmony_ci        /* necessary to properly copy empty SM2 keys */
642e1051a39Sopenharmony_ci        return EVP_PKEY_set_type(to, from->type);
643e1051a39Sopenharmony_ci    }
644e1051a39Sopenharmony_ci
645e1051a39Sopenharmony_ci    ret = EVP_PKEY_assign_EC_KEY(to, dupkey);
646e1051a39Sopenharmony_ci    if (!ret)
647e1051a39Sopenharmony_ci        EC_KEY_free(dupkey);
648e1051a39Sopenharmony_ci    return ret;
649e1051a39Sopenharmony_ci}
650e1051a39Sopenharmony_ci
651e1051a39Sopenharmony_ciconst EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = {
652e1051a39Sopenharmony_ci    EVP_PKEY_EC,
653e1051a39Sopenharmony_ci    EVP_PKEY_EC,
654e1051a39Sopenharmony_ci    0,
655e1051a39Sopenharmony_ci    "EC",
656e1051a39Sopenharmony_ci    "OpenSSL EC algorithm",
657e1051a39Sopenharmony_ci
658e1051a39Sopenharmony_ci    eckey_pub_decode,
659e1051a39Sopenharmony_ci    eckey_pub_encode,
660e1051a39Sopenharmony_ci    eckey_pub_cmp,
661e1051a39Sopenharmony_ci    eckey_pub_print,
662e1051a39Sopenharmony_ci
663e1051a39Sopenharmony_ci    NULL,
664e1051a39Sopenharmony_ci    eckey_priv_encode,
665e1051a39Sopenharmony_ci    eckey_priv_print,
666e1051a39Sopenharmony_ci
667e1051a39Sopenharmony_ci    int_ec_size,
668e1051a39Sopenharmony_ci    ec_bits,
669e1051a39Sopenharmony_ci    ec_security_bits,
670e1051a39Sopenharmony_ci
671e1051a39Sopenharmony_ci    eckey_param_decode,
672e1051a39Sopenharmony_ci    eckey_param_encode,
673e1051a39Sopenharmony_ci    ec_missing_parameters,
674e1051a39Sopenharmony_ci    ec_copy_parameters,
675e1051a39Sopenharmony_ci    ec_cmp_parameters,
676e1051a39Sopenharmony_ci    eckey_param_print,
677e1051a39Sopenharmony_ci    0,
678e1051a39Sopenharmony_ci
679e1051a39Sopenharmony_ci    int_ec_free,
680e1051a39Sopenharmony_ci    ec_pkey_ctrl,
681e1051a39Sopenharmony_ci    old_ec_priv_decode,
682e1051a39Sopenharmony_ci    old_ec_priv_encode,
683e1051a39Sopenharmony_ci
684e1051a39Sopenharmony_ci    0, 0, 0,
685e1051a39Sopenharmony_ci
686e1051a39Sopenharmony_ci    ec_pkey_check,
687e1051a39Sopenharmony_ci    ec_pkey_public_check,
688e1051a39Sopenharmony_ci    ec_pkey_param_check,
689e1051a39Sopenharmony_ci
690e1051a39Sopenharmony_ci    0, /* set_priv_key */
691e1051a39Sopenharmony_ci    0, /* set_pub_key */
692e1051a39Sopenharmony_ci    0, /* get_priv_key */
693e1051a39Sopenharmony_ci    0, /* get_pub_key */
694e1051a39Sopenharmony_ci
695e1051a39Sopenharmony_ci    ec_pkey_dirty_cnt,
696e1051a39Sopenharmony_ci    ec_pkey_export_to,
697e1051a39Sopenharmony_ci    ec_pkey_import_from,
698e1051a39Sopenharmony_ci    ec_pkey_copy,
699e1051a39Sopenharmony_ci    eckey_priv_decode_ex
700e1051a39Sopenharmony_ci};
701e1051a39Sopenharmony_ci
702e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_SM2)
703e1051a39Sopenharmony_ciconst EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = {
704e1051a39Sopenharmony_ci   EVP_PKEY_SM2,
705e1051a39Sopenharmony_ci   EVP_PKEY_EC,
706e1051a39Sopenharmony_ci   ASN1_PKEY_ALIAS
707e1051a39Sopenharmony_ci};
708e1051a39Sopenharmony_ci#endif
709e1051a39Sopenharmony_ci
710e1051a39Sopenharmony_ciint EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
711e1051a39Sopenharmony_ci{
712e1051a39Sopenharmony_ci    int private = EC_KEY_get0_private_key(x) != NULL;
713e1051a39Sopenharmony_ci
714e1051a39Sopenharmony_ci    return do_EC_KEY_print(bp, x, off,
715e1051a39Sopenharmony_ci                private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC);
716e1051a39Sopenharmony_ci}
717e1051a39Sopenharmony_ci
718e1051a39Sopenharmony_ciint ECParameters_print(BIO *bp, const EC_KEY *x)
719e1051a39Sopenharmony_ci{
720e1051a39Sopenharmony_ci    return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
721e1051a39Sopenharmony_ci}
722