summaryrefslogtreecommitdiff
path: root/src/usr.bin/openssl/genpkey.c
diff options
context:
space:
mode:
authorjsing <>2014-08-26 17:47:25 +0000
committerjsing <>2014-08-26 17:47:25 +0000
commitf3755acd5513f85ff734de6a822b6f804d3776ce (patch)
tree1f859a78eae941040f58599de8c0e1e56d61fdad /src/usr.bin/openssl/genpkey.c
parent0779b9f30aa9875c290af18a4362799668829707 (diff)
downloadopenbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.tar.gz
openbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.tar.bz2
openbsd-f3755acd5513f85ff734de6a822b6f804d3776ce.zip
Move openssl(1) from /usr/sbin/openssl to /usr/bin/openssl, since it is not
a system/superuser binary. At the same time, move the source code from its current lib/libssl/src/apps location to a more appropriate home under usr.bin/openssl. ok deraadt@ miod@
Diffstat (limited to 'src/usr.bin/openssl/genpkey.c')
-rw-r--r--src/usr.bin/openssl/genpkey.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/src/usr.bin/openssl/genpkey.c b/src/usr.bin/openssl/genpkey.c
new file mode 100644
index 0000000000..02332f6682
--- /dev/null
+++ b/src/usr.bin/openssl/genpkey.c
@@ -0,0 +1,383 @@
1/* $OpenBSD: genpkey.c,v 1.1 2014/08/26 17:47:24 jsing 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#ifndef OPENSSL_NO_ENGINE
69#include <openssl/engine.h>
70#endif
71
72static int
73init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx, const char *file,
74 ENGINE * e);
75static int genpkey_cb(EVP_PKEY_CTX * ctx);
76
77
78int genpkey_main(int, char **);
79
80int
81genpkey_main(int argc, char **argv)
82{
83 ENGINE *e = NULL;
84 char **args, *outfile = NULL;
85 char *passarg = NULL;
86 BIO *in = NULL, *out = NULL;
87 const EVP_CIPHER *cipher = NULL;
88 int outformat;
89 int text = 0;
90 EVP_PKEY *pkey = NULL;
91 EVP_PKEY_CTX *ctx = NULL;
92 char *pass = NULL;
93 int badarg = 0;
94 int ret = 1, rv;
95
96 int do_param = 0;
97
98 outformat = FORMAT_PEM;
99
100 ERR_load_crypto_strings();
101 OpenSSL_add_all_algorithms();
102 args = argv + 1;
103 while (!badarg && *args && *args[0] == '-') {
104 if (!strcmp(*args, "-outform")) {
105 if (args[1]) {
106 args++;
107 outformat = str2fmt(*args);
108 } else
109 badarg = 1;
110 } else if (!strcmp(*args, "-pass")) {
111 if (!args[1])
112 goto bad;
113 passarg = *(++args);
114 }
115#ifndef OPENSSL_NO_ENGINE
116 else if (strcmp(*args, "-engine") == 0) {
117 if (!args[1])
118 goto bad;
119 e = setup_engine(bio_err, *(++args), 0);
120 }
121#endif
122 else if (!strcmp(*args, "-paramfile")) {
123 if (!args[1])
124 goto bad;
125 args++;
126 if (do_param == 1)
127 goto bad;
128 if (!init_keygen_file(bio_err, &ctx, *args, e))
129 goto end;
130 } else if (!strcmp(*args, "-out")) {
131 if (args[1]) {
132 args++;
133 outfile = *args;
134 } else
135 badarg = 1;
136 } else if (strcmp(*args, "-algorithm") == 0) {
137 if (!args[1])
138 goto bad;
139 if (!init_gen_str(bio_err, &ctx, *(++args), e, do_param))
140 goto end;
141 } else if (strcmp(*args, "-pkeyopt") == 0) {
142 if (!args[1])
143 goto bad;
144 if (!ctx) {
145 BIO_puts(bio_err, "No keytype specified\n");
146 goto bad;
147 } else if (pkey_ctrl_string(ctx, *(++args)) <= 0) {
148 BIO_puts(bio_err, "parameter setting error\n");
149 ERR_print_errors(bio_err);
150 goto end;
151 }
152 } else if (strcmp(*args, "-genparam") == 0) {
153 if (ctx)
154 goto bad;
155 do_param = 1;
156 } else if (strcmp(*args, "-text") == 0)
157 text = 1;
158 else {
159 cipher = EVP_get_cipherbyname(*args + 1);
160 if (!cipher) {
161 BIO_printf(bio_err, "Unknown cipher %s\n",
162 *args + 1);
163 badarg = 1;
164 }
165 if (do_param == 1)
166 badarg = 1;
167 }
168 args++;
169 }
170
171 if (!ctx)
172 badarg = 1;
173
174 if (badarg) {
175bad:
176 BIO_printf(bio_err, "Usage: genpkey [options]\n");
177 BIO_printf(bio_err, "where options may be\n");
178 BIO_printf(bio_err, "-out file output file\n");
179 BIO_printf(bio_err, "-outform X output format (DER or PEM)\n");
180 BIO_printf(bio_err, "-pass arg output file pass phrase source\n");
181 BIO_printf(bio_err, "-<cipher> use cipher <cipher> to encrypt the key\n");
182#ifndef OPENSSL_NO_ENGINE
183 BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n");
184#endif
185 BIO_printf(bio_err, "-paramfile file parameters file\n");
186 BIO_printf(bio_err, "-algorithm alg the public key algorithm\n");
187 BIO_printf(bio_err, "-pkeyopt opt:value set the public key algorithm option <opt>\n"
188 " to value <value>\n");
189 BIO_printf(bio_err, "-genparam generate parameters, not key\n");
190 BIO_printf(bio_err, "-text print the in text\n");
191 BIO_printf(bio_err, "NB: options order may be important! See the manual page.\n");
192 goto end;
193 }
194 if (!app_passwd(bio_err, passarg, NULL, &pass, NULL)) {
195 BIO_puts(bio_err, "Error getting password\n");
196 goto end;
197 }
198 if (outfile) {
199 if (!(out = BIO_new_file(outfile, "wb"))) {
200 BIO_printf(bio_err,
201 "Can't open output file %s\n", outfile);
202 goto end;
203 }
204 } else {
205 out = BIO_new_fp(stdout, BIO_NOCLOSE);
206 }
207
208 EVP_PKEY_CTX_set_cb(ctx, genpkey_cb);
209 EVP_PKEY_CTX_set_app_data(ctx, bio_err);
210
211 if (do_param) {
212 if (EVP_PKEY_paramgen(ctx, &pkey) <= 0) {
213 BIO_puts(bio_err, "Error generating parameters\n");
214 ERR_print_errors(bio_err);
215 goto end;
216 }
217 } else {
218 if (EVP_PKEY_keygen(ctx, &pkey) <= 0) {
219 BIO_puts(bio_err, "Error generating key\n");
220 ERR_print_errors(bio_err);
221 goto end;
222 }
223 }
224
225 if (do_param)
226 rv = PEM_write_bio_Parameters(out, pkey);
227 else if (outformat == FORMAT_PEM)
228 rv = PEM_write_bio_PrivateKey(out, pkey, cipher, NULL, 0,
229 NULL, pass);
230 else if (outformat == FORMAT_ASN1)
231 rv = i2d_PrivateKey_bio(out, pkey);
232 else {
233 BIO_printf(bio_err, "Bad format specified for key\n");
234 goto end;
235 }
236
237 if (rv <= 0) {
238 BIO_puts(bio_err, "Error writing key\n");
239 ERR_print_errors(bio_err);
240 }
241 if (text) {
242 if (do_param)
243 rv = EVP_PKEY_print_params(out, pkey, 0, NULL);
244 else
245 rv = EVP_PKEY_print_private(out, pkey, 0, NULL);
246
247 if (rv <= 0) {
248 BIO_puts(bio_err, "Error printing key\n");
249 ERR_print_errors(bio_err);
250 }
251 }
252 ret = 0;
253
254end:
255 if (pkey)
256 EVP_PKEY_free(pkey);
257 if (ctx)
258 EVP_PKEY_CTX_free(ctx);
259 if (out)
260 BIO_free_all(out);
261 BIO_free(in);
262 free(pass);
263
264 return ret;
265}
266
267static int
268init_keygen_file(BIO * err, EVP_PKEY_CTX ** pctx,
269 const char *file, ENGINE * e)
270{
271 BIO *pbio;
272 EVP_PKEY *pkey = NULL;
273 EVP_PKEY_CTX *ctx = NULL;
274 if (*pctx) {
275 BIO_puts(err, "Parameters already set!\n");
276 return 0;
277 }
278 pbio = BIO_new_file(file, "r");
279 if (!pbio) {
280 BIO_printf(err, "Can't open parameter file %s\n", file);
281 return 0;
282 }
283 pkey = PEM_read_bio_Parameters(pbio, NULL);
284 BIO_free(pbio);
285
286 if (!pkey) {
287 BIO_printf(bio_err, "Error reading parameter file %s\n", file);
288 return 0;
289 }
290 ctx = EVP_PKEY_CTX_new(pkey, e);
291 if (!ctx)
292 goto err;
293 if (EVP_PKEY_keygen_init(ctx) <= 0)
294 goto err;
295 EVP_PKEY_free(pkey);
296 *pctx = ctx;
297 return 1;
298
299err:
300 BIO_puts(err, "Error initializing context\n");
301 ERR_print_errors(err);
302 if (ctx)
303 EVP_PKEY_CTX_free(ctx);
304 if (pkey)
305 EVP_PKEY_free(pkey);
306 return 0;
307
308}
309
310int
311init_gen_str(BIO * err, EVP_PKEY_CTX ** pctx,
312 const char *algname, ENGINE * e, int do_param)
313{
314 EVP_PKEY_CTX *ctx = NULL;
315 const EVP_PKEY_ASN1_METHOD *ameth;
316 ENGINE *tmpeng = NULL;
317 int pkey_id;
318
319 if (*pctx) {
320 BIO_puts(err, "Algorithm already set!\n");
321 return 0;
322 }
323 ameth = EVP_PKEY_asn1_find_str(&tmpeng, algname, -1);
324
325#ifndef OPENSSL_NO_ENGINE
326 if (!ameth && e)
327 ameth = ENGINE_get_pkey_asn1_meth_str(e, algname, -1);
328#endif
329
330 if (!ameth) {
331 BIO_printf(bio_err, "Algorithm %s not found\n", algname);
332 return 0;
333 }
334 ERR_clear_error();
335
336 EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
337#ifndef OPENSSL_NO_ENGINE
338 if (tmpeng)
339 ENGINE_finish(tmpeng);
340#endif
341 ctx = EVP_PKEY_CTX_new_id(pkey_id, e);
342
343 if (!ctx)
344 goto err;
345 if (do_param) {
346 if (EVP_PKEY_paramgen_init(ctx) <= 0)
347 goto err;
348 } else {
349 if (EVP_PKEY_keygen_init(ctx) <= 0)
350 goto err;
351 }
352
353 *pctx = ctx;
354 return 1;
355
356err:
357 BIO_printf(err, "Error initializing %s context\n", algname);
358 ERR_print_errors(err);
359 if (ctx)
360 EVP_PKEY_CTX_free(ctx);
361 return 0;
362
363}
364
365static int
366genpkey_cb(EVP_PKEY_CTX * ctx)
367{
368 char c = '*';
369 BIO *b = EVP_PKEY_CTX_get_app_data(ctx);
370 int p;
371 p = EVP_PKEY_CTX_get_keygen_info(ctx, 0);
372 if (p == 0)
373 c = '.';
374 if (p == 1)
375 c = '+';
376 if (p == 2)
377 c = '*';
378 if (p == 3)
379 c = '\n';
380 BIO_write(b, &c, 1);
381 (void) BIO_flush(b);
382 return 1;
383}