1 /* $OpenBSD: pkey.c,v 1.15 2019/07/14 03:30:46 guenther Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006
4 */
5 /* ====================================================================
6 * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59 #include <stdio.h>
60 #include <string.h>
61
62 #include "apps.h"
63
64 #include <openssl/err.h>
65 #include <openssl/evp.h>
66 #include <openssl/pem.h>
67
68 static struct {
69 const EVP_CIPHER *cipher;
70 char *infile;
71 int informat;
72 int noout;
73 char *outfile;
74 int outformat;
75 char *passargin;
76 char *passargout;
77 int pubin;
78 int pubout;
79 int pubtext;
80 int text;
81 } pkey_config;
82
83 static int
pkey_opt_cipher(int argc,char ** argv,int * argsused)84 pkey_opt_cipher(int argc, char **argv, int *argsused)
85 {
86 char *name = argv[0];
87
88 if (*name++ != '-')
89 return (1);
90
91 if ((pkey_config.cipher = EVP_get_cipherbyname(name)) == NULL) {
92 BIO_printf(bio_err, "Unknown cipher %s\n", name);
93 return (1);
94 }
95
96 *argsused = 1;
97 return (0);
98 }
99
100 static const struct option pkey_options[] = {
101 {
102 .name = "in",
103 .argname = "file",
104 .desc = "Input file (default stdin)",
105 .type = OPTION_ARG,
106 .opt.arg = &pkey_config.infile,
107 },
108 {
109 .name = "inform",
110 .argname = "format",
111 .desc = "Input format (DER or PEM (default))",
112 .type = OPTION_ARG_FORMAT,
113 .opt.value = &pkey_config.informat,
114 },
115 {
116 .name = "noout",
117 .desc = "Do not print encoded version of the key",
118 .type = OPTION_FLAG,
119 .opt.flag = &pkey_config.noout,
120 },
121 {
122 .name = "out",
123 .argname = "file",
124 .desc = "Output file (default stdout)",
125 .type = OPTION_ARG,
126 .opt.arg = &pkey_config.outfile,
127 },
128 {
129 .name = "outform",
130 .argname = "format",
131 .desc = "Output format (DER or PEM (default))",
132 .type = OPTION_ARG_FORMAT,
133 .opt.value = &pkey_config.outformat,
134 },
135 {
136 .name = "passin",
137 .argname = "src",
138 .desc = "Input file passphrase source",
139 .type = OPTION_ARG,
140 .opt.arg = &pkey_config.passargin,
141 },
142 {
143 .name = "passout",
144 .argname = "src",
145 .desc = "Output file passphrase source",
146 .type = OPTION_ARG,
147 .opt.arg = &pkey_config.passargout,
148 },
149 {
150 .name = "pubin",
151 .desc = "Expect a public key (default private key)",
152 .type = OPTION_VALUE,
153 .value = 1,
154 .opt.value = &pkey_config.pubin,
155 },
156 {
157 .name = "pubout",
158 .desc = "Output a public key (default private key)",
159 .type = OPTION_VALUE,
160 .value = 1,
161 .opt.value = &pkey_config.pubout,
162 },
163 {
164 .name = "text",
165 .desc = "Print the public/private key in plain text",
166 .type = OPTION_FLAG,
167 .opt.flag = &pkey_config.text,
168 },
169 {
170 .name = "text_pub",
171 .desc = "Print out only public key in plain text",
172 .type = OPTION_FLAG,
173 .opt.flag = &pkey_config.pubtext,
174 },
175 {
176 .name = NULL,
177 .type = OPTION_ARGV_FUNC,
178 .opt.argvfunc = pkey_opt_cipher,
179 },
180 { NULL }
181 };
182
183 static void
pkey_usage()184 pkey_usage()
185 {
186 int n = 0;
187
188 fprintf(stderr,
189 "usage: pkey [-ciphername] [-in file] [-inform fmt] [-noout] "
190 "[-out file]\n"
191 " [-outform fmt] [-passin src] [-passout src] [-pubin] "
192 "[-pubout] [-text]\n"
193 " [-text_pub]\n\n");
194 options_usage(pkey_options);
195 fprintf(stderr, "\n");
196
197 fprintf(stderr, "Valid ciphername values:\n\n");
198 OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH, show_cipher, &n);
199 fprintf(stderr, "\n");
200 }
201
202 int
pkey_main(int argc,char ** argv)203 pkey_main(int argc, char **argv)
204 {
205 BIO *in = NULL, *out = NULL;
206 EVP_PKEY *pkey = NULL;
207 char *passin = NULL, *passout = NULL;
208 int ret = 1;
209
210 if (single_execution) {
211 if (pledge("stdio cpath wpath rpath tty", NULL) == -1) {
212 perror("pledge");
213 exit(1);
214 }
215 }
216
217 memset(&pkey_config, 0, sizeof(pkey_config));
218 pkey_config.informat = FORMAT_PEM;
219 pkey_config.outformat = FORMAT_PEM;
220
221 if (options_parse(argc, argv, pkey_options, NULL, NULL) != 0) {
222 pkey_usage();
223 goto end;
224 }
225
226 if (pkey_config.pubtext)
227 pkey_config.text = 1;
228 if (pkey_config.pubin)
229 pkey_config.pubout = pkey_config.pubtext = 1;
230
231 if (!app_passwd(bio_err, pkey_config.passargin, pkey_config.passargout,
232 &passin, &passout)) {
233 BIO_printf(bio_err, "Error getting passwords\n");
234 goto end;
235 }
236 if (pkey_config.outfile) {
237 if (!(out = BIO_new_file(pkey_config.outfile, "wb"))) {
238 BIO_printf(bio_err,
239 "Can't open output file %s\n", pkey_config.outfile);
240 goto end;
241 }
242 } else {
243 out = BIO_new_fp(stdout, BIO_NOCLOSE);
244 }
245
246 if (pkey_config.pubin)
247 pkey = load_pubkey(bio_err, pkey_config.infile,
248 pkey_config.informat, 1, passin, "Public Key");
249 else
250 pkey = load_key(bio_err, pkey_config.infile,
251 pkey_config.informat, 1, passin, "key");
252 if (!pkey)
253 goto end;
254
255 if (!pkey_config.noout) {
256 if (pkey_config.outformat == FORMAT_PEM) {
257 if (pkey_config.pubout)
258 PEM_write_bio_PUBKEY(out, pkey);
259 else
260 PEM_write_bio_PrivateKey(out, pkey,
261 pkey_config.cipher, NULL, 0, NULL, passout);
262 } else if (pkey_config.outformat == FORMAT_ASN1) {
263 if (pkey_config.pubout)
264 i2d_PUBKEY_bio(out, pkey);
265 else
266 i2d_PrivateKey_bio(out, pkey);
267 } else {
268 BIO_printf(bio_err, "Bad format specified for key\n");
269 goto end;
270 }
271
272 }
273 if (pkey_config.text) {
274 if (pkey_config.pubtext)
275 EVP_PKEY_print_public(out, pkey, 0, NULL);
276 else
277 EVP_PKEY_print_private(out, pkey, 0, NULL);
278 }
279 ret = 0;
280
281 end:
282 EVP_PKEY_free(pkey);
283 BIO_free_all(out);
284 BIO_free(in);
285 free(passin);
286 free(passout);
287
288 return ret;
289 }
290