X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fpkcs12.c;h=a027566ac04288f2187acbf31b285b946a60b282;hp=8ead8bc4aa10b680a2b59bbab9889c3a0a04ed27;hb=aa82db4fb49e8e3da38e39861837117ce12256bf;hpb=1b266dabf5417e228d9e970d4f2923fec92fea1e diff --git a/apps/pkcs12.c b/apps/pkcs12.c index 8ead8bc4aa..a027566ac0 100644 --- a/apps/pkcs12.c +++ b/apps/pkcs12.c @@ -1,4 +1,6 @@ /* pkcs12.c */ +#if !defined(NO_DES) && !defined(NO_SHA1) + /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL * project 1999. */ @@ -59,6 +61,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +72,6 @@ EVP_CIPHER *enc; -#define _ITER_ 1000 #define NOKEYS 0x1 #define NOCERTS 0x2 @@ -77,15 +79,14 @@ EVP_CIPHER *enc; #define CLCERTS 0x8 #define CACERTS 0x10 -int get_cert_chain(X509 *cert, STACK **chain); -int dump_cert_text (BIO *out, X509 *x); +int get_cert_chain(X509 *cert, STACK_OF(X509) **chain); int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options); int dump_certs_pkeys_bags(BIO *out, STACK *bags, char *pass, int passlen, int options); int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen, int options); -int print_attribs(BIO *out, STACK *attrlst, char *name); +int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name); void hex_prin(BIO *out, unsigned char *buf, int len); int alg_print(BIO *x, X509_ALGOR *alg); -int cert_load(BIO *in, STACK *sk); +int cert_load(BIO *in, STACK_OF(X509) *sk); int MAIN(int argc, char **argv) { char *infile=NULL, *outfile=NULL, *keyname = NULL; @@ -99,11 +100,12 @@ int MAIN(int argc, char **argv) int options = 0; int chain = 0; int badarg = 0; - int iter = _ITER_; - int maciter = 1; + int iter = PKCS12_DEFAULT_ITER; + int maciter = PKCS12_DEFAULT_ITER; int twopass = 0; int keytype = 0; int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; + int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1; int macver = 1; int noprompt = 0; @@ -140,9 +142,32 @@ int MAIN(int argc, char **argv) #endif else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc(); else if (!strcmp (*args, "-noiter")) iter = 1; - else if (!strcmp (*args, "-maciter")) maciter = _ITER_; + else if (!strcmp (*args, "-maciter")) + maciter = PKCS12_DEFAULT_ITER; + else if (!strcmp (*args, "-nomaciter")) + maciter = 1; else if (!strcmp (*args, "-nodes")) enc=NULL; - else if (!strcmp (*args, "-inkey")) { + else if (!strcmp (*args, "-certpbe")) { + if (args[1]) { + args++; + cert_pbe=OBJ_txt2nid(*args); + if(cert_pbe == NID_undef) { + BIO_printf(bio_err, + "Unknown PBE algorithm %s\n", *args); + badarg = 1; + } + } else badarg = 1; + } else if (!strcmp (*args, "-keypbe")) { + if (args[1]) { + args++; + key_pbe=OBJ_txt2nid(*args); + if(key_pbe == NID_undef) { + BIO_printf(bio_err, + "Unknown PBE algorithm %s\n", *args); + badarg = 1; + } + } else badarg = 1; + } else if (!strcmp (*args, "-inkey")) { if (args[1]) { args++; keyname = *args; @@ -223,6 +248,8 @@ int MAIN(int argc, char **argv) BIO_printf (bio_err, "-maciter use MAC iteration\n"); BIO_printf (bio_err, "-twopass separate MAC, encryption passwords\n"); BIO_printf (bio_err, "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n"); + BIO_printf (bio_err, "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n"); + BIO_printf (bio_err, "-keypbe alg specify private key PBE algorithm (default 3DES)\n"); BIO_printf (bio_err, "-keyex set MS key exchange type\n"); BIO_printf (bio_err, "-keysig set MS key signature type\n"); BIO_printf (bio_err, "-password p set import/export password (NOT RECOMMENDED)\n"); @@ -238,69 +265,88 @@ int MAIN(int argc, char **argv) ERR_load_crypto_strings(); - in = BIO_new (BIO_s_file()); - out = BIO_new (BIO_s_file()); +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("read files"); +#endif - if (!infile) BIO_set_fp (in, stdin, BIO_NOCLOSE); - else { - if (BIO_read_filename (in, infile) <= 0) { + if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE); + else in = BIO_new_file(infile, "rb"); + if (!in) { + BIO_printf(bio_err, "Error opening input file %s\n", + infile ? infile : ""); perror (infile); goto end; - } - } + } if (certfile) { - certsin = BIO_new (BIO_s_file()); - if (BIO_read_filename (certsin, certfile) <= 0) { + if(!(certsin = BIO_new_file(certfile, "r"))) { + BIO_printf(bio_err, "Can't open certificate file %s\n", certfile); perror (certfile); goto end; } } if (keyname) { - inkey = BIO_new (BIO_s_file()); - if (BIO_read_filename (inkey, keyname) <= 0) { + if(!(inkey = BIO_new_file(keyname, "r"))) { + BIO_printf(bio_err, "Can't key certificate file %s\n", keyname); perror (keyname); goto end; } } - if (!outfile) BIO_set_fp (out, stdout, BIO_NOCLOSE); - else { - if (BIO_write_filename (out, outfile) <= 0) { - perror (outfile); - goto end; - } +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); + CRYPTO_push_info("write files"); +#endif + + if (!outfile) out = BIO_new_fp(stdout, BIO_NOCLOSE); + else out = BIO_new_file(outfile, "wb"); + if (!out) { + BIO_printf(bio_err, "Error opening output file %s\n", + outfile ? outfile : ""); + perror (outfile); + goto end; } if (twopass) { - if(EVP_read_pw_string (macpass, 50, "Enter MAC Password:", export_cert)) { +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("read MAC password"); +#endif + if(EVP_read_pw_string (macpass, 50, "Enter MAC Password:", export_cert)) + { BIO_printf (bio_err, "Can't read Password\n"); goto end; } +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); +#endif } -if (export_cert) { + if (export_cert) { EVP_PKEY *key; STACK *bags, *safes; PKCS12_SAFEBAG *bag; PKCS8_PRIV_KEY_INFO *p8; PKCS7 *authsafe; - X509 *cert, *ucert = NULL; - STACK *certs; + X509 *ucert = NULL; + STACK_OF(X509) *certs=NULL; char *catmp; - int i, pmatch = 0; + int i; unsigned char keyid[EVP_MAX_MD_SIZE]; - unsigned int keyidlen; - /* Get private key so we can match it to a certificate */ - key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL); - if (!inkey) BIO_reset(in); + unsigned int keyidlen = 0; + +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("process -export_cert"); +#endif + key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL, NULL); + if (!inkey) (void) BIO_reset(in); + else BIO_free(inkey); if (!key) { BIO_printf (bio_err, "Error loading private key\n"); ERR_print_errors(bio_err); goto end; } - certs = sk_new(NULL); + certs = sk_X509_new(NULL); /* Load in all certs in input file */ if(!cert_load(in, certs)) { @@ -308,6 +354,19 @@ if (export_cert) { ERR_print_errors(bio_err); goto end; } + + for(i = 0; i < sk_X509_num(certs); i++) { + ucert = sk_X509_value(certs, i); + if(X509_check_private_key(ucert, key)) { + X509_digest(ucert, EVP_sha1(), keyid, &keyidlen); + break; + } + } + + if(!keyidlen) { + BIO_printf(bio_err, "No certificate matches private key\n"); + goto end; + } bags = sk_new (NULL); @@ -321,26 +380,10 @@ if (export_cert) { BIO_free(certsin); } - /* Find certificate (if any) matching private key */ - - for(i = 0; i < sk_num(certs); i++) { - cert = (X509 *)sk_value(certs, i); - if(X509_check_private_key(cert, key)) { - ucert = cert; - break; - } - } - - if(!ucert) { - BIO_printf(bio_err, "No certificate matches private key\n"); - goto end; - } - /* If chaining get chain from user cert */ if (chain) { int vret; - STACK *chain2; - + STACK_OF(X509) *chain2; vret = get_cert_chain (ucert, &chain2); if (vret) { BIO_printf (bio_err, "Error %s getting chain.\n", @@ -348,27 +391,26 @@ if (export_cert) { goto end; } /* Exclude verified certificate */ - for (i = 1; i < sk_num (chain2) ; i++) - sk_push(certs, sk_value (chain2, i)); - sk_free(chain2); + for (i = 1; i < sk_X509_num (chain2) ; i++) + sk_X509_push(certs, sk_X509_value (chain2, i)); + sk_X509_free(chain2); } /* We now have loads of certificates: include them all */ - for(i = 0; i < sk_num(certs); i++) { - cert = (X509 *)sk_value(certs, i); + for(i = 0; i < sk_X509_num(certs); i++) { + X509 *cert = NULL; + cert = sk_X509_value(certs, i); bag = M_PKCS12_x5092certbag(cert); - /* If it matches private key mark it */ + /* If it matches private key set id */ if(cert == ucert) { if(name) PKCS12_add_friendlyname(bag, name, -1); - X509_digest(cert, EVP_sha1(), keyid, &keyidlen); PKCS12_add_localkeyid(bag, keyid, keyidlen); - pmatch = 1; } else if((catmp = sk_shift(canames))) PKCS12_add_friendlyname(bag, catmp, -1); sk_push(bags, (char *)bag); } - + sk_X509_pop_free(certs, X509_free); if (canames) sk_free(canames); if(!noprompt && @@ -378,7 +420,7 @@ if (export_cert) { } if (!twopass) strcpy(macpass, pass); /* Turn certbags into encrypted authsafe */ - authsafe = PKCS12_pack_p7encdata (cert_pbe, cpass, -1, NULL, 0, + authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0, iter, bags); sk_pop_free(bags, PKCS12_SAFEBAG_free); @@ -394,11 +436,10 @@ if (export_cert) { p8 = EVP_PKEY2PKCS8 (key); EVP_PKEY_free(key); if(keytype) PKCS8_add_keyusage(p8, keytype); - bag = PKCS12_MAKE_SHKEYBAG (NID_pbe_WithSHA1And3_Key_TripleDES_CBC, - cpass, -1, NULL, 0, iter, p8); + bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8); PKCS8_PRIV_KEY_INFO_free(p8); if (name) PKCS12_add_friendlyname (bag, name, -1); - if(!pmatch) PKCS12_add_localkeyid (bag, keyid, keyidlen); + PKCS12_add_localkeyid (bag, keyid, keyidlen); bags = sk_new(NULL); sk_push (bags, (char *)bag); /* Turn it into unencrypted safe bag */ @@ -419,6 +460,10 @@ if (export_cert) { PKCS12_free(p12); ret = 0; + +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); +#endif goto end; } @@ -428,47 +473,56 @@ if (export_cert) { goto end; } +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("read import password"); +#endif if(!noprompt && EVP_read_pw_string(pass, 50, "Enter Import Password:", 0)) { BIO_printf (bio_err, "Can't read Password\n"); goto end; } +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); +#endif if (!twopass) strcpy(macpass, pass); if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1); if(macver) { +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("verify MAC"); +#endif if (!PKCS12_verify_mac (p12, mpass, -1)) { BIO_printf (bio_err, "Mac verify errror: invalid password?\n"); ERR_print_errors (bio_err); goto end; } else BIO_printf (bio_err, "MAC verified OK\n"); +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); +#endif } +#ifdef CRYPTO_MDEBUG + CRYPTO_push_info("output keys and certificates"); +#endif if (!dump_certs_keys_p12 (out, p12, cpass, -1, options)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors (bio_err); goto end; } +#ifdef CRYPTO_MDEBUG + CRYPTO_pop_info(); +#endif PKCS12_free(p12); ret = 0; end: +#ifdef CRYPTO_MDEBUG + CRYPTO_remove_all_info(); +#endif + BIO_free(in); + BIO_free(out); EXIT(ret); } -int dump_cert_text (BIO *out, X509 *x) -{ - char buf[256]; - X509_NAME_oneline(X509_get_subject_name(x),buf,256); - BIO_puts(out,"subject="); - BIO_puts(out,buf); - - X509_NAME_oneline(X509_get_issuer_name(x),buf,256); - BIO_puts(out,"\nissuer= "); - BIO_puts(out,buf); - BIO_puts(out,"\n"); - return 0; -} - int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass, int passlen, int options) { @@ -530,7 +584,7 @@ int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass, p8 = bag->value.keybag; if (!(pkey = EVP_PKCS82PKEY (p8))) return 0; print_attribs (out, p8->attributes, "Key Attributes"); - PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL); + PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, NULL); EVP_PKEY_free(pkey); break; @@ -546,7 +600,7 @@ int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass, if (!(pkey = EVP_PKCS82PKEY (p8))) return 0; print_attribs (out, p8->attributes, "Key Attributes"); PKCS8_PRIV_KEY_INFO_free(p8); - PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL); + PEM_write_bio_PrivateKey (out, pkey, enc, NULL, 0, NULL, NULL); EVP_PKEY_free(pkey); break; @@ -585,13 +639,13 @@ int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass, /* Hope this is OK .... */ -int get_cert_chain (X509 *cert, STACK **chain) +int get_cert_chain (X509 *cert, STACK_OF(X509) **chain) { X509_STORE *store; X509_STORE_CTX store_ctx; - STACK *chn; + STACK_OF(X509) *chn; int i; - X509 *x; + store = X509_STORE_new (); X509_STORE_set_default_paths (store); X509_STORE_CTX_init(&store_ctx, store, cert, NULL); @@ -599,11 +653,7 @@ int get_cert_chain (X509 *cert, STACK **chain) i = X509_STORE_CTX_get_error (&store_ctx); goto err; } - chn = sk_dup(X509_STORE_CTX_get_chain (&store_ctx)); - for (i = 0; i < sk_num(chn); i++) { - x = (X509 *)sk_value(chn, i); - CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509); - } + chn = X509_STORE_CTX_rget_chain(&store_ctx); i = 0; *chain = chn; err: @@ -627,14 +677,14 @@ int alg_print (BIO *x, X509_ALGOR *alg) /* Load all certificates from a given file */ -int cert_load(BIO *in, STACK *sk) +int cert_load(BIO *in, STACK_OF(X509) *sk) { int ret; X509 *cert; ret = 0; - while((cert = PEM_read_bio_X509(in, NULL, NULL))) { + while((cert = PEM_read_bio_X509(in, NULL, NULL, NULL))) { ret = 1; - sk_push(sk, (char *)cert); + sk_X509_push(sk, cert); } if(ret) ERR_clear_error(); return ret; @@ -642,7 +692,7 @@ int cert_load(BIO *in, STACK *sk) /* Generalised attribute print: handle PKCS#8 and bag attributes */ -int print_attribs (BIO *out, STACK *attrlst, char *name) +int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name) { X509_ATTRIBUTE *attr; ASN1_TYPE *av; @@ -652,13 +702,13 @@ int print_attribs (BIO *out, STACK *attrlst, char *name) BIO_printf(out, "%s: \n", name); return 1; } - if(!sk_num(attrlst)) { + if(!sk_X509_ATTRIBUTE_num(attrlst)) { BIO_printf(out, "%s: \n", name); return 1; } BIO_printf(out, "%s\n", name); - for(i = 0; i < sk_num(attrlst); i++) { - attr = (X509_ATTRIBUTE *) sk_value(attrlst, i); + for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) { + attr = sk_X509_ATTRIBUTE_value(attrlst, i); attr_nid = OBJ_obj2nid(attr->object); BIO_printf(out, " "); if(attr_nid == NID_undef) { @@ -702,3 +752,5 @@ void hex_prin(BIO *out, unsigned char *buf, int len) int i; for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]); } + +#endif