2 * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
14 #include "ec_common.h"
15 #include <openssl/pem.h>
16 #include <openssl/err.h>
17 #include <openssl/evp.h>
18 #include <openssl/core_names.h>
20 typedef enum OPTION_choice
{
22 OPT_INFORM
, OPT_OUTFORM
, OPT_PASSIN
, OPT_PASSOUT
, OPT_ENGINE
,
23 OPT_IN
, OPT_OUT
, OPT_PUBIN
, OPT_PUBOUT
, OPT_TEXT_PUB
,
24 OPT_TEXT
, OPT_NOOUT
, OPT_CIPHER
, OPT_TRADITIONAL
, OPT_CHECK
, OPT_PUB_CHECK
,
25 OPT_EC_PARAM_ENC
, OPT_EC_CONV_FORM
,
29 const OPTIONS pkey_options
[] = {
30 OPT_SECTION("General"),
31 {"help", OPT_HELP
, '-', "Display this summary"},
32 #ifndef OPENSSL_NO_ENGINE
33 {"engine", OPT_ENGINE
, 's', "Use engine, possibly a hardware device"},
37 {"check", OPT_CHECK
, '-', "Check key consistency"},
38 {"pubcheck", OPT_PUB_CHECK
, '-', "Check public key consistency"},
41 {"in", OPT_IN
, 's', "Input key"},
42 {"inform", OPT_INFORM
, 'f',
43 "Key input format (ENGINE, other values ignored)"},
44 {"passin", OPT_PASSIN
, 's', "Key input pass phrase source"},
45 {"pubin", OPT_PUBIN
, '-',
46 "Read only public components from key input"},
48 OPT_SECTION("Output"),
49 {"out", OPT_OUT
, '>', "Output file for encoded and/or text output"},
50 {"outform", OPT_OUTFORM
, 'F', "Output encoding format (DER or PEM)"},
51 {"", OPT_CIPHER
, '-', "Any supported cipher to be used for encryption"},
52 {"passout", OPT_PASSOUT
, 's', "Output PEM file pass phrase source"},
53 {"traditional", OPT_TRADITIONAL
, '-',
54 "Use traditional format for private key PEM output"},
55 {"pubout", OPT_PUBOUT
, '-', "Restrict encoded output to public components"},
56 {"noout", OPT_NOOUT
, '-', "Do not output the key in encoded form"},
57 {"text", OPT_TEXT
, '-', "Output key components in plaintext"},
58 {"text_pub", OPT_TEXT_PUB
, '-',
59 "Output only public key components in text form"},
60 {"ec_conv_form", OPT_EC_CONV_FORM
, 's',
61 "Specifies the EC point conversion form in the encoding"},
62 {"ec_param_enc", OPT_EC_PARAM_ENC
, 's',
63 "Specifies the way the EC parameters are encoded"},
68 int pkey_main(int argc
, char **argv
)
72 EVP_PKEY
*pkey
= NULL
;
73 EVP_PKEY_CTX
*ctx
= NULL
;
74 EVP_CIPHER
*cipher
= NULL
;
75 char *infile
= NULL
, *outfile
= NULL
, *passin
= NULL
, *passout
= NULL
;
76 char *passinarg
= NULL
, *passoutarg
= NULL
, *ciphername
= NULL
, *prog
;
78 int informat
= FORMAT_UNDEF
, outformat
= FORMAT_PEM
;
79 int pubin
= 0, pubout
= 0, text_pub
= 0, text
= 0, noout
= 0, ret
= 1;
80 int private = 0, traditional
= 0, check
= 0, pub_check
= 0;
82 char *asn1_encoding
= NULL
;
83 char *point_format
= NULL
;
86 opt_set_unknown_name("cipher");
87 prog
= opt_init(argc
, argv
, pkey_options
);
88 while ((o
= opt_next()) != OPT_EOF
) {
93 BIO_printf(bio_err
, "%s: Use -help for summary.\n", prog
);
96 opt_help(pkey_options
);
100 if (!opt_format(opt_arg(), OPT_FMT_ANY
, &informat
))
104 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &outformat
))
108 passinarg
= opt_arg();
111 passoutarg
= opt_arg();
114 e
= setup_engine(opt_arg(), 0);
137 case OPT_TRADITIONAL
:
147 ciphername
= opt_unknown();
149 case OPT_EC_CONV_FORM
:
153 point_format
= opt_arg();
154 if (!opt_string(point_format
, point_format_options
))
158 case OPT_EC_PARAM_ENC
:
162 asn1_encoding
= opt_arg();
163 if (!opt_string(asn1_encoding
, asn1_encoding_options
))
168 if (!opt_provider(o
))
174 /* No extra arguments. */
175 if (!opt_check_rest_arg(NULL
))
178 if (text
&& text_pub
)
180 "Warning: The -text option is ignored with -text_pub\n");
181 if (traditional
&& (noout
|| outformat
!= FORMAT_PEM
))
183 "Warning: The -traditional is ignored since there is no PEM output\n");
185 /* -pubout and -text is the same as -text_pub */
186 if (!text_pub
&& pubout
&& text
) {
191 private = (!noout
&& !pubout
) || (text
&& !text_pub
);
193 if (!opt_cipher(ciphername
, &cipher
))
195 if (cipher
== NULL
) {
196 if (passoutarg
!= NULL
)
198 "Warning: The -passout option is ignored without a cipher option\n");
200 if (noout
|| outformat
!= FORMAT_PEM
) {
202 "Error: Cipher options are supported only for PEM output\n");
206 if (!app_passwd(passinarg
, passoutarg
, &passin
, &passout
)) {
207 BIO_printf(bio_err
, "Error getting passwords\n");
211 out
= bio_open_owner(outfile
, outformat
, private);
216 pkey
= load_pubkey(infile
, informat
, 1, passin
, e
, "Public Key");
218 pkey
= load_key(infile
, informat
, 1, passin
, e
, "key");
222 #ifndef OPENSSL_NO_EC
223 if (asn1_encoding
!= NULL
|| point_format
!= NULL
) {
224 OSSL_PARAM params
[3], *p
= params
;
226 if (!EVP_PKEY_is_a(pkey
, "EC"))
229 if (asn1_encoding
!= NULL
)
230 *p
++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING
,
232 if (point_format
!= NULL
)
233 *p
++ = OSSL_PARAM_construct_utf8_string(
234 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
,
236 *p
= OSSL_PARAM_construct_end();
237 if (EVP_PKEY_set_params(pkey
, params
) <= 0)
242 if (check
|| pub_check
) {
245 ctx
= EVP_PKEY_CTX_new(pkey
, e
);
247 ERR_print_errors(bio_err
);
252 r
= EVP_PKEY_check(ctx
);
254 r
= EVP_PKEY_public_check(ctx
);
257 BIO_printf(out
, "Key is valid\n");
260 * Note: at least for RSA keys if this function returns
261 * -1, there will be no error reasons.
263 BIO_printf(bio_err
, "Key is invalid\n");
264 ERR_print_errors(bio_err
);
270 if (outformat
== FORMAT_PEM
) {
272 if (!PEM_write_bio_PUBKEY(out
, pkey
))
277 if (!PEM_write_bio_PrivateKey_traditional(out
, pkey
, cipher
,
282 if (!PEM_write_bio_PrivateKey(out
, pkey
, cipher
,
283 NULL
, 0, NULL
, passout
))
287 } else if (outformat
== FORMAT_ASN1
) {
288 if (text
|| text_pub
) {
290 "Error: Text output cannot be combined with DER output\n");
294 if (!i2d_PUBKEY_bio(out
, pkey
))
298 if (!i2d_PrivateKey_bio(out
, pkey
))
302 BIO_printf(bio_err
, "Bad format specified for key\n");
308 if (EVP_PKEY_print_public(out
, pkey
, 0, NULL
) <= 0)
312 if (EVP_PKEY_print_private(out
, pkey
, 0, NULL
) <= 0)
320 ERR_print_errors(bio_err
);
321 EVP_PKEY_CTX_free(ctx
);
323 EVP_CIPHER_free(cipher
);
326 OPENSSL_free(passin
);
327 OPENSSL_free(passout
);