pki: Document correct output formats for --pkcs12 --export
[strongswan.git] / src / pki / commands / pkcs12.c
1 /*
2 * Copyright (C) 2014 Tobias Brunner
3 * 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 }