int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass, int passlen, int options, char *pempass) { STACK_OF(PKCS7) *asafes; STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid; PKCS7 *p7; if (!( asafes = PKCS12_unpack_authsafes(p12))) return 0; for (i = 0; i < sk_PKCS7_num (asafes); i++) { p7 = sk_PKCS7_value (asafes, i); bagnid = OBJ_obj2nid (p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); if (options & INFO) BIO_printf (bio_err, "PKCS7 Data\n"); } else if (bagnid == NID_pkcs7_encrypted) { if (options & INFO) { BIO_printf(bio_err, "PKCS7 Encrypted data: "); alg_print(bio_err, p7->d.encrypted->enc_data->algorithm); } bags = PKCS12_unpack_p7encdata(p7, pass, passlen); } else continue; if (!bags) return 0; if (!dump_certs_pkeys_bags (out, bags, pass, passlen, options, pempass)) { sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); return 0; } sk_PKCS12_SAFEBAG_pop_free (bags, PKCS12_SAFEBAG_free); } sk_PKCS7_pop_free (asafes, PKCS7_free); return 1; }
static EVP_PKEY *getPrivateKey(PKCS12 *p12, X509 *x509, const char* pass) { // Extract all PKCS7 safes STACK_OF(PKCS7) *pkcs7s = PKCS12_unpack_authsafes(p12); if (!pkcs7s) { certutil_updateErrorString(); return NULL; } // For each PKCS7 safe int nump = sk_PKCS7_num(pkcs7s); for (int p = 0; p < nump; p++) { PKCS7 *p7 = sk_PKCS7_value(pkcs7s, p); if (!p7) continue; STACK_OF(PKCS12_SAFEBAG) *safebags = PKCS12_unpack_p7data(p7); if (!safebags) continue; // For each PKCS12 safebag int numb = sk_PKCS12_SAFEBAG_num(safebags); for (int i = 0; i < numb; i++) { PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(safebags, i); if (!bag) continue; switch (M_PKCS12_bag_type(bag)) { case NID_pkcs8ShroudedKeyBag:; // Encrypted key PKCS8_PRIV_KEY_INFO *p8 = PKCS12_decrypt_skey(bag, pass, strlen(pass)); if (p8) { EVP_PKEY *pk = EVP_PKCS82PKEY(p8); PKCS8_PRIV_KEY_INFO_free(p8); if (!pk) break; // out of switch if (X509_check_private_key(x509, pk) > 0) { sk_PKCS12_SAFEBAG_pop_free(safebags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(pkcs7s, PKCS7_free); return pk; } EVP_PKEY_free(pk); } break; } } sk_PKCS12_SAFEBAG_pop_free(safebags, PKCS12_SAFEBAG_free); } sk_PKCS7_pop_free(pkcs7s, PKCS7_free); return NULL; }
static char *find_friendly_name(PKCS12 *p12) { STACK_OF(PKCS7) *safes; int n, m; char *name = NULL; PKCS7 *safe; STACK_OF(PKCS12_SAFEBAG) *bags; PKCS12_SAFEBAG *bag; if ((safes = PKCS12_unpack_authsafes(p12)) == NULL) return NULL; for (n = 0; n < sk_PKCS7_num(safes) && name == NULL; n++) { safe = sk_PKCS7_value(safes, n); if (OBJ_obj2nid(safe->type) != NID_pkcs7_data || (bags = PKCS12_unpack_p7data(safe)) == NULL) continue; for (m = 0; m < sk_PKCS12_SAFEBAG_num(bags) && name == NULL; m++) { bag = sk_PKCS12_SAFEBAG_value(bags, m); name = PKCS12_get_friendlyname(bag); } sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); } sk_PKCS7_pop_free(safes, PKCS7_free); return name; }
/** * Returns a list of all x509 certificates in a PKCS12 object. */ static STACK_OF(X509) *pkcs12_listCerts(PKCS12 *p12) { STACK_OF(X509) *x509s = sk_X509_new_null(); if (!x509s) return NULL; // Extract all PKCS7 safes STACK_OF(PKCS7) *pkcs7s = PKCS12_unpack_authsafes(p12); if (!pkcs7s) { certutil_updateErrorString(); sk_X509_free(x509s); return NULL; } // For each PKCS7 safe int nump = sk_PKCS7_num(pkcs7s); for (int p = 0; p < nump; p++) { PKCS7 *p7 = sk_PKCS7_value(pkcs7s, p); if (!p7) continue; STACK_OF(PKCS12_SAFEBAG) *safebags = PKCS12_unpack_p7data(p7); if (!safebags) { certutil_updateErrorString(); continue; } // For each PKCS12 safebag int numb = sk_PKCS12_SAFEBAG_num(safebags); for (int i = 0; i < numb; i++) { PKCS12_SAFEBAG *bag = sk_PKCS12_SAFEBAG_value(safebags, i); if (!bag) continue; if (M_PKCS12_bag_type(bag) == NID_certBag) { // Extract x509 cert X509 *x509 = PKCS12_certbag2x509(bag); if (x509 == NULL) { certutil_updateErrorString(); } else { sk_X509_push(x509s, x509); } } } sk_PKCS12_SAFEBAG_pop_free(safebags, PKCS12_SAFEBAG_free); } sk_PKCS7_pop_free(pkcs7s, PKCS7_free); return x509s; }
static TokenError saveKeys(const CertReq *reqs, const char *hostname, const char *password, FILE *file) { TokenError error = TokenError_Unknown; PKCS12 *p12 = NULL; // Add PKCS7 safes with the keys STACK_OF(PKCS7) *authsafes = NULL; uint32_t localKeyId = 0; size_t error_count = 0; while (reqs) { STACK_OF(PKCS12_SAFEBAG) *bags = NULL; X509 *cert = NULL; ASN1_OBJECT *objOwningHost = NULL; uint32_t keyid = htonl(localKeyId++); bool success = false; // Add private key PKCS12_SAFEBAG *bag = PKCS12_add_key(&bags, reqs->privkey, opensslKeyUsages[reqs->pkcs10->keyUsage], ENC_ITER, ENC_NID, (char*)password); if (!bag) goto loop_end; // Add name and localKeyId to the key bag // TODO extract name from subject DN char *name = "names are not implemented yet"; if (!X509at_add1_attr_by_NID(&bag->attrib, NID_friendlyName, MBSTRING_UTF8, (unsigned char*)name, strlen(name)) || !PKCS12_add_localkeyid(bag, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; // Add a certificate so we can find the key by the subject name cert = X509_REQ_to_X509(reqs->x509, 3650, reqs->privkey); if (!cert || !X509_keyid_set1(cert, (unsigned char*)&keyid, sizeof(keyid))) goto loop_end; if (!X509_add_ext(cert, makeKeyUsageExt(reqs->pkcs10->keyUsage), -1)) goto loop_end; if (!PKCS12_add_cert(&bags, cert)) goto loop_end; // Add hostname (FriBID extension) so we can do same-origin checks // TODO maybe we should use document.domain instead of document.location.hostname? objOwningHost = OBJ_txt2obj(OID_OWNING_HOST, 1); if (!objOwningHost) goto loop_end; bag = sk_PKCS12_SAFEBAG_value(bags, sk_PKCS12_SAFEBAG_num(bags)-1); if (!X509at_add1_attr_by_OBJ(&bag->attrib, objOwningHost, MBSTRING_UTF8, (unsigned char*)hostname, strlen(hostname))) goto loop_end; // Add a new authsafe if (!PKCS12_add_safe(&authsafes, bags, -1, 0, NULL)) goto loop_end; // Success! success = true; loop_end: if (!success) { error_count--; certutil_updateErrorString(); } ASN1_OBJECT_free(objOwningHost); X509_free(cert); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); reqs = reqs->next; } if (error_count != 0) goto end; // Create the PKCS12 wrapper p12 = PKCS12_add_safes(authsafes, 0); if (!p12) { certutil_updateErrorString(); goto end; } PKCS12_set_mac(p12, (char*)password, -1, NULL, 0, MAC_ITER, NULL); // Save file if (i2d_PKCS12_fp(file, p12)) { error = TokenError_Success; } end: sk_PKCS7_pop_free(authsafes, PKCS7_free); PKCS12_free(p12); return error; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; char *infile=NULL, *outfile=NULL, *keyname = NULL; char *certfile=NULL; BIO *in=NULL, *out = NULL; char **args; char *name = NULL; char *csp_name = NULL; PKCS12 *p12 = NULL; char pass[50], macpass[50]; int export_cert = 0; int options = 0; int chain = 0; int badarg = 0; 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; STACK *canames = NULL; char *cpass = NULL, *mpass = NULL; char *passargin = NULL, *passargout = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL; char *inrand = NULL; char *CApath = NULL, *CAfile = NULL; char *engine=NULL; apps_startup(); enc = EVP_des_ede3_cbc(); if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; args = argv + 1; while (*args) { if (*args[0] == '-') { if (!strcmp (*args, "-nokeys")) options |= NOKEYS; else if (!strcmp (*args, "-keyex")) keytype = KEY_EX; else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG; else if (!strcmp (*args, "-nocerts")) options |= NOCERTS; else if (!strcmp (*args, "-clcerts")) options |= CLCERTS; else if (!strcmp (*args, "-cacerts")) options |= CACERTS; else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS); else if (!strcmp (*args, "-info")) options |= INFO; else if (!strcmp (*args, "-chain")) chain = 1; else if (!strcmp (*args, "-twopass")) twopass = 1; else if (!strcmp (*args, "-nomacver")) macver = 0; else if (!strcmp (*args, "-descert")) cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; else if (!strcmp (*args, "-export")) export_cert = 1; else if (!strcmp (*args, "-des")) enc=EVP_des_cbc(); #ifndef OPENSSL_NO_IDEA else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc(); #endif else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc(); #ifndef OPENSSL_NO_AES else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc(); else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc(); else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc(); #endif else if (!strcmp (*args, "-noiter")) iter = 1; 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, "-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, "-rand")) { if (args[1]) { args++; inrand = *args; } else badarg = 1; } else if (!strcmp (*args, "-inkey")) { if (args[1]) { args++; keyname = *args; } else badarg = 1; } else if (!strcmp (*args, "-certfile")) { if (args[1]) { args++; certfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-name")) { if (args[1]) { args++; name = *args; } else badarg = 1; } else if (!strcmp (*args, "-CSP")) { if (args[1]) { args++; csp_name = *args; } else badarg = 1; } else if (!strcmp (*args, "-caname")) { if (args[1]) { args++; if (!canames) canames = sk_new_null(); sk_push(canames, *args); } else badarg = 1; } else if (!strcmp (*args, "-in")) { if (args[1]) { args++; infile = *args; } else badarg = 1; } else if (!strcmp (*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (!strcmp(*args,"-passin")) { if (args[1]) { args++; passargin = *args; } else badarg = 1; } else if (!strcmp(*args,"-passout")) { if (args[1]) { args++; passargout = *args; } else badarg = 1; } else if (!strcmp (*args, "-password")) { if (args[1]) { args++; passarg = *args; noprompt = 1; } else badarg = 1; } else if (!strcmp(*args,"-CApath")) { if (args[1]) { args++; CApath = *args; } else badarg = 1; } else if (!strcmp(*args,"-CAfile")) { if (args[1]) { args++; CAfile = *args; } else badarg = 1; } else if (!strcmp(*args,"-engine")) { if (args[1]) { args++; engine = *args; } else badarg = 1; } else badarg = 1; } else badarg = 1; args++; } if (badarg) { BIO_printf (bio_err, "Usage: pkcs12 [options]\n"); BIO_printf (bio_err, "where options are\n"); BIO_printf (bio_err, "-export output PKCS12 file\n"); BIO_printf (bio_err, "-chain add certificate chain\n"); BIO_printf (bio_err, "-inkey file private key if not infile\n"); BIO_printf (bio_err, "-certfile f add all certs in f\n"); BIO_printf (bio_err, "-CApath arg - PEM format directory of CA's\n"); BIO_printf (bio_err, "-CAfile arg - PEM format file of CA's\n"); BIO_printf (bio_err, "-name \"name\" use name as friendly name\n"); BIO_printf (bio_err, "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n"); BIO_printf (bio_err, "-in infile input filename\n"); BIO_printf (bio_err, "-out outfile output filename\n"); BIO_printf (bio_err, "-noout don't output anything, just verify.\n"); BIO_printf (bio_err, "-nomacver don't verify MAC.\n"); BIO_printf (bio_err, "-nocerts don't output certificates.\n"); BIO_printf (bio_err, "-clcerts only output client certificates.\n"); BIO_printf (bio_err, "-cacerts only output CA certificates.\n"); BIO_printf (bio_err, "-nokeys don't output private keys.\n"); BIO_printf (bio_err, "-info give info about PKCS#12 structure.\n"); BIO_printf (bio_err, "-des encrypt private keys with DES\n"); BIO_printf (bio_err, "-des3 encrypt private keys with triple DES (default)\n"); #ifndef OPENSSL_NO_IDEA BIO_printf (bio_err, "-idea encrypt private keys with idea\n"); #endif #ifndef OPENSSL_NO_AES BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); #endif BIO_printf (bio_err, "-nodes don't encrypt private keys\n"); BIO_printf (bio_err, "-noiter don't use encryption iteration\n"); 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 source\n"); BIO_printf (bio_err, "-passin p input file pass phrase source\n"); BIO_printf (bio_err, "-passout p output file pass phrase source\n"); BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); BIO_printf(bio_err, " the random number generator\n"); goto end; } e = setup_engine(bio_err, engine, 0); if(passarg) { if(export_cert) passargout = passarg; else passargin = passarg; } if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } if(!cpass) { if(export_cert) cpass = passout; else cpass = passin; } if(cpass) { mpass = cpass; noprompt = 1; } else { cpass = pass; mpass = macpass; } if(export_cert || inrand) { app_RAND_load_file(NULL, bio_err, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } ERR_load_crypto_strings(); #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read files"); #endif 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 : "<stdin>"); perror (infile); goto end; } #if 0 if (certfile) { 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) { if(!(inkey = BIO_new_file(keyname, "r"))) { BIO_printf(bio_err, "Can't key certificate file %s\n", keyname); perror (keyname); goto end; } } #endif #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("write files"); #endif if (!outfile) { out = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else out = BIO_new_file(outfile, "wb"); if (!out) { BIO_printf(bio_err, "Error opening output file %s\n", outfile ? outfile : "<stdout>"); perror (outfile); goto end; } if (twopass) { #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read MAC password"); #endif if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n"); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif } if (export_cert) { EVP_PKEY *key = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; STACK_OF(PKCS7) *safes = NULL; PKCS12_SAFEBAG *bag = NULL; PKCS8_PRIV_KEY_INFO *p8 = NULL; PKCS7 *authsafe = NULL; X509 *ucert = NULL; STACK_OF(X509) *certs=NULL; char *catmp = NULL; int i; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; #ifdef CRYPTO_MDEBUG CRYPTO_push_info("process -export_cert"); CRYPTO_push_info("reading private key"); #endif key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1, passin, e, "private key"); if (!key) { goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input"); #endif /* Load in all certs in input file */ if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, "certificates"))) { goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input 2"); #endif 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) { ucert = NULL; BIO_printf(bio_err, "No certificate matches private key\n"); goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from certfile"); #endif bags = sk_PKCS12_SAFEBAG_new_null (); /* Add any more certificates asked for */ if (certfile) { STACK_OF(X509) *morecerts=NULL; if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, NULL, e, "certificates from certfile"))) { goto export_end; } while(sk_X509_num(morecerts) > 0) { sk_X509_push(certs, sk_X509_shift(morecerts)); } sk_X509_free(morecerts); } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building chain"); #endif /* If chaining get chain from user cert */ if (chain) { int vret; STACK_OF(X509) *chain2; X509_STORE *store = X509_STORE_new(); if (!store) { BIO_printf (bio_err, "Memory allocation error\n"); goto export_end; } if (!X509_STORE_load_locations(store, CAfile, CApath)) X509_STORE_set_default_paths (store); vret = get_cert_chain (ucert, store, &chain2); X509_STORE_free(store); if (!vret) { /* Exclude verified certificate */ for (i = 1; i < sk_X509_num (chain2) ; i++) sk_X509_push(certs, sk_X509_value (chain2, i)); /* Free first certificate */ X509_free(sk_X509_value(chain2, 0)); sk_X509_free(chain2); } else { BIO_printf (bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); goto export_end; } } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building bags"); #endif /* We now have loads of certificates: include them all */ for(i = 0; i < sk_X509_num(certs); i++) { X509 *cert = NULL; cert = sk_X509_value(certs, i); bag = PKCS12_x5092certbag(cert); /* If it matches private key set id */ if(cert == ucert) { if(name) PKCS12_add_friendlyname(bag, name, -1); PKCS12_add_localkeyid(bag, keyid, keyidlen); } else if((catmp = sk_shift(canames))) PKCS12_add_friendlyname(bag, catmp, -1); sk_PKCS12_SAFEBAG_push(bags, bag); } sk_X509_pop_free(certs, X509_free); certs = NULL; #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("encrypting bags"); #endif if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n"); goto export_end; } if (!twopass) strcpy(macpass, pass); /* Turn certbags into encrypted authsafe */ authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0, iter, bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; if (!authsafe) { ERR_print_errors (bio_err); goto export_end; } safes = sk_PKCS7_new_null (); sk_PKCS7_push (safes, authsafe); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building shrouded key bag"); #endif /* Make a shrouded key bag */ p8 = EVP_PKEY2PKCS8 (key); if(keytype) PKCS8_add_keyusage(p8, keytype); bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8); PKCS8_PRIV_KEY_INFO_free(p8); p8 = NULL; if (name) PKCS12_add_friendlyname (bag, name, -1); if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1); PKCS12_add_localkeyid (bag, keyid, keyidlen); bags = sk_PKCS12_SAFEBAG_new_null(); sk_PKCS12_SAFEBAG_push (bags, bag); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("encrypting shrouded key bag"); #endif /* Turn it into unencrypted safe bag */ authsafe = PKCS12_pack_p7data (bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; sk_PKCS7_push (safes, authsafe); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building pkcs12"); #endif p12 = PKCS12_init(NID_pkcs7_data); PKCS12_pack_authsafes(p12, safes); sk_PKCS7_pop_free(safes, PKCS7_free); safes = NULL; PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("writing pkcs12"); #endif i2d_PKCS12_bio (out, p12); ret = 0; export_end: #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_pop_info(); CRYPTO_push_info("process -export_cert: freeing"); #endif if (key) EVP_PKEY_free(key); if (certs) sk_X509_pop_free(certs, X509_free); if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif goto end; } if (!(p12 = d2i_PKCS12_bio (in, NULL))) { ERR_print_errors(bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read import password"); #endif if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"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 we enter empty password try no password first */ if(!macpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ if(!twopass) cpass = NULL; } else if (!PKCS12_verify_mac(p12, mpass, -1)) { BIO_printf (bio_err, "Mac verify error: invalid password?\n"); ERR_print_errors (bio_err); goto end; } 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, passout)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors (bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif ret = 0; end: if (p12) PKCS12_free(p12); if(export_cert || inrand) app_RAND_write_file(NULL, bio_err); #ifdef CRYPTO_MDEBUG CRYPTO_remove_all_info(); #endif BIO_free(in); BIO_free_all(out); if (canames) sk_free(canames); if(passin) OPENSSL_free(passin); if(passout) OPENSSL_free(passout); apps_shutdown(); OPENSSL_EXIT(ret); }
static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass) { STACK_OF(PKCS7) *asafes, *newsafes; STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; if (!(asafes = PKCS12_unpack_authsafes(p12))) return 0; if(!(newsafes = sk_PKCS7_new_null())) return 0; for (i = 0; i < sk_PKCS7_num (asafes); i++) { p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); alg_get(p7->d.encrypted->enc_data->algorithm, &pbe_nid, &pbe_iter, &pbe_saltlen); } else continue; if (!bags) { sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } if (!newpass_bags(bags, oldpass, newpass)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, pbe_saltlen, pbe_iter, bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if(!p7new) { sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } sk_PKCS7_push(newsafes, p7new); } sk_PKCS7_pop_free(asafes, PKCS7_free); /* Repack safe: save old safe in case of error */ p12_data_tmp = p12->authsafes->d.data; if(!(p12->authsafes->d.data = ASN1_OCTET_STRING_new())) goto saferr; if(!PKCS12_pack_authsafes(p12, newsafes)) goto saferr; if(!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto saferr; if(!(macnew = ASN1_OCTET_STRING_new())) goto saferr; if(!ASN1_OCTET_STRING_set(macnew, mac, maclen)) goto saferr; ASN1_OCTET_STRING_free(p12->mac->dinfo->digest); p12->mac->dinfo->digest = macnew; ASN1_OCTET_STRING_free(p12_data_tmp); return 1; saferr: /* Restore old safe */ ASN1_OCTET_STRING_free(p12->authsafes->d.data); ASN1_OCTET_STRING_free(macnew); p12->authsafes->d.data = p12_data_tmp; return 0; }
char *Pem2Pfx(char *pemFile, char *pemPass) { BIO *in=NULL, *out = NULL; char tempDirPath[MAX_PATH]; char baseFileName[MAX_PATH]; char *retFileName = NULL; EVP_PKEY *key = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; STACK_OF(PKCS7) *safes = NULL; PKCS12_SAFEBAG *bag = NULL; PKCS8_PRIV_KEY_INFO *p8 = NULL; PKCS7 *authsafe = NULL; X509 *ucert = NULL; STACK_OF(X509) *certs=NULL; char *catmp = NULL; int i; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; char *name = NULL; STACK *canames = NULL; int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int iter = PKCS12_DEFAULT_ITER; int maciter = PKCS12_DEFAULT_ITER; int keytype = 0; char *csp_name = NULL; HRESULT ret = S_FALSE; PKCS12 *p12 = NULL; FILE *test; apps_startup(); enc = EVP_des_ede3_cbc(); app_RAND_load_file(NULL, bio_err, FALSE); ERR_load_crypto_strings(); in = BIO_new_file(pemFile, "rb"); if (!in) { BIO_printf(bio_err, "Error opening input file %s\n", pemFile); perror (pemFile); goto end; } // Get the Temp Path for the user GetTempPath((DWORD)MAX_PATH, tempDirPath); retFileName = (char *)malloc(MAX_PATH * sizeof(char)); GetBaseName(pemFile, baseFileName); // sprintf(retFileName, "%s%s.pfx", "C:\\Temp\\Debug\\", baseFileName); sprintf(retFileName, "%s%s.pfx", tempDirPath, baseFileName); out = BIO_new_file(retFileName, "wb"); if (!out) { BIO_printf(bio_err, "Error opening output file %s\n", retFileName); perror(retFileName); goto end; } key = load_key(bio_err, pemFile, FORMAT_PEM, 1, pemPass, NULL, "private key"); if (!key) goto end; /* Load in all certs in input file */ if(!(certs = load_certs(bio_err, pemFile, FORMAT_PEM, NULL, NULL, "certificates"))) 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) { ucert = NULL; BIO_printf(bio_err, "No certificate matches private key\n"); goto end; } bags = sk_PKCS12_SAFEBAG_new_null(); /* We now have loads of certificates: include them all */ for(i = 0; i < sk_X509_num(certs); i++) { X509 *cert = NULL; cert = sk_X509_value(certs, i); bag = PKCS12_x5092certbag(cert); /* If it matches private key set id */ if(cert == ucert) { if(name) PKCS12_add_friendlyname(bag, name, -1); PKCS12_add_localkeyid(bag, keyid, keyidlen); } else if((catmp = sk_shift(canames))) PKCS12_add_friendlyname(bag, catmp, -1); sk_PKCS12_SAFEBAG_push(bags, bag); } sk_X509_pop_free(certs, X509_free); certs = NULL; /* Turn certbags into encrypted authsafe */ authsafe = PKCS12_pack_p7encdata(cert_pbe, pemPass, -1, NULL, 0, iter, bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; if (!authsafe) { ERR_print_errors(bio_err); goto end; } safes = sk_PKCS7_new_null(); sk_PKCS7_push(safes, authsafe); /* Make a shrouded key bag */ p8 = EVP_PKEY2PKCS8(key); if(keytype) PKCS8_add_keyusage(p8, keytype); bag = PKCS12_MAKE_SHKEYBAG(key_pbe, pemPass, -1, NULL, 0, iter, p8); PKCS8_PRIV_KEY_INFO_free(p8); p8 = NULL; if (name) PKCS12_add_friendlyname(bag, name, -1); if (csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1); PKCS12_add_localkeyid (bag, keyid, keyidlen); bags = sk_PKCS12_SAFEBAG_new_null(); sk_PKCS12_SAFEBAG_push (bags, bag); /* Turn it into unencrypted safe bag */ authsafe = PKCS12_pack_p7data(bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; sk_PKCS7_push(safes, authsafe); p12 = PKCS12_init(NID_pkcs7_data); PKCS12_pack_authsafes(p12, safes); sk_PKCS7_pop_free(safes, PKCS7_free); safes = NULL; PKCS12_set_mac(p12, pemPass, -1, NULL, 0, maciter, NULL); i2d_PKCS12_bio (out, p12); ret = S_OK; end: if (key) EVP_PKEY_free(key); if (certs) sk_X509_pop_free(certs, X509_free); if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if (p12) PKCS12_free(p12); app_RAND_write_file(NULL, bio_err); BIO_free(in); BIO_free_all(out); if (canames) sk_free(canames); apps_shutdown(); if (ret != S_OK) return NULL; return retFileName; }
static int newpass_p12(PKCS12 *p12, const char *oldpass, const char *newpass) { STACK_OF(PKCS7) *asafes = NULL, *newsafes = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macoct = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; int rv = 0; if ((asafes = PKCS12_unpack_authsafes(p12)) == NULL) goto err; if ((newsafes = sk_PKCS7_new_null()) == NULL) goto err; for (i = 0; i < sk_PKCS7_num(asafes); i++) { p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); if (!alg_get(p7->d.encrypted->enc_data->algorithm, &pbe_nid, &pbe_iter, &pbe_saltlen)) goto err; } else { continue; } if (bags == NULL) goto err; if (!newpass_bags(bags, oldpass, newpass)) goto err; /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, pbe_saltlen, pbe_iter, bags); if (!p7new || !sk_PKCS7_push(newsafes, p7new)) goto err; sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; } /* Repack safe: save old safe in case of error */ p12_data_tmp = p12->authsafes->d.data; if ((p12->authsafes->d.data = ASN1_OCTET_STRING_new()) == NULL) goto err; if (!PKCS12_pack_authsafes(p12, newsafes)) goto err; if (!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto err; X509_SIG_get0(NULL, &macoct, p12->mac->dinfo); if (!ASN1_OCTET_STRING_set(macoct, mac, maclen)) goto err; rv = 1; err: /* Restore old safe if necessary */ if (rv == 1) { ASN1_OCTET_STRING_free(p12_data_tmp); } else if (p12_data_tmp != NULL) { ASN1_OCTET_STRING_free(p12->authsafes->d.data); p12->authsafes->d.data = p12_data_tmp; } sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); sk_PKCS7_pop_free(newsafes, PKCS7_free); return rv; }