1: /*
2: * Copyright (C) 2014 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <errno.h>
17:
18: #include "pki.h"
19:
20: #include <credentials/certificates/x509.h>
21: #include <credentials/containers/pkcs12.h>
22:
23: /**
24: * Show info about PKCS#12 container
25: */
26: static int show(pkcs12_t *pkcs12)
27: {
28: enumerator_t *enumerator;
29: certificate_t *cert;
30: private_key_t *key;
31: int index = 1;
32:
33: printf("Certificates:\n");
34: enumerator = pkcs12->create_cert_enumerator(pkcs12);
35: while (enumerator->enumerate(enumerator, &cert))
36: {
37: x509_t *x509 = (x509_t*)cert;
38:
39: if (x509->get_flags(x509) & X509_CA)
40: {
41: printf("[%2d] \"%Y\" (CA)\n", index++, cert->get_subject(cert));
42: }
43: else
44: {
45: printf("[%2d] \"%Y\"\n", index++, cert->get_subject(cert));
46: }
47: }
48: enumerator->destroy(enumerator);
49:
50: printf("Private keys:\n");
51: enumerator = pkcs12->create_key_enumerator(pkcs12);
52: while (enumerator->enumerate(enumerator, &key))
53: {
54: printf("[%2d] %N %d bits\n", index++, key_type_names,
55: key->get_type(key), key->get_keysize(key));
56: }
57: enumerator->destroy(enumerator);
58: return 0;
59: }
60:
61: static int export(pkcs12_t *pkcs12, int index, char *outform)
62: {
63: cred_encoding_type_t form;
64: enumerator_t *enumerator;
65: certificate_t *cert;
66: private_key_t *key;
67: chunk_t encoding;
68: int i = 1;
69:
70: enumerator = pkcs12->create_cert_enumerator(pkcs12);
71: while (enumerator->enumerate(enumerator, &cert))
72: {
73: if (i++ == index)
74: {
75: form = CERT_ASN1_DER;
76: if (outform && !get_form(outform, &form, CRED_CERTIFICATE))
77: {
78: enumerator->destroy(enumerator);
79: return command_usage("invalid output format");
80: }
81: if (cert->get_encoding(cert, form, &encoding))
82: {
83: set_file_mode(stdout, form);
84: if (fwrite(encoding.ptr, encoding.len, 1, stdout) == 1)
85: {
86: free(encoding.ptr);
87: enumerator->destroy(enumerator);
88: return 0;
89: }
90: free(encoding.ptr);
91: }
92: fprintf(stderr, "certificate export failed\n");
93: enumerator->destroy(enumerator);
94: return 1;
95: }
96: }
97: enumerator->destroy(enumerator);
98:
99: enumerator = pkcs12->create_key_enumerator(pkcs12);
100: while (enumerator->enumerate(enumerator, &key))
101: {
102: if (i++ == index)
103: {
104: form = PRIVKEY_ASN1_DER;
105: if (outform && !get_form(outform, &form, CRED_PRIVATE_KEY))
106: {
107: enumerator->destroy(enumerator);
108: return command_usage("invalid output format");
109: }
110: if (key->get_encoding(key, form, &encoding))
111: {
112: set_file_mode(stdout, form);
113: if (fwrite(encoding.ptr, encoding.len, 1, stdout) == 1)
114: {
115: free(encoding.ptr);
116: enumerator->destroy(enumerator);
117: return 0;
118: }
119: free(encoding.ptr);
120: }
121: fprintf(stderr, "private key export failed\n");
122: enumerator->destroy(enumerator);
123: return 0;
124: }
125: }
126: enumerator->destroy(enumerator);
127:
128: fprintf(stderr, "invalid index %d\n", index);
129: return 1;
130: }
131:
132:
133: /**
134: * Handle PKCs#12 containers
135: */
136: static int pkcs12()
137: {
138: char *arg, *file = NULL, *outform = NULL;
139: pkcs12_t *p12 = NULL;
140: int res = 1, index = 0;
141: enum {
142: OP_NONE,
143: OP_LIST,
144: OP_EXPORT,
145: } op = OP_NONE;
146:
147: while (TRUE)
148: {
149: switch (command_getopt(&arg))
150: {
151: case 'h':
152: return command_usage(NULL);
153: case 'i':
154: file = arg;
155: continue;
156: case 'l':
157: if (op != OP_NONE)
158: {
159: goto invalid;
160: }
161: op = OP_LIST;
162: continue;
163: case 'e':
164: if (op != OP_NONE)
165: {
166: goto invalid;
167: }
168: op = OP_EXPORT;
169: index = atoi(arg);
170: continue;
171: case 'f':
172: outform = arg;
173: continue;
174: case EOF:
175: break;
176: default:
177: invalid:
178: return command_usage("invalid --pkcs12 option");
179: }
180: break;
181: }
182:
183: if (file)
184: {
185: p12 = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS12,
186: BUILD_FROM_FILE, file, BUILD_END);
187: }
188: else
189: {
190: chunk_t chunk;
191:
192: set_file_mode(stdin, CERT_ASN1_DER);
193: if (!chunk_from_fd(0, &chunk))
194: {
195: fprintf(stderr, "reading input failed: %s\n", strerror(errno));
196: return 1;
197: }
198: p12 = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS12,
199: BUILD_BLOB, chunk, BUILD_END);
200: free(chunk.ptr);
201: }
202:
203: if (!p12)
204: {
205: fprintf(stderr, "reading input failed!\n");
206: goto end;
207: }
208:
209: switch (op)
210: {
211: case OP_LIST:
212: res = show(p12);
213: break;
214: case OP_EXPORT:
215: res = export(p12, index, outform);
216: break;
217: default:
218: p12->container.destroy(&p12->container);
219: return command_usage(NULL);
220: }
221:
222: end:
223: if (p12)
224: {
225: p12->container.destroy(&p12->container);
226: }
227: return res;
228: }
229:
230: /**
231: * Register the command.
232: */
233: static void __attribute__ ((constructor))reg()
234: {
235: command_register((command_t) {
236: pkcs12, 'u', "pkcs12", "PKCS#12 functions",
237: {"--export index|--list [--in file]",
238: "[--outform der|pem]"},
239: {
240: {"help", 'h', 0, "show usage information"},
241: {"in", 'i', 1, "input file, default: stdin"},
242: {"list", 'l', 0, "list certificates and keys"},
243: {"export", 'e', 1, "export the credential with the given index"},
244: {"outform", 'f', 1, "encoding of exported credentials, default: der"},
245: }
246: });
247: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>