xref: /dragonfly/crypto/libressl/apps/openssl/pkey.c (revision cca6fc52)
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
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
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
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