13b4e3dcbSSimon L. B. Nielsen /*
2*b077aed3SPierre Pronchery * Copyright 2002-2022 The OpenSSL Project Authors. All Rights Reserved.
3e71b7053SJung-uk Kim * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
43b4e3dcbSSimon L. B. Nielsen *
5*b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
6e71b7053SJung-uk Kim * this file except in compliance with the License. You can obtain a copy
7e71b7053SJung-uk Kim * in the file LICENSE in the source distribution or at
8e71b7053SJung-uk Kim * https://www.openssl.org/source/license.html
93b4e3dcbSSimon L. B. Nielsen */
103b4e3dcbSSimon L. B. Nielsen
113b4e3dcbSSimon L. B. Nielsen #include <string.h>
12*b077aed3SPierre Pronchery #include <openssl/opensslconf.h>
13*b077aed3SPierre Pronchery #include <openssl/evp.h>
14*b077aed3SPierre Pronchery #include <openssl/encoder.h>
15*b077aed3SPierre Pronchery #include <openssl/decoder.h>
16*b077aed3SPierre Pronchery #include <openssl/core_names.h>
17*b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
18*b077aed3SPierre Pronchery #include <openssl/params.h>
19*b077aed3SPierre Pronchery #include <openssl/err.h>
203b4e3dcbSSimon L. B. Nielsen #include "apps.h"
21e71b7053SJung-uk Kim #include "progs.h"
22*b077aed3SPierre Pronchery #include "ec_common.h"
233b4e3dcbSSimon L. B. Nielsen
24e71b7053SJung-uk Kim typedef enum OPTION_choice {
25*b077aed3SPierre Pronchery OPT_COMMON,
26*b077aed3SPierre Pronchery OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_TEXT,
27e71b7053SJung-uk Kim OPT_CHECK, OPT_LIST_CURVES, OPT_NO_SEED, OPT_NOOUT, OPT_NAME,
28*b077aed3SPierre Pronchery OPT_CONV_FORM, OPT_PARAM_ENC, OPT_GENKEY, OPT_ENGINE, OPT_CHECK_NAMED,
29*b077aed3SPierre Pronchery OPT_R_ENUM, OPT_PROV_ENUM
30e71b7053SJung-uk Kim } OPTION_CHOICE;
313b4e3dcbSSimon L. B. Nielsen
32e71b7053SJung-uk Kim const OPTIONS ecparam_options[] = {
33*b077aed3SPierre Pronchery OPT_SECTION("General"),
34e71b7053SJung-uk Kim {"help", OPT_HELP, '-', "Display this summary"},
35e71b7053SJung-uk Kim {"list_curves", OPT_LIST_CURVES, '-',
36e71b7053SJung-uk Kim "Prints a list of all curve 'short names'"},
37e71b7053SJung-uk Kim #ifndef OPENSSL_NO_ENGINE
38e71b7053SJung-uk Kim {"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
39e71b7053SJung-uk Kim #endif
40*b077aed3SPierre Pronchery
41*b077aed3SPierre Pronchery {"genkey", OPT_GENKEY, '-', "Generate ec key"},
42*b077aed3SPierre Pronchery {"in", OPT_IN, '<', "Input file - default stdin"},
43*b077aed3SPierre Pronchery {"inform", OPT_INFORM, 'F', "Input format - default PEM (DER or PEM)"},
44*b077aed3SPierre Pronchery {"out", OPT_OUT, '>', "Output file - default stdout"},
45*b077aed3SPierre Pronchery {"outform", OPT_OUTFORM, 'F', "Output format - default PEM"},
46*b077aed3SPierre Pronchery
47*b077aed3SPierre Pronchery OPT_SECTION("Output"),
48*b077aed3SPierre Pronchery {"text", OPT_TEXT, '-', "Print the ec parameters in text form"},
49*b077aed3SPierre Pronchery {"noout", OPT_NOOUT, '-', "Do not print the ec parameter"},
50*b077aed3SPierre Pronchery {"param_enc", OPT_PARAM_ENC, 's',
51*b077aed3SPierre Pronchery "Specifies the way the ec parameters are encoded"},
52*b077aed3SPierre Pronchery
53*b077aed3SPierre Pronchery OPT_SECTION("Parameter"),
54*b077aed3SPierre Pronchery {"check", OPT_CHECK, '-', "Validate the ec parameters"},
55*b077aed3SPierre Pronchery {"check_named", OPT_CHECK_NAMED, '-',
56*b077aed3SPierre Pronchery "Check that named EC curve parameters have not been modified"},
57*b077aed3SPierre Pronchery {"no_seed", OPT_NO_SEED, '-',
58*b077aed3SPierre Pronchery "If 'explicit' parameters are chosen do not use the seed"},
59*b077aed3SPierre Pronchery {"name", OPT_NAME, 's',
60*b077aed3SPierre Pronchery "Use the ec parameters with specified 'short name'"},
61*b077aed3SPierre Pronchery {"conv_form", OPT_CONV_FORM, 's', "Specifies the point conversion form "},
62*b077aed3SPierre Pronchery
63*b077aed3SPierre Pronchery OPT_R_OPTIONS,
64*b077aed3SPierre Pronchery OPT_PROV_OPTIONS,
65e71b7053SJung-uk Kim {NULL}
66e71b7053SJung-uk Kim };
673b4e3dcbSSimon L. B. Nielsen
list_builtin_curves(BIO * out)68*b077aed3SPierre Pronchery static int list_builtin_curves(BIO *out)
69*b077aed3SPierre Pronchery {
70*b077aed3SPierre Pronchery int ret = 0;
71*b077aed3SPierre Pronchery EC_builtin_curve *curves = NULL;
72*b077aed3SPierre Pronchery size_t n, crv_len = EC_get_builtin_curves(NULL, 0);
733b4e3dcbSSimon L. B. Nielsen
74*b077aed3SPierre Pronchery curves = app_malloc((int)sizeof(*curves) * crv_len, "list curves");
75*b077aed3SPierre Pronchery if (!EC_get_builtin_curves(curves, crv_len))
76*b077aed3SPierre Pronchery goto end;
77*b077aed3SPierre Pronchery
78*b077aed3SPierre Pronchery for (n = 0; n < crv_len; n++) {
79*b077aed3SPierre Pronchery const char *comment = curves[n].comment;
80*b077aed3SPierre Pronchery const char *sname = OBJ_nid2sn(curves[n].nid);
81*b077aed3SPierre Pronchery
82*b077aed3SPierre Pronchery if (comment == NULL)
83*b077aed3SPierre Pronchery comment = "CURVE DESCRIPTION NOT AVAILABLE";
84*b077aed3SPierre Pronchery if (sname == NULL)
85*b077aed3SPierre Pronchery sname = "";
86*b077aed3SPierre Pronchery
87*b077aed3SPierre Pronchery BIO_printf(out, " %-10s: ", sname);
88*b077aed3SPierre Pronchery BIO_printf(out, "%s\n", comment);
89*b077aed3SPierre Pronchery }
90*b077aed3SPierre Pronchery ret = 1;
91*b077aed3SPierre Pronchery end:
92*b077aed3SPierre Pronchery OPENSSL_free(curves);
93*b077aed3SPierre Pronchery return ret;
94*b077aed3SPierre Pronchery }
953b4e3dcbSSimon L. B. Nielsen
ecparam_main(int argc,char ** argv)96e71b7053SJung-uk Kim int ecparam_main(int argc, char **argv)
973b4e3dcbSSimon L. B. Nielsen {
98*b077aed3SPierre Pronchery EVP_PKEY_CTX *gctx_params = NULL, *gctx_key = NULL, *pctx = NULL;
99*b077aed3SPierre Pronchery EVP_PKEY *params_key = NULL, *key = NULL;
100*b077aed3SPierre Pronchery OSSL_ENCODER_CTX *ectx_key = NULL, *ectx_params = NULL;
101*b077aed3SPierre Pronchery OSSL_DECODER_CTX *dctx_params = NULL;
102e71b7053SJung-uk Kim ENGINE *e = NULL;
103*b077aed3SPierre Pronchery BIO *out = NULL;
104e71b7053SJung-uk Kim char *curve_name = NULL;
105*b077aed3SPierre Pronchery char *asn1_encoding = NULL;
106*b077aed3SPierre Pronchery char *point_format = NULL;
1073b4e3dcbSSimon L. B. Nielsen char *infile = NULL, *outfile = NULL, *prog;
108e71b7053SJung-uk Kim OPTION_CHOICE o;
109*b077aed3SPierre Pronchery int informat = FORMAT_PEM, outformat = FORMAT_PEM, noout = 0;
110e71b7053SJung-uk Kim int ret = 1, private = 0;
111*b077aed3SPierre Pronchery int no_seed = 0, check = 0, check_named = 0, text = 0, genkey = 0;
112*b077aed3SPierre Pronchery int list_curves = 0;
1133b4e3dcbSSimon L. B. Nielsen
114e71b7053SJung-uk Kim prog = opt_init(argc, argv, ecparam_options);
115e71b7053SJung-uk Kim while ((o = opt_next()) != OPT_EOF) {
116e71b7053SJung-uk Kim switch (o) {
117e71b7053SJung-uk Kim case OPT_EOF:
118e71b7053SJung-uk Kim case OPT_ERR:
119e71b7053SJung-uk Kim opthelp:
120e71b7053SJung-uk Kim BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
1213b4e3dcbSSimon L. B. Nielsen goto end;
122e71b7053SJung-uk Kim case OPT_HELP:
123e71b7053SJung-uk Kim opt_help(ecparam_options);
124e71b7053SJung-uk Kim ret = 0;
125e71b7053SJung-uk Kim goto end;
126e71b7053SJung-uk Kim case OPT_INFORM:
127e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
128e71b7053SJung-uk Kim goto opthelp;
129e71b7053SJung-uk Kim break;
130e71b7053SJung-uk Kim case OPT_IN:
131e71b7053SJung-uk Kim infile = opt_arg();
132e71b7053SJung-uk Kim break;
133e71b7053SJung-uk Kim case OPT_OUTFORM:
134e71b7053SJung-uk Kim if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat))
135e71b7053SJung-uk Kim goto opthelp;
136e71b7053SJung-uk Kim break;
137e71b7053SJung-uk Kim case OPT_OUT:
138e71b7053SJung-uk Kim outfile = opt_arg();
139e71b7053SJung-uk Kim break;
140e71b7053SJung-uk Kim case OPT_TEXT:
1413b4e3dcbSSimon L. B. Nielsen text = 1;
142e71b7053SJung-uk Kim break;
143e71b7053SJung-uk Kim case OPT_CHECK:
1443b4e3dcbSSimon L. B. Nielsen check = 1;
145e71b7053SJung-uk Kim break;
146*b077aed3SPierre Pronchery case OPT_CHECK_NAMED:
147*b077aed3SPierre Pronchery check_named = 1;
148*b077aed3SPierre Pronchery break;
149e71b7053SJung-uk Kim case OPT_LIST_CURVES:
1503b4e3dcbSSimon L. B. Nielsen list_curves = 1;
151e71b7053SJung-uk Kim break;
152e71b7053SJung-uk Kim case OPT_NO_SEED:
1533b4e3dcbSSimon L. B. Nielsen no_seed = 1;
154e71b7053SJung-uk Kim break;
155e71b7053SJung-uk Kim case OPT_NOOUT:
1563b4e3dcbSSimon L. B. Nielsen noout = 1;
157e71b7053SJung-uk Kim break;
158e71b7053SJung-uk Kim case OPT_NAME:
159e71b7053SJung-uk Kim curve_name = opt_arg();
160e71b7053SJung-uk Kim break;
161e71b7053SJung-uk Kim case OPT_CONV_FORM:
162*b077aed3SPierre Pronchery point_format = opt_arg();
163*b077aed3SPierre Pronchery if (!opt_string(point_format, point_format_options))
164e71b7053SJung-uk Kim goto opthelp;
165e71b7053SJung-uk Kim break;
166e71b7053SJung-uk Kim case OPT_PARAM_ENC:
167*b077aed3SPierre Pronchery asn1_encoding = opt_arg();
168*b077aed3SPierre Pronchery if (!opt_string(asn1_encoding, asn1_encoding_options))
169e71b7053SJung-uk Kim goto opthelp;
170e71b7053SJung-uk Kim break;
171e71b7053SJung-uk Kim case OPT_GENKEY:
1723b4e3dcbSSimon L. B. Nielsen genkey = 1;
173e71b7053SJung-uk Kim break;
174e71b7053SJung-uk Kim case OPT_R_CASES:
175e71b7053SJung-uk Kim if (!opt_rand(o))
176e71b7053SJung-uk Kim goto end;
177e71b7053SJung-uk Kim break;
178*b077aed3SPierre Pronchery case OPT_PROV_CASES:
179*b077aed3SPierre Pronchery if (!opt_provider(o))
180*b077aed3SPierre Pronchery goto end;
181*b077aed3SPierre Pronchery break;
182e71b7053SJung-uk Kim case OPT_ENGINE:
183e71b7053SJung-uk Kim e = setup_engine(opt_arg(), 0);
1843b4e3dcbSSimon L. B. Nielsen break;
1853b4e3dcbSSimon L. B. Nielsen }
1863b4e3dcbSSimon L. B. Nielsen }
187*b077aed3SPierre Pronchery
188*b077aed3SPierre Pronchery /* No extra args. */
189e71b7053SJung-uk Kim argc = opt_num_rest();
190e71b7053SJung-uk Kim if (argc != 0)
191e71b7053SJung-uk Kim goto opthelp;
1923b4e3dcbSSimon L. B. Nielsen
193*b077aed3SPierre Pronchery if (!app_RAND_load())
194*b077aed3SPierre Pronchery goto end;
195*b077aed3SPierre Pronchery
196e71b7053SJung-uk Kim private = genkey ? 1 : 0;
197e71b7053SJung-uk Kim
198e71b7053SJung-uk Kim out = bio_open_owner(outfile, outformat, private);
199e71b7053SJung-uk Kim if (out == NULL)
2003b4e3dcbSSimon L. B. Nielsen goto end;
2013b4e3dcbSSimon L. B. Nielsen
2026f9291ceSJung-uk Kim if (list_curves) {
203*b077aed3SPierre Pronchery if (list_builtin_curves(out))
2043b4e3dcbSSimon L. B. Nielsen ret = 0;
2053b4e3dcbSSimon L. B. Nielsen goto end;
2063b4e3dcbSSimon L. B. Nielsen }
2073b4e3dcbSSimon L. B. Nielsen
2086f9291ceSJung-uk Kim if (curve_name != NULL) {
209*b077aed3SPierre Pronchery OSSL_PARAM params[4];
210*b077aed3SPierre Pronchery OSSL_PARAM *p = params;
2113b4e3dcbSSimon L. B. Nielsen
212e71b7053SJung-uk Kim if (strcmp(curve_name, "secp192r1") == 0) {
213*b077aed3SPierre Pronchery BIO_printf(bio_err,
214*b077aed3SPierre Pronchery "using curve name prime192v1 instead of secp192r1\n");
215*b077aed3SPierre Pronchery curve_name = SN_X9_62_prime192v1;
216e71b7053SJung-uk Kim } else if (strcmp(curve_name, "secp256r1") == 0) {
217*b077aed3SPierre Pronchery BIO_printf(bio_err,
218*b077aed3SPierre Pronchery "using curve name prime256v1 instead of secp256r1\n");
219*b077aed3SPierre Pronchery curve_name = SN_X9_62_prime256v1;
220*b077aed3SPierre Pronchery }
221*b077aed3SPierre Pronchery *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME,
222*b077aed3SPierre Pronchery curve_name, 0);
223*b077aed3SPierre Pronchery if (asn1_encoding != NULL)
224*b077aed3SPierre Pronchery *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING,
225*b077aed3SPierre Pronchery asn1_encoding, 0);
226*b077aed3SPierre Pronchery if (point_format != NULL)
227*b077aed3SPierre Pronchery *p++ = OSSL_PARAM_construct_utf8_string(
228*b077aed3SPierre Pronchery OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
229*b077aed3SPierre Pronchery point_format, 0);
230*b077aed3SPierre Pronchery *p = OSSL_PARAM_construct_end();
231*b077aed3SPierre Pronchery
232*b077aed3SPierre Pronchery if (OPENSSL_strcasecmp(curve_name, "SM2") == 0)
233*b077aed3SPierre Pronchery gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "sm2",
234*b077aed3SPierre Pronchery app_get0_propq());
235*b077aed3SPierre Pronchery else
236*b077aed3SPierre Pronchery gctx_params = EVP_PKEY_CTX_new_from_name(app_get0_libctx(), "ec",
237*b077aed3SPierre Pronchery app_get0_propq());
238*b077aed3SPierre Pronchery if (gctx_params == NULL
239*b077aed3SPierre Pronchery || EVP_PKEY_keygen_init(gctx_params) <= 0
240*b077aed3SPierre Pronchery || EVP_PKEY_CTX_set_params(gctx_params, params) <= 0
241*b077aed3SPierre Pronchery || EVP_PKEY_keygen(gctx_params, ¶ms_key) <= 0) {
242*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to generate key\n");
243*b077aed3SPierre Pronchery goto end;
244*b077aed3SPierre Pronchery }
245e71b7053SJung-uk Kim } else {
246*b077aed3SPierre Pronchery params_key = load_keyparams(infile, informat, 1, "EC", "EC parameters");
247*b077aed3SPierre Pronchery if (params_key == NULL || !EVP_PKEY_is_a(params_key, "EC"))
248*b077aed3SPierre Pronchery goto end;
249*b077aed3SPierre Pronchery if (point_format
250*b077aed3SPierre Pronchery && !EVP_PKEY_set_utf8_string_param(
251*b077aed3SPierre Pronchery params_key, OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT,
252*b077aed3SPierre Pronchery point_format)) {
253*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to set point conversion format\n");
2543b4e3dcbSSimon L. B. Nielsen goto end;
2553b4e3dcbSSimon L. B. Nielsen }
2563b4e3dcbSSimon L. B. Nielsen
257*b077aed3SPierre Pronchery if (asn1_encoding != NULL
258*b077aed3SPierre Pronchery && !EVP_PKEY_set_utf8_string_param(
259*b077aed3SPierre Pronchery params_key, OSSL_PKEY_PARAM_EC_ENCODING, asn1_encoding)) {
260*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to set asn1 encoding format\n");
2613b4e3dcbSSimon L. B. Nielsen goto end;
2623b4e3dcbSSimon L. B. Nielsen }
2633b4e3dcbSSimon L. B. Nielsen }
264*b077aed3SPierre Pronchery
265*b077aed3SPierre Pronchery if (no_seed
266*b077aed3SPierre Pronchery && !EVP_PKEY_set_octet_string_param(params_key, OSSL_PKEY_PARAM_EC_SEED,
267*b077aed3SPierre Pronchery NULL, 0)) {
268*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to clear seed\n");
2693b4e3dcbSSimon L. B. Nielsen goto end;
2703b4e3dcbSSimon L. B. Nielsen }
2713b4e3dcbSSimon L. B. Nielsen
272*b077aed3SPierre Pronchery if (text
273*b077aed3SPierre Pronchery && !EVP_PKEY_print_params(out, params_key, 0, NULL)) {
274*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to print params\n");
2753b4e3dcbSSimon L. B. Nielsen goto end;
2763b4e3dcbSSimon L. B. Nielsen }
2773b4e3dcbSSimon L. B. Nielsen
278*b077aed3SPierre Pronchery if (check || check_named) {
2793b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "checking elliptic curve parameters: ");
280*b077aed3SPierre Pronchery
281*b077aed3SPierre Pronchery if (check_named
282*b077aed3SPierre Pronchery && !EVP_PKEY_set_utf8_string_param(params_key,
283*b077aed3SPierre Pronchery OSSL_PKEY_PARAM_EC_GROUP_CHECK_TYPE,
284*b077aed3SPierre Pronchery OSSL_PKEY_EC_GROUP_CHECK_NAMED)) {
285*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to set check_type\n");
286*b077aed3SPierre Pronchery goto end;
287*b077aed3SPierre Pronchery }
288*b077aed3SPierre Pronchery pctx = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
289*b077aed3SPierre Pronchery app_get0_propq());
290*b077aed3SPierre Pronchery if (pctx == NULL || EVP_PKEY_param_check(pctx) <= 0) {
2913b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "failed\n");
29280815a77SJung-uk Kim goto end;
29380815a77SJung-uk Kim }
2943b4e3dcbSSimon L. B. Nielsen BIO_printf(bio_err, "ok\n");
2953b4e3dcbSSimon L. B. Nielsen }
2963b4e3dcbSSimon L. B. Nielsen
297dee36b4fSJung-uk Kim if (outformat == FORMAT_ASN1 && genkey)
298dee36b4fSJung-uk Kim noout = 1;
299dee36b4fSJung-uk Kim
3006f9291ceSJung-uk Kim if (!noout) {
301*b077aed3SPierre Pronchery ectx_params = OSSL_ENCODER_CTX_new_for_pkey(
302*b077aed3SPierre Pronchery params_key, OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
303*b077aed3SPierre Pronchery outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
304*b077aed3SPierre Pronchery if (!OSSL_ENCODER_to_bio(ectx_params, out)) {
305*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to write elliptic curve parameters\n");
3063b4e3dcbSSimon L. B. Nielsen goto end;
3073b4e3dcbSSimon L. B. Nielsen }
3083b4e3dcbSSimon L. B. Nielsen }
3093b4e3dcbSSimon L. B. Nielsen
3106f9291ceSJung-uk Kim if (genkey) {
311*b077aed3SPierre Pronchery /*
312*b077aed3SPierre Pronchery * NOTE: EC keygen does not normally need to pass in the param_key
313*b077aed3SPierre Pronchery * for named curves. This can be achieved using:
314*b077aed3SPierre Pronchery * gctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL);
315*b077aed3SPierre Pronchery * EVP_PKEY_keygen_init(gctx);
316*b077aed3SPierre Pronchery * EVP_PKEY_CTX_set_group_name(gctx, curvename);
317*b077aed3SPierre Pronchery * EVP_PKEY_keygen(gctx, &key) <= 0)
318*b077aed3SPierre Pronchery */
319*b077aed3SPierre Pronchery gctx_key = EVP_PKEY_CTX_new_from_pkey(app_get0_libctx(), params_key,
320*b077aed3SPierre Pronchery app_get0_propq());
321*b077aed3SPierre Pronchery if (EVP_PKEY_keygen_init(gctx_key) <= 0
322*b077aed3SPierre Pronchery || EVP_PKEY_keygen(gctx_key, &key) <= 0) {
323e71b7053SJung-uk Kim BIO_printf(bio_err, "unable to generate key\n");
3243b4e3dcbSSimon L. B. Nielsen goto end;
3253b4e3dcbSSimon L. B. Nielsen }
326e71b7053SJung-uk Kim assert(private);
327*b077aed3SPierre Pronchery ectx_key = OSSL_ENCODER_CTX_new_for_pkey(
328*b077aed3SPierre Pronchery key, OSSL_KEYMGMT_SELECT_ALL,
329*b077aed3SPierre Pronchery outformat == FORMAT_ASN1 ? "DER" : "PEM", NULL, NULL);
330*b077aed3SPierre Pronchery if (!OSSL_ENCODER_to_bio(ectx_key, out)) {
331*b077aed3SPierre Pronchery BIO_printf(bio_err, "unable to write elliptic "
332*b077aed3SPierre Pronchery "curve parameters\n");
333*b077aed3SPierre Pronchery goto end;
334*b077aed3SPierre Pronchery }
3353b4e3dcbSSimon L. B. Nielsen }
3363b4e3dcbSSimon L. B. Nielsen
3373b4e3dcbSSimon L. B. Nielsen ret = 0;
3383b4e3dcbSSimon L. B. Nielsen end:
339*b077aed3SPierre Pronchery if (ret != 0)
340*b077aed3SPierre Pronchery ERR_print_errors(bio_err);
3416cf8931aSJung-uk Kim release_engine(e);
342*b077aed3SPierre Pronchery EVP_PKEY_free(params_key);
343*b077aed3SPierre Pronchery EVP_PKEY_free(key);
344*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(pctx);
345*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(gctx_params);
346*b077aed3SPierre Pronchery EVP_PKEY_CTX_free(gctx_key);
347*b077aed3SPierre Pronchery OSSL_DECODER_CTX_free(dctx_params);
348*b077aed3SPierre Pronchery OSSL_ENCODER_CTX_free(ectx_params);
349*b077aed3SPierre Pronchery OSSL_ENCODER_CTX_free(ectx_key);
3503b4e3dcbSSimon L. B. Nielsen BIO_free_all(out);
351e71b7053SJung-uk Kim return ret;
3523b4e3dcbSSimon L. B. Nielsen }
353