Branch data Line data Source code
1 : : /* pkcs8.c */
2 : : /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 : : * project 1999-2004.
4 : : */
5 : : /* ====================================================================
6 : : * Copyright (c) 1999 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 : : #include <stdio.h>
59 : : #include <stdlib.h>
60 : : #include <string.h>
61 : : #include "apps.h"
62 : : #include <openssl/pem.h>
63 : : #include <openssl/err.h>
64 : : #include <openssl/evp.h>
65 : : #include <openssl/pkcs12.h>
66 : :
67 : : #define PROG pkcs8_main
68 : :
69 : : int MAIN(int, char **);
70 : :
71 : 0 : int MAIN(int argc, char **argv)
72 : : {
73 : 0 : ENGINE *e = NULL;
74 : 0 : char **args, *infile = NULL, *outfile = NULL;
75 : 0 : char *passargin = NULL, *passargout = NULL;
76 : 0 : BIO *in = NULL, *out = NULL;
77 : 0 : int topk8 = 0;
78 : 0 : int pbe_nid = -1;
79 : 0 : const EVP_CIPHER *cipher = NULL;
80 : 0 : int iter = PKCS12_DEFAULT_ITER;
81 : : int informat, outformat;
82 : 0 : int p8_broken = PKCS8_OK;
83 : 0 : int nocrypt = 0;
84 : 0 : X509_SIG *p8 = NULL;
85 : 0 : PKCS8_PRIV_KEY_INFO *p8inf = NULL;
86 : 0 : EVP_PKEY *pkey=NULL;
87 : 0 : char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL;
88 : 0 : int badarg = 0;
89 : 0 : int ret = 1;
90 : : #ifndef OPENSSL_NO_ENGINE
91 : 0 : char *engine=NULL;
92 : : #endif
93 : :
94 [ # # ]: 0 : if (bio_err == NULL) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE);
95 : :
96 [ # # ]: 0 : if (!load_config(bio_err, NULL))
97 : : goto end;
98 : :
99 : 0 : informat=FORMAT_PEM;
100 : 0 : outformat=FORMAT_PEM;
101 : :
102 : 0 : ERR_load_crypto_strings();
103 : 0 : OpenSSL_add_all_algorithms();
104 : 0 : args = argv + 1;
105 [ # # ][ # # ]: 0 : while (!badarg && *args && *args[0] == '-')
[ # # ]
106 : : {
107 [ # # ]: 0 : if (!strcmp(*args,"-v2"))
108 : : {
109 [ # # ]: 0 : if (args[1])
110 : : {
111 : 0 : args++;
112 : 0 : cipher=EVP_get_cipherbyname(*args);
113 [ # # ]: 0 : if (!cipher)
114 : : {
115 : 0 : BIO_printf(bio_err,
116 : : "Unknown cipher %s\n", *args);
117 : 0 : badarg = 1;
118 : : }
119 : : }
120 : : else
121 : : badarg = 1;
122 : : }
123 [ # # ]: 0 : else if (!strcmp(*args,"-v1"))
124 : : {
125 [ # # ]: 0 : if (args[1])
126 : : {
127 : 0 : args++;
128 : 0 : pbe_nid=OBJ_txt2nid(*args);
129 [ # # ]: 0 : if (pbe_nid == NID_undef)
130 : : {
131 : 0 : BIO_printf(bio_err,
132 : : "Unknown PBE algorithm %s\n", *args);
133 : 0 : badarg = 1;
134 : : }
135 : : }
136 : : else
137 : : badarg = 1;
138 : : }
139 [ # # ]: 0 : else if (!strcmp(*args,"-v2prf"))
140 : : {
141 [ # # ]: 0 : if (args[1])
142 : : {
143 : 0 : args++;
144 : 0 : pbe_nid=OBJ_txt2nid(*args);
145 [ # # ]: 0 : if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0))
146 : : {
147 : 0 : BIO_printf(bio_err,
148 : : "Unknown PRF algorithm %s\n", *args);
149 : 0 : badarg = 1;
150 : : }
151 : : }
152 : : else
153 : : badarg = 1;
154 : : }
155 [ # # ]: 0 : else if (!strcmp(*args,"-inform"))
156 : : {
157 [ # # ]: 0 : if (args[1])
158 : : {
159 : 0 : args++;
160 : 0 : informat=str2fmt(*args);
161 : : }
162 : : else badarg = 1;
163 : : }
164 [ # # ]: 0 : else if (!strcmp(*args,"-outform"))
165 : : {
166 [ # # ]: 0 : if (args[1])
167 : : {
168 : 0 : args++;
169 : 0 : outformat=str2fmt(*args);
170 : : }
171 : : else badarg = 1;
172 : : }
173 [ # # ]: 0 : else if (!strcmp (*args, "-topk8"))
174 : : topk8 = 1;
175 [ # # ]: 0 : else if (!strcmp (*args, "-noiter"))
176 : : iter = 1;
177 [ # # ]: 0 : else if (!strcmp (*args, "-iter"))
178 : : {
179 [ # # ]: 0 : if (args[1])
180 : : {
181 : 0 : iter = atoi(*(++args));
182 [ # # ]: 0 : if (iter <= 0) badarg = 1;
183 : : }
184 : : else badarg = 1;
185 : : }
186 [ # # ]: 0 : else if (!strcmp (*args, "-nocrypt"))
187 : : nocrypt = 1;
188 [ # # ]: 0 : else if (!strcmp (*args, "-nooct"))
189 : : p8_broken = PKCS8_NO_OCTET;
190 [ # # ]: 0 : else if (!strcmp (*args, "-nsdb"))
191 : : p8_broken = PKCS8_NS_DB;
192 [ # # ]: 0 : else if (!strcmp (*args, "-embed"))
193 : : p8_broken = PKCS8_EMBEDDED_PARAM;
194 [ # # ]: 0 : else if (!strcmp(*args,"-passin"))
195 : : {
196 [ # # ]: 0 : if (args[1])
197 : 0 : passargin= *(++args);
198 : : else badarg = 1;
199 : : }
200 [ # # ]: 0 : else if (!strcmp(*args,"-passout"))
201 : : {
202 [ # # ]: 0 : if (args[1])
203 : 0 : passargout= *(++args);
204 : : else badarg = 1;
205 : : }
206 : : #ifndef OPENSSL_NO_ENGINE
207 [ # # ]: 0 : else if (strcmp(*args,"-engine") == 0)
208 : : {
209 [ # # ]: 0 : if (args[1])
210 : 0 : engine= *(++args);
211 : : else badarg = 1;
212 : : }
213 : : #endif
214 [ # # ]: 0 : else if (!strcmp (*args, "-in"))
215 : : {
216 [ # # ]: 0 : if (args[1])
217 : : {
218 : 0 : args++;
219 : 0 : infile = *args;
220 : : }
221 : : else badarg = 1;
222 : : }
223 [ # # ]: 0 : else if (!strcmp (*args, "-out"))
224 : : {
225 [ # # ]: 0 : if (args[1])
226 : : {
227 : 0 : args++;
228 : 0 : outfile = *args;
229 : : }
230 : : else badarg = 1;
231 : : }
232 : : else badarg = 1;
233 : 0 : args++;
234 : : }
235 : :
236 [ # # ]: 0 : if (badarg)
237 : : {
238 : 0 : BIO_printf(bio_err, "Usage pkcs8 [options]\n");
239 : 0 : BIO_printf(bio_err, "where options are\n");
240 : 0 : BIO_printf(bio_err, "-in file input file\n");
241 : 0 : BIO_printf(bio_err, "-inform X input format (DER or PEM)\n");
242 : 0 : BIO_printf(bio_err, "-passin arg input file pass phrase source\n");
243 : 0 : BIO_printf(bio_err, "-outform X output format (DER or PEM)\n");
244 : 0 : BIO_printf(bio_err, "-out file output file\n");
245 : 0 : BIO_printf(bio_err, "-passout arg output file pass phrase source\n");
246 : 0 : BIO_printf(bio_err, "-topk8 output PKCS8 file\n");
247 : 0 : BIO_printf(bio_err, "-nooct use (nonstandard) no octet format\n");
248 : 0 : BIO_printf(bio_err, "-embed use (nonstandard) embedded DSA parameters format\n");
249 : 0 : BIO_printf(bio_err, "-nsdb use (nonstandard) DSA Netscape DB format\n");
250 : 0 : BIO_printf(bio_err, "-iter count use count as iteration count\n");
251 : 0 : BIO_printf(bio_err, "-noiter use 1 as iteration count\n");
252 : 0 : BIO_printf(bio_err, "-nocrypt use or expect unencrypted private key\n");
253 : 0 : BIO_printf(bio_err, "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n");
254 : 0 : BIO_printf(bio_err, "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n");
255 : : #ifndef OPENSSL_NO_ENGINE
256 : 0 : BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n");
257 : : #endif
258 : 0 : goto end;
259 : : }
260 : :
261 : : #ifndef OPENSSL_NO_ENGINE
262 : 0 : e = setup_engine(bio_err, engine, 0);
263 : : #endif
264 : :
265 [ # # ]: 0 : if (!app_passwd(bio_err, passargin, passargout, &passin, &passout))
266 : : {
267 : 0 : BIO_printf(bio_err, "Error getting passwords\n");
268 : 0 : goto end;
269 : : }
270 : :
271 [ # # ]: 0 : if ((pbe_nid == -1) && !cipher)
272 : 0 : pbe_nid = NID_pbeWithMD5AndDES_CBC;
273 : :
274 [ # # ]: 0 : if (infile)
275 : : {
276 [ # # ]: 0 : if (!(in = BIO_new_file(infile, "rb")))
277 : : {
278 : 0 : BIO_printf(bio_err,
279 : : "Can't open input file %s\n", infile);
280 : 0 : goto end;
281 : : }
282 : : }
283 : : else
284 : 0 : in = BIO_new_fp (stdin, BIO_NOCLOSE);
285 : :
286 [ # # ]: 0 : if (outfile)
287 : : {
288 [ # # ]: 0 : if (!(out = BIO_new_file (outfile, "wb")))
289 : : {
290 : 0 : BIO_printf(bio_err,
291 : : "Can't open output file %s\n", outfile);
292 : 0 : goto end;
293 : : }
294 : : }
295 : : else
296 : : {
297 : 0 : out = BIO_new_fp (stdout, BIO_NOCLOSE);
298 : : #ifdef OPENSSL_SYS_VMS
299 : : {
300 : : BIO *tmpbio = BIO_new(BIO_f_linebuffer());
301 : : out = BIO_push(tmpbio, out);
302 : : }
303 : : #endif
304 : : }
305 [ # # ]: 0 : if (topk8)
306 : : {
307 : 0 : pkey = load_key(bio_err, infile, informat, 1,
308 : : passin, e, "key");
309 [ # # ]: 0 : if (!pkey)
310 : : goto end;
311 [ # # ]: 0 : if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken)))
312 : : {
313 : 0 : BIO_printf(bio_err, "Error converting key\n");
314 : 0 : ERR_print_errors(bio_err);
315 : 0 : goto end;
316 : : }
317 [ # # ]: 0 : if (nocrypt)
318 : : {
319 [ # # ]: 0 : if (outformat == FORMAT_PEM)
320 : 0 : PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
321 [ # # ]: 0 : else if (outformat == FORMAT_ASN1)
322 : 0 : i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
323 : : else
324 : : {
325 : 0 : BIO_printf(bio_err, "Bad format specified for key\n");
326 : 0 : goto end;
327 : : }
328 : : }
329 : : else
330 : : {
331 [ # # ]: 0 : if (passout)
332 : : p8pass = passout;
333 : : else
334 : : {
335 : 0 : p8pass = pass;
336 [ # # ]: 0 : if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1))
337 : : goto end;
338 : : }
339 : 0 : app_RAND_load_file(NULL, bio_err, 0);
340 [ # # ]: 0 : if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
341 : 0 : p8pass, strlen(p8pass),
342 : : NULL, 0, iter, p8inf)))
343 : : {
344 : 0 : BIO_printf(bio_err, "Error encrypting key\n");
345 : 0 : ERR_print_errors(bio_err);
346 : 0 : goto end;
347 : : }
348 : 0 : app_RAND_write_file(NULL, bio_err);
349 [ # # ]: 0 : if (outformat == FORMAT_PEM)
350 : 0 : PEM_write_bio_PKCS8(out, p8);
351 [ # # ]: 0 : else if (outformat == FORMAT_ASN1)
352 : 0 : i2d_PKCS8_bio(out, p8);
353 : : else
354 : : {
355 : 0 : BIO_printf(bio_err, "Bad format specified for key\n");
356 : 0 : goto end;
357 : : }
358 : : }
359 : :
360 : : ret = 0;
361 : : goto end;
362 : : }
363 : :
364 [ # # ]: 0 : if (nocrypt)
365 : : {
366 [ # # ]: 0 : if (informat == FORMAT_PEM)
367 : 0 : p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in,NULL,NULL, NULL);
368 [ # # ]: 0 : else if (informat == FORMAT_ASN1)
369 : 0 : p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
370 : : else
371 : : {
372 : 0 : BIO_printf(bio_err, "Bad format specified for key\n");
373 : 0 : goto end;
374 : : }
375 : : }
376 : : else
377 : : {
378 [ # # ]: 0 : if (informat == FORMAT_PEM)
379 : 0 : p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
380 [ # # ]: 0 : else if (informat == FORMAT_ASN1)
381 : 0 : p8 = d2i_PKCS8_bio(in, NULL);
382 : : else
383 : : {
384 : 0 : BIO_printf(bio_err, "Bad format specified for key\n");
385 : 0 : goto end;
386 : : }
387 : :
388 [ # # ]: 0 : if (!p8)
389 : : {
390 : 0 : BIO_printf (bio_err, "Error reading key\n");
391 : 0 : ERR_print_errors(bio_err);
392 : 0 : goto end;
393 : : }
394 [ # # ]: 0 : if (passin)
395 : : p8pass = passin;
396 : : else
397 : : {
398 : 0 : p8pass = pass;
399 : 0 : EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
400 : : }
401 : 0 : p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
402 : : }
403 : :
404 [ # # ]: 0 : if (!p8inf)
405 : : {
406 : 0 : BIO_printf(bio_err, "Error decrypting key\n");
407 : 0 : ERR_print_errors(bio_err);
408 : 0 : goto end;
409 : : }
410 : :
411 [ # # ]: 0 : if (!(pkey = EVP_PKCS82PKEY(p8inf)))
412 : : {
413 : 0 : BIO_printf(bio_err, "Error converting key\n");
414 : 0 : ERR_print_errors(bio_err);
415 : 0 : goto end;
416 : : }
417 : :
418 [ # # ]: 0 : if (p8inf->broken)
419 : : {
420 : 0 : BIO_printf(bio_err, "Warning: broken key encoding: ");
421 [ # # # # : 0 : switch (p8inf->broken)
# ]
422 : : {
423 : : case PKCS8_NO_OCTET:
424 : 0 : BIO_printf(bio_err, "No Octet String in PrivateKey\n");
425 : 0 : break;
426 : :
427 : : case PKCS8_EMBEDDED_PARAM:
428 : 0 : BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
429 : 0 : break;
430 : :
431 : : case PKCS8_NS_DB:
432 : 0 : BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
433 : 0 : break;
434 : :
435 : : case PKCS8_NEG_PRIVKEY:
436 : 0 : BIO_printf(bio_err, "DSA private key value is negative\n");
437 : 0 : break;
438 : :
439 : : default:
440 : 0 : BIO_printf(bio_err, "Unknown broken type\n");
441 : 0 : break;
442 : : }
443 : : }
444 : :
445 [ # # ]: 0 : if (outformat == FORMAT_PEM)
446 : 0 : PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
447 [ # # ]: 0 : else if (outformat == FORMAT_ASN1)
448 : 0 : i2d_PrivateKey_bio(out, pkey);
449 : : else
450 : : {
451 : 0 : BIO_printf(bio_err, "Bad format specified for key\n");
452 : 0 : goto end;
453 : : }
454 : : ret = 0;
455 : :
456 : : end:
457 : 0 : X509_SIG_free(p8);
458 : 0 : PKCS8_PRIV_KEY_INFO_free(p8inf);
459 : 0 : EVP_PKEY_free(pkey);
460 : 0 : BIO_free_all(out);
461 : 0 : BIO_free(in);
462 [ # # ]: 0 : if (passin)
463 : 0 : OPENSSL_free(passin);
464 [ # # ]: 0 : if (passout)
465 : 0 : OPENSSL_free(passout);
466 : :
467 : 0 : return ret;
468 : : }
|