/** * xmlSecOpenSSLX509StoreVerify: * @store: the pointer to X509 key data store klass. * @certs: the untrusted certificates stack. * @crls: the crls stack. * @keyInfoCtx: the pointer to <dsig:KeyInfo/> element processing context. * * Verifies @certs list. * * Returns: pointer to the first verified certificate from @certs. */ X509* xmlSecOpenSSLX509StoreVerify(xmlSecKeyDataStorePtr store, XMLSEC_STACK_OF_X509* certs, XMLSEC_STACK_OF_X509_CRL* crls, xmlSecKeyInfoCtx* keyInfoCtx) { xmlSecOpenSSLX509StoreCtxPtr ctx; STACK_OF(X509)* certs2 = NULL; STACK_OF(X509_CRL)* crls2 = NULL; X509 * res = NULL; X509 * cert; X509 * err_cert = NULL; X509_STORE_CTX *xsc; char buf[256]; int err = 0; int i; int ret; xmlSecAssert2(xmlSecKeyDataStoreCheckId(store, xmlSecOpenSSLX509StoreId), NULL); xmlSecAssert2(certs != NULL, NULL); xmlSecAssert2(keyInfoCtx != NULL, NULL); xsc = X509_STORE_CTX_new(); if(xsc == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_STORE_CTX_new"); goto done; } ctx = xmlSecOpenSSLX509StoreGetCtx(store); xmlSecAssert2(ctx != NULL, NULL); xmlSecAssert2(ctx->xst != NULL, NULL); /* dup certs */ certs2 = sk_X509_dup(certs); if(certs2 == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_dup"); goto done; } /* add untrusted certs from the store */ if(ctx->untrusted != NULL) { for(i = 0; i < sk_X509_num(ctx->untrusted); ++i) { ret = sk_X509_push(certs2, sk_X509_value(ctx->untrusted, i)); if(ret < 1) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_push"); goto done; } } } /* dup crls but remove all non-verified */ if(crls != NULL) { crls2 = sk_X509_CRL_dup(crls); if(crls2 == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "sk_X509_CRL_dup"); goto done; } for(i = 0; i < sk_X509_CRL_num(crls2); ) { ret = xmlSecOpenSSLX509VerifyCRL(ctx->xst, sk_X509_CRL_value(crls2, i)); if(ret == 1) { ++i; } else if(ret == 0) { (void)sk_X509_CRL_delete(crls2, i); } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCRL", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } } /* remove all revoked certs */ for(i = 0; i < sk_X509_num(certs2);) { cert = sk_X509_value(certs2, i); if(crls2 != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(crls2, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } if(ctx->crls != NULL) { ret = xmlSecOpenSSLX509VerifyCertAgainstCrls(ctx->crls, cert); if(ret == 0) { (void)sk_X509_delete(certs2, i); continue; } else if(ret != 1) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "xmlSecOpenSSLX509VerifyCertAgainstCrls", XMLSEC_ERRORS_R_XMLSEC_FAILED, XMLSEC_ERRORS_NO_MESSAGE); goto done; } } ++i; } /* get one cert after another and try to verify */ for(i = 0; i < sk_X509_num(certs2); ++i) { cert = sk_X509_value(certs2, i); if(xmlSecOpenSSLX509FindNextChainCert(certs2, cert) == NULL) { ret = X509_STORE_CTX_init(xsc, ctx->xst, cert, certs2); if(ret != 1) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_STORE_CTX_init"); goto done; } if(keyInfoCtx->certsVerificationTime > 0) { X509_STORE_CTX_set_time(xsc, 0, keyInfoCtx->certsVerificationTime); } { X509_VERIFY_PARAM * vpm = NULL; unsigned long vpm_flags = 0; vpm = X509_VERIFY_PARAM_new(); if(vpm == NULL) { xmlSecOpenSSLError(xmlSecKeyDataStoreGetName(store), "X509_VERIFY_PARAM_new"); goto done; } vpm_flags = X509_VERIFY_PARAM_get_flags(vpm); vpm_flags &= (~X509_V_FLAG_CRL_CHECK); if(keyInfoCtx->certsVerificationTime > 0) { vpm_flags |= X509_V_FLAG_USE_CHECK_TIME; X509_VERIFY_PARAM_set_time(vpm, keyInfoCtx->certsVerificationTime); } X509_VERIFY_PARAM_set_depth(vpm, keyInfoCtx->certsVerificationDepth); X509_VERIFY_PARAM_set_flags(vpm, vpm_flags); X509_STORE_CTX_set0_param(xsc, vpm); } ret = X509_verify_cert(xsc); err_cert = X509_STORE_CTX_get_current_cert(xsc); err = X509_STORE_CTX_get_error(xsc); X509_STORE_CTX_cleanup (xsc); if(ret == 1) { res = cert; goto done; } else if(ret < 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); goto done; } else if(ret == 0) { const char* err_msg; buf[0] = '\0'; X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof buf); err_msg = X509_verify_cert_error_string(err); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), "X509_verify_cert", XMLSEC_ERRORS_R_CRYPTO_FAILED, "subj=%s;err=%d;msg=%s", xmlSecErrorsSafeString(buf), err, xmlSecErrorsSafeString(err_msg)); } } } /* if we came here then we found nothing. do we have any error? */ if((err != 0) && (err_cert != NULL)) { const char* err_msg; err_msg = X509_verify_cert_error_string(err); switch (err) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof buf); xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_ISSUER_FAILED, "err=%d;msg=%s;issuer=%s", err, xmlSecErrorsSafeString(err_msg), xmlSecErrorsSafeString(buf)); break; case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_NOT_YET_VALID, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; case X509_V_ERR_CERT_HAS_EXPIRED: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_HAS_EXPIRED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); break; default: xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecKeyDataStoreGetName(store)), NULL, XMLSEC_ERRORS_R_CERT_VERIFY_FAILED, "err=%d;msg=%s", err, xmlSecErrorsSafeString(err_msg)); } } done: if(certs2 != NULL) { sk_X509_free(certs2); } if(crls2 != NULL) { sk_X509_CRL_free(crls2); } if(xsc != NULL) { X509_STORE_CTX_free(xsc); } return(res); }
int pkcs12_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; int add_lmk = 0; 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; int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1; int macver = 1; int noprompt = 0; STACK_OF(OPENSSL_STRING) * canames = NULL; char *cpass = NULL, *mpass = NULL; char *passargin = NULL, *passargout = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL; char *inrand = NULL; char *macalg = NULL; char *CApath = NULL, *CAfile = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif signal(SIGPIPE, SIG_IGN); cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; 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(); else if (!strcmp(*args, "-des3")) enc = EVP_des_ede3_cbc(); #ifndef OPENSSL_NO_IDEA else if (!strcmp(*args, "-idea")) enc = EVP_idea_cbc(); #endif #ifndef OPENSSL_NO_SEED else if (!strcmp(*args, "-seed")) enc = EVP_seed_cbc(); #endif #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 #ifndef OPENSSL_NO_CAMELLIA else if (!strcmp(*args, "-camellia128")) enc = EVP_camellia_128_cbc(); else if (!strcmp(*args, "-camellia192")) enc = EVP_camellia_192_cbc(); else if (!strcmp(*args, "-camellia256")) enc = EVP_camellia_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, "-nomac")) maciter = -1; else if (!strcmp(*args, "-macalg")) if (args[1]) { args++; macalg = *args; } else badarg = 1; else if (!strcmp(*args, "-nodes")) enc = NULL; else if (!strcmp(*args, "-certpbe")) { if (!set_pbe(bio_err, &cert_pbe, *++args)) badarg = 1; } else if (!strcmp(*args, "-keypbe")) { if (!set_pbe(bio_err, &key_pbe, *++args)) 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, "-LMK")) add_lmk = 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_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_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; #ifndef OPENSSL_NO_ENGINE } else if (!strcmp(*args, "-engine")) { if (args[1]) { args++; engine = *args; } else badarg = 1; #endif } 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_SEED BIO_printf(bio_err, "-seed encrypt private keys with seed\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 #ifndef OPENSSL_NO_CAMELLIA BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); BIO_printf(bio_err, " encrypt PEM output with cbc camellia\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, "-nomaciter don't use MAC iteration\n"); BIO_printf(bio_err, "-maciter use MAC iteration\n"); BIO_printf(bio_err, "-nomac don't generate MAC\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, "-macalg alg digest algorithm used in MAC (default SHA1)\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"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err, "-rand file:file:...\n"); BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); BIO_printf(bio_err, " the random number generator\n"); BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); BIO_printf(bio_err, "-LMK Add local machine keyset attribute to private key\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif 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; } 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; } #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 : "<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; X509 *ucert = NULL, *x = NULL; STACK_OF(X509) * certs = NULL; const EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { BIO_printf(bio_err, "Nothing to do!\n"); goto export_end; } if (options & NOCERTS) chain = 0; #ifdef CRYPTO_MDEBUG CRYPTO_push_info("process -export_cert"); CRYPTO_push_info("reading private key"); #endif if (!(options & NOKEYS)) { 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 (!(options & NOCERTS)) { certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, "certificates"); if (!certs) goto export_end; if (key) { /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); if (X509_check_private_key(x, key)) { ucert = x; /* Zero keyid and alias */ X509_keyid_set1(ucert, NULL, 0); X509_alias_set1(ucert, NULL, 0); /* Remove from list */ (void) sk_X509_delete(certs, i); break; } } if (!ucert) { 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 input 2"); #endif /* 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("reading certs from certfile"); #endif #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 { if (vret >= 0) BIO_printf(bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); else ERR_print_errors(bio_err); goto export_end; } } /* Add any CA names */ for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) { catmp = (unsigned char *) sk_OPENSSL_STRING_value(canames, i); X509_alias_set1(sk_X509_value(certs, i), catmp, -1); } if (csp_name && key) EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, MBSTRING_ASC, (unsigned char *) csp_name, -1); if (add_lmk && key) EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading password"); #endif if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n"); goto export_end; } if (!twopass) strlcpy(macpass, pass, sizeof macpass); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("creating PKCS#12 structure"); #endif p12 = PKCS12_create(cpass, name, key, ucert, certs, key_pbe, cert_pbe, iter, -1, keytype); if (!p12) { ERR_print_errors(bio_err); goto export_end; } if (macalg) { macmd = EVP_get_digestbyname(macalg); if (!macmd) { BIO_printf(bio_err, "Unknown digest algorithm %s\n", macalg); } } if (maciter != -1) PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); #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 (ucert) X509_free(ucert); #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) strlcpy(macpass, pass, sizeof macpass); if ((options & INFO) && p12->mac) 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 (!mpass[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); #ifdef CRYPTO_MDEBUG CRYPTO_remove_all_info(); #endif BIO_free(in); BIO_free_all(out); if (canames) sk_OPENSSL_STRING_free(canames); if (passin) free(passin); if (passout) free(passout); return (ret); }
int pkcs12_main(int argc, char **argv) { char *infile = NULL, *outfile = NULL, *keyname = NULL, *certfile = NULL; char *name = NULL, *csp_name = NULL; char pass[50], macpass[50]; int export_cert = 0, options = 0, chain = 0, twopass = 0, keytype = 0; int iter = PKCS12_DEFAULT_ITER, maciter = PKCS12_DEFAULT_ITER; # ifndef OPENSSL_NO_RC2 int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; # else int cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; # endif int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1, macver = 1, noprompt = 0, add_lmk = 0; char *passinarg = NULL, *passoutarg = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL, *inrand = NULL, *macalg = NULL; char *cpass = NULL, *mpass = NULL, *CApath = NULL, *CAfile = NULL; char *prog; ENGINE *e = NULL; BIO *in = NULL, *out = NULL; PKCS12 *p12 = NULL; STACK_OF(OPENSSL_STRING) *canames = NULL; const EVP_CIPHER *enc = EVP_des_ede3_cbc(); OPTION_CHOICE o; prog = opt_init(argc, argv, pkcs12_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(pkcs12_options); ret = 0; goto end; case OPT_NOKEYS: options |= NOKEYS; break; case OPT_KEYEX: keytype = KEY_EX; break; case OPT_KEYSIG: keytype = KEY_SIG; break; case OPT_NOCERTS: options |= NOCERTS; break; case OPT_CLCERTS: options |= CLCERTS; break; case OPT_CACERTS: options |= CACERTS; break; case OPT_NOOUT: options |= (NOKEYS | NOCERTS); break; case OPT_INFO: options |= INFO; break; case OPT_CHAIN: chain = 1; break; case OPT_TWOPASS: twopass = 1; break; case OPT_NOMACVER: macver = 0; break; case OPT_DESCERT: cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; break; case OPT_EXPORT: export_cert = 1; break; case OPT_CIPHER: if (!opt_cipher(opt_unknown(), &enc)) goto opthelp; break; case OPT_NOITER: iter = 1; break; case OPT_MACITER: maciter = PKCS12_DEFAULT_ITER; break; case OPT_NOMACITER: maciter = 1; break; case OPT_NOMAC: maciter = -1; break; case OPT_MACALG: macalg = opt_arg(); break; case OPT_NODES: enc = NULL; break; case OPT_CERTPBE: if (!set_pbe(&cert_pbe, opt_arg())) goto opthelp; break; case OPT_KEYPBE: if (!set_pbe(&key_pbe, opt_arg())) goto opthelp; break; case OPT_RAND: inrand = opt_arg(); break; case OPT_INKEY: keyname = opt_arg(); break; case OPT_CERTFILE: certfile = opt_arg(); break; case OPT_NAME: name = opt_arg(); break; case OPT_LMK: add_lmk = 1; break; case OPT_CSP: csp_name = opt_arg(); break; case OPT_CANAME: if (canames == NULL && (canames = sk_OPENSSL_STRING_new_null()) == NULL) goto end; sk_OPENSSL_STRING_push(canames, opt_arg()); break; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_PASSIN: passinarg = opt_arg(); break; case OPT_PASSOUT: passoutarg = opt_arg(); break; case OPT_PASSWORD: passarg = opt_arg(); break; case OPT_CAPATH: CApath = opt_arg(); break; case OPT_CAFILE: CAfile = opt_arg(); break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); break; } } argc = opt_num_rest(); argv = opt_rest(); if (passarg) { if (export_cert) passoutarg = passarg; else passinarg = passarg; } if (!app_passwd(passinarg, passoutarg, &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, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err, "%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } in = bio_open_default(infile, "rb"); if (in == NULL) goto end; out = bio_open_default(outfile, "wb"); if (out == NULL) goto end; if (twopass) { if (EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n"); goto end; } } if (export_cert) { EVP_PKEY *key = NULL; X509 *ucert = NULL, *x = NULL; STACK_OF(X509) *certs = NULL; const EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { BIO_printf(bio_err, "Nothing to do!\n"); goto export_end; } if (options & NOCERTS) chain = 0; if (!(options & NOKEYS)) { key = load_key(keyname ? keyname : infile, FORMAT_PEM, 1, passin, e, "private key"); if (!key) goto export_end; } /* Load in all certs in input file */ if (!(options & NOCERTS)) { certs = load_certs(infile, FORMAT_PEM, NULL, e, "certificates"); if (!certs) goto export_end; if (key) { /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); if (X509_check_private_key(x, key)) { ucert = x; /* Zero keyid and alias */ X509_keyid_set1(ucert, NULL, 0); X509_alias_set1(ucert, NULL, 0); /* Remove from list */ (void)sk_X509_delete(certs, i); break; } } if (!ucert) { BIO_printf(bio_err, "No certificate matches private key\n"); goto export_end; } } } /* Add any more certificates asked for */ if (certfile) { STACK_OF(X509) *morecerts = NULL; if (!(morecerts = load_certs(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); } /* If chaining get chain from user cert */ if (chain) { int vret; STACK_OF(X509) *chain2; X509_STORE *store; if (!(store = setup_verify(CAfile, CApath))) goto export_end; 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 { if (vret >= 0) BIO_printf(bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); else ERR_print_errors(bio_err); goto export_end; } } /* Add any CA names */ for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) { catmp = (unsigned char *)sk_OPENSSL_STRING_value(canames, i); X509_alias_set1(sk_X509_value(certs, i), catmp, -1); } if (csp_name && key) EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, MBSTRING_ASC, (unsigned char *)csp_name, -1); if (add_lmk && key) EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n"); goto export_end; } if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); p12 = PKCS12_create(cpass, name, key, ucert, certs, key_pbe, cert_pbe, iter, -1, keytype); if (!p12) { ERR_print_errors(bio_err); goto export_end; } if (macalg) { if (!opt_md(macalg, &macmd)) goto opthelp; } if (maciter != -1) PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); i2d_PKCS12_bio(out, p12); ret = 0; export_end: EVP_PKEY_free(key); if (certs) sk_X509_pop_free(certs, X509_free); if (ucert) X509_free(ucert); goto end; } if (!(p12 = d2i_PKCS12_bio(in, NULL))) { ERR_print_errors(bio_err); goto end; } if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n"); goto end; } if (!twopass) BUF_strlcpy(macpass, pass, sizeof macpass); if ((options & INFO) && p12->mac) BIO_printf(bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); if (macver) { /* If we enter empty password try no password first */ if (!mpass[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; } } if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout, enc)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors(bio_err); goto end; } ret = 0; end: PKCS12_free(p12); if (export_cert || inrand) app_RAND_write_file(NULL); BIO_free(in); BIO_free_all(out); if (canames) sk_OPENSSL_STRING_free(canames); if (passin) OPENSSL_free(passin); if (passout) OPENSSL_free(passout); return (ret); }