pkcs12.c revision 296465
150397Sobrien/* pkcs12.c */ 250397Sobrien/* 350397Sobrien * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 450397Sobrien * project. 550397Sobrien */ 650397Sobrien/* ==================================================================== 750397Sobrien * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved. 850397Sobrien * 950397Sobrien * Redistribution and use in source and binary forms, with or without 1050397Sobrien * modification, are permitted provided that the following conditions 1150397Sobrien * are met: 1250397Sobrien * 1350397Sobrien * 1. Redistributions of source code must retain the above copyright 1450397Sobrien * notice, this list of conditions and the following disclaimer. 1550397Sobrien * 1650397Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1750397Sobrien * notice, this list of conditions and the following disclaimer in 1850397Sobrien * the documentation and/or other materials provided with the 1950397Sobrien * distribution. 2050397Sobrien * 2150397Sobrien * 3. All advertising materials mentioning features or use of this 2250397Sobrien * software must display the following acknowledgment: 2350397Sobrien * "This product includes software developed by the OpenSSL Project 2450397Sobrien * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2550397Sobrien * 2650397Sobrien * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2750397Sobrien * endorse or promote products derived from this software without 2850397Sobrien * prior written permission. For written permission, please contact 2950397Sobrien * licensing@OpenSSL.org. 3050397Sobrien * 3150397Sobrien * 5. Products derived from this software may not be called "OpenSSL" 3250397Sobrien * nor may "OpenSSL" appear in their names without prior written 3350397Sobrien * permission of the OpenSSL Project. 3450397Sobrien * 3550397Sobrien * 6. Redistributions of any form whatsoever must retain the following 3650397Sobrien * acknowledgment: 3750397Sobrien * "This product includes software developed by the OpenSSL Project 3850397Sobrien * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3950397Sobrien * 4050397Sobrien * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4150397Sobrien * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4250397Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4350397Sobrien * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4450397Sobrien * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4550397Sobrien * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4650397Sobrien * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4750397Sobrien * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4850397Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4950397Sobrien * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 5050397Sobrien * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5150397Sobrien * OF THE POSSIBILITY OF SUCH DAMAGE. 5250397Sobrien * ==================================================================== 5350397Sobrien * 5450397Sobrien * This product includes cryptographic software written by Eric Young 5550397Sobrien * (eay@cryptsoft.com). This product includes software written by Tim 5650397Sobrien * Hudson (tjh@cryptsoft.com). 5750397Sobrien * 5850397Sobrien */ 5950397Sobrien 6050397Sobrien#include <openssl/opensslconf.h> 6150397Sobrien#if !defined(OPENSSL_NO_DES) && !defined(OPENSSL_NO_SHA1) 6250397Sobrien 6350397Sobrien# include <stdio.h> 6450397Sobrien# include <stdlib.h> 6550397Sobrien# include <string.h> 6650397Sobrien# include "apps.h" 6750397Sobrien# include <openssl/crypto.h> 6850397Sobrien# include <openssl/err.h> 6950397Sobrien# include <openssl/pem.h> 7050397Sobrien# include <openssl/pkcs12.h> 7150397Sobrien 7250397Sobrien# ifdef OPENSSL_SYS_NETWARE 7350397Sobrien/* Rename these functions to avoid name clashes on NetWare OS */ 7450397Sobrien# define uni2asc OPENSSL_uni2asc 7550397Sobrien# define asc2uni OPENSSL_asc2uni 7650397Sobrien# endif 7750397Sobrien 7850397Sobrien# define PROG pkcs12_main 7950397Sobrien 8050397Sobrienconst EVP_CIPHER *enc; 8150397Sobrien 8250397Sobrien# define NOKEYS 0x1 8350397Sobrien# define NOCERTS 0x2 8450397Sobrien# define INFO 0x4 8550397Sobrien# define CLCERTS 0x8 8650397Sobrien# define CACERTS 0x10 8750397Sobrien 8850397Sobrienint get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain); 8950397Sobrienint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, 9050397Sobrien int options, char *pempass); 9150397Sobrienint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, 9250397Sobrien char *pass, int passlen, int options, 9350397Sobrien char *pempass); 9450397Sobrienint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, 9550397Sobrien int passlen, int options, char *pempass); 9650397Sobrienint print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, 9750397Sobrien const char *name); 9850397Sobrienvoid hex_prin(BIO *out, unsigned char *buf, int len); 9950397Sobrienint alg_print(BIO *x, X509_ALGOR *alg); 10050397Sobrienint cert_load(BIO *in, STACK_OF(X509) *sk); 10150397Sobrien 10250397Sobrienint MAIN(int, char **); 10350397Sobrien 10450397Sobrienint MAIN(int argc, char **argv) 10550397Sobrien{ 10650397Sobrien ENGINE *e = NULL; 10750397Sobrien char *infile = NULL, *outfile = NULL, *keyname = NULL; 10850397Sobrien char *certfile = NULL; 10950397Sobrien BIO *in = NULL, *out = NULL; 11050397Sobrien char **args; 11150397Sobrien char *name = NULL; 11250397Sobrien char *csp_name = NULL; 11350397Sobrien int add_lmk = 0; 11450397Sobrien PKCS12 *p12 = NULL; 11550397Sobrien char pass[50], macpass[50]; 11650397Sobrien int export_cert = 0; 11750397Sobrien int options = 0; 11850397Sobrien int chain = 0; 11950397Sobrien int badarg = 0; 12050397Sobrien int iter = PKCS12_DEFAULT_ITER; 12150397Sobrien int maciter = PKCS12_DEFAULT_ITER; 12250397Sobrien int twopass = 0; 12350397Sobrien int keytype = 0; 12450397Sobrien int cert_pbe; 12550397Sobrien int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 12650397Sobrien int ret = 1; 12750397Sobrien int macver = 1; 12850397Sobrien int noprompt = 0; 12950397Sobrien STACK *canames = NULL; 13050397Sobrien char *cpass = NULL, *mpass = NULL; 13150397Sobrien char *passargin = NULL, *passargout = NULL, *passarg = NULL; 13250397Sobrien char *passin = NULL, *passout = NULL; 13350397Sobrien char *inrand = NULL; 13450397Sobrien char *CApath = NULL, *CAfile = NULL; 13550397Sobrien# ifndef OPENSSL_NO_ENGINE 13650397Sobrien char *engine = NULL; 13750397Sobrien# endif 13850397Sobrien 13950397Sobrien apps_startup(); 14050397Sobrien 14150397Sobrien# ifdef OPENSSL_FIPS 14250397Sobrien if (FIPS_mode()) 14350397Sobrien cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 14450397Sobrien else 14550397Sobrien# endif 14650397Sobrien cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; 14750397Sobrien 14850397Sobrien enc = EVP_des_ede3_cbc(); 14950397Sobrien if (bio_err == NULL) 15050397Sobrien bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); 15150397Sobrien 15250397Sobrien if (!load_config(bio_err, NULL)) 15350397Sobrien goto end; 15450397Sobrien 15550397Sobrien args = argv + 1; 15650397Sobrien 15750397Sobrien while (*args) { 15850397Sobrien if (*args[0] == '-') { 15950397Sobrien if (!strcmp(*args, "-nokeys")) 16050397Sobrien options |= NOKEYS; 16150397Sobrien else if (!strcmp(*args, "-keyex")) 16250397Sobrien keytype = KEY_EX; 16350397Sobrien else if (!strcmp(*args, "-keysig")) 16450397Sobrien keytype = KEY_SIG; 16550397Sobrien else if (!strcmp(*args, "-nocerts")) 16650397Sobrien options |= NOCERTS; 16750397Sobrien else if (!strcmp(*args, "-clcerts")) 16850397Sobrien options |= CLCERTS; 16950397Sobrien else if (!strcmp(*args, "-cacerts")) 17050397Sobrien options |= CACERTS; 17150397Sobrien else if (!strcmp(*args, "-noout")) 17250397Sobrien options |= (NOKEYS | NOCERTS); 17350397Sobrien else if (!strcmp(*args, "-info")) 17450397Sobrien options |= INFO; 17550397Sobrien else if (!strcmp(*args, "-chain")) 17650397Sobrien chain = 1; 17750397Sobrien else if (!strcmp(*args, "-twopass")) 17850397Sobrien twopass = 1; 17950397Sobrien else if (!strcmp(*args, "-nomacver")) 18050397Sobrien macver = 0; 18150397Sobrien else if (!strcmp(*args, "-descert")) 18250397Sobrien cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; 18350397Sobrien else if (!strcmp(*args, "-export")) 18450397Sobrien export_cert = 1; 18550397Sobrien else if (!strcmp(*args, "-des")) 18650397Sobrien enc = EVP_des_cbc(); 18750397Sobrien else if (!strcmp(*args, "-des3")) 18850397Sobrien enc = EVP_des_ede3_cbc(); 18950397Sobrien# ifndef OPENSSL_NO_IDEA 19050397Sobrien else if (!strcmp(*args, "-idea")) 19150397Sobrien enc = EVP_idea_cbc(); 19250397Sobrien# endif 19350397Sobrien# ifndef OPENSSL_NO_SEED 19450397Sobrien else if (!strcmp(*args, "-seed")) 19550397Sobrien enc = EVP_seed_cbc(); 19650397Sobrien# endif 19750397Sobrien# ifndef OPENSSL_NO_AES 19850397Sobrien else if (!strcmp(*args, "-aes128")) 19950397Sobrien enc = EVP_aes_128_cbc(); 20050397Sobrien else if (!strcmp(*args, "-aes192")) 20150397Sobrien enc = EVP_aes_192_cbc(); 20250397Sobrien else if (!strcmp(*args, "-aes256")) 20350397Sobrien enc = EVP_aes_256_cbc(); 20450397Sobrien# endif 20550397Sobrien# ifndef OPENSSL_NO_CAMELLIA 20650397Sobrien else if (!strcmp(*args, "-camellia128")) 20750397Sobrien enc = EVP_camellia_128_cbc(); 20850397Sobrien else if (!strcmp(*args, "-camellia192")) 20950397Sobrien enc = EVP_camellia_192_cbc(); 21050397Sobrien else if (!strcmp(*args, "-camellia256")) 21150397Sobrien enc = EVP_camellia_256_cbc(); 21250397Sobrien# endif 21350397Sobrien else if (!strcmp(*args, "-noiter")) 21450397Sobrien iter = 1; 21550397Sobrien else if (!strcmp(*args, "-maciter")) 21650397Sobrien maciter = PKCS12_DEFAULT_ITER; 21750397Sobrien else if (!strcmp(*args, "-nomaciter")) 21850397Sobrien maciter = 1; 21950397Sobrien else if (!strcmp(*args, "-nomac")) 22050397Sobrien maciter = -1; 22150397Sobrien else if (!strcmp(*args, "-nodes")) 22250397Sobrien enc = NULL; 22350397Sobrien else if (!strcmp(*args, "-certpbe")) { 22450397Sobrien if (args[1]) { 22550397Sobrien args++; 22650397Sobrien if (!strcmp(*args, "NONE")) 22750397Sobrien cert_pbe = -1; 22850397Sobrien else 22950397Sobrien cert_pbe = OBJ_txt2nid(*args); 23050397Sobrien if (cert_pbe == NID_undef) { 23150397Sobrien BIO_printf(bio_err, 23250397Sobrien "Unknown PBE algorithm %s\n", *args); 23350397Sobrien badarg = 1; 23450397Sobrien } 23550397Sobrien } else 23650397Sobrien badarg = 1; 23750397Sobrien } else if (!strcmp(*args, "-keypbe")) { 23850397Sobrien if (args[1]) { 23950397Sobrien args++; 24050397Sobrien if (!strcmp(*args, "NONE")) 24150397Sobrien key_pbe = -1; 24250397Sobrien else 24350397Sobrien key_pbe = OBJ_txt2nid(*args); 24450397Sobrien if (key_pbe == NID_undef) { 24550397Sobrien BIO_printf(bio_err, 24650397Sobrien "Unknown PBE algorithm %s\n", *args); 24750397Sobrien badarg = 1; 24850397Sobrien } 24950397Sobrien } else 25050397Sobrien badarg = 1; 25150397Sobrien } else if (!strcmp(*args, "-rand")) { 25250397Sobrien if (args[1]) { 25350397Sobrien args++; 25450397Sobrien inrand = *args; 25550397Sobrien } else 25650397Sobrien badarg = 1; 25750397Sobrien } else if (!strcmp(*args, "-inkey")) { 25850397Sobrien if (args[1]) { 25950397Sobrien args++; 26050397Sobrien keyname = *args; 26150397Sobrien } else 26250397Sobrien badarg = 1; 26350397Sobrien } else if (!strcmp(*args, "-certfile")) { 26450397Sobrien if (args[1]) { 26550397Sobrien args++; 26650397Sobrien certfile = *args; 26750397Sobrien } else 26850397Sobrien badarg = 1; 26950397Sobrien } else if (!strcmp(*args, "-name")) { 27050397Sobrien if (args[1]) { 27150397Sobrien args++; 27250397Sobrien name = *args; 27350397Sobrien } else 27450397Sobrien badarg = 1; 27550397Sobrien } else if (!strcmp(*args, "-LMK")) 27650397Sobrien add_lmk = 1; 27750397Sobrien else if (!strcmp(*args, "-CSP")) { 27850397Sobrien if (args[1]) { 27950397Sobrien args++; 28050397Sobrien csp_name = *args; 28150397Sobrien } else 28250397Sobrien badarg = 1; 28350397Sobrien } else if (!strcmp(*args, "-caname")) { 28450397Sobrien if (args[1]) { 28550397Sobrien args++; 28650397Sobrien if (!canames) 28750397Sobrien canames = sk_new_null(); 28850397Sobrien sk_push(canames, *args); 28950397Sobrien } else 29050397Sobrien badarg = 1; 29150397Sobrien } else if (!strcmp(*args, "-in")) { 29250397Sobrien if (args[1]) { 29350397Sobrien args++; 29450397Sobrien infile = *args; 29550397Sobrien } else 29650397Sobrien badarg = 1; 29750397Sobrien } else if (!strcmp(*args, "-out")) { 29850397Sobrien if (args[1]) { 29950397Sobrien args++; 30050397Sobrien outfile = *args; 30150397Sobrien } else 30250397Sobrien badarg = 1; 30350397Sobrien } else if (!strcmp(*args, "-passin")) { 30450397Sobrien if (args[1]) { 30550397Sobrien args++; 30650397Sobrien passargin = *args; 30750397Sobrien } else 30850397Sobrien badarg = 1; 30950397Sobrien } else if (!strcmp(*args, "-passout")) { 31050397Sobrien if (args[1]) { 31150397Sobrien args++; 31250397Sobrien passargout = *args; 31350397Sobrien } else 31450397Sobrien badarg = 1; 31550397Sobrien } else if (!strcmp(*args, "-password")) { 31650397Sobrien if (args[1]) { 31750397Sobrien args++; 31850397Sobrien passarg = *args; 31950397Sobrien noprompt = 1; 32050397Sobrien } else 32150397Sobrien badarg = 1; 32250397Sobrien } else if (!strcmp(*args, "-CApath")) { 32350397Sobrien if (args[1]) { 32450397Sobrien args++; 32550397Sobrien CApath = *args; 32650397Sobrien } else 32750397Sobrien badarg = 1; 32850397Sobrien } else if (!strcmp(*args, "-CAfile")) { 32950397Sobrien if (args[1]) { 33050397Sobrien args++; 33150397Sobrien CAfile = *args; 33250397Sobrien } else 33350397Sobrien badarg = 1; 33450397Sobrien# ifndef OPENSSL_NO_ENGINE 33550397Sobrien } else if (!strcmp(*args, "-engine")) { 33650397Sobrien if (args[1]) { 33750397Sobrien args++; 33850397Sobrien engine = *args; 33950397Sobrien } else 34050397Sobrien badarg = 1; 34150397Sobrien# endif 34250397Sobrien } else 34350397Sobrien badarg = 1; 34450397Sobrien 34550397Sobrien } else 34650397Sobrien badarg = 1; 34750397Sobrien args++; 34850397Sobrien } 34950397Sobrien 35050397Sobrien if (badarg) { 35150397Sobrien BIO_printf(bio_err, "Usage: pkcs12 [options]\n"); 35250397Sobrien BIO_printf(bio_err, "where options are\n"); 35350397Sobrien BIO_printf(bio_err, "-export output PKCS12 file\n"); 35450397Sobrien BIO_printf(bio_err, "-chain add certificate chain\n"); 35550397Sobrien BIO_printf(bio_err, "-inkey file private key if not infile\n"); 35650397Sobrien BIO_printf(bio_err, "-certfile f add all certs in f\n"); 35750397Sobrien BIO_printf(bio_err, "-CApath arg - PEM format directory of CA's\n"); 35850397Sobrien BIO_printf(bio_err, "-CAfile arg - PEM format file of CA's\n"); 35950397Sobrien BIO_printf(bio_err, "-name \"name\" use name as friendly name\n"); 36050397Sobrien BIO_printf(bio_err, 36150397Sobrien "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n"); 36250397Sobrien BIO_printf(bio_err, "-in infile input filename\n"); 36350397Sobrien BIO_printf(bio_err, "-out outfile output filename\n"); 36450397Sobrien BIO_printf(bio_err, 36550397Sobrien "-noout don't output anything, just verify.\n"); 36650397Sobrien BIO_printf(bio_err, "-nomacver don't verify MAC.\n"); 36750397Sobrien BIO_printf(bio_err, "-nocerts don't output certificates.\n"); 36850397Sobrien BIO_printf(bio_err, 36950397Sobrien "-clcerts only output client certificates.\n"); 37050397Sobrien BIO_printf(bio_err, "-cacerts only output CA certificates.\n"); 37150397Sobrien BIO_printf(bio_err, "-nokeys don't output private keys.\n"); 37250397Sobrien BIO_printf(bio_err, 37350397Sobrien "-info give info about PKCS#12 structure.\n"); 37450397Sobrien BIO_printf(bio_err, "-des encrypt private keys with DES\n"); 37550397Sobrien BIO_printf(bio_err, 37650397Sobrien "-des3 encrypt private keys with triple DES (default)\n"); 37750397Sobrien# ifndef OPENSSL_NO_IDEA 37850397Sobrien BIO_printf(bio_err, "-idea encrypt private keys with idea\n"); 37950397Sobrien# endif 38050397Sobrien# ifndef OPENSSL_NO_SEED 38150397Sobrien BIO_printf(bio_err, "-seed encrypt private keys with seed\n"); 38250397Sobrien# endif 38350397Sobrien# ifndef OPENSSL_NO_AES 38450397Sobrien BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); 38550397Sobrien BIO_printf(bio_err, 38650397Sobrien " encrypt PEM output with cbc aes\n"); 38750397Sobrien# endif 38850397Sobrien# ifndef OPENSSL_NO_CAMELLIA 38950397Sobrien BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); 39050397Sobrien BIO_printf(bio_err, 39150397Sobrien " encrypt PEM output with cbc camellia\n"); 39250397Sobrien# endif 39350397Sobrien BIO_printf(bio_err, "-nodes don't encrypt private keys\n"); 39450397Sobrien BIO_printf(bio_err, "-noiter don't use encryption iteration\n"); 39550397Sobrien BIO_printf(bio_err, "-maciter use MAC iteration\n"); 39650397Sobrien BIO_printf(bio_err, 39750397Sobrien "-twopass separate MAC, encryption passwords\n"); 39850397Sobrien BIO_printf(bio_err, 39950397Sobrien "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n"); 40050397Sobrien BIO_printf(bio_err, 40150397Sobrien "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n"); 40250397Sobrien BIO_printf(bio_err, 40350397Sobrien "-keypbe alg specify private key PBE algorithm (default 3DES)\n"); 40450397Sobrien BIO_printf(bio_err, "-keyex set MS key exchange type\n"); 40550397Sobrien BIO_printf(bio_err, "-keysig set MS key signature type\n"); 40650397Sobrien BIO_printf(bio_err, 40750397Sobrien "-password p set import/export password source\n"); 40850397Sobrien BIO_printf(bio_err, "-passin p input file pass phrase source\n"); 40950397Sobrien BIO_printf(bio_err, "-passout p output file pass phrase source\n"); 41050397Sobrien# ifndef OPENSSL_NO_ENGINE 41150397Sobrien BIO_printf(bio_err, 41250397Sobrien "-engine e use engine e, possibly a hardware device.\n"); 41350397Sobrien# endif 41450397Sobrien BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, 41550397Sobrien LIST_SEPARATOR_CHAR); 41650397Sobrien BIO_printf(bio_err, 41750397Sobrien " load the file (or the files in the directory) into\n"); 41850397Sobrien BIO_printf(bio_err, " the random number generator\n"); 41950397Sobrien BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); 42050397Sobrien BIO_printf(bio_err, 42150397Sobrien "-LMK Add local machine keyset attribute to private key\n"); 42250397Sobrien goto end; 42350397Sobrien } 42450397Sobrien# ifndef OPENSSL_NO_ENGINE 42550397Sobrien e = setup_engine(bio_err, engine, 0); 42650397Sobrien# endif 42750397Sobrien 42850397Sobrien if (passarg) { 42950397Sobrien if (export_cert) 43050397Sobrien passargout = passarg; 43150397Sobrien else 43250397Sobrien passargin = passarg; 43350397Sobrien } 43450397Sobrien 43550397Sobrien if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { 43650397Sobrien BIO_printf(bio_err, "Error getting passwords\n"); 43750397Sobrien goto end; 43850397Sobrien } 43950397Sobrien 44050397Sobrien if (!cpass) { 44150397Sobrien if (export_cert) 44250397Sobrien cpass = passout; 44350397Sobrien else 44450397Sobrien cpass = passin; 44550397Sobrien } 44650397Sobrien 44750397Sobrien if (cpass) { 44850397Sobrien mpass = cpass; 44950397Sobrien noprompt = 1; 45050397Sobrien } else { 45150397Sobrien cpass = pass; 45250397Sobrien mpass = macpass; 45350397Sobrien } 45450397Sobrien 45550397Sobrien if (export_cert || inrand) { 45650397Sobrien app_RAND_load_file(NULL, bio_err, (inrand != NULL)); 45750397Sobrien if (inrand != NULL) 45850397Sobrien BIO_printf(bio_err, "%ld semi-random bytes loaded\n", 45950397Sobrien app_RAND_load_files(inrand)); 46050397Sobrien } 46150397Sobrien ERR_load_crypto_strings(); 46250397Sobrien 46350397Sobrien# ifdef CRYPTO_MDEBUG 46450397Sobrien CRYPTO_push_info("read files"); 46550397Sobrien# endif 46650397Sobrien 46750397Sobrien if (!infile) 46850397Sobrien in = BIO_new_fp(stdin, BIO_NOCLOSE); 46950397Sobrien else 47050397Sobrien in = BIO_new_file(infile, "rb"); 47150397Sobrien if (!in) { 47250397Sobrien BIO_printf(bio_err, "Error opening input file %s\n", 47350397Sobrien infile ? infile : "<stdin>"); 47450397Sobrien perror(infile); 47550397Sobrien goto end; 47650397Sobrien } 47750397Sobrien# ifdef CRYPTO_MDEBUG 47850397Sobrien CRYPTO_pop_info(); 47950397Sobrien CRYPTO_push_info("write files"); 48050397Sobrien# endif 48150397Sobrien 48250397Sobrien if (!outfile) { 48350397Sobrien out = BIO_new_fp(stdout, BIO_NOCLOSE); 48450397Sobrien# ifdef OPENSSL_SYS_VMS 48550397Sobrien { 48650397Sobrien BIO *tmpbio = BIO_new(BIO_f_linebuffer()); 48750397Sobrien out = BIO_push(tmpbio, out); 48850397Sobrien } 48950397Sobrien# endif 49050397Sobrien } else 49150397Sobrien out = BIO_new_file(outfile, "wb"); 49250397Sobrien if (!out) { 49350397Sobrien BIO_printf(bio_err, "Error opening output file %s\n", 49450397Sobrien outfile ? outfile : "<stdout>"); 49550397Sobrien perror(outfile); 49650397Sobrien goto end; 49750397Sobrien } 49850397Sobrien if (twopass) { 49950397Sobrien# ifdef CRYPTO_MDEBUG 50050397Sobrien CRYPTO_push_info("read MAC password"); 50150397Sobrien# endif 50250397Sobrien if (EVP_read_pw_string 50350397Sobrien (macpass, sizeof macpass, "Enter MAC Password:", export_cert)) { 50450397Sobrien BIO_printf(bio_err, "Can't read Password\n"); 50550397Sobrien goto end; 50650397Sobrien } 50750397Sobrien# ifdef CRYPTO_MDEBUG 50850397Sobrien CRYPTO_pop_info(); 50950397Sobrien# endif 51050397Sobrien } 51150397Sobrien 51250397Sobrien if (export_cert) { 51350397Sobrien EVP_PKEY *key = NULL; 51450397Sobrien X509 *ucert = NULL, *x = NULL; 51550397Sobrien STACK_OF(X509) *certs = NULL; 51650397Sobrien unsigned char *catmp = NULL; 51750397Sobrien int i; 51850397Sobrien 51950397Sobrien if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { 52050397Sobrien BIO_printf(bio_err, "Nothing to do!\n"); 52150397Sobrien goto export_end; 52250397Sobrien } 52350397Sobrien 52450397Sobrien if (options & NOCERTS) 52550397Sobrien chain = 0; 52650397Sobrien 52750397Sobrien# ifdef CRYPTO_MDEBUG 52850397Sobrien CRYPTO_push_info("process -export_cert"); 52950397Sobrien CRYPTO_push_info("reading private key"); 53050397Sobrien# endif 53150397Sobrien if (!(options & NOKEYS)) { 53250397Sobrien key = load_key(bio_err, keyname ? keyname : infile, 53350397Sobrien FORMAT_PEM, 1, passin, e, "private key"); 53450397Sobrien if (!key) 53550397Sobrien goto export_end; 53650397Sobrien } 53750397Sobrien# ifdef CRYPTO_MDEBUG 53850397Sobrien CRYPTO_pop_info(); 53950397Sobrien CRYPTO_push_info("reading certs from input"); 54050397Sobrien# endif 54150397Sobrien 54250397Sobrien /* Load in all certs in input file */ 54350397Sobrien if (!(options & NOCERTS)) { 54450397Sobrien certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, 54550397Sobrien "certificates"); 54650397Sobrien if (!certs) 54750397Sobrien goto export_end; 54850397Sobrien 54950397Sobrien if (key) { 55050397Sobrien /* Look for matching private key */ 55150397Sobrien for (i = 0; i < sk_X509_num(certs); i++) { 55250397Sobrien x = sk_X509_value(certs, i); 55350397Sobrien if (X509_check_private_key(x, key)) { 55450397Sobrien ucert = x; 55550397Sobrien /* Zero keyid and alias */ 55650397Sobrien X509_keyid_set1(ucert, NULL, 0); 55750397Sobrien X509_alias_set1(ucert, NULL, 0); 55850397Sobrien /* Remove from list */ 55950397Sobrien (void)sk_X509_delete(certs, i); 56050397Sobrien break; 56150397Sobrien } 56250397Sobrien } 56350397Sobrien if (!ucert) { 56450397Sobrien BIO_printf(bio_err, 56550397Sobrien "No certificate matches private key\n"); 56650397Sobrien goto export_end; 56750397Sobrien } 56850397Sobrien } 56950397Sobrien 57050397Sobrien } 57150397Sobrien# ifdef CRYPTO_MDEBUG 57250397Sobrien CRYPTO_pop_info(); 57350397Sobrien CRYPTO_push_info("reading certs from input 2"); 57450397Sobrien# endif 57550397Sobrien 57650397Sobrien /* Add any more certificates asked for */ 57750397Sobrien if (certfile) { 57850397Sobrien STACK_OF(X509) *morecerts = NULL; 57950397Sobrien if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, 58050397Sobrien NULL, e, 58150397Sobrien "certificates from certfile"))) 58250397Sobrien goto export_end; 58350397Sobrien while (sk_X509_num(morecerts) > 0) 58450397Sobrien sk_X509_push(certs, sk_X509_shift(morecerts)); 58550397Sobrien sk_X509_free(morecerts); 58650397Sobrien } 58750397Sobrien# ifdef CRYPTO_MDEBUG 58850397Sobrien CRYPTO_pop_info(); 58950397Sobrien CRYPTO_push_info("reading certs from certfile"); 59050397Sobrien# endif 59150397Sobrien 59250397Sobrien# ifdef CRYPTO_MDEBUG 59350397Sobrien CRYPTO_pop_info(); 59450397Sobrien CRYPTO_push_info("building chain"); 59550397Sobrien# endif 59650397Sobrien 59750397Sobrien /* If chaining get chain from user cert */ 59850397Sobrien if (chain) { 59950397Sobrien int vret; 60050397Sobrien STACK_OF(X509) *chain2; 60150397Sobrien X509_STORE *store = X509_STORE_new(); 60250397Sobrien if (!store) { 60350397Sobrien BIO_printf(bio_err, "Memory allocation error\n"); 60450397Sobrien goto export_end; 60550397Sobrien } 60650397Sobrien if (!X509_STORE_load_locations(store, CAfile, CApath)) 60750397Sobrien X509_STORE_set_default_paths(store); 60850397Sobrien 60950397Sobrien vret = get_cert_chain(ucert, store, &chain2); 61050397Sobrien X509_STORE_free(store); 61150397Sobrien 61250397Sobrien if (!vret) { 61350397Sobrien /* Exclude verified certificate */ 61450397Sobrien for (i = 1; i < sk_X509_num(chain2); i++) 61550397Sobrien sk_X509_push(certs, sk_X509_value(chain2, i)); 61650397Sobrien /* Free first certificate */ 61750397Sobrien X509_free(sk_X509_value(chain2, 0)); 61850397Sobrien sk_X509_free(chain2); 61950397Sobrien } else { 62050397Sobrien if (vret >= 0) 62150397Sobrien BIO_printf(bio_err, "Error %s getting chain.\n", 62250397Sobrien X509_verify_cert_error_string(vret)); 62350397Sobrien else 62450397Sobrien ERR_print_errors(bio_err); 62550397Sobrien goto export_end; 62650397Sobrien } 62750397Sobrien } 62850397Sobrien 62950397Sobrien /* Add any CA names */ 63050397Sobrien 63150397Sobrien for (i = 0; i < sk_num(canames); i++) { 63250397Sobrien catmp = (unsigned char *)sk_value(canames, i); 63350397Sobrien X509_alias_set1(sk_X509_value(certs, i), catmp, -1); 63450397Sobrien } 63550397Sobrien 63650397Sobrien if (csp_name && key) 63750397Sobrien EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, 63850397Sobrien MBSTRING_ASC, (unsigned char *)csp_name, 63950397Sobrien -1); 64050397Sobrien 64150397Sobrien if (add_lmk && key) 64250397Sobrien EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); 64350397Sobrien 64450397Sobrien# ifdef CRYPTO_MDEBUG 64550397Sobrien CRYPTO_pop_info(); 64650397Sobrien CRYPTO_push_info("reading password"); 64750397Sobrien# endif 64850397Sobrien 64950397Sobrien if (!noprompt && 65050397Sobrien EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:", 65150397Sobrien 1)) { 65250397Sobrien BIO_printf(bio_err, "Can't read Password\n"); 65350397Sobrien goto export_end; 65450397Sobrien } 65550397Sobrien if (!twopass) 65650397Sobrien BUF_strlcpy(macpass, pass, sizeof macpass); 65750397Sobrien 65850397Sobrien# ifdef CRYPTO_MDEBUG 65950397Sobrien CRYPTO_pop_info(); 66050397Sobrien CRYPTO_push_info("creating PKCS#12 structure"); 66150397Sobrien# endif 66250397Sobrien 66350397Sobrien p12 = PKCS12_create(cpass, name, key, ucert, certs, 66450397Sobrien key_pbe, cert_pbe, iter, -1, keytype); 66550397Sobrien 66650397Sobrien if (!p12) { 66750397Sobrien ERR_print_errors(bio_err); 66850397Sobrien goto export_end; 66950397Sobrien } 67050397Sobrien 67150397Sobrien if (maciter != -1) 67250397Sobrien PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, NULL); 67350397Sobrien 67450397Sobrien# ifdef CRYPTO_MDEBUG 67550397Sobrien CRYPTO_pop_info(); 67650397Sobrien CRYPTO_push_info("writing pkcs12"); 67750397Sobrien# endif 67850397Sobrien 67950397Sobrien i2d_PKCS12_bio(out, p12); 68050397Sobrien 68150397Sobrien ret = 0; 68250397Sobrien 68350397Sobrien export_end: 68450397Sobrien# ifdef CRYPTO_MDEBUG 68550397Sobrien CRYPTO_pop_info(); 68650397Sobrien CRYPTO_pop_info(); 68750397Sobrien CRYPTO_push_info("process -export_cert: freeing"); 68850397Sobrien# endif 68950397Sobrien 69050397Sobrien if (key) 69150397Sobrien EVP_PKEY_free(key); 69250397Sobrien if (certs) 69350397Sobrien sk_X509_pop_free(certs, X509_free); 69450397Sobrien if (ucert) 69550397Sobrien X509_free(ucert); 69650397Sobrien 69750397Sobrien# ifdef CRYPTO_MDEBUG 69850397Sobrien CRYPTO_pop_info(); 69950397Sobrien# endif 70050397Sobrien goto end; 70150397Sobrien 70250397Sobrien } 70350397Sobrien 70450397Sobrien if (!(p12 = d2i_PKCS12_bio(in, NULL))) { 70550397Sobrien ERR_print_errors(bio_err); 70650397Sobrien goto end; 70750397Sobrien } 70850397Sobrien# ifdef CRYPTO_MDEBUG 70950397Sobrien CRYPTO_push_info("read import password"); 71050397Sobrien# endif 71150397Sobrien if (!noprompt 71250397Sobrien && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:", 71350397Sobrien 0)) { 71450397Sobrien BIO_printf(bio_err, "Can't read Password\n"); 71550397Sobrien goto end; 71650397Sobrien } 71750397Sobrien# ifdef CRYPTO_MDEBUG 71850397Sobrien CRYPTO_pop_info(); 71950397Sobrien# endif 72050397Sobrien 72150397Sobrien if (!twopass) 72250397Sobrien BUF_strlcpy(macpass, pass, sizeof macpass); 72350397Sobrien 72450397Sobrien if ((options & INFO) && p12->mac) 72550397Sobrien BIO_printf(bio_err, "MAC Iteration %ld\n", 72650397Sobrien p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); 72750397Sobrien if (macver) { 72850397Sobrien# ifdef CRYPTO_MDEBUG 72950397Sobrien CRYPTO_push_info("verify MAC"); 73050397Sobrien# endif 73150397Sobrien /* If we enter empty password try no password first */ 73250397Sobrien if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { 73350397Sobrien /* If mac and crypto pass the same set it to NULL too */ 73450397Sobrien if (!twopass) 73550397Sobrien cpass = NULL; 73650397Sobrien } else if (!PKCS12_verify_mac(p12, mpass, -1)) { 73750397Sobrien BIO_printf(bio_err, "Mac verify error: invalid password?\n"); 73850397Sobrien ERR_print_errors(bio_err); 73950397Sobrien goto end; 74050397Sobrien } 74150397Sobrien BIO_printf(bio_err, "MAC verified OK\n"); 74250397Sobrien# ifdef CRYPTO_MDEBUG 74350397Sobrien CRYPTO_pop_info(); 74450397Sobrien# endif 74550397Sobrien } 74650397Sobrien# ifdef CRYPTO_MDEBUG 74750397Sobrien CRYPTO_push_info("output keys and certificates"); 74850397Sobrien# endif 74950397Sobrien if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) { 75050397Sobrien BIO_printf(bio_err, "Error outputting keys and certificates\n"); 75150397Sobrien ERR_print_errors(bio_err); 75250397Sobrien goto end; 75350397Sobrien } 75450397Sobrien# ifdef CRYPTO_MDEBUG 75550397Sobrien CRYPTO_pop_info(); 75650397Sobrien# endif 75750397Sobrien ret = 0; 75850397Sobrien end: 75950397Sobrien if (p12) 76050397Sobrien PKCS12_free(p12); 76150397Sobrien if (export_cert || inrand) 76250397Sobrien app_RAND_write_file(NULL, bio_err); 76350397Sobrien# ifdef CRYPTO_MDEBUG 76450397Sobrien CRYPTO_remove_all_info(); 76550397Sobrien# endif 76650397Sobrien BIO_free(in); 76750397Sobrien BIO_free_all(out); 76850397Sobrien if (canames) 76950397Sobrien sk_free(canames); 77050397Sobrien if (passin) 77150397Sobrien OPENSSL_free(passin); 77250397Sobrien if (passout) 77350397Sobrien OPENSSL_free(passout); 77450397Sobrien apps_shutdown(); 77550397Sobrien OPENSSL_EXIT(ret); 77650397Sobrien} 77750397Sobrien 77850397Sobrienint dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, 77950397Sobrien int passlen, int options, char *pempass) 78050397Sobrien{ 78150397Sobrien STACK_OF(PKCS7) *asafes = NULL; 78250397Sobrien STACK_OF(PKCS12_SAFEBAG) *bags; 78350397Sobrien int i, bagnid; 78450397Sobrien int ret = 0; 78550397Sobrien PKCS7 *p7; 78650397Sobrien 78750397Sobrien if (!(asafes = PKCS12_unpack_authsafes(p12))) 78850397Sobrien return 0; 78950397Sobrien for (i = 0; i < sk_PKCS7_num(asafes); i++) { 79050397Sobrien p7 = sk_PKCS7_value(asafes, i); 79150397Sobrien bagnid = OBJ_obj2nid(p7->type); 79250397Sobrien if (bagnid == NID_pkcs7_data) { 79350397Sobrien bags = PKCS12_unpack_p7data(p7); 79450397Sobrien if (options & INFO) 79550397Sobrien BIO_printf(bio_err, "PKCS7 Data\n"); 79650397Sobrien } else if (bagnid == NID_pkcs7_encrypted) { 79750397Sobrien if (options & INFO) { 79850397Sobrien BIO_printf(bio_err, "PKCS7 Encrypted data: "); 79950397Sobrien alg_print(bio_err, p7->d.encrypted->enc_data->algorithm); 80050397Sobrien } 80150397Sobrien bags = PKCS12_unpack_p7encdata(p7, pass, passlen); 80250397Sobrien } else 80350397Sobrien continue; 80450397Sobrien if (!bags) 80550397Sobrien goto err; 80650397Sobrien if (!dump_certs_pkeys_bags(out, bags, pass, passlen, 80750397Sobrien options, pempass)) { 80850397Sobrien sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 80950397Sobrien goto err; 81050397Sobrien } 81150397Sobrien sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); 81250397Sobrien bags = NULL; 81350397Sobrien } 81450397Sobrien ret = 1; 81550397Sobrien 81650397Sobrien err: 81750397Sobrien 81850397Sobrien if (asafes) 81950397Sobrien sk_PKCS7_pop_free(asafes, PKCS7_free); 82050397Sobrien return ret; 82150397Sobrien} 82250397Sobrien 82350397Sobrienint dump_certs_pkeys_bags(BIO *out, STACK_OF(PKCS12_SAFEBAG) *bags, 82450397Sobrien char *pass, int passlen, int options, char *pempass) 82550397Sobrien{ 82650397Sobrien int i; 82750397Sobrien for (i = 0; i < sk_PKCS12_SAFEBAG_num(bags); i++) { 82850397Sobrien if (!dump_certs_pkeys_bag(out, 82950397Sobrien sk_PKCS12_SAFEBAG_value(bags, i), 83050397Sobrien pass, passlen, options, pempass)) 83150397Sobrien return 0; 83250397Sobrien } 83350397Sobrien return 1; 83450397Sobrien} 83550397Sobrien 83650397Sobrienint dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bag, char *pass, 83750397Sobrien int passlen, int options, char *pempass) 83850397Sobrien{ 83950397Sobrien EVP_PKEY *pkey; 84050397Sobrien PKCS8_PRIV_KEY_INFO *p8; 84150397Sobrien X509 *x509; 84250397Sobrien 84350397Sobrien switch (M_PKCS12_bag_type(bag)) { 84450397Sobrien case NID_keyBag: 84550397Sobrien if (options & INFO) 84650397Sobrien BIO_printf(bio_err, "Key bag\n"); 84750397Sobrien if (options & NOKEYS) 84850397Sobrien return 1; 84950397Sobrien print_attribs(out, bag->attrib, "Bag Attributes"); 85050397Sobrien p8 = bag->value.keybag; 85150397Sobrien if (!(pkey = EVP_PKCS82PKEY(p8))) 85250397Sobrien return 0; 85350397Sobrien print_attribs(out, p8->attributes, "Key Attributes"); 85450397Sobrien PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); 85550397Sobrien EVP_PKEY_free(pkey); 85650397Sobrien break; 85750397Sobrien 85850397Sobrien case NID_pkcs8ShroudedKeyBag: 85950397Sobrien if (options & INFO) { 860 BIO_printf(bio_err, "Shrouded Keybag: "); 861 alg_print(bio_err, bag->value.shkeybag->algor); 862 } 863 if (options & NOKEYS) 864 return 1; 865 print_attribs(out, bag->attrib, "Bag Attributes"); 866 if (!(p8 = PKCS12_decrypt_skey(bag, pass, passlen))) 867 return 0; 868 if (!(pkey = EVP_PKCS82PKEY(p8))) { 869 PKCS8_PRIV_KEY_INFO_free(p8); 870 return 0; 871 } 872 print_attribs(out, p8->attributes, "Key Attributes"); 873 PKCS8_PRIV_KEY_INFO_free(p8); 874 PEM_write_bio_PrivateKey(out, pkey, enc, NULL, 0, NULL, pempass); 875 EVP_PKEY_free(pkey); 876 break; 877 878 case NID_certBag: 879 if (options & INFO) 880 BIO_printf(bio_err, "Certificate bag\n"); 881 if (options & NOCERTS) 882 return 1; 883 if (PKCS12_get_attr(bag, NID_localKeyID)) { 884 if (options & CACERTS) 885 return 1; 886 } else if (options & CLCERTS) 887 return 1; 888 print_attribs(out, bag->attrib, "Bag Attributes"); 889 if (M_PKCS12_cert_bag_type(bag) != NID_x509Certificate) 890 return 1; 891 if (!(x509 = PKCS12_certbag2x509(bag))) 892 return 0; 893 dump_cert_text(out, x509); 894 PEM_write_bio_X509(out, x509); 895 X509_free(x509); 896 break; 897 898 case NID_safeContentsBag: 899 if (options & INFO) 900 BIO_printf(bio_err, "Safe Contents bag\n"); 901 print_attribs(out, bag->attrib, "Bag Attributes"); 902 return dump_certs_pkeys_bags(out, bag->value.safes, pass, 903 passlen, options, pempass); 904 905 default: 906 BIO_printf(bio_err, "Warning unsupported bag type: "); 907 i2a_ASN1_OBJECT(bio_err, bag->type); 908 BIO_printf(bio_err, "\n"); 909 return 1; 910 break; 911 } 912 return 1; 913} 914 915/* Given a single certificate return a verified chain or NULL if error */ 916 917/* Hope this is OK .... */ 918 919int get_cert_chain(X509 *cert, X509_STORE *store, STACK_OF(X509) **chain) 920{ 921 X509_STORE_CTX store_ctx; 922 STACK_OF(X509) *chn; 923 int i = 0; 924 925 /* 926 * FIXME: Should really check the return status of X509_STORE_CTX_init 927 * for an error, but how that fits into the return value of this function 928 * is less obvious. 929 */ 930 X509_STORE_CTX_init(&store_ctx, store, cert, NULL); 931 if (X509_verify_cert(&store_ctx) <= 0) { 932 i = X509_STORE_CTX_get_error(&store_ctx); 933 if (i == 0) 934 /* 935 * avoid returning 0 if X509_verify_cert() did not set an 936 * appropriate error value in the context 937 */ 938 i = -1; 939 chn = NULL; 940 goto err; 941 } else 942 chn = X509_STORE_CTX_get1_chain(&store_ctx); 943 err: 944 X509_STORE_CTX_cleanup(&store_ctx); 945 *chain = chn; 946 947 return i; 948} 949 950int alg_print(BIO *x, X509_ALGOR *alg) 951{ 952 PBEPARAM *pbe; 953 const unsigned char *p; 954 p = alg->parameter->value.sequence->data; 955 pbe = d2i_PBEPARAM(NULL, &p, alg->parameter->value.sequence->length); 956 if (!pbe) 957 return 1; 958 BIO_printf(bio_err, "%s, Iteration %ld\n", 959 OBJ_nid2ln(OBJ_obj2nid(alg->algorithm)), 960 ASN1_INTEGER_get(pbe->iter)); 961 PBEPARAM_free(pbe); 962 return 1; 963} 964 965/* Load all certificates from a given file */ 966 967int cert_load(BIO *in, STACK_OF(X509) *sk) 968{ 969 int ret; 970 X509 *cert; 971 ret = 0; 972# ifdef CRYPTO_MDEBUG 973 CRYPTO_push_info("cert_load(): reading one cert"); 974# endif 975 while ((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { 976# ifdef CRYPTO_MDEBUG 977 CRYPTO_pop_info(); 978# endif 979 ret = 1; 980 sk_X509_push(sk, cert); 981# ifdef CRYPTO_MDEBUG 982 CRYPTO_push_info("cert_load(): reading one cert"); 983# endif 984 } 985# ifdef CRYPTO_MDEBUG 986 CRYPTO_pop_info(); 987# endif 988 if (ret) 989 ERR_clear_error(); 990 return ret; 991} 992 993/* Generalised attribute print: handle PKCS#8 and bag attributes */ 994 995int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, 996 const char *name) 997{ 998 X509_ATTRIBUTE *attr; 999 ASN1_TYPE *av; 1000 char *value; 1001 int i, attr_nid; 1002 if (!attrlst) { 1003 BIO_printf(out, "%s: <No Attributes>\n", name); 1004 return 1; 1005 } 1006 if (!sk_X509_ATTRIBUTE_num(attrlst)) { 1007 BIO_printf(out, "%s: <Empty Attributes>\n", name); 1008 return 1; 1009 } 1010 BIO_printf(out, "%s\n", name); 1011 for (i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { 1012 attr = sk_X509_ATTRIBUTE_value(attrlst, i); 1013 attr_nid = OBJ_obj2nid(attr->object); 1014 BIO_printf(out, " "); 1015 if (attr_nid == NID_undef) { 1016 i2a_ASN1_OBJECT(out, attr->object); 1017 BIO_printf(out, ": "); 1018 } else 1019 BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid)); 1020 1021 if (sk_ASN1_TYPE_num(attr->value.set)) { 1022 av = sk_ASN1_TYPE_value(attr->value.set, 0); 1023 switch (av->type) { 1024 case V_ASN1_BMPSTRING: 1025 value = uni2asc(av->value.bmpstring->data, 1026 av->value.bmpstring->length); 1027 BIO_printf(out, "%s\n", value); 1028 OPENSSL_free(value); 1029 break; 1030 1031 case V_ASN1_OCTET_STRING: 1032 hex_prin(out, av->value.octet_string->data, 1033 av->value.octet_string->length); 1034 BIO_printf(out, "\n"); 1035 break; 1036 1037 case V_ASN1_BIT_STRING: 1038 hex_prin(out, av->value.bit_string->data, 1039 av->value.bit_string->length); 1040 BIO_printf(out, "\n"); 1041 break; 1042 1043 default: 1044 BIO_printf(out, "<Unsupported tag %d>\n", av->type); 1045 break; 1046 } 1047 } else 1048 BIO_printf(out, "<No Values>\n"); 1049 } 1050 return 1; 1051} 1052 1053void hex_prin(BIO *out, unsigned char *buf, int len) 1054{ 1055 int i; 1056 for (i = 0; i < len; i++) 1057 BIO_printf(out, "%02X ", buf[i]); 1058} 1059 1060#endif 1061