Annotation of src/usr.bin/openssl/pkcs8.c, Revision 1.3
1.3 ! jsing 1: /* $OpenBSD: pkcs8.c,v 1.2 2014/08/28 14:23:52 jsing Exp $ */
1.1 jsing 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:
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: #include <openssl/pkcs12.h>
68:
69: int pkcs8_main(int, char **);
70:
71: int
72: pkcs8_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: informat = FORMAT_PEM;
96: outformat = FORMAT_PEM;
97:
98: args = argv + 1;
99: while (!badarg && *args && *args[0] == '-') {
100: if (!strcmp(*args, "-v2")) {
101: if (args[1]) {
102: args++;
103: cipher = EVP_get_cipherbyname(*args);
104: if (!cipher) {
105: BIO_printf(bio_err,
106: "Unknown cipher %s\n", *args);
107: badarg = 1;
108: }
109: } else
110: badarg = 1;
111: } else if (!strcmp(*args, "-v1")) {
112: if (args[1]) {
113: args++;
114: pbe_nid = OBJ_txt2nid(*args);
115: if (pbe_nid == NID_undef) {
116: BIO_printf(bio_err,
117: "Unknown PBE algorithm %s\n", *args);
118: badarg = 1;
119: }
120: } else
121: badarg = 1;
122: } else if (!strcmp(*args, "-inform")) {
123: if (args[1]) {
124: args++;
125: informat = str2fmt(*args);
126: } else
127: badarg = 1;
128: } else if (!strcmp(*args, "-outform")) {
129: if (args[1]) {
130: args++;
131: outformat = str2fmt(*args);
132: } else
133: badarg = 1;
134: } else if (!strcmp(*args, "-topk8"))
135: topk8 = 1;
136: else if (!strcmp(*args, "-noiter"))
137: iter = 1;
138: else if (!strcmp(*args, "-nocrypt"))
139: nocrypt = 1;
140: else if (!strcmp(*args, "-nooct"))
141: p8_broken = PKCS8_NO_OCTET;
142: else if (!strcmp(*args, "-nsdb"))
143: p8_broken = PKCS8_NS_DB;
144: else if (!strcmp(*args, "-embed"))
145: p8_broken = PKCS8_EMBEDDED_PARAM;
146: else if (!strcmp(*args, "-passin")) {
147: if (!args[1])
148: goto bad;
149: passargin = *(++args);
150: } else if (!strcmp(*args, "-passout")) {
151: if (!args[1])
152: goto bad;
153: passargout = *(++args);
154: }
155: #ifndef OPENSSL_NO_ENGINE
156: else if (strcmp(*args, "-engine") == 0) {
157: if (!args[1])
158: goto bad;
159: engine = *(++args);
160: }
161: #endif
162: else if (!strcmp(*args, "-in")) {
163: if (args[1]) {
164: args++;
165: infile = *args;
166: } else
167: badarg = 1;
168: } else if (!strcmp(*args, "-out")) {
169: if (args[1]) {
170: args++;
171: outfile = *args;
172: } else
173: badarg = 1;
174: } else
175: badarg = 1;
176: args++;
177: }
178:
179: if (badarg) {
180: bad:
181: BIO_printf(bio_err, "Usage pkcs8 [options]\n");
182: BIO_printf(bio_err, "where options are\n");
183: BIO_printf(bio_err, "-in file input file\n");
184: BIO_printf(bio_err, "-inform X input format (DER or PEM)\n");
185: BIO_printf(bio_err, "-passin arg input file pass phrase source\n");
186: BIO_printf(bio_err, "-outform X output format (DER or PEM)\n");
187: BIO_printf(bio_err, "-out file output file\n");
188: BIO_printf(bio_err, "-passout arg output file pass phrase source\n");
189: BIO_printf(bio_err, "-topk8 output PKCS8 file\n");
190: BIO_printf(bio_err, "-nooct use (nonstandard) no octet format\n");
191: BIO_printf(bio_err, "-embed use (nonstandard) embedded DSA parameters format\n");
192: BIO_printf(bio_err, "-nsdb use (nonstandard) DSA Netscape DB format\n");
193: BIO_printf(bio_err, "-noiter use 1 as iteration count\n");
194: BIO_printf(bio_err, "-nocrypt use or expect unencrypted private key\n");
195: BIO_printf(bio_err, "-v2 alg use PKCS#5 v2.0 and cipher \"alg\"\n");
196: BIO_printf(bio_err, "-v1 obj use PKCS#5 v1.5 and cipher \"alg\"\n");
197: #ifndef OPENSSL_NO_ENGINE
198: BIO_printf(bio_err, " -engine e use engine e, possibly a hardware device.\n");
199: #endif
200: goto end;
201: }
202: #ifndef OPENSSL_NO_ENGINE
203: e = setup_engine(bio_err, engine, 0);
204: #endif
205:
206: if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) {
207: BIO_printf(bio_err, "Error getting passwords\n");
208: goto end;
209: }
210: if ((pbe_nid == -1) && !cipher)
211: pbe_nid = NID_pbeWithMD5AndDES_CBC;
212:
213: if (infile) {
214: if (!(in = BIO_new_file(infile, "rb"))) {
215: BIO_printf(bio_err,
216: "Can't open input file %s\n", infile);
217: goto end;
218: }
219: } else
220: in = BIO_new_fp(stdin, BIO_NOCLOSE);
221:
222: if (outfile) {
223: if (!(out = BIO_new_file(outfile, "wb"))) {
224: BIO_printf(bio_err,
225: "Can't open output file %s\n", outfile);
226: goto end;
227: }
228: } else {
229: out = BIO_new_fp(stdout, BIO_NOCLOSE);
230: }
231: if (topk8) {
232: pkey = load_key(bio_err, infile, informat, 1,
233: passin, e, "key");
234: if (!pkey)
235: goto end;
236: if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) {
237: BIO_printf(bio_err, "Error converting key\n");
238: ERR_print_errors(bio_err);
239: goto end;
240: }
241: if (nocrypt) {
242: if (outformat == FORMAT_PEM)
243: PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
244: else if (outformat == FORMAT_ASN1)
245: i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8inf);
246: else {
247: BIO_printf(bio_err, "Bad format specified for key\n");
248: goto end;
249: }
250: } else {
251: if (passout)
252: p8pass = passout;
253: else {
254: p8pass = pass;
255: if (EVP_read_pw_string(pass, sizeof pass, "Enter Encryption Password:", 1))
256: goto end;
257: }
258: if (!(p8 = PKCS8_encrypt(pbe_nid, cipher,
259: p8pass, strlen(p8pass),
260: NULL, 0, iter, p8inf))) {
261: BIO_printf(bio_err, "Error encrypting key\n");
262: ERR_print_errors(bio_err);
263: goto end;
264: }
265: if (outformat == FORMAT_PEM)
266: PEM_write_bio_PKCS8(out, p8);
267: else if (outformat == FORMAT_ASN1)
268: i2d_PKCS8_bio(out, p8);
269: else {
270: BIO_printf(bio_err, "Bad format specified for key\n");
271: goto end;
272: }
273: }
274:
275: ret = 0;
276: goto end;
277: }
278: if (nocrypt) {
279: if (informat == FORMAT_PEM)
280: p8inf = PEM_read_bio_PKCS8_PRIV_KEY_INFO(in, NULL, NULL, NULL);
281: else if (informat == FORMAT_ASN1)
282: p8inf = d2i_PKCS8_PRIV_KEY_INFO_bio(in, NULL);
283: else {
284: BIO_printf(bio_err, "Bad format specified for key\n");
285: goto end;
286: }
287: } else {
288: if (informat == FORMAT_PEM)
289: p8 = PEM_read_bio_PKCS8(in, NULL, NULL, NULL);
290: else if (informat == FORMAT_ASN1)
291: p8 = d2i_PKCS8_bio(in, NULL);
292: else {
293: BIO_printf(bio_err, "Bad format specified for key\n");
294: goto end;
295: }
296:
297: if (!p8) {
298: BIO_printf(bio_err, "Error reading key\n");
299: ERR_print_errors(bio_err);
300: goto end;
301: }
302: if (passin)
303: p8pass = passin;
304: else {
305: p8pass = pass;
306: EVP_read_pw_string(pass, sizeof pass, "Enter Password:", 0);
307: }
308: p8inf = PKCS8_decrypt(p8, p8pass, strlen(p8pass));
309: }
310:
311: if (!p8inf) {
312: BIO_printf(bio_err, "Error decrypting key\n");
313: ERR_print_errors(bio_err);
314: goto end;
315: }
316: if (!(pkey = EVP_PKCS82PKEY(p8inf))) {
317: BIO_printf(bio_err, "Error converting key\n");
318: ERR_print_errors(bio_err);
319: goto end;
320: }
321: if (p8inf->broken) {
322: BIO_printf(bio_err, "Warning: broken key encoding: ");
323: switch (p8inf->broken) {
324: case PKCS8_NO_OCTET:
325: BIO_printf(bio_err, "No Octet String in PrivateKey\n");
326: break;
327:
328: case PKCS8_EMBEDDED_PARAM:
329: BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
330: break;
331:
332: case PKCS8_NS_DB:
333: BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
334: break;
335:
336: case PKCS8_NEG_PRIVKEY:
337: BIO_printf(bio_err, "DSA private key value is negative\n");
338: break;
339:
340: default:
341: BIO_printf(bio_err, "Unknown broken type\n");
342: break;
343: }
344: }
345: if (outformat == FORMAT_PEM)
346: PEM_write_bio_PrivateKey(out, pkey, NULL, NULL, 0, NULL, passout);
347: else if (outformat == FORMAT_ASN1)
348: i2d_PrivateKey_bio(out, pkey);
349: else {
350: BIO_printf(bio_err, "Bad format specified for key\n");
351: goto end;
352: }
353: ret = 0;
354:
355: end:
356: X509_SIG_free(p8);
357: PKCS8_PRIV_KEY_INFO_free(p8inf);
358: EVP_PKEY_free(pkey);
359: BIO_free_all(out);
360: BIO_free(in);
361: free(passin);
362: free(passout);
363:
364: return ret;
365: }