| OLD | NEW |
| (Empty) |
| 1 /* pkcs12.c */ | |
| 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 #if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) | |
| 61 | |
| 62 #include <stdio.h> | |
| 63 #include <stdlib.h> | |
| 64 #include <string.h> | |
| 65 #include "apps.h" | |
| 66 #include <openssl/crypto.h> | |
| 67 #include <openssl/err.h> | |
| 68 #include <openssl/pem.h> | |
| 69 #include <openssl/pkcs12.h> | |
| 70 | |
| 71 #define PROG pkcs12_main | |
| 72 | |
| 73 const EVP_CIPHER *enc; | |
| 74 | |
| 75 | |
| 76 #define NOKEYS 0x1 | |
| 77 #define NOCERTS 0x2 | |
| 78 #define INFO 0x4 | |
| 79 #define CLCERTS 0x8 | |
| 80 #define CACERTS 0x10 | |
| 81 | |
| 82 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); | |
| 83 int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int opti
ons, char *pempass); | |
| 84 int dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, char *pass, | |
| 85 int passlen, int options, char *pempass); | |
| 86 int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen
, int options, char *pempass); | |
| 87 int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name); | |
| 88 void hex_prin(BIO *out, unsigned char *buf, int len); | |
| 89 int alg_print(BIO *x, X509_ALGOR *alg); | |
| 90 int cert_load(BIO *in, STACK_OF(X509) *sk); | |
| 91 static int set_pbe(BIO *err, int *ppbe, const char *str); | |
| 92 | |
| 93 int MAIN(int, char **); | |
| 94 | |
| 95 int MAIN(int argc, char **argv) | |
| 96 { | |
| 97 ENGINE *e = NULL; | |
| 98 char *infile=NULL, *outfile=NULL, *keyname = NULL; | |
| 99 char *certfile=NULL; | |
| 100 BIO *in=NULL, *out = NULL; | |
| 101 char **args; | |
| 102 char *name = NULL; | |
| 103 char *csp_name = NULL; | |
| 104 int add_lmk = 0; | |
| 105 PKCS12 *p12 = NULL; | |
| 106 char pass[50], macpass[50]; | |
| 107 int export_cert = 0; | |
| 108 int options = 0; | |
| 109 int chain = 0; | |
| 110 int badarg = 0; | |
| 111 int iter = PKCS12_DEFAULT_ITER; | |
| 112 int maciter = PKCS12_DEFAULT_ITER; | |
| 113 int twopass = 0; | |
| 114 int keytype = 0; | |
| 115 int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; | |
| 116 int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; | |
| 117 int ret = 1; | |
| 118 int macver = 1; | |
| 119 int noprompt = 0; | |
| 120 STACK_OF(OPENSSL_STRING) *canames = NULL; | |
| 121 char *cpass = NULL, *mpass = NULL; | |
| 122 char *passargin = NULL, *passargout = NULL, *passarg = NULL; | |
| 123 char *passin = NULL, *passout = NULL; | |
| 124 char *inrand = NULL; | |
| 125 char *macalg = NULL; | |
| 126 char *CApath = NULL, *CAfile = NULL; | |
| 127 #ifndef OPENSSL_NO_ENGINE | |
| 128 char *engine=NULL; | |
| 129 #endif | |
| 130 | |
| 131 apps_startup(); | |
| 132 | |
| 133 enc = EVP_des_ede3_cbc(); | |
| 134 if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); | |
| 135 | |
| 136 if (!load_config(bio_err, NULL)) | |
| 137 goto end; | |
| 138 | |
| 139 args = argv + 1; | |
| 140 | |
| 141 | |
| 142 while (*args) { | |
| 143 if (*args[0] == '-') { | |
| 144 if (!strcmp (*args, "-nokeys")) options |= NOKEYS; | |
| 145 else if (!strcmp (*args, "-keyex")) keytype = KEY_EX; | |
| 146 else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG; | |
| 147 else if (!strcmp (*args, "-nocerts")) options |= NOCERTS; | |
| 148 else if (!strcmp (*args, "-clcerts")) options |= CLCERTS; | |
| 149 else if (!strcmp (*args, "-cacerts")) options |= CACERTS; | |
| 150 else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS); | |
| 151 else if (!strcmp (*args, "-info")) options |= INFO; | |
| 152 else if (!strcmp (*args, "-chain")) chain = 1; | |
| 153 else if (!strcmp (*args, "-twopass")) twopass = 1; | |
| 154 else if (!strcmp (*args, "-nomacver")) macver = 0; | |
| 155 else if (!strcmp (*args, "-descert")) | |
| 156 cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; | |
| 157 else if (!strcmp (*args, "-export")) export_cert = 1; | |
| 158 else if (!strcmp (*args, "-des")) enc=EVP_des_cbc(); | |
| 159 else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc(); | |
| 160 #ifndef OPENSSL_NO_IDEA | |
| 161 else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc(); | |
| 162 #endif | |
| 163 #ifndef OPENSSL_NO_SEED | |
| 164 else if (!strcmp(*args, "-seed")) enc=EVP_seed_cbc(); | |
| 165 #endif | |
| 166 #ifndef OPENSSL_NO_AES | |
| 167 else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc(); | |
| 168 else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc(); | |
| 169 else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc(); | |
| 170 #endif | |
| 171 #ifndef OPENSSL_NO_CAMELLIA | |
| 172 else if (!strcmp(*args,"-camellia128")) enc=EVP_camellia_128_cbc
(); | |
| 173 else if (!strcmp(*args,"-camellia192")) enc=EVP_camellia_192_cbc
(); | |
| 174 else if (!strcmp(*args,"-camellia256")) enc=EVP_camellia_256_cbc
(); | |
| 175 #endif | |
| 176 else if (!strcmp (*args, "-noiter")) iter = 1; | |
| 177 else if (!strcmp (*args, "-maciter")) | |
| 178 maciter = PKCS12_DEFAULT_ITER; | |
| 179 else if (!strcmp (*args, "-nomaciter")) | |
| 180 maciter = 1; | |
| 181 else if (!strcmp (*args, "-nomac")) | |
| 182 maciter = -1; | |
| 183 else if (!strcmp (*args, "-macalg")) | |
| 184 if (args[1]) { | |
| 185 args++; | |
| 186 macalg = *args; | |
| 187 } else badarg = 1; | |
| 188 else if (!strcmp (*args, "-nodes")) enc=NULL; | |
| 189 else if (!strcmp (*args, "-certpbe")) { | |
| 190 if (!set_pbe(bio_err, &cert_pbe, *++args)) | |
| 191 badarg = 1; | |
| 192 } else if (!strcmp (*args, "-keypbe")) { | |
| 193 if (!set_pbe(bio_err, &key_pbe, *++args)) | |
| 194 badarg = 1; | |
| 195 } else if (!strcmp (*args, "-rand")) { | |
| 196 if (args[1]) { | |
| 197 args++; | |
| 198 inrand = *args; | |
| 199 } else badarg = 1; | |
| 200 } else if (!strcmp (*args, "-inkey")) { | |
| 201 if (args[1]) { | |
| 202 args++; | |
| 203 keyname = *args; | |
| 204 } else badarg = 1; | |
| 205 } else if (!strcmp (*args, "-certfile")) { | |
| 206 if (args[1]) { | |
| 207 args++; | |
| 208 certfile = *args; | |
| 209 } else badarg = 1; | |
| 210 } else if (!strcmp (*args, "-name")) { | |
| 211 if (args[1]) { | |
| 212 args++; | |
| 213 name = *args; | |
| 214 } else badarg = 1; | |
| 215 } else if (!strcmp (*args, "-LMK")) | |
| 216 add_lmk = 1; | |
| 217 else if (!strcmp (*args, "-CSP")) { | |
| 218 if (args[1]) { | |
| 219 args++; | |
| 220 csp_name = *args; | |
| 221 } else badarg = 1; | |
| 222 } else if (!strcmp (*args, "-caname")) { | |
| 223 if (args[1]) { | |
| 224 args++; | |
| 225 if (!canames) canames = sk_OPENSSL_STRING_new_null(); | |
| 226 sk_OPENSSL_STRING_push(canames, *args); | |
| 227 } else badarg = 1; | |
| 228 } else if (!strcmp (*args, "-in")) { | |
| 229 if (args[1]) { | |
| 230 args++; | |
| 231 infile = *args; | |
| 232 } else badarg = 1; | |
| 233 } else if (!strcmp (*args, "-out")) { | |
| 234 if (args[1]) { | |
| 235 args++; | |
| 236 outfile = *args; | |
| 237 } else badarg = 1; | |
| 238 } else if (!strcmp(*args,"-passin")) { | |
| 239 if (args[1]) { | |
| 240 args++; | |
| 241 passargin = *args; | |
| 242 } else badarg = 1; | |
| 243 } else if (!strcmp(*args,"-passout")) { | |
| 244 if (args[1]) { | |
| 245 args++; | |
| 246 passargout = *args; | |
| 247 } else badarg = 1; | |
| 248 } else if (!strcmp (*args, "-password")) { | |
| 249 if (args[1]) { | |
| 250 args++; | |
| 251 passarg = *args; | |
| 252 noprompt = 1; | |
| 253 } else badarg = 1; | |
| 254 } else if (!strcmp(*args,"-CApath")) { | |
| 255 if (args[1]) { | |
| 256 args++; | |
| 257 CApath = *args; | |
| 258 } else badarg = 1; | |
| 259 } else if (!strcmp(*args,"-CAfile")) { | |
| 260 if (args[1]) { | |
| 261 args++; | |
| 262 CAfile = *args; | |
| 263 } else badarg = 1; | |
| 264 #ifndef OPENSSL_NO_ENGINE | |
| 265 } else if (!strcmp(*args,"-engine")) { | |
| 266 if (args[1]) { | |
| 267 args++; | |
| 268 engine = *args; | |
| 269 } else badarg = 1; | |
| 270 #endif | |
| 271 } else badarg = 1; | |
| 272 | |
| 273 } else badarg = 1; | |
| 274 args++; | |
| 275 } | |
| 276 | |
| 277 if (badarg) { | |
| 278 BIO_printf (bio_err, "Usage: pkcs12 [options]\n"); | |
| 279 BIO_printf (bio_err, "where options are\n"); | |
| 280 BIO_printf (bio_err, "-export output PKCS12 file\n"); | |
| 281 BIO_printf (bio_err, "-chain add certificate chain\n"); | |
| 282 BIO_printf (bio_err, "-inkey file private key if not infile\n"); | |
| 283 BIO_printf (bio_err, "-certfile f add all certs in f\n"); | |
| 284 BIO_printf (bio_err, "-CApath arg - PEM format directory of CA's\n"); | |
| 285 BIO_printf (bio_err, "-CAfile arg - PEM format file of CA's\n"); | |
| 286 BIO_printf (bio_err, "-name \"name\" use name as friendly name\n"); | |
| 287 BIO_printf (bio_err, "-caname \"nm\" use nm as CA friendly name (can be
used more than once).\n"); | |
| 288 BIO_printf (bio_err, "-in infile input filename\n"); | |
| 289 BIO_printf (bio_err, "-out outfile output filename\n"); | |
| 290 BIO_printf (bio_err, "-noout don't output anything, just verify.\
n"); | |
| 291 BIO_printf (bio_err, "-nomacver don't verify MAC.\n"); | |
| 292 BIO_printf (bio_err, "-nocerts don't output certificates.\n"); | |
| 293 BIO_printf (bio_err, "-clcerts only output client certificates.\n")
; | |
| 294 BIO_printf (bio_err, "-cacerts only output CA certificates.\n"); | |
| 295 BIO_printf (bio_err, "-nokeys don't output private keys.\n"); | |
| 296 BIO_printf (bio_err, "-info give info about PKCS#12 structure.\n
"); | |
| 297 BIO_printf (bio_err, "-des encrypt private keys with DES\n"); | |
| 298 BIO_printf (bio_err, "-des3 encrypt private keys with triple DES
(default)\n"); | |
| 299 #ifndef OPENSSL_NO_IDEA | |
| 300 BIO_printf (bio_err, "-idea encrypt private keys with idea\n"); | |
| 301 #endif | |
| 302 #ifndef OPENSSL_NO_SEED | |
| 303 BIO_printf (bio_err, "-seed encrypt private keys with seed\n"); | |
| 304 #endif | |
| 305 #ifndef OPENSSL_NO_AES | |
| 306 BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); | |
| 307 BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); | |
| 308 #endif | |
| 309 #ifndef OPENSSL_NO_CAMELLIA | |
| 310 BIO_printf (bio_err, "-camellia128, -camellia192, -camellia256\n"); | |
| 311 BIO_printf (bio_err, " encrypt PEM output with cbc camellia
\n"); | |
| 312 #endif | |
| 313 BIO_printf (bio_err, "-nodes don't encrypt private keys\n"); | |
| 314 BIO_printf (bio_err, "-noiter don't use encryption iteration\n"); | |
| 315 BIO_printf (bio_err, "-nomaciter don't use MAC iteration\n"); | |
| 316 BIO_printf (bio_err, "-maciter use MAC iteration\n"); | |
| 317 BIO_printf (bio_err, "-nomac don't generate MAC\n"); | |
| 318 BIO_printf (bio_err, "-twopass separate MAC, encryption passwords\n
"); | |
| 319 BIO_printf (bio_err, "-descert encrypt PKCS#12 certificates with tr
iple DES (default RC2-40)\n"); | |
| 320 BIO_printf (bio_err, "-certpbe alg specify certificate PBE algorithm (d
efault RC2-40)\n"); | |
| 321 BIO_printf (bio_err, "-keypbe alg specify private key PBE algorithm (d
efault 3DES)\n"); | |
| 322 BIO_printf (bio_err, "-macalg alg digest algorithm used in MAC (defaul
t SHA1)\n"); | |
| 323 BIO_printf (bio_err, "-keyex set MS key exchange type\n"); | |
| 324 BIO_printf (bio_err, "-keysig set MS key signature type\n"); | |
| 325 BIO_printf (bio_err, "-password p set import/export password source\n"
); | |
| 326 BIO_printf (bio_err, "-passin p input file pass phrase source\n"); | |
| 327 BIO_printf (bio_err, "-passout p output file pass phrase source\n"); | |
| 328 #ifndef OPENSSL_NO_ENGINE | |
| 329 BIO_printf (bio_err, "-engine e use engine e, possibly a hardware de
vice.\n"); | |
| 330 #endif | |
| 331 BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIS
T_SEPARATOR_CHAR); | |
| 332 BIO_printf(bio_err, " load the file (or the files in the d
irectory) into\n"); | |
| 333 BIO_printf(bio_err, " the random number generator\n"); | |
| 334 BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); | |
| 335 BIO_printf(bio_err, "-LMK Add local machine keyset attribute t
o private key\n"); | |
| 336 goto end; | |
| 337 } | |
| 338 | |
| 339 #ifndef OPENSSL_NO_ENGINE | |
| 340 e = setup_engine(bio_err, engine, 0); | |
| 341 #endif | |
| 342 | |
| 343 if(passarg) { | |
| 344 if(export_cert) passargout = passarg; | |
| 345 else passargin = passarg; | |
| 346 } | |
| 347 | |
| 348 if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { | |
| 349 BIO_printf(bio_err, "Error getting passwords\n"); | |
| 350 goto end; | |
| 351 } | |
| 352 | |
| 353 if(!cpass) { | |
| 354 if(export_cert) cpass = passout; | |
| 355 else cpass = passin; | |
| 356 } | |
| 357 | |
| 358 if(cpass) { | |
| 359 mpass = cpass; | |
| 360 noprompt = 1; | |
| 361 } else { | |
| 362 cpass = pass; | |
| 363 mpass = macpass; | |
| 364 } | |
| 365 | |
| 366 if(export_cert || inrand) { | |
| 367 app_RAND_load_file(NULL, bio_err, (inrand != NULL)); | |
| 368 if (inrand != NULL) | |
| 369 BIO_printf(bio_err,"%ld semi-random bytes loaded\n", | |
| 370 app_RAND_load_files(inrand)); | |
| 371 } | |
| 372 ERR_load_crypto_strings(); | |
| 373 | |
| 374 #ifdef CRYPTO_MDEBUG | |
| 375 CRYPTO_push_info("read files"); | |
| 376 #endif | |
| 377 | |
| 378 if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE); | |
| 379 else in = BIO_new_file(infile, "rb"); | |
| 380 if (!in) { | |
| 381 BIO_printf(bio_err, "Error opening input file %s\n", | |
| 382 infile ? infile : "<stdin>"); | |
| 383 perror (infile); | |
| 384 goto end; | |
| 385 } | |
| 386 | |
| 387 #ifdef CRYPTO_MDEBUG | |
| 388 CRYPTO_pop_info(); | |
| 389 CRYPTO_push_info("write files"); | |
| 390 #endif | |
| 391 | |
| 392 if (!outfile) { | |
| 393 out = BIO_new_fp(stdout, BIO_NOCLOSE); | |
| 394 #ifdef OPENSSL_SYS_VMS | |
| 395 { | |
| 396 BIO *tmpbio = BIO_new(BIO_f_linebuffer()); | |
| 397 out = BIO_push(tmpbio, out); | |
| 398 } | |
| 399 #endif | |
| 400 } else out = BIO_new_file(outfile, "wb"); | |
| 401 if (!out) { | |
| 402 BIO_printf(bio_err, "Error opening output file %s\n", | |
| 403 outfile ? outfile : "<stdout>"); | |
| 404 perror (outfile); | |
| 405 goto end; | |
| 406 } | |
| 407 if (twopass) { | |
| 408 #ifdef CRYPTO_MDEBUG | |
| 409 CRYPTO_push_info("read MAC password"); | |
| 410 #endif | |
| 411 if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:", e
xport_cert)) | |
| 412 { | |
| 413 BIO_printf (bio_err, "Can't read Password\n"); | |
| 414 goto end; | |
| 415 } | |
| 416 #ifdef CRYPTO_MDEBUG | |
| 417 CRYPTO_pop_info(); | |
| 418 #endif | |
| 419 } | |
| 420 | |
| 421 if (export_cert) { | |
| 422 EVP_PKEY *key = NULL; | |
| 423 X509 *ucert = NULL, *x = NULL; | |
| 424 STACK_OF(X509) *certs=NULL; | |
| 425 const EVP_MD *macmd = NULL; | |
| 426 unsigned char *catmp = NULL; | |
| 427 int i; | |
| 428 | |
| 429 if ((options & (NOCERTS|NOKEYS)) == (NOCERTS|NOKEYS)) | |
| 430 { | |
| 431 BIO_printf(bio_err, "Nothing to do!\n"); | |
| 432 goto export_end; | |
| 433 } | |
| 434 | |
| 435 if (options & NOCERTS) | |
| 436 chain = 0; | |
| 437 | |
| 438 #ifdef CRYPTO_MDEBUG | |
| 439 CRYPTO_push_info("process -export_cert"); | |
| 440 CRYPTO_push_info("reading private key"); | |
| 441 #endif | |
| 442 if (!(options & NOKEYS)) | |
| 443 { | |
| 444 key = load_key(bio_err, keyname ? keyname : infile, | |
| 445 FORMAT_PEM, 1, passin, e, "private key"); | |
| 446 if (!key) | |
| 447 goto export_end; | |
| 448 } | |
| 449 | |
| 450 #ifdef CRYPTO_MDEBUG | |
| 451 CRYPTO_pop_info(); | |
| 452 CRYPTO_push_info("reading certs from input"); | |
| 453 #endif | |
| 454 | |
| 455 /* Load in all certs in input file */ | |
| 456 if(!(options & NOCERTS)) | |
| 457 { | |
| 458 certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, | |
| 459 "certificates"); | |
| 460 if (!certs) | |
| 461 goto export_end; | |
| 462 | |
| 463 if (key) | |
| 464 { | |
| 465 /* Look for matching private key */ | |
| 466 for(i = 0; i < sk_X509_num(certs); i++) | |
| 467 { | |
| 468 x = sk_X509_value(certs, i); | |
| 469 if(X509_check_private_key(x, key)) | |
| 470 { | |
| 471 ucert = x; | |
| 472 /* Zero keyid and alias */ | |
| 473 X509_keyid_set1(ucert, NULL, 0); | |
| 474 X509_alias_set1(ucert, NULL, 0); | |
| 475 /* Remove from list */ | |
| 476 (void)sk_X509_delete(certs, i); | |
| 477 break; | |
| 478 } | |
| 479 } | |
| 480 if (!ucert) | |
| 481 { | |
| 482 BIO_printf(bio_err, "No certificate matches priv
ate key\n"); | |
| 483 goto export_end; | |
| 484 } | |
| 485 } | |
| 486 | |
| 487 } | |
| 488 | |
| 489 #ifdef CRYPTO_MDEBUG | |
| 490 CRYPTO_pop_info(); | |
| 491 CRYPTO_push_info("reading certs from input 2"); | |
| 492 #endif | |
| 493 | |
| 494 /* Add any more certificates asked for */ | |
| 495 if(certfile) | |
| 496 { | |
| 497 STACK_OF(X509) *morecerts=NULL; | |
| 498 if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, | |
| 499 NULL, e, | |
| 500 "certificates from certfile"))) | |
| 501 goto export_end; | |
| 502 while(sk_X509_num(morecerts) > 0) | |
| 503 sk_X509_push(certs, sk_X509_shift(morecerts)); | |
| 504 sk_X509_free(morecerts); | |
| 505 } | |
| 506 | |
| 507 #ifdef CRYPTO_MDEBUG | |
| 508 CRYPTO_pop_info(); | |
| 509 CRYPTO_push_info("reading certs from certfile"); | |
| 510 #endif | |
| 511 | |
| 512 #ifdef CRYPTO_MDEBUG | |
| 513 CRYPTO_pop_info(); | |
| 514 CRYPTO_push_info("building chain"); | |
| 515 #endif | |
| 516 | |
| 517 /* If chaining get chain from user cert */ | |
| 518 if (chain) { | |
| 519 int vret; | |
| 520 STACK_OF(X509) *chain2; | |
| 521 X509_STORE *store = X509_STORE_new(); | |
| 522 if (!store) | |
| 523 { | |
| 524 BIO_printf (bio_err, "Memory allocation error\n"); | |
| 525 goto export_end; | |
| 526 } | |
| 527 if (!X509_STORE_load_locations(store, CAfile, CApath)) | |
| 528 X509_STORE_set_default_paths (store); | |
| 529 | |
| 530 vret = get_cert_chain (ucert, store, &chain2); | |
| 531 X509_STORE_free(store); | |
| 532 | |
| 533 if (!vret) { | |
| 534 /* Exclude verified certificate */ | |
| 535 for (i = 1; i < sk_X509_num (chain2) ; i++) | |
| 536 sk_X509_push(certs, sk_X509_value (chain2, i)); | |
| 537 /* Free first certificate */ | |
| 538 X509_free(sk_X509_value(chain2, 0)); | |
| 539 sk_X509_free(chain2); | |
| 540 } else { | |
| 541 if (vret >= 0) | |
| 542 BIO_printf (bio_err, "Error %s getting chain.\n"
, | |
| 543 X509_verify_cert_error_string(vret)); | |
| 544 else | |
| 545 ERR_print_errors(bio_err); | |
| 546 goto export_end; | |
| 547 } | |
| 548 } | |
| 549 | |
| 550 /* Add any CA names */ | |
| 551 | |
| 552 for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) | |
| 553 { | |
| 554 catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i); | |
| 555 X509_alias_set1(sk_X509_value(certs, i), catmp, -1); | |
| 556 } | |
| 557 | |
| 558 if (csp_name && key) | |
| 559 EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, | |
| 560 MBSTRING_ASC, (unsigned char *)csp_name, -1); | |
| 561 | |
| 562 if (add_lmk && key) | |
| 563 EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); | |
| 564 | |
| 565 #ifdef CRYPTO_MDEBUG | |
| 566 CRYPTO_pop_info(); | |
| 567 CRYPTO_push_info("reading password"); | |
| 568 #endif | |
| 569 | |
| 570 if(!noprompt && | |
| 571 EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:",
1)) | |
| 572 { | |
| 573 BIO_printf (bio_err, "Can't read Password\n"); | |
| 574 goto export_end; | |
| 575 } | |
| 576 if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); | |
| 577 | |
| 578 #ifdef CRYPTO_MDEBUG | |
| 579 CRYPTO_pop_info(); | |
| 580 CRYPTO_push_info("creating PKCS#12 structure"); | |
| 581 #endif | |
| 582 | |
| 583 p12 = PKCS12_create(cpass, name, key, ucert, certs, | |
| 584 key_pbe, cert_pbe, iter, -1, keytype); | |
| 585 | |
| 586 if (!p12) | |
| 587 { | |
| 588 ERR_print_errors (bio_err); | |
| 589 goto export_end; | |
| 590 } | |
| 591 | |
| 592 if (macalg) | |
| 593 { | |
| 594 macmd = EVP_get_digestbyname(macalg); | |
| 595 if (!macmd) | |
| 596 { | |
| 597 BIO_printf(bio_err, "Unknown digest algorithm %s\n", | |
| 598 macalg); | |
| 599 } | |
| 600 } | |
| 601 | |
| 602 if (maciter != -1) | |
| 603 PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); | |
| 604 | |
| 605 #ifdef CRYPTO_MDEBUG | |
| 606 CRYPTO_pop_info(); | |
| 607 CRYPTO_push_info("writing pkcs12"); | |
| 608 #endif | |
| 609 | |
| 610 i2d_PKCS12_bio(out, p12); | |
| 611 | |
| 612 ret = 0; | |
| 613 | |
| 614 export_end: | |
| 615 #ifdef CRYPTO_MDEBUG | |
| 616 CRYPTO_pop_info(); | |
| 617 CRYPTO_pop_info(); | |
| 618 CRYPTO_push_info("process -export_cert: freeing"); | |
| 619 #endif | |
| 620 | |
| 621 if (key) EVP_PKEY_free(key); | |
| 622 if (certs) sk_X509_pop_free(certs, X509_free); | |
| 623 if (ucert) X509_free(ucert); | |
| 624 | |
| 625 #ifdef CRYPTO_MDEBUG | |
| 626 CRYPTO_pop_info(); | |
| 627 #endif | |
| 628 goto end; | |
| 629 | |
| 630 } | |
| 631 | |
| 632 if (!(p12 = d2i_PKCS12_bio (in, NULL))) { | |
| 633 ERR_print_errors(bio_err); | |
| 634 goto end; | |
| 635 } | |
| 636 | |
| 637 #ifdef CRYPTO_MDEBUG | |
| 638 CRYPTO_push_info("read import password"); | |
| 639 #endif | |
| 640 if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password
:", 0)) { | |
| 641 BIO_printf (bio_err, "Can't read Password\n"); | |
| 642 goto end; | |
| 643 } | |
| 644 #ifdef CRYPTO_MDEBUG | |
| 645 CRYPTO_pop_info(); | |
| 646 #endif | |
| 647 | |
| 648 if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); | |
| 649 | |
| 650 if ((options & INFO) && p12->mac) BIO_printf (bio_err, "MAC Iteration %ld\n"
, p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1); | |
| 651 if(macver) { | |
| 652 #ifdef CRYPTO_MDEBUG | |
| 653 CRYPTO_push_info("verify MAC"); | |
| 654 #endif | |
| 655 /* If we enter empty password try no password first */ | |
| 656 if(!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { | |
| 657 /* If mac and crypto pass the same set it to NULL too */ | |
| 658 if(!twopass) cpass = NULL; | |
| 659 } else if (!PKCS12_verify_mac(p12, mpass, -1)) { | |
| 660 BIO_printf (bio_err, "Mac verify error: invalid password?\n"); | |
| 661 ERR_print_errors (bio_err); | |
| 662 goto end; | |
| 663 } | |
| 664 BIO_printf (bio_err, "MAC verified OK\n"); | |
| 665 #ifdef CRYPTO_MDEBUG | |
| 666 CRYPTO_pop_info(); | |
| 667 #endif | |
| 668 } | |
| 669 | |
| 670 #ifdef CRYPTO_MDEBUG | |
| 671 CRYPTO_push_info("output keys and certificates"); | |
| 672 #endif | |
| 673 if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) { | |
| 674 BIO_printf(bio_err, "Error outputting keys and certificates\n"); | |
| 675 ERR_print_errors (bio_err); | |
| 676 goto end; | |
| 677 } | |
| 678 #ifdef CRYPTO_MDEBUG | |
| 679 CRYPTO_pop_info(); | |
| 680 #endif | |
| 681 ret = 0; | |
| 682 end: | |
| 683 if (p12) PKCS12_free(p12); | |
| 684 if(export_cert || inrand) app_RAND_write_file(NULL, bio_err); | |
| 685 #ifdef CRYPTO_MDEBUG | |
| 686 CRYPTO_remove_all_info(); | |
| 687 #endif | |
| 688 BIO_free(in); | |
| 689 BIO_free_all(out); | |
| 690 if (canames) sk_OPENSSL_STRING_free(canames); | |
| 691 if(passin) OPENSSL_free(passin); | |
| 692 if(passout) OPENSSL_free(passout); | |
| 693 apps_shutdown(); | |
| 694 OPENSSL_EXIT(ret); | |
| 695 } | |
| 696 | |
| 697 int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass, | |
| 698 int passlen, int options, char *pempass) | |
| 699 { | |
| 700 STACK_OF(PKCS7) *asafes = NULL; | |
| 701 STACK_OF(PKCS12_SAFEBAG) *bags; | |
| 702 int i, bagnid; | |
| 703 int ret = 0; | |
| 704 PKCS7 *p7; | |
| 705 | |
| 706 if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0; | |
| 707 for (i = 0; i < sk_PKCS7_num (asafes); i++) { | |
| 708 p7 = sk_PKCS7_value (asafes, i); | |
| 709 bagnid = OBJ_obj2nid (p7->type); | |
| 710 if (bagnid == NID_pkcs7_data) { | |
| 711 bags = PKCS12_unpack_p7data(p7); | |
| 712 if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n")
; | |
| 713 } else if (bagnid == NID_pkcs7_encrypted) { | |
| 714 if (options & INFO) { | |
| 715 BIO_printf(bio_err, "PKCS7 Encrypted data: "); | |
| 716 alg_print(bio_err, | |
| 717 p7->d.encrypted->enc_data->algorithm); | |
| 718 } | |
| 719 bags = PKCS12_unpack_p7encdata(p7, pass, passlen); | |
| 720 } else continue; | |
| 721 if (!bags) goto err; | |
| 722 if (!dump_certs_pkeys_bags (out, bags, pass, passlen, | |
| 723 options, pempass)) { | |
| 724 sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); | |
| 725 goto err; | |
| 726 } | |
| 727 sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); | |
| 728 bags = NULL; | |
| 729 } | |
| 730 ret = 1; | |
| 731 | |
| 732 err: | |
| 733 | |
| 734 if (asafes) | |
| 735 sk_PKCS7_pop_free (asafes, PKCS7_free); | |
| 736 return ret; | |
| 737 } | |
| 738 | |
| 739 int dump_certs_pkeys_bags (BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, | |
| 740 char *pass, int passlen, int options, char *pempass) | |
| 741 { | |
| 742 int i; | |
| 743 for (i = 0; i < sk_PKCS12_SAFEBAG_num (bags); i++) { | |
| 744 if (!dump_certs_pkeys_bag (out, | |
| 745 sk_PKCS12_SAFEBAG_value (bags, i), | |
| 746 pass, passlen, | |
| 747 options, pempass)) | |
| 748 return 0; | |
| 749 } | |
| 750 return 1; | |
| 751 } | |
| 752 | |
| 753 int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass, | |
| 754 int passlen, int options, char *pempass) | |
| 755 { | |
| 756 EVP_PKEY *pkey; | |
| 757 PKCS8_PRIV_KEY_INFO *p8; | |
| 758 X509 *x509; | |
| 759 | |
| 760 switch (M_PKCS12_bag_type(bag)) | |
| 761 { | |
| 762 case NID_keyBag: | |
| 763 if (options & INFO) BIO_printf (bio_err, "Key bag\n"); | |
| 764 if (options & NOKEYS) return 1; | |
| 765 print_attribs (out, bag->attrib, "Bag Attributes"); | |
| 766 p8 = bag->value.keybag; | |
| 767 if (!(pkey = EVP_PKCS82PKEY (p8))) return 0; | |
| 768 print_attribs (out, p8->attributes, "Key Attributes"); | |
| 769 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass
); | |
| 770 EVP_PKEY_free(pkey); | |
| 771 break; | |
| 772 | |
| 773 case NID_pkcs8ShroudedKeyBag: | |
| 774 if (options & INFO) { | |
| 775 BIO_printf (bio_err, "Shrouded Keybag: "); | |
| 776 alg_print (bio_err, bag->value.shkeybag->algor); | |
| 777 } | |
| 778 if (options & NOKEYS) return 1; | |
| 779 print_attribs (out, bag->attrib, "Bag Attributes"); | |
| 780 if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) | |
| 781 return 0; | |
| 782 if (!(pkey = EVP_PKCS82PKEY (p8))) { | |
| 783 PKCS8_PRIV_KEY_INFO_free(p8); | |
| 784 return 0; | |
| 785 } | |
| 786 print_attribs (out, p8->attributes, "Key Attributes"); | |
| 787 PKCS8_PRIV_KEY_INFO_free(p8); | |
| 788 PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, pempass
); | |
| 789 EVP_PKEY_free(pkey); | |
| 790 break; | |
| 791 | |
| 792 case NID_certBag: | |
| 793 if (options & INFO) BIO_printf (bio_err, "Certificate bag\n"); | |
| 794 if (options & NOCERTS) return 1; | |
| 795 if (PKCS12_get_attr(bag, NID_localKeyID)) { | |
| 796 if (options & CACERTS) return 1; | |
| 797 } else if (options & CLCERTS) return 1; | |
| 798 print_attribs (out, bag->attrib, "Bag Attributes"); | |
| 799 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate ) | |
| 800 return 1; | |
| 801 if (!(x509 = PKCS12_certbag2x509(bag))) return 0; | |
| 802 dump_cert_text (out, x509); | |
| 803 PEM_write_bio_X509 (out, x509); | |
| 804 X509_free(x509); | |
| 805 break; | |
| 806 | |
| 807 case NID_safeContentsBag: | |
| 808 if (options & INFO) BIO_printf (bio_err, "Safe Contents bag\n"); | |
| 809 print_attribs (out, bag->attrib, "Bag Attributes"); | |
| 810 return dump_certs_pkeys_bags (out, bag->value.safes, pass, | |
| 811 passlen, options, pe
mpass); | |
| 812 | |
| 813 default: | |
| 814 BIO_printf (bio_err, "Warning unsupported bag type: "); | |
| 815 i2a_ASN1_OBJECT (bio_err, bag->type); | |
| 816 BIO_printf (bio_err, "\n"); | |
| 817 return 1; | |
| 818 break; | |
| 819 } | |
| 820 return 1; | |
| 821 } | |
| 822 | |
| 823 /* Given a single certificate return a verified chain or NULL if error */ | |
| 824 | |
| 825 /* Hope this is OK .... */ | |
| 826 | |
| 827 int get_cert_chain (X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) | |
| 828 { | |
| 829 X509_STORE_CTX store_ctx; | |
| 830 STACK_OF(X509) *chn; | |
| 831 int i = 0; | |
| 832 | |
| 833 /* FIXME: Should really check the return status of X509_STORE_CTX_init | |
| 834 * for an error, but how that fits into the return value of this | |
| 835 * function is less obvious. */ | |
| 836 X509_STORE_CTX_init(&store_ctx, store, cert, NULL); | |
| 837 if (X509_verify_cert(&store_ctx) <= 0) { | |
| 838 i = X509_STORE_CTX_get_error (&store_ctx); | |
| 839 if (i == 0) | |
| 840 /* avoid returning 0 if X509_verify_cert() did not | |
| 841 * set an appropriate error value in the context */ | |
| 842 i = -1; | |
| 843 chn = NULL; | |
| 844 goto err; | |
| 845 } else | |
| 846 chn = X509_STORE_CTX_get1_chain(&store_ctx); | |
| 847 err: | |
| 848 X509_STORE_CTX_cleanup(&store_ctx); | |
| 849 *chain = chn; | |
| 850 | |
| 851 return i; | |
| 852 } | |
| 853 | |
| 854 int alg_print (BIO *x, X509_ALGOR *alg) | |
| 855 { | |
| 856 PBEPARAM *pbe; | |
| 857 const unsigned char *p; | |
| 858 p = alg->parameter->value.sequence->data; | |
| 859 pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); | |
| 860 if (!pbe) | |
| 861 return 1; | |
| 862 BIO_printf (bio_err, "%s, Iteration %ld\n", | |
| 863 OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)), | |
| 864 ASN1_INTEGER_get(pbe->iter)); | |
| 865 PBEPARAM_free (pbe); | |
| 866 return 1; | |
| 867 } | |
| 868 | |
| 869 /* Load all certificates from a given file */ | |
| 870 | |
| 871 int cert_load(BIO *in, STACK_OF(X509) *sk) | |
| 872 { | |
| 873 int ret; | |
| 874 X509 *cert; | |
| 875 ret = 0; | |
| 876 #ifdef CRYPTO_MDEBUG | |
| 877 CRYPTO_push_info("cert_load(): reading one cert"); | |
| 878 #endif | |
| 879 while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { | |
| 880 #ifdef CRYPTO_MDEBUG | |
| 881 CRYPTO_pop_info(); | |
| 882 #endif | |
| 883 ret = 1; | |
| 884 sk_X509_push(sk, cert); | |
| 885 #ifdef CRYPTO_MDEBUG | |
| 886 CRYPTO_push_info("cert_load(): reading one cert"); | |
| 887 #endif | |
| 888 } | |
| 889 #ifdef CRYPTO_MDEBUG | |
| 890 CRYPTO_pop_info(); | |
| 891 #endif | |
| 892 if(ret) ERR_clear_error(); | |
| 893 return ret; | |
| 894 } | |
| 895 | |
| 896 /* Generalised attribute print: handle PKCS#8 and bag attributes */ | |
| 897 | |
| 898 int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst,const char *name) | |
| 899 { | |
| 900 X509_ATTRIBUTE *attr; | |
| 901 ASN1_TYPE *av; | |
| 902 char *value; | |
| 903 int i, attr_nid; | |
| 904 if(!attrlst) { | |
| 905 BIO_printf(out, "%s: <No Attributes>\n", name); | |
| 906 return 1; | |
| 907 } | |
| 908 if(!sk_X509_ATTRIBUTE_num(attrlst)) { | |
| 909 BIO_printf(out, "%s: <Empty Attributes>\n", name); | |
| 910 return 1; | |
| 911 } | |
| 912 BIO_printf(out, "%s\n", name); | |
| 913 for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { | |
| 914 attr = sk_X509_ATTRIBUTE_value(attrlst, i); | |
| 915 attr_nid = OBJ_obj2nid(attr->object); | |
| 916 BIO_printf(out, " "); | |
| 917 if(attr_nid == NID_undef) { | |
| 918 i2a_ASN1_OBJECT (out, attr->object); | |
| 919 BIO_printf(out, ": "); | |
| 920 } else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); | |
| 921 | |
| 922 if(sk_ASN1_TYPE_num(attr->value.set)) { | |
| 923 av = sk_ASN1_TYPE_value(attr->value.set, 0); | |
| 924 switch(av->type) { | |
| 925 case V_ASN1_BMPSTRING: | |
| 926 value = OPENSSL_uni2asc(av->value.bmpstring->dat
a, | |
| 927 av->value.bmpstring->length); | |
| 928 BIO_printf(out, "%s\n", value); | |
| 929 OPENSSL_free(value); | |
| 930 break; | |
| 931 | |
| 932 case V_ASN1_OCTET_STRING: | |
| 933 hex_prin(out, av->value.octet_string->data, | |
| 934 av->value.octet_string->length); | |
| 935 BIO_printf(out, "\n"); | |
| 936 break; | |
| 937 | |
| 938 case V_ASN1_BIT_STRING: | |
| 939 hex_prin(out, av->value.bit_string->data, | |
| 940 av->value.bit_string->length); | |
| 941 BIO_printf(out, "\n"); | |
| 942 break; | |
| 943 | |
| 944 default: | |
| 945 BIO_printf(out, "<Unsupported tag %d>\n"
, av->type); | |
| 946 break; | |
| 947 } | |
| 948 } else BIO_printf(out, "<No Values>\n"); | |
| 949 } | |
| 950 return 1; | |
| 951 } | |
| 952 | |
| 953 void hex_prin(BIO *out, unsigned char *buf, int len) | |
| 954 { | |
| 955 int i; | |
| 956 for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]); | |
| 957 } | |
| 958 | |
| 959 static int set_pbe(BIO *err, int *ppbe, const char *str) | |
| 960 { | |
| 961 if (!str) | |
| 962 return 0; | |
| 963 if (!strcmp(str, "NONE")) | |
| 964 { | |
| 965 *ppbe = -1; | |
| 966 return 1; | |
| 967 } | |
| 968 *ppbe=OBJ_txt2nid(str); | |
| 969 if (*ppbe == NID_undef) | |
| 970 { | |
| 971 BIO_printf(bio_err, "Unknown PBE algorithm %s\n", str); | |
| 972 return 0; | |
| 973 } | |
| 974 return 1; | |
| 975 } | |
| 976 | |
| 977 #endif | |
| OLD | NEW |