diff options
author | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
---|---|---|
committer | cvs2svn <admin@example.com> | 2025-04-14 17:32:06 +0000 |
commit | eb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch) | |
tree | edb6da6af7e865d488dc1a29309f1e1ec226e603 /src/usr.bin/openssl/pkcs12.c | |
parent | 247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff) | |
download | openbsd-tb_20250414.tar.gz openbsd-tb_20250414.tar.bz2 openbsd-tb_20250414.zip |
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/usr.bin/openssl/pkcs12.c')
-rw-r--r-- | src/usr.bin/openssl/pkcs12.c | 1124 |
1 files changed, 0 insertions, 1124 deletions
diff --git a/src/usr.bin/openssl/pkcs12.c b/src/usr.bin/openssl/pkcs12.c deleted file mode 100644 index 1407a96e03..0000000000 --- a/src/usr.bin/openssl/pkcs12.c +++ /dev/null | |||
@@ -1,1124 +0,0 @@ | |||
1 | /* $OpenBSD: pkcs12.c,v 1.29 2024/12/26 14:10:48 tb Exp $ */ | ||
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | ||
3 | * project. | ||
4 | */ | ||
5 | /* ==================================================================== | ||
6 | * Copyright (c) 1999-2006 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 <openssl/opensslconf.h> | ||
60 | |||
61 | #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) | ||
62 | |||
63 | #include <stdio.h> | ||
64 | #include <stdlib.h> | ||
65 | #include <string.h> | ||
66 | |||
67 | #include "apps.h" | ||
68 | |||
69 | #include <openssl/crypto.h> | ||
70 | #include <openssl/err.h> | ||
71 | #include <openssl/pem.h> | ||
72 | #include <openssl/pkcs12.h> | ||
73 | #include <openssl/x509.h> | ||
74 | |||
75 | #define NOKEYS 0x1 | ||
76 | #define NOCERTS 0x2 | ||
77 | #define INFO 0x4 | ||
78 | #define CLCERTS 0x8 | ||
79 | #define CACERTS 0x10 | ||
80 | |||
81 | static int get_cert_chain(X509 *cert, X509_STORE *store, | ||
82 | STACK_OF(X509) **chain); | ||
83 | static int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, | ||
84 | int options, char *pempass); | ||
85 | static int dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, | ||
86 | char *pass, int passlen, int options, char *pempass); | ||
87 | static int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, | ||
88 | int passlen, int options, char *pempass); | ||
89 | static int print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, | ||
90 | const char *name); | ||
91 | static void hex_prin(BIO *out, unsigned char *buf, int len); | ||
92 | static int alg_print(BIO *x, const X509_ALGOR *alg); | ||
93 | static int set_pbe(BIO *err, int *ppbe, const char *str); | ||
94 | |||
95 | static struct { | ||
96 | char *CAfile; | ||
97 | STACK_OF(OPENSSL_STRING) *canames; | ||
98 | char *CApath; | ||
99 | int cert_pbe; | ||
100 | char *certfile; | ||
101 | int chain; | ||
102 | const EVP_CIPHER *enc; | ||
103 | int export_cert; | ||
104 | int key_pbe; | ||
105 | char *keyname; | ||
106 | int keytype; | ||
107 | char *infile; | ||
108 | int iter; | ||
109 | char *macalg; | ||
110 | int maciter; | ||
111 | int macver; | ||
112 | char *name; | ||
113 | int noprompt; | ||
114 | int options; | ||
115 | char *outfile; | ||
116 | char *passarg; | ||
117 | char *passargin; | ||
118 | char *passargout; | ||
119 | int twopass; | ||
120 | } cfg; | ||
121 | |||
122 | static int | ||
123 | pkcs12_opt_canames(char *arg) | ||
124 | { | ||
125 | if (cfg.canames == NULL && | ||
126 | (cfg.canames = sk_OPENSSL_STRING_new_null()) == NULL) | ||
127 | return (1); | ||
128 | |||
129 | if (!sk_OPENSSL_STRING_push(cfg.canames, arg)) | ||
130 | return (1); | ||
131 | |||
132 | return (0); | ||
133 | } | ||
134 | |||
135 | static int | ||
136 | pkcs12_opt_cert_pbe(char *arg) | ||
137 | { | ||
138 | return (!set_pbe(bio_err, &cfg.cert_pbe, arg)); | ||
139 | } | ||
140 | |||
141 | static int | ||
142 | pkcs12_opt_key_pbe(char *arg) | ||
143 | { | ||
144 | return (!set_pbe(bio_err, &cfg.key_pbe, arg)); | ||
145 | } | ||
146 | |||
147 | static int | ||
148 | pkcs12_opt_passarg(char *arg) | ||
149 | { | ||
150 | cfg.passarg = arg; | ||
151 | cfg.noprompt = 1; | ||
152 | return (0); | ||
153 | } | ||
154 | |||
155 | static const EVP_CIPHER *get_cipher_by_name(char *name) | ||
156 | { | ||
157 | if (name == NULL || strcmp(name, "") == 0) | ||
158 | return (NULL); | ||
159 | #ifndef OPENSSL_NO_AES | ||
160 | else if (strcmp(name, "aes128") == 0) | ||
161 | return EVP_aes_128_cbc(); | ||
162 | else if (strcmp(name, "aes192") == 0) | ||
163 | return EVP_aes_192_cbc(); | ||
164 | else if (strcmp(name, "aes256") == 0) | ||
165 | return EVP_aes_256_cbc(); | ||
166 | #endif | ||
167 | #ifndef OPENSSL_NO_CAMELLIA | ||
168 | else if (strcmp(name, "camellia128") == 0) | ||
169 | return EVP_camellia_128_cbc(); | ||
170 | else if (strcmp(name, "camellia192") == 0) | ||
171 | return EVP_camellia_192_cbc(); | ||
172 | else if (strcmp(name, "camellia256") == 0) | ||
173 | return EVP_camellia_256_cbc(); | ||
174 | #endif | ||
175 | #ifndef OPENSSL_NO_DES | ||
176 | else if (strcmp(name, "des") == 0) | ||
177 | return EVP_des_cbc(); | ||
178 | else if (strcmp(name, "des3") == 0) | ||
179 | return EVP_des_ede3_cbc(); | ||
180 | #endif | ||
181 | #ifndef OPENSSL_NO_IDEA | ||
182 | else if (strcmp(name, "idea") == 0) | ||
183 | return EVP_idea_cbc(); | ||
184 | #endif | ||
185 | else | ||
186 | return (NULL); | ||
187 | } | ||
188 | |||
189 | static int | ||
190 | pkcs12_opt_enc(int argc, char **argv, int *argsused) | ||
191 | { | ||
192 | char *name = argv[0]; | ||
193 | |||
194 | if (*name++ != '-') | ||
195 | return (1); | ||
196 | |||
197 | if (strcmp(name, "nodes") == 0) | ||
198 | cfg.enc = NULL; | ||
199 | else if ((cfg.enc = get_cipher_by_name(name)) == NULL) | ||
200 | return (1); | ||
201 | |||
202 | *argsused = 1; | ||
203 | return (0); | ||
204 | } | ||
205 | |||
206 | static const struct option pkcs12_options[] = { | ||
207 | #ifndef OPENSSL_NO_AES | ||
208 | { | ||
209 | .name = "aes128", | ||
210 | .desc = "Encrypt PEM output with CBC AES", | ||
211 | .type = OPTION_ARGV_FUNC, | ||
212 | .opt.argvfunc = pkcs12_opt_enc, | ||
213 | }, | ||
214 | { | ||
215 | .name = "aes192", | ||
216 | .desc = "Encrypt PEM output with CBC AES", | ||
217 | .type = OPTION_ARGV_FUNC, | ||
218 | .opt.argvfunc = pkcs12_opt_enc, | ||
219 | }, | ||
220 | { | ||
221 | .name = "aes256", | ||
222 | .desc = "Encrypt PEM output with CBC AES", | ||
223 | .type = OPTION_ARGV_FUNC, | ||
224 | .opt.argvfunc = pkcs12_opt_enc, | ||
225 | }, | ||
226 | #endif | ||
227 | #ifndef OPENSSL_NO_CAMELLIA | ||
228 | { | ||
229 | .name = "camellia128", | ||
230 | .desc = "Encrypt PEM output with CBC Camellia", | ||
231 | .type = OPTION_ARGV_FUNC, | ||
232 | .opt.argvfunc = pkcs12_opt_enc, | ||
233 | }, | ||
234 | { | ||
235 | .name = "camellia192", | ||
236 | .desc = "Encrypt PEM output with CBC Camellia", | ||
237 | .type = OPTION_ARGV_FUNC, | ||
238 | .opt.argvfunc = pkcs12_opt_enc, | ||
239 | }, | ||
240 | { | ||
241 | .name = "camellia256", | ||
242 | .desc = "Encrypt PEM output with CBC Camellia", | ||
243 | .type = OPTION_ARGV_FUNC, | ||
244 | .opt.argvfunc = pkcs12_opt_enc, | ||
245 | }, | ||
246 | #endif | ||
247 | { | ||
248 | .name = "des", | ||
249 | .desc = "Encrypt private keys with DES", | ||
250 | .type = OPTION_ARGV_FUNC, | ||
251 | .opt.argvfunc = pkcs12_opt_enc, | ||
252 | }, | ||
253 | { | ||
254 | .name = "des3", | ||
255 | .desc = "Encrypt private keys with triple DES (default)", | ||
256 | .type = OPTION_ARGV_FUNC, | ||
257 | .opt.argvfunc = pkcs12_opt_enc, | ||
258 | }, | ||
259 | #ifndef OPENSSL_NO_IDEA | ||
260 | { | ||
261 | .name = "idea", | ||
262 | .desc = "Encrypt private keys with IDEA", | ||
263 | .type = OPTION_ARGV_FUNC, | ||
264 | .opt.argvfunc = pkcs12_opt_enc, | ||
265 | }, | ||
266 | #endif | ||
267 | { | ||
268 | .name = "cacerts", | ||
269 | .desc = "Only output CA certificates", | ||
270 | .type = OPTION_VALUE_OR, | ||
271 | .opt.value = &cfg.options, | ||
272 | .value = CACERTS, | ||
273 | }, | ||
274 | { | ||
275 | .name = "CAfile", | ||
276 | .argname = "file", | ||
277 | .desc = "PEM format file of CA certificates", | ||
278 | .type = OPTION_ARG, | ||
279 | .opt.arg = &cfg.CAfile, | ||
280 | }, | ||
281 | { | ||
282 | .name = "caname", | ||
283 | .argname = "name", | ||
284 | .desc = "Use name as CA friendly name (can be used more than once)", | ||
285 | .type = OPTION_ARG_FUNC, | ||
286 | .opt.argfunc = pkcs12_opt_canames, | ||
287 | }, | ||
288 | { | ||
289 | .name = "CApath", | ||
290 | .argname = "directory", | ||
291 | .desc = "PEM format directory of CA certificates", | ||
292 | .type = OPTION_ARG, | ||
293 | .opt.arg = &cfg.CApath, | ||
294 | }, | ||
295 | { | ||
296 | .name = "certfile", | ||
297 | .argname = "file", | ||
298 | .desc = "Add all certs in file", | ||
299 | .type = OPTION_ARG, | ||
300 | .opt.arg = &cfg.certfile, | ||
301 | }, | ||
302 | { | ||
303 | .name = "certpbe", | ||
304 | .argname = "alg", | ||
305 | .desc = "Specify certificate PBE algorithm (default RC2-40)", | ||
306 | .type = OPTION_ARG_FUNC, | ||
307 | .opt.argfunc = pkcs12_opt_cert_pbe, | ||
308 | }, | ||
309 | { | ||
310 | .name = "chain", | ||
311 | .desc = "Add certificate chain", | ||
312 | .type = OPTION_FLAG, | ||
313 | .opt.flag = &cfg.chain, | ||
314 | }, | ||
315 | { | ||
316 | .name = "clcerts", | ||
317 | .desc = "Only output client certificates", | ||
318 | .type = OPTION_VALUE_OR, | ||
319 | .opt.value = &cfg.options, | ||
320 | .value = CLCERTS, | ||
321 | }, | ||
322 | { | ||
323 | .name = "descert", | ||
324 | .desc = "Encrypt PKCS#12 certificates with triple DES (default RC2-40)", | ||
325 | .type = OPTION_VALUE, | ||
326 | .opt.value = &cfg.cert_pbe, | ||
327 | .value = NID_pbe_WithSHA1And3_Key_TripleDES_CBC, | ||
328 | }, | ||
329 | { | ||
330 | .name = "export", | ||
331 | .desc = "Output PKCS#12 file", | ||
332 | .type = OPTION_FLAG, | ||
333 | .opt.flag = &cfg.export_cert, | ||
334 | }, | ||
335 | { | ||
336 | .name = "in", | ||
337 | .argname = "file", | ||
338 | .desc = "Input filename", | ||
339 | .type = OPTION_ARG, | ||
340 | .opt.arg = &cfg.infile, | ||
341 | }, | ||
342 | { | ||
343 | .name = "info", | ||
344 | .desc = "Give info about PKCS#12 structure", | ||
345 | .type = OPTION_VALUE_OR, | ||
346 | .opt.value = &cfg.options, | ||
347 | .value = INFO, | ||
348 | }, | ||
349 | { | ||
350 | .name = "inkey", | ||
351 | .argname = "file", | ||
352 | .desc = "Private key if not infile", | ||
353 | .type = OPTION_ARG, | ||
354 | .opt.arg = &cfg.keyname, | ||
355 | }, | ||
356 | { | ||
357 | .name = "keyex", | ||
358 | .desc = "Set MS key exchange type", | ||
359 | .type = OPTION_VALUE, | ||
360 | .opt.value = &cfg.keytype, | ||
361 | .value = KEY_EX, | ||
362 | }, | ||
363 | { | ||
364 | .name = "keypbe", | ||
365 | .argname = "alg", | ||
366 | .desc = "Specify private key PBE algorithm (default 3DES)", | ||
367 | .type = OPTION_ARG_FUNC, | ||
368 | .opt.argfunc = pkcs12_opt_key_pbe, | ||
369 | }, | ||
370 | { | ||
371 | .name = "keysig", | ||
372 | .desc = "Set MS key signature type", | ||
373 | .type = OPTION_VALUE, | ||
374 | .opt.value = &cfg.keytype, | ||
375 | .value = KEY_SIG, | ||
376 | }, | ||
377 | { | ||
378 | .name = "macalg", | ||
379 | .argname = "alg", | ||
380 | .desc = "Digest algorithm used in MAC (default SHA1)", | ||
381 | .type = OPTION_ARG, | ||
382 | .opt.arg = &cfg.macalg, | ||
383 | }, | ||
384 | { | ||
385 | .name = "maciter", | ||
386 | .desc = "Use MAC iteration", | ||
387 | .type = OPTION_VALUE, | ||
388 | .opt.value = &cfg.maciter, | ||
389 | .value = PKCS12_DEFAULT_ITER, | ||
390 | }, | ||
391 | { | ||
392 | .name = "name", | ||
393 | .argname = "name", | ||
394 | .desc = "Use name as friendly name", | ||
395 | .type = OPTION_ARG, | ||
396 | .opt.arg = &cfg.name, | ||
397 | }, | ||
398 | { | ||
399 | .name = "nocerts", | ||
400 | .desc = "Don't output certificates", | ||
401 | .type = OPTION_VALUE_OR, | ||
402 | .opt.value = &cfg.options, | ||
403 | .value = NOCERTS, | ||
404 | }, | ||
405 | { | ||
406 | .name = "nodes", | ||
407 | .desc = "Don't encrypt private keys", | ||
408 | .type = OPTION_ARGV_FUNC, | ||
409 | .opt.argvfunc = pkcs12_opt_enc, | ||
410 | }, | ||
411 | { | ||
412 | .name = "noiter", | ||
413 | .desc = "Don't use encryption iteration", | ||
414 | .type = OPTION_VALUE, | ||
415 | .opt.value = &cfg.iter, | ||
416 | .value = 1, | ||
417 | }, | ||
418 | { | ||
419 | .name = "nokeys", | ||
420 | .desc = "Don't output private keys", | ||
421 | .type = OPTION_VALUE_OR, | ||
422 | .opt.value = &cfg.options, | ||
423 | .value = NOKEYS, | ||
424 | }, | ||
425 | { | ||
426 | .name = "nomac", | ||
427 | .desc = "Don't generate MAC", | ||
428 | .type = OPTION_VALUE, | ||
429 | .opt.value = &cfg.maciter, | ||
430 | .value = -1, | ||
431 | }, | ||
432 | { | ||
433 | .name = "nomaciter", | ||
434 | .desc = "Don't use MAC iteration", | ||
435 | .type = OPTION_VALUE, | ||
436 | .opt.value = &cfg.maciter, | ||
437 | .value = 1, | ||
438 | }, | ||
439 | { | ||
440 | .name = "nomacver", | ||
441 | .desc = "Don't verify MAC", | ||
442 | .type = OPTION_VALUE, | ||
443 | .opt.value = &cfg.macver, | ||
444 | .value = 0, | ||
445 | }, | ||
446 | { | ||
447 | .name = "noout", | ||
448 | .desc = "Don't output anything, just verify", | ||
449 | .type = OPTION_VALUE_OR, | ||
450 | .opt.value = &cfg.options, | ||
451 | .value = (NOKEYS | NOCERTS), | ||
452 | }, | ||
453 | { | ||
454 | .name = "out", | ||
455 | .argname = "file", | ||
456 | .desc = "Output filename", | ||
457 | .type = OPTION_ARG, | ||
458 | .opt.arg = &cfg.outfile, | ||
459 | }, | ||
460 | { | ||
461 | .name = "passin", | ||
462 | .argname = "arg", | ||
463 | .desc = "Input file passphrase source", | ||
464 | .type = OPTION_ARG, | ||
465 | .opt.arg = &cfg.passargin, | ||
466 | }, | ||
467 | { | ||
468 | .name = "passout", | ||
469 | .argname = "arg", | ||
470 | .desc = "Output file passphrase source", | ||
471 | .type = OPTION_ARG, | ||
472 | .opt.arg = &cfg.passargout, | ||
473 | }, | ||
474 | { | ||
475 | .name = "password", | ||
476 | .argname = "arg", | ||
477 | .desc = "Set import/export password source", | ||
478 | .type = OPTION_ARG_FUNC, | ||
479 | .opt.argfunc = pkcs12_opt_passarg, | ||
480 | }, | ||
481 | { | ||
482 | .name = "twopass", | ||
483 | .desc = "Separate MAC, encryption passwords", | ||
484 | .type = OPTION_FLAG, | ||
485 | .opt.flag = &cfg.twopass, | ||
486 | }, | ||
487 | { NULL }, | ||
488 | }; | ||
489 | |||
490 | static void | ||
491 | pkcs12_usage(void) | ||
492 | { | ||
493 | fprintf(stderr, "usage: pkcs12 [-aes128 | -aes192 | -aes256 |"); | ||
494 | fprintf(stderr, " -camellia128 |\n"); | ||
495 | fprintf(stderr, " -camellia192 | -camellia256 | -des | -des3 |"); | ||
496 | fprintf(stderr, " -idea]\n"); | ||
497 | fprintf(stderr, " [-cacerts] [-CAfile file] [-caname name]\n"); | ||
498 | fprintf(stderr, " [-CApath directory] [-certfile file]"); | ||
499 | fprintf(stderr, " [-certpbe alg]\n"); | ||
500 | fprintf(stderr, " [-chain] [-clcerts] [-CSP name] [-descert]"); | ||
501 | fprintf(stderr, " [-export]\n"); | ||
502 | fprintf(stderr, " [-in file] [-info] [-inkey file] [-keyex]"); | ||
503 | fprintf(stderr, " [-keypbe alg]\n"); | ||
504 | fprintf(stderr, " [-keysig] [-LMK] [-macalg alg] [-maciter]"); | ||
505 | fprintf(stderr, " [-name name]\n"); | ||
506 | fprintf(stderr, " [-nocerts] [-nodes] [-noiter] [-nokeys]"); | ||
507 | fprintf(stderr, " [-nomac]\n"); | ||
508 | fprintf(stderr, " [-nomaciter] [-nomacver] [-noout] [-out file]\n"); | ||
509 | fprintf(stderr, " [-passin arg] [-passout arg] [-password arg]"); | ||
510 | fprintf(stderr, " [-twopass]\n\n"); | ||
511 | options_usage(pkcs12_options); | ||
512 | fprintf(stderr, "\n"); | ||
513 | } | ||
514 | |||
515 | int | ||
516 | pkcs12_main(int argc, char **argv) | ||
517 | { | ||
518 | BIO *in = NULL, *out = NULL; | ||
519 | PKCS12 *p12 = NULL; | ||
520 | char pass[50], macpass[50]; | ||
521 | int ret = 1; | ||
522 | char *cpass = NULL, *mpass = NULL; | ||
523 | char *passin = NULL, *passout = NULL; | ||
524 | |||
525 | if (pledge("stdio cpath wpath rpath tty", NULL) == -1) { | ||
526 | perror("pledge"); | ||
527 | exit(1); | ||
528 | } | ||
529 | |||
530 | memset(&cfg, 0, sizeof(cfg)); | ||
531 | cfg.cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; | ||
532 | cfg.enc = EVP_des_ede3_cbc(); | ||
533 | cfg.iter = PKCS12_DEFAULT_ITER; | ||
534 | cfg.key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; | ||
535 | cfg.maciter = PKCS12_DEFAULT_ITER; | ||
536 | cfg.macver = 1; | ||
537 | |||
538 | if (options_parse(argc, argv, pkcs12_options, NULL, NULL) != 0) { | ||
539 | pkcs12_usage(); | ||
540 | goto end; | ||
541 | } | ||
542 | |||
543 | if (cfg.passarg != NULL) { | ||
544 | if (cfg.export_cert) | ||
545 | cfg.passargout = cfg.passarg; | ||
546 | else | ||
547 | cfg.passargin = cfg.passarg; | ||
548 | } | ||
549 | if (!app_passwd(bio_err, cfg.passargin, | ||
550 | cfg.passargout, &passin, &passout)) { | ||
551 | BIO_printf(bio_err, "Error getting passwords\n"); | ||
552 | goto end; | ||
553 | } | ||
554 | if (cpass == NULL) { | ||
555 | if (cfg.export_cert) | ||
556 | cpass = passout; | ||
557 | else | ||
558 | cpass = passin; | ||
559 | } | ||
560 | if (cpass != NULL) { | ||
561 | mpass = cpass; | ||
562 | cfg.noprompt = 1; | ||
563 | } else { | ||
564 | cpass = pass; | ||
565 | mpass = macpass; | ||
566 | } | ||
567 | |||
568 | if (cfg.infile == NULL) | ||
569 | in = BIO_new_fp(stdin, BIO_NOCLOSE); | ||
570 | else | ||
571 | in = BIO_new_file(cfg.infile, "rb"); | ||
572 | if (in == NULL) { | ||
573 | BIO_printf(bio_err, "Error opening input file %s\n", | ||
574 | cfg.infile ? cfg.infile : "<stdin>"); | ||
575 | perror(cfg.infile); | ||
576 | goto end; | ||
577 | } | ||
578 | |||
579 | if (cfg.outfile == NULL) { | ||
580 | out = BIO_new_fp(stdout, BIO_NOCLOSE); | ||
581 | } else | ||
582 | out = BIO_new_file(cfg.outfile, "wb"); | ||
583 | if (out == NULL) { | ||
584 | BIO_printf(bio_err, "Error opening output file %s\n", | ||
585 | cfg.outfile ? cfg.outfile : "<stdout>"); | ||
586 | perror(cfg.outfile); | ||
587 | goto end; | ||
588 | } | ||
589 | if (cfg.twopass) { | ||
590 | if (EVP_read_pw_string(macpass, sizeof macpass, | ||
591 | "Enter MAC Password:", cfg.export_cert)) { | ||
592 | BIO_printf(bio_err, "Can't read Password\n"); | ||
593 | goto end; | ||
594 | } | ||
595 | } | ||
596 | if (cfg.export_cert) { | ||
597 | EVP_PKEY *key = NULL; | ||
598 | X509 *ucert = NULL, *x = NULL; | ||
599 | STACK_OF(X509) *certs = NULL; | ||
600 | const EVP_MD *macmd = NULL; | ||
601 | unsigned char *catmp = NULL; | ||
602 | int i; | ||
603 | |||
604 | if ((cfg.options & (NOCERTS | NOKEYS)) == | ||
605 | (NOCERTS | NOKEYS)) { | ||
606 | BIO_printf(bio_err, "Nothing to do!\n"); | ||
607 | goto export_end; | ||
608 | } | ||
609 | if (cfg.options & NOCERTS) | ||
610 | cfg.chain = 0; | ||
611 | |||
612 | if (!(cfg.options & NOKEYS)) { | ||
613 | key = load_key(bio_err, cfg.keyname ? | ||
614 | cfg.keyname : cfg.infile, | ||
615 | FORMAT_PEM, 1, passin, "private key"); | ||
616 | if (!key) | ||
617 | goto export_end; | ||
618 | } | ||
619 | |||
620 | /* Load in all certs in input file */ | ||
621 | if (!(cfg.options & NOCERTS)) { | ||
622 | certs = load_certs(bio_err, cfg.infile, | ||
623 | FORMAT_PEM, NULL, "certificates"); | ||
624 | if (certs == NULL) | ||
625 | goto export_end; | ||
626 | |||
627 | if (key != NULL) { | ||
628 | /* Look for matching private key */ | ||
629 | for (i = 0; i < sk_X509_num(certs); i++) { | ||
630 | x = sk_X509_value(certs, i); | ||
631 | if (X509_check_private_key(x, key)) { | ||
632 | ucert = x; | ||
633 | /* Zero keyid and alias */ | ||
634 | X509_keyid_set1(ucert, NULL, 0); | ||
635 | X509_alias_set1(ucert, NULL, 0); | ||
636 | /* Remove from list */ | ||
637 | (void) sk_X509_delete(certs, i); | ||
638 | break; | ||
639 | } | ||
640 | } | ||
641 | if (ucert == NULL) { | ||
642 | BIO_printf(bio_err, | ||
643 | "No certificate matches private key\n"); | ||
644 | goto export_end; | ||
645 | } | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* Add any more certificates asked for */ | ||
650 | if (cfg.certfile != NULL) { | ||
651 | STACK_OF(X509) *morecerts = NULL; | ||
652 | if ((morecerts = load_certs(bio_err, | ||
653 | cfg.certfile, FORMAT_PEM, NULL, | ||
654 | "certificates from certfile")) == NULL) | ||
655 | goto export_end; | ||
656 | while (sk_X509_num(morecerts) > 0) { | ||
657 | X509 *cert = sk_X509_shift(morecerts); | ||
658 | |||
659 | if (!sk_X509_push(certs, cert)) { | ||
660 | X509_free(cert); | ||
661 | sk_X509_pop_free(morecerts, X509_free); | ||
662 | goto export_end; | ||
663 | } | ||
664 | } | ||
665 | |||
666 | sk_X509_free(morecerts); | ||
667 | } | ||
668 | |||
669 | |||
670 | /* If chaining get chain from user cert */ | ||
671 | if (cfg.chain) { | ||
672 | int vret; | ||
673 | STACK_OF(X509) *chain2; | ||
674 | X509_STORE *store = X509_STORE_new(); | ||
675 | if (store == NULL) { | ||
676 | BIO_printf(bio_err, | ||
677 | "Memory allocation error\n"); | ||
678 | goto export_end; | ||
679 | } | ||
680 | if (!X509_STORE_load_locations(store, | ||
681 | cfg.CAfile, cfg.CApath)) | ||
682 | X509_STORE_set_default_paths(store); | ||
683 | |||
684 | vret = get_cert_chain(ucert, store, &chain2); | ||
685 | X509_STORE_free(store); | ||
686 | |||
687 | if (vret == X509_V_OK) { | ||
688 | /* Exclude verified certificate */ | ||
689 | X509_free(sk_X509_shift(chain2)); | ||
690 | |||
691 | while (sk_X509_num(chain2) > 0) { | ||
692 | X509 *cert = sk_X509_shift(chain2); | ||
693 | |||
694 | if (!sk_X509_push(certs, cert)) { | ||
695 | X509_free(cert); | ||
696 | sk_X509_pop_free(chain2, | ||
697 | X509_free); | ||
698 | goto export_end; | ||
699 | } | ||
700 | } | ||
701 | sk_X509_free(chain2); | ||
702 | } else { | ||
703 | if (vret != X509_V_ERR_UNSPECIFIED) | ||
704 | BIO_printf(bio_err, | ||
705 | "Error %s getting chain.\n", | ||
706 | X509_verify_cert_error_string( | ||
707 | vret)); | ||
708 | else | ||
709 | ERR_print_errors(bio_err); | ||
710 | sk_X509_pop_free(chain2, X509_free); | ||
711 | goto export_end; | ||
712 | } | ||
713 | } | ||
714 | /* Add any CA names */ | ||
715 | |||
716 | for (i = 0; i < sk_OPENSSL_STRING_num(cfg.canames); | ||
717 | i++) { | ||
718 | catmp = (unsigned char *) sk_OPENSSL_STRING_value( | ||
719 | cfg.canames, i); | ||
720 | X509_alias_set1(sk_X509_value(certs, i), catmp, -1); | ||
721 | } | ||
722 | |||
723 | if (!cfg.noprompt && | ||
724 | EVP_read_pw_string(pass, sizeof pass, | ||
725 | "Enter Export Password:", 1)) { | ||
726 | BIO_printf(bio_err, "Can't read Password\n"); | ||
727 | goto export_end; | ||
728 | } | ||
729 | if (!cfg.twopass) | ||
730 | strlcpy(macpass, pass, sizeof macpass); | ||
731 | |||
732 | |||
733 | p12 = PKCS12_create(cpass, cfg.name, key, ucert, | ||
734 | certs, cfg.key_pbe, cfg.cert_pbe, | ||
735 | cfg.iter, -1, cfg.keytype); | ||
736 | |||
737 | if (p12 == NULL) { | ||
738 | ERR_print_errors(bio_err); | ||
739 | goto export_end; | ||
740 | } | ||
741 | if (cfg.macalg != NULL) { | ||
742 | macmd = EVP_get_digestbyname(cfg.macalg); | ||
743 | if (macmd == NULL) { | ||
744 | BIO_printf(bio_err, | ||
745 | "Unknown digest algorithm %s\n", | ||
746 | cfg.macalg); | ||
747 | } | ||
748 | } | ||
749 | if (cfg.maciter != -1) | ||
750 | PKCS12_set_mac(p12, mpass, -1, NULL, 0, | ||
751 | cfg.maciter, macmd); | ||
752 | |||
753 | i2d_PKCS12_bio(out, p12); | ||
754 | |||
755 | ret = 0; | ||
756 | |||
757 | export_end: | ||
758 | EVP_PKEY_free(key); | ||
759 | sk_X509_pop_free(certs, X509_free); | ||
760 | X509_free(ucert); | ||
761 | |||
762 | goto end; | ||
763 | |||
764 | } | ||
765 | if ((p12 = d2i_PKCS12_bio(in, NULL)) == NULL) { | ||
766 | ERR_print_errors(bio_err); | ||
767 | goto end; | ||
768 | } | ||
769 | if (!cfg.noprompt && EVP_read_pw_string(pass, sizeof pass, | ||
770 | "Enter Import Password:", 0)) { | ||
771 | BIO_printf(bio_err, "Can't read Password\n"); | ||
772 | goto end; | ||
773 | } | ||
774 | |||
775 | if (!cfg.twopass) | ||
776 | strlcpy(macpass, pass, sizeof macpass); | ||
777 | |||
778 | if ((cfg.options & INFO) != 0 && PKCS12_mac_present(p12)) { | ||
779 | const ASN1_INTEGER *iter; | ||
780 | |||
781 | PKCS12_get0_mac(NULL, NULL, NULL, &iter, p12); | ||
782 | BIO_printf(bio_err, "MAC Iteration %ld\n", | ||
783 | iter != NULL ? ASN1_INTEGER_get(iter) : 1); | ||
784 | } | ||
785 | if (cfg.macver) { | ||
786 | /* If we enter empty password try no password first */ | ||
787 | if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { | ||
788 | /* If mac and crypto pass the same set it to NULL too */ | ||
789 | if (!cfg.twopass) | ||
790 | cpass = NULL; | ||
791 | } else if (!PKCS12_verify_mac(p12, mpass, -1)) { | ||
792 | BIO_printf(bio_err, | ||
793 | "Mac verify error: invalid password?\n"); | ||
794 | ERR_print_errors(bio_err); | ||
795 | goto end; | ||
796 | } | ||
797 | BIO_printf(bio_err, "MAC verified OK\n"); | ||
798 | } | ||
799 | if (!dump_certs_keys_p12(out, p12, cpass, -1, cfg.options, | ||
800 | passout)) { | ||
801 | BIO_printf(bio_err, "Error outputting keys and certificates\n"); | ||
802 | ERR_print_errors(bio_err); | ||
803 | goto end; | ||
804 | } | ||
805 | ret = 0; | ||
806 | end: | ||
807 | PKCS12_free(p12); | ||
808 | BIO_free(in); | ||
809 | BIO_free_all(out); | ||
810 | sk_OPENSSL_STRING_free(cfg.canames); | ||
811 | free(passin); | ||
812 | free(passout); | ||
813 | |||
814 | return (ret); | ||
815 | } | ||
816 | |||
817 | static int | ||
818 | dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options, | ||
819 | char *pempass) | ||
820 | { | ||
821 | STACK_OF(PKCS7) *asafes = NULL; | ||
822 | STACK_OF(PKCS12_SAFEBAG) *bags; | ||
823 | int i, bagnid; | ||
824 | int ret = 0; | ||
825 | PKCS7 *p7; | ||
826 | |||
827 | if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) | ||
828 | return 0; | ||
829 | for (i = 0; i < sk_PKCS7_num(asafes); i++) { | ||
830 | p7 = sk_PKCS7_value(asafes, i); | ||
831 | bagnid = OBJ_obj2nid(p7->type); | ||
832 | if (bagnid == NID_pkcs7_data) { | ||
833 | bags = PKCS12_unpack_p7data(p7); | ||
834 | if (options & INFO) | ||
835 | BIO_printf(bio_err, "PKCS7 Data\n"); | ||
836 | } else if (bagnid == NID_pkcs7_encrypted) { | ||
837 | if (options & INFO) { | ||
838 | BIO_printf(bio_err, "PKCS7 Encrypted data: "); | ||
839 | alg_print(bio_err, | ||
840 | p7->d.encrypted->enc_data->algorithm); | ||
841 | } | ||
842 | bags = PKCS12_unpack_p7encdata(p7, pass, passlen); | ||
843 | } else | ||
844 | continue; | ||
845 | if (bags == NULL) | ||
846 | goto err; | ||
847 | if (!dump_certs_pkeys_bags(out, bags, pass, passlen, | ||
848 | options, pempass)) { | ||
849 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); | ||
850 | goto err; | ||
851 | } | ||
852 | sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); | ||
853 | bags = NULL; | ||
854 | } | ||
855 | ret = 1; | ||
856 | |||
857 | err: | ||
858 | sk_PKCS7_pop_free(asafes, PKCS7_free); | ||
859 | return ret; | ||
860 | } | ||
861 | |||
862 | static int | ||
863 | dump_certs_pkeys_bags(BIO *out, const STACK_OF(PKCS12_SAFEBAG) *bags, | ||
864 | char *pass, int passlen, int options, char *pempass) | ||
865 | { | ||
866 | int i; | ||
867 | |||
868 | for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { | ||
869 | if (!dump_certs_pkeys_bag(out, | ||
870 | sk_PKCS12_SAFEBAG_value(bags, i), | ||
871 | pass, passlen, | ||
872 | options, pempass)) | ||
873 | return 0; | ||
874 | } | ||
875 | return 1; | ||
876 | } | ||
877 | |||
878 | static int | ||
879 | dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, int passlen, | ||
880 | int options, char *pempass) | ||
881 | { | ||
882 | EVP_PKEY *pkey; | ||
883 | const STACK_OF(X509_ATTRIBUTE) *attrs; | ||
884 | X509 *x509; | ||
885 | |||
886 | attrs = PKCS12_SAFEBAG_get0_attrs(bag); | ||
887 | |||
888 | switch (PKCS12_SAFEBAG_get_nid(bag)) { | ||
889 | case NID_keyBag: | ||
890 | { | ||
891 | const PKCS8_PRIV_KEY_INFO *p8; | ||
892 | |||
893 | if (options & INFO) | ||
894 | BIO_printf(bio_err, "Key bag\n"); | ||
895 | if (options & NOKEYS) | ||
896 | return 1; | ||
897 | print_attribs(out, attrs, "Bag Attributes"); | ||
898 | if ((p8 = PKCS12_SAFEBAG_get0_p8inf(bag)) == NULL) | ||
899 | return 0; | ||
900 | if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) | ||
901 | return 0; | ||
902 | print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); | ||
903 | PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0, | ||
904 | NULL, pempass); | ||
905 | EVP_PKEY_free(pkey); | ||
906 | break; | ||
907 | } | ||
908 | |||
909 | case NID_pkcs8ShroudedKeyBag: | ||
910 | { | ||
911 | PKCS8_PRIV_KEY_INFO *p8; | ||
912 | |||
913 | if (options & INFO) { | ||
914 | const X509_SIG *tp8; | ||
915 | const X509_ALGOR *tp8alg; | ||
916 | |||
917 | BIO_printf(bio_err, "Shrouded Keybag: "); | ||
918 | if ((tp8 = PKCS12_SAFEBAG_get0_pkcs8(bag)) == NULL) | ||
919 | return 0; | ||
920 | X509_SIG_get0(tp8, &tp8alg, NULL); | ||
921 | alg_print(bio_err, tp8alg); | ||
922 | } | ||
923 | if (options & NOKEYS) | ||
924 | return 1; | ||
925 | print_attribs(out, attrs, "Bag Attributes"); | ||
926 | if ((p8 = PKCS12_decrypt_skey(bag, pass, passlen)) == NULL) | ||
927 | return 0; | ||
928 | if ((pkey = EVP_PKCS82PKEY(p8)) == NULL) { | ||
929 | PKCS8_PRIV_KEY_INFO_free(p8); | ||
930 | return 0; | ||
931 | } | ||
932 | print_attribs(out, PKCS8_pkey_get0_attrs(p8), "Key Attributes"); | ||
933 | PKCS8_PRIV_KEY_INFO_free(p8); | ||
934 | PEM_write_bio_PrivateKey(out, pkey, cfg.enc, NULL, 0, | ||
935 | NULL, pempass); | ||
936 | EVP_PKEY_free(pkey); | ||
937 | break; | ||
938 | } | ||
939 | |||
940 | case NID_certBag: | ||
941 | if (options & INFO) | ||
942 | BIO_printf(bio_err, "Certificate bag\n"); | ||
943 | if (options & NOCERTS) | ||
944 | return 1; | ||
945 | if (PKCS12_SAFEBAG_get0_attr(bag, NID_localKeyID) != NULL) { | ||
946 | if (options & CACERTS) | ||
947 | return 1; | ||
948 | } else if (options & CLCERTS) | ||
949 | return 1; | ||
950 | print_attribs(out, attrs, "Bag Attributes"); | ||
951 | if (PKCS12_SAFEBAG_get_bag_nid(bag) != NID_x509Certificate) | ||
952 | return 1; | ||
953 | if ((x509 = PKCS12_certbag2x509(bag)) == NULL) | ||
954 | return 0; | ||
955 | dump_cert_text(out, x509); | ||
956 | PEM_write_bio_X509(out, x509); | ||
957 | X509_free(x509); | ||
958 | break; | ||
959 | |||
960 | case NID_safeContentsBag: | ||
961 | if (options & INFO) | ||
962 | BIO_printf(bio_err, "Safe Contents bag\n"); | ||
963 | print_attribs(out, attrs, "Bag Attributes"); | ||
964 | return dump_certs_pkeys_bags(out, PKCS12_SAFEBAG_get0_safes(bag), | ||
965 | pass, passlen, options, pempass); | ||
966 | |||
967 | default: | ||
968 | BIO_printf(bio_err, "Warning unsupported bag type: "); | ||
969 | i2a_ASN1_OBJECT(bio_err, PKCS12_SAFEBAG_get0_type(bag)); | ||
970 | BIO_printf(bio_err, "\n"); | ||
971 | return 1; | ||
972 | break; | ||
973 | } | ||
974 | return 1; | ||
975 | } | ||
976 | |||
977 | /* Given a single certificate return a verified chain or NULL if error */ | ||
978 | static int | ||
979 | get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **out_chain) | ||
980 | { | ||
981 | X509_STORE_CTX *store_ctx = NULL; | ||
982 | STACK_OF(X509) *chain = NULL; | ||
983 | int ret = X509_V_ERR_UNSPECIFIED; | ||
984 | |||
985 | if ((store_ctx = X509_STORE_CTX_new()) == NULL) | ||
986 | goto err; | ||
987 | if (!X509_STORE_CTX_init(store_ctx, store, cert, NULL)) | ||
988 | goto err; | ||
989 | |||
990 | if (X509_verify_cert(store_ctx) > 0) { | ||
991 | if ((chain = X509_STORE_CTX_get1_chain(store_ctx)) == NULL) | ||
992 | goto err; | ||
993 | } | ||
994 | ret = X509_STORE_CTX_get_error(store_ctx); | ||
995 | |||
996 | err: | ||
997 | X509_STORE_CTX_free(store_ctx); | ||
998 | *out_chain = chain; | ||
999 | |||
1000 | return ret; | ||
1001 | } | ||
1002 | |||
1003 | static int | ||
1004 | alg_print(BIO *x, const X509_ALGOR *alg) | ||
1005 | { | ||
1006 | PBEPARAM *pbe = NULL; | ||
1007 | const ASN1_OBJECT *aobj; | ||
1008 | int param_type; | ||
1009 | const void *param; | ||
1010 | |||
1011 | X509_ALGOR_get0(&aobj, ¶m_type, ¶m, alg); | ||
1012 | if (param_type == V_ASN1_SEQUENCE) | ||
1013 | pbe = ASN1_item_unpack(param, &PBEPARAM_it); | ||
1014 | if (pbe == NULL) | ||
1015 | return 1; | ||
1016 | BIO_printf(bio_err, "%s, Iteration %ld\n", | ||
1017 | OBJ_nid2ln(OBJ_obj2nid(aobj)), | ||
1018 | ASN1_INTEGER_get(pbe->iter)); | ||
1019 | ASN1_item_free((ASN1_VALUE *)pbe, &PBEPARAM_it); | ||
1020 | return 1; | ||
1021 | } | ||
1022 | |||
1023 | /* Generalised attribute print: handle PKCS#8 and bag attributes */ | ||
1024 | static void | ||
1025 | print_attribute(BIO *out, const ASN1_TYPE *av) | ||
1026 | { | ||
1027 | char *value; | ||
1028 | |||
1029 | switch (av->type) { | ||
1030 | case V_ASN1_BMPSTRING: | ||
1031 | value = OPENSSL_uni2asc( | ||
1032 | av->value.bmpstring->data, | ||
1033 | av->value.bmpstring->length); | ||
1034 | BIO_printf(out, "%s\n", value); | ||
1035 | free(value); | ||
1036 | break; | ||
1037 | |||
1038 | case V_ASN1_OCTET_STRING: | ||
1039 | hex_prin(out, av->value.octet_string->data, | ||
1040 | av->value.octet_string->length); | ||
1041 | BIO_printf(out, "\n"); | ||
1042 | break; | ||
1043 | |||
1044 | case V_ASN1_BIT_STRING: | ||
1045 | hex_prin(out, av->value.bit_string->data, | ||
1046 | av->value.bit_string->length); | ||
1047 | BIO_printf(out, "\n"); | ||
1048 | break; | ||
1049 | |||
1050 | default: | ||
1051 | BIO_printf(out, "<Unsupported tag %d>\n", | ||
1052 | av->type); | ||
1053 | break; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | static int | ||
1058 | print_attribs(BIO *out, const STACK_OF(X509_ATTRIBUTE) *attrlst, | ||
1059 | const char *name) | ||
1060 | { | ||
1061 | X509_ATTRIBUTE *attr; | ||
1062 | ASN1_TYPE *av; | ||
1063 | int i, j, attr_nid; | ||
1064 | |||
1065 | if (attrlst == NULL) { | ||
1066 | BIO_printf(out, "%s: <No Attributes>\n", name); | ||
1067 | return 1; | ||
1068 | } | ||
1069 | if (!sk_X509_ATTRIBUTE_num(attrlst)) { | ||
1070 | BIO_printf(out, "%s: <Empty Attributes>\n", name); | ||
1071 | return 1; | ||
1072 | } | ||
1073 | BIO_printf(out, "%s\n", name); | ||
1074 | for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { | ||
1075 | ASN1_OBJECT *obj; | ||
1076 | |||
1077 | attr = sk_X509_ATTRIBUTE_value(attrlst, i); | ||
1078 | obj = X509_ATTRIBUTE_get0_object(attr); | ||
1079 | attr_nid = OBJ_obj2nid(X509_ATTRIBUTE_get0_object(attr)); | ||
1080 | BIO_printf(out, " "); | ||
1081 | if (attr_nid == NID_undef) { | ||
1082 | i2a_ASN1_OBJECT(out, obj); | ||
1083 | BIO_printf(out, ": "); | ||
1084 | } else | ||
1085 | BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); | ||
1086 | |||
1087 | if (X509_ATTRIBUTE_count(attr)) { | ||
1088 | for (j = 0; j < X509_ATTRIBUTE_count(attr); j++) { | ||
1089 | av = X509_ATTRIBUTE_get0_type(attr, j); | ||
1090 | print_attribute(out, av); | ||
1091 | } | ||
1092 | } else | ||
1093 | BIO_printf(out, "<No Values>\n"); | ||
1094 | } | ||
1095 | return 1; | ||
1096 | } | ||
1097 | |||
1098 | static void | ||
1099 | hex_prin(BIO *out, unsigned char *buf, int len) | ||
1100 | { | ||
1101 | int i; | ||
1102 | |||
1103 | for (i = 0; i < len; i++) | ||
1104 | BIO_printf(out, "%02X ", buf[i]); | ||
1105 | } | ||
1106 | |||
1107 | static int | ||
1108 | set_pbe(BIO *err, int *ppbe, const char *str) | ||
1109 | { | ||
1110 | if (str == NULL) | ||
1111 | return 0; | ||
1112 | if (strcmp(str, "NONE") == 0) { | ||
1113 | *ppbe = -1; | ||
1114 | return 1; | ||
1115 | } | ||
1116 | *ppbe = OBJ_txt2nid(str); | ||
1117 | if (*ppbe == NID_undef) { | ||
1118 | BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str); | ||
1119 | return 0; | ||
1120 | } | ||
1121 | return 1; | ||
1122 | } | ||
1123 | |||
1124 | #endif | ||