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 prog
= opt_init(argc
, argv
, pkey_options
);
87 while ((o
= opt_next()) != OPT_EOF
) {
92 BIO_printf(bio_err
, "%s: Use -help for summary.\n", prog
);
95 opt_help(pkey_options
);
99 if (!opt_format(opt_arg(), OPT_FMT_ANY
, &informat
))
103 if (!opt_format(opt_arg(), OPT_FMT_PEMDER
, &outformat
))
107 passinarg
= opt_arg();
110 passoutarg
= opt_arg();
113 e
= setup_engine(opt_arg(), 0);
136 case OPT_TRADITIONAL
:
146 ciphername
= opt_unknown();
148 case OPT_EC_CONV_FORM
:
152 point_format
= opt_arg();
153 if (!opt_string(point_format
, point_format_options
))
157 case OPT_EC_PARAM_ENC
:
161 asn1_encoding
= opt_arg();
162 if (!opt_string(asn1_encoding
, asn1_encoding_options
))
167 if (!opt_provider(o
))
173 /* No extra arguments. */
174 argc
= opt_num_rest();
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 (ciphername
!= NULL
) {
194 if (!opt_cipher(ciphername
, &cipher
))
197 if (cipher
== NULL
) {
198 if (passoutarg
!= NULL
)
200 "Warning: The -passout option is ignored without a cipher option\n");
202 if (noout
|| outformat
!= FORMAT_PEM
) {
204 "Error: Cipher options are supported only for PEM output\n");
208 if (!app_passwd(passinarg
, passoutarg
, &passin
, &passout
)) {
209 BIO_printf(bio_err
, "Error getting passwords\n");
213 out
= bio_open_owner(outfile
, outformat
, private);
218 pkey
= load_pubkey(infile
, informat
, 1, passin
, e
, "Public Key");
220 pkey
= load_key(infile
, informat
, 1, passin
, e
, "key");
224 #ifndef OPENSSL_NO_EC
225 if (asn1_encoding
!= NULL
|| point_format
!= NULL
) {
226 OSSL_PARAM params
[3], *p
= params
;
228 if (!EVP_PKEY_is_a(pkey
, "EC"))
231 if (asn1_encoding
!= NULL
)
232 *p
++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_ENCODING
,
234 if (point_format
!= NULL
)
235 *p
++ = OSSL_PARAM_construct_utf8_string(
236 OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT
,
238 *p
= OSSL_PARAM_construct_end();
239 if (EVP_PKEY_set_params(pkey
, params
) <= 0)
244 if (check
|| pub_check
) {
247 ctx
= EVP_PKEY_CTX_new(pkey
, e
);
249 ERR_print_errors(bio_err
);
254 r
= EVP_PKEY_check(ctx
);
256 r
= EVP_PKEY_public_check(ctx
);
259 BIO_printf(out
, "Key is valid\n");
262 * Note: at least for RSA keys if this function returns
263 * -1, there will be no error reasons.
265 BIO_printf(bio_err
, "Key is invalid\n");
266 ERR_print_errors(bio_err
);
272 if (outformat
== FORMAT_PEM
) {
274 if (!PEM_write_bio_PUBKEY(out
, pkey
))
279 if (!PEM_write_bio_PrivateKey_traditional(out
, pkey
, cipher
,
284 if (!PEM_write_bio_PrivateKey(out
, pkey
, cipher
,
285 NULL
, 0, NULL
, passout
))
289 } else if (outformat
== FORMAT_ASN1
) {
290 if (text
|| text_pub
) {
292 "Error: Text output cannot be combined with DER output\n");
296 if (!i2d_PUBKEY_bio(out
, pkey
))
300 if (!i2d_PrivateKey_bio(out
, pkey
))
304 BIO_printf(bio_err
, "Bad format specified for key\n");
310 if (EVP_PKEY_print_public(out
, pkey
, 0, NULL
) <= 0)
314 if (EVP_PKEY_print_private(out
, pkey
, 0, NULL
) <= 0)
322 ERR_print_errors(bio_err
);
323 EVP_PKEY_CTX_free(ctx
);
325 EVP_CIPHER_free(cipher
);
328 OPENSSL_free(passin
);
329 OPENSSL_free(passout
);