Appease clang -Wshadow
[openssl.git] / apps / pkcs8.c
1 /* pkcs8.c */
2 /*
3  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
4  * 1999-2004.
5  */
6 /* ====================================================================
7  * Copyright (c) 1999 The OpenSSL Project.  All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in
18  *    the documentation and/or other materials provided with the
19  *    distribution.
20  *
21  * 3. All advertising materials mentioning features or use of this
22  *    software must display the following acknowledgment:
23  *    "This product includes software developed by the OpenSSL Project
24  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
25  *
26  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
27  *    endorse or promote products derived from this software without
28  *    prior written permission. For written permission, please contact
29  *    licensing@OpenSSL.org.
30  *
31  * 5. Products derived from this software may not be called "OpenSSL"
32  *    nor may "OpenSSL" appear in their names without prior written
33  *    permission of the OpenSSL Project.
34  *
35  * 6. Redistributions of any form whatsoever must retain the following
36  *    acknowledgment:
37  *    "This product includes software developed by the OpenSSL Project
38  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
41  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
43  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
46  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
47  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
49  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
51  * OF THE POSSIBILITY OF SUCH DAMAGE.
52  * ====================================================================
53  *
54  * This product includes cryptographic software written by Eric Young
55  * (eay@cryptsoft.com).  This product includes software written by Tim
56  * Hudson (tjh@cryptsoft.com).
57  *
58  */
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include "apps.h"
63 #include <openssl/pem.h>
64 #include <openssl/err.h>
65 #include <openssl/evp.h>
66 #include <openssl/pkcs12.h>
67
68 #define PROG pkcs8_main
69
70 int MAIN(int, char **);
71
72 int MAIN(int argc, char **argv)
73 {
74     ENGINE *e = NULL;
75     char **args, *infile = NULL, *outfile = NULL;
76     char *passargin = NULL, *passargout = NULL;
77     BIO *in = NULL, *out = NULL;
78     int topk8 = 0;
79     int pbe_nid = -1;
80     const EVP_CIPHER *cipher = NULL;
81     int iter = PKCS12_DEFAULT_ITER;
82     int informat, outformat;
83     int p8_broken = PKCS8_OK;
84     int nocrypt = 0;
85     X509_SIG *p8 = NULL;
86     PKCS8_PRIV_KEY_INFO *p8inf = NULL;
87     EVP_PKEY *pkey = NULL;
88     char pass[50], *passin = NULL, *passout = NULL, *p8pass = NULL;
89     int badarg = 0;
90     int ret = 1;
91 #ifndef OPENSSL_NO_ENGINE
92     char *engine = NULL;
93 #endif
94
95     if (bio_err == NULL)
96         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
97
98     if (!load_config(bio_err, NULL))
99         goto end;
100
101     informat = FORMAT_PEM;
102     outformat = FORMAT_PEM;
103
104     ERR_load_crypto_strings();
105     OpenSSL_add_all_algorithms();
106     args = argv + 1;
107     while (!badarg && *args && *args[0] == '-') {
108         if (!strcmp(*args, "-v2")) {
109             if (args[1]) {
110                 args++;
111                 cipher = EVP_get_cipherbyname(*args);
112                 if (!cipher) {
113                     BIO_printf(bio_err, "Unknown cipher %s\n", *args);
114                     badarg = 1;
115                 }
116             } else
117                 badarg = 1;
118         } else if (!strcmp(*args, "-v1")) {
119             if (args[1]) {
120                 args++;
121                 pbe_nid = OBJ_txt2nid(*args);
122                 if (pbe_nid == NID_undef) {
123                     BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args);
124                     badarg = 1;
125                 }
126             } else
127                 badarg = 1;
128         } else if (!strcmp(*args, "-v2prf")) {
129             if (args[1]) {
130                 args++;
131                 pbe_nid = OBJ_txt2nid(*args);
132                 if (!EVP_PBE_find(EVP_PBE_TYPE_PRF, pbe_nid, NULL, NULL, 0)) {
133                     BIO_printf(bio_err, "Unknown PRF algorithm %s\n", *args);
134                     badarg = 1;
135                 }
136             } else
137                 badarg = 1;
138         } else if (!strcmp(*args, "-inform")) {
139             if (args[1]) {
140                 args++;
141                 informat = str2fmt(*args);
142             } else
143                 badarg = 1;
144         } else if (!strcmp(*args, "-outform")) {
145             if (args[1]) {
146                 args++;
147                 outformat = str2fmt(*args);
148             } else
149                 badarg = 1;
150         } else if (!strcmp(*args, "-topk8"))
151             topk8 = 1;
152         else if (!strcmp(*args, "-noiter"))
153             iter = 1;
154         else if (!strcmp(*args, "-iter")) {
155             if (args[1]) {
156                 iter = atoi(*(++args));
157                 if (iter <= 0)
158                     badarg = 1;
159             } else
160                 badarg = 1;
161         } else if (!strcmp(*args, "-nocrypt"))
162             nocrypt = 1;
163         else if (!strcmp(*args, "-nooct"))
164             p8_broken = PKCS8_NO_OCTET;
165         else if (!strcmp(*args, "-nsdb"))
166             p8_broken = PKCS8_NS_DB;
167         else if (!strcmp(*args, "-embed"))
168             p8_broken = PKCS8_EMBEDDED_PARAM;
169         else if (!strcmp(*args, "-passin")) {
170             if (args[1])
171                 passargin = *(++args);
172             else
173                 badarg = 1;
174         } else if (!strcmp(*args, "-passout")) {
175             if (args[1])
176                 passargout = *(++args);
177             else
178                 badarg = 1;
179         }
180 #ifndef OPENSSL_NO_ENGINE
181         else if (strcmp(*args, "-engine") == 0) {
182             if (args[1])
183                 engine = *(++args);
184             else
185                 badarg = 1;
186         }
187 #endif
188         else if (!strcmp(*args, "-in")) {
189             if (args[1]) {
190                 args++;
191                 infile = *args;
192             } else
193                 badarg = 1;
194         } else if (!strcmp(*args, "-out")) {
195             if (args[1]) {
196                 args++;
197                 outfile = *args;
198             } else
199                 badarg = 1;
200         } else
201             badarg = 1;
202         args++;
203     }
204
205     if (badarg) {
206         BIO_printf(bio_err, "Usage pkcs8 [options]\n");
207         BIO_printf(bio_err, "where options are\n");
208         BIO_printf(bio_err, "-in file        input file\n");
209         BIO_printf(bio_err, "-inform X       input format (DER or PEM)\n");
210         BIO_printf(bio_err,
211                    "-passin arg     input file pass phrase source\n");
212         BIO_printf(bio_err, "-outform X      output format (DER or PEM)\n");
213         BIO_printf(bio_err, "-out file       output file\n");
214         BIO_printf(bio_err,
215                    "-passout arg    output file pass phrase source\n");
216         BIO_printf(bio_err, "-topk8          output PKCS8 file\n");
217         BIO_printf(bio_err,
218                    "-nooct          use (nonstandard) no octet format\n");
219         BIO_printf(bio_err,
220                    "-embed          use (nonstandard) embedded DSA parameters format\n");
221         BIO_printf(bio_err,
222                    "-nsdb           use (nonstandard) DSA Netscape DB format\n");
223         BIO_printf(bio_err, "-iter count     use count as iteration count\n");
224         BIO_printf(bio_err, "-noiter         use 1 as iteration count\n");
225         BIO_printf(bio_err,
226                    "-nocrypt        use or expect unencrypted private key\n");
227         BIO_printf(bio_err,
228                    "-v2 alg         use PKCS#5 v2.0 and cipher \"alg\"\n");
229         BIO_printf(bio_err,
230                    "-v1 obj         use PKCS#5 v1.5 and cipher \"alg\"\n");
231 #ifndef OPENSSL_NO_ENGINE
232         BIO_printf(bio_err,
233                    " -engine e       use engine e, possibly a hardware device.\n");
234 #endif
235         goto end;
236     }
237 #ifndef OPENSSL_NO_ENGINE
238     e = setup_engine(bio_err, engine, 0);
239 #endif
240
241     if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
242         BIO_printf(bio_err, "Error getting passwords\n");
243         goto end;
244     }
245
246     if ((pbe_nid == -1) && !cipher)
247         pbe_nid = NID_pbeWithMD5AndDES_CBC;
248
249     if (infile) {
250         if (!(in = BIO_new_file(infile, "rb"))) {
251             BIO_printf(bio_err, "Can't open input file %s\n", infile);
252             goto end;
253         }
254     } else
255         in = BIO_new_fp(stdin, BIO_NOCLOSE);
256
257     if (outfile) {
258         if (!(out = BIO_new_file(outfile, "wb"))) {
259             BIO_printf(bio_err, "Can't open output file %s\n", outfile);
260             goto end;
261         }
262     } else {
263         out = BIO_new_fp(stdout, BIO_NOCLOSE);
264 #ifdef OPENSSL_SYS_VMS
265         {
266             BIO *tmpbio = BIO_new(BIO_f_linebuffer());
267             out = BIO_push(tmpbio, out);
268         }
269 #endif
270     }
271     if (topk8) {
272         pkey = load_key(bio_err, infile, informat, 1, passin, e, "key");
273         if (!pkey)
274             goto end;
275         if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) {
276             BIO_printf(bio_err, "Error converting key\n");
277             ERR_print_errors(bio_err);
278             goto end;
279         }
280         if (nocrypt) {
281             if (outformat == FORMAT_PEM)
282                 PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
283             else if (outformat == FORMAT_ASN1)
284                 i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
285             else {
286                 BIO_printf(bio_err, "Bad format specified for key\n");
287                 goto end;
288             }
289         } else {
290             if (passout)
291                 p8pass = passout;
292             else {
293                 p8pass = pass;
294                 if (EVP_read_pw_string
295                     (pass, sizeof pass, "Enter Encryption Password:", 1))
296                     goto end;
297             }
298             app_RAND_load_file(NULL, bio_err, 0);
299             if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
300                                      p8pass, strlen(p8pass),
301                                      NULL, 0, iter, p8inf))) {
302                 BIO_printf(bio_err, "Error encrypting key\n");
303                 ERR_print_errors(bio_err);
304                 goto end;
305             }
306             app_RAND_write_file(NULL, bio_err);
307             if (outformat == FORMAT_PEM)
308                 PEM_write_bio_PKCS8(out, p8);
309             else if (outformat == FORMAT_ASN1)
310                 i2d_PKCS8_bio(out, p8);
311             else {
312                 BIO_printf(bio_err, "Bad format specified for key\n");
313                 goto end;
314             }
315         }
316
317         ret = 0;
318         goto end;
319     }
320
321     if (nocrypt) {
322         if (informat == FORMAT_PEM)
323             p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
324         else if (informat == FORMAT_ASN1)
325             p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
326         else {
327             BIO_printf(bio_err, "Bad format specified for key\n");
328             goto end;
329         }
330     } else {
331         if (informat == FORMAT_PEM)
332             p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
333         else if (informat == FORMAT_ASN1)
334             p8 = d2i_PKCS8_bio(in, NULL);
335         else {
336             BIO_printf(bio_err, "Bad format specified for key\n");
337             goto end;
338         }
339
340         if (!p8) {
341             BIO_printf(bio_err, "Error reading key\n");
342             ERR_print_errors(bio_err);
343             goto end;
344         }
345         if (passin)
346             p8pass = passin;
347         else {
348             p8pass = pass;
349             EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
350         }
351         p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
352     }
353
354     if (!p8inf) {
355         BIO_printf(bio_err, "Error decrypting key\n");
356         ERR_print_errors(bio_err);
357         goto end;
358     }
359
360     if (!(pkey = EVP_PKCS82PKEY(p8inf))) {
361         BIO_printf(bio_err, "Error converting key\n");
362         ERR_print_errors(bio_err);
363         goto end;
364     }
365
366     if (p8inf->broken) {
367         BIO_printf(bio_err, "Warning: broken key encoding: ");
368         switch (p8inf->broken) {
369         case PKCS8_NO_OCTET:
370             BIO_printf(bio_err, "No Octet String in PrivateKey\n");
371             break;
372
373         case PKCS8_EMBEDDED_PARAM:
374             BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
375             break;
376
377         case PKCS8_NS_DB:
378             BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
379             break;
380
381         case PKCS8_NEG_PRIVKEY:
382             BIO_printf(bio_err, "DSA private key value is negative\n");
383             break;
384
385         default:
386             BIO_printf(bio_err, "Unknown broken type\n");
387             break;
388         }
389     }
390
391     if (outformat == FORMAT_PEM)
392         PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
393     else if (outformat == FORMAT_ASN1)
394         i2d_PrivateKey_bio(out, pkey);
395     else {
396         BIO_printf(bio_err, "Bad format specified for key\n");
397         goto end;
398     }
399     ret = 0;
400
401  end:
402     X509_SIG_free(p8);
403     PKCS8_PRIV_KEY_INFO_free(p8inf);
404     EVP_PKEY_free(pkey);
405     BIO_free_all(out);
406     BIO_free(in);
407     if (passin)
408         OPENSSL_free(passin);
409     if (passout)
410         OPENSSL_free(passout);
411
412     return ret;
413 }