static Bool IsPKCS12(const char *file) { Bool ret = TRUE; EVP_PKEY *key = NULL; X509 *cert = NULL; BIO *input; PKCS12 *p12; int err_reason; if ((input = BIO_new_file(file, "r")) == NULL){ if (d2i_PKCS12_bio(input, &p12) == NULL) return FALSE; } p12 = d2i_PKCS12_bio(input, NULL); BIO_free(input); if (p12 == NULL) return FALSE; err_reason = PKCS12_parse(p12, "", &key, &cert, NULL); if (err_reason == PKCS12_R_MAC_VERIFY_FAILURE){ ret = FALSE; } if (cert){ X509_free(cert); cert = NULL; } if (key){ EVP_PKEY_free(key); key = NULL; } ERR_clear_error(); PKCS12_free(p12); return ret; }
Settings::KeyPair CertWizard::importCert(QByteArray data, const QString &pw) { X509 *x509 = NULL; EVP_PKEY *pkey = NULL; PKCS12 *pkcs = NULL; BIO *mem = NULL; STACK_OF(X509) *certs = NULL; Settings::KeyPair kp; int ret = 0; mem = BIO_new_mem_buf(data.data(), data.size()); Q_UNUSED(BIO_set_close(mem, BIO_NOCLOSE)); pkcs = d2i_PKCS12_bio(mem, NULL); if (pkcs) { ret = PKCS12_parse(pkcs, NULL, &pkey, &x509, &certs); if (pkcs && !pkey && !x509 && ! pw.isEmpty()) { if (certs) { if (ret) sk_X509_free(certs); certs = NULL; } ret = PKCS12_parse(pkcs, pw.toUtf8().constData(), &pkey, &x509, &certs); } if (pkey && x509 && X509_check_private_key(x509, pkey)) { unsigned char *dptr; QByteArray key, crt; key.resize(i2d_PrivateKey(pkey, NULL)); dptr=reinterpret_cast<unsigned char *>(key.data()); i2d_PrivateKey(pkey, &dptr); crt.resize(i2d_X509(x509, NULL)); dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(x509, &dptr); QSslCertificate qscCert = QSslCertificate(crt, QSsl::Der); QSslKey qskKey = QSslKey(key, QSsl::Rsa, QSsl::Der); QList<QSslCertificate> qlCerts; qlCerts << qscCert; if (certs) { for (int i=0;i<sk_X509_num(certs);++i) { X509 *c = sk_X509_value(certs, i); crt.resize(i2d_X509(c, NULL)); dptr=reinterpret_cast<unsigned char *>(crt.data()); i2d_X509(c, &dptr); QSslCertificate cert = QSslCertificate(crt, QSsl::Der); qlCerts << cert; } } bool valid = ! qskKey.isNull(); foreach(const QSslCertificate &cert, qlCerts) valid = valid && ! cert.isNull(); if (valid) kp = Settings::KeyPair(qlCerts, qskKey); } }
static int _parcPkcs12KeyStore_ParseFile(PARCPkcs12KeyStore *keystore, const char *filename, const char *password) { parcSecurity_AssertIsInitialized(); FILE *fp = fopen(filename, "rb"); assertNotNull(fp, "Error opening %s: %s", filename, strerror(errno)); if (fp == NULL) { return -1; } PKCS12 *p12Keystore = NULL; d2i_PKCS12_fp(fp, &p12Keystore); fclose(fp); int success = PKCS12_parse(p12Keystore, password, &keystore->private_key, &keystore->x509_cert, NULL); PKCS12_free(p12Keystore); if (!success) { unsigned long errcode; while ((errcode = ERR_get_error()) != 0) { fprintf(stderr, "openssl error: %s\n", ERR_error_string(errcode, NULL)); } return -1; } keystore->public_key = X509_get_pubkey(keystore->x509_cert); return 0; }
void PEM_From_P12(PA_PluginParameters params) { sLONG_PTR *pResult = (sLONG_PTR *)params->fResult; PackagePtr pParams = (PackagePtr)params->fParameters; C_BLOB Param1; C_BLOB Param2; C_TEXT Param3; C_TEXT returnValue; Param1.fromParamAtIndex(pParams, 1); Param3.fromParamAtIndex(pParams, 3); BIO *bio = BIO_new_mem_buf((void *)Param1.getBytesPtr(), Param1.getBytesLength()); if(bio){ PKCS12 *p12 = d2i_PKCS12_bio(bio, NULL); if(p12){ EVP_PKEY *key = NULL; X509 *cert = NULL; STACK_OF(X509) *ca = NULL; CUTF8String pass; Param3.copyUTF8String(&pass); if(PKCS12_parse(p12, (const char *)pass.c_str(), &key, &cert, &ca)){ BIO *pem = BIO_new(BIO_s_mem()); if(pem){ PEM_write_bio_PrivateKey(pem, key, NULL, NULL, NULL, NULL, (void *)pass.c_str()); char *buf = NULL; int len = BIO_get_mem_data(pem, &buf); if(len){ Param2.setBytes((const uint8_t *)buf, len); Param2.toParamAtIndex(pParams, 2); CUTF8String pemStr = CUTF8String((const uint8_t *)buf, len); returnValue.setUTF8String(&pemStr); } BIO_free(pem); } } } BIO_free(bio); } Param2.toParamAtIndex(pParams, 2); returnValue.setReturn(pResult); }
bool Engine::set_p12_certificate_privatekey(const Data & data, const std::string & password) { if( data.empty() ) // BIO undefined behaviour when writing 0 return false; BIO *mem = BIO_new(BIO_s_mem()); BIO_write(mem, data.getData(), data.getSize()); PKCS12 * pkcs12 = d2i_PKCS12_bio(mem, NULL); BIO_free(mem); mem = 0; X509 * cax = 0; EVP_PKEY * pkey = 0; // int succ = PKCS12_parse(pkcs12, password.c_str(), &pkey, &cax, NULL); // int err = ERR_get_error(); // const char * err_str = ERR_error_string(err, 0); int cert_res = SSL_use_certificate(ssl, cax); if (cax) X509_free(cax); cax = 0; int key_res = SSL_use_PrivateKey(ssl, pkey); if( pkey ) EVP_PKEY_free(pkey); pkey = 0; int check_res = SSL_check_private_key(ssl); return cert_res == 1 && key_res == 1 && check_res == 1; }
pki_pkcs12::pki_pkcs12(const QString fname, pem_password_cb *cb) :pki_base(fname) { FILE *fp; char pass[MAX_PASS_LENGTH]; EVP_PKEY *mykey = NULL; X509 *mycert = NULL; key=NULL; cert=NULL; passcb = cb; class_name="pki_pkcs12"; certstack = sk_X509_new_null(); pass_info p(XCA_TITLE, tr("Please enter the password to decrypt the PKCS#12 file.") + "\n'" + fname + "'"); fp = fopen(QString2filename(fname), "rb"); if (fp) { PKCS12 *pkcs12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (ign_openssl_error()) { if (pkcs12) PKCS12_free(pkcs12); throw errorEx(tr("Unable to load the PKCS#12 (pfx) file %1.").arg(fname)); } if (PKCS12_verify_mac(pkcs12, "", 0) || PKCS12_verify_mac(pkcs12, NULL, 0)) pass[0] = '\0'; else if (passcb(pass, MAX_PASS_LENGTH, 0, &p) < 0) { /* cancel pressed */ PKCS12_free(pkcs12); throw errorEx("",""); } PKCS12_parse(pkcs12, pass, &mykey, &mycert, &certstack); int error = ERR_peek_error(); if (ERR_GET_REASON(error) == PKCS12_R_MAC_VERIFY_FAILURE) { ign_openssl_error(); PKCS12_free(pkcs12); throw errorEx(getClassName(), tr("The supplied password was wrong (%1)").arg(ERR_reason_error_string(error))); } ign_openssl_error(); if (mycert) { if (mycert->aux && mycert->aux->alias) { alias = asn1ToQString(mycert->aux->alias); alias = QString::fromUtf8(alias.toAscii()); } cert = new pki_x509(mycert); if (alias.isEmpty()) { cert->autoIntName(); } else { cert->setIntName(alias); } alias = cert->getIntName(); } if (mykey) { key = new pki_evp(mykey); key->setIntName(alias + "_key"); key->bogusEncryptKey(); } PKCS12_free(pkcs12); } else fopen_error(fname); }
int useCertFile(SSL_CTX* ctx, const char* path, const char* passphrase, const char* cacertfile) { FILE *p12_file; PKCS12 *p12_cert = NULL; EVP_PKEY *pkey; X509 *x509_cert; p12_file = fopen(path, "r"); if (!p12_file) { timestamp_f(stderr); perror(path); return -1; } d2i_PKCS12_fp(p12_file, &p12_cert); fclose(p12_file); if (!PKCS12_parse(p12_cert, passphrase, &pkey, &x509_cert, NULL)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to parse p12 file; error %d\n", error); PKCS12_free(p12_cert); return -1; } PKCS12_free(p12_cert); if (!SSL_CTX_use_certificate(ctx, x509_cert)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to set cert for SSL context; error %d\n", error); X509_free(x509_cert); EVP_PKEY_free(pkey); return -1; } X509_free(x509_cert); if (!SSL_CTX_use_PrivateKey(ctx, pkey)) { int error = ERR_get_error(); timestamp_f(stderr); fprintf(stderr, "failed to set private key for SSL context; error %d\n", error); EVP_PKEY_free(pkey); return -1; } EVP_PKEY_free(pkey); if (cacertfile && *cacertfile && !SSL_CTX_load_verify_locations(ctx, cacertfile, NULL)) { timestamp_f(stderr); fprintf(stderr, "failed to load root cert for verification from %s\n", cacertfile); return -1; } return 0; }
void SafetPKCS12Private::init( const QByteArray &data, const QByteArray &pin ) { OpenSSL_add_all_algorithms(); qDebug("... SafetPKCS12Private::init ... 1"); BIO *bio = BIO_new_mem_buf( const_cast<char*>(data.constData()), data.size() ); if( !bio ){ return setLastError(); /* qDebug("!bio"); qDebug(qPrintable(errorString)); SafetYAWL::streamlog << SafetLog::Error << QObject::tr("Error al inicializar objeto PKCS12: BIO no valida"); return; */ } PKCS12 *p12 = d2i_PKCS12_bio( bio, NULL ); BIO_free( bio ); if( !p12 ){ return setLastError(); /* qDebug("!p12"); qDebug(qPrintable(errorString)); SafetYAWL::streamlog << SafetLog::Debug << errorString; SafetYAWL::streamlog << SafetLog::Error << QObject::tr("Error al inicializar objeto PKCS12: PKCS12 no valida"); return; */ } X509 *c = NULL; EVP_PKEY *k = NULL; int ret = PKCS12_parse( p12, pin.constData(), &k, &c, NULL ); PKCS12_free( p12 ); if( !ret ){ return setLastError(); /* setLastError(); qDebug("!ret"); qDebug(qPrintable(errorString)); SafetYAWL::streamlog << SafetLog::Error << QObject::tr("Error al inicializar objeto PKCS12: EVP_PKEY no valida"); return; */ } SafetYAWL::streamlog << SafetLog::Debug << QObject::tr("Analizada correctamente la estructura PKCS12"); cert = SafetPKCS12::fromX509( c ); key = SafetPKCS12::keyFromEVP( k ); X509_free( c ); EVP_PKEY_free( k ); qDebug("... SafetPKCS12Private::init ... 2"); SafetYAWL::streamlog << SafetLog::Action << QObject::tr("Inicializado objeto SafetPKCS12 correctamente!"); }
int __fastcall util_from_p12(char* data, int datalen, char* password, struct util_cert* cert) { int r = 0; PKCS12 *p12 = NULL; if (data == NULL || datalen ==0) return 0; cert->x509 = NULL; cert->pkey = NULL; p12 = d2i_PKCS12(&p12, (const unsigned char**)&data, datalen); r = PKCS12_parse(p12, password, &(cert->pkey), &(cert->x509), NULL); PKCS12_free(p12); return r; }
int sign_with_rsa_sha256(const char *input, const char *private_key, unsigned char *buffer_out, int *buffer_out_len) { FILE *fp; EVP_PKEY *pkey = 0; EVP_MD_CTX *ctx = 0; const EVP_MD *sha256_md = 0; unsigned int s = 0; PKCS12 *p12 = 0; X509 *cert = 0; OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); ctx = EVP_MD_CTX_create(); EVP_MD_CTX_init(ctx); sha256_md = EVP_sha256(); EVP_SignInit(ctx, sha256_md); EVP_SignUpdate(ctx, input, strlen(input)); ERR_load_crypto_strings(); if (!(fp = fopen(private_key, "rb"))) { perror("Error opening file with private key"); return -1; } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { perror("Error reading PKCS#12 file"); return -1; } if (!PKCS12_parse(p12, "notasecret", &pkey, &cert, NULL)) { perror("Error parsing PKCS#12 file"); return -1; } s = EVP_PKEY_size(pkey); EVP_SignFinal(ctx, buffer_out, &s, pkey); *buffer_out_len = s; PKCS12_free(p12); EVP_MD_CTX_destroy(ctx); X509_free(cert); EVP_cleanup(); return 0; }
int main(int argc, char **argv) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; if (argc != 4) { fprintf(stderr, "Usage: pkread p12file password opfile\n"); exit (1); } SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); if (!(fp = fopen(argv[1], "rb"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { fprintf(stderr, "Error reading PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } if (!PKCS12_parse(p12, argv[2], &pkey, &cert, &ca)) { fprintf(stderr, "Error parsing PKCS#12 file\n"); ERR_print_errors_fp(stderr); exit (1); } PKCS12_free(p12); if (!(fp = fopen(argv[3], "w"))) { fprintf(stderr, "Error opening file %s\n", argv[1]); exit(1); } if (pkey) { fprintf(fp, "***Private Key***\n"); PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL); } if (cert) { fprintf(fp, "***User Certificate***\n"); PEM_write_X509_AUX(fp, cert); } if (ca && sk_X509_num(ca)) { fprintf(fp, "***Other Certificates***\n"); for (i = 0; i < sk_X509_num(ca); i++) PEM_write_X509_AUX(fp, sk_X509_value(ca, i)); } fclose(fp); return 0; }
SEXP loadPKCS12(SEXP privateKey) { EVP_PKEY *key; BIO *bio_mem; PKCS12 *p12; X509 *cert; if (TYPEOF(privateKey) != RAWSXP) Rf_error("PKCS12 private key must be a raw vector"); bio_mem = BIO_new_mem_buf((void *) RAW(privateKey), LENGTH(privateKey)); p12 = d2i_PKCS12_bio(bio_mem, &p12); if (!p12 || !PKCS12_verify_mac(p12, pass, strlen(pass)) || !PKCS12_parse(p12, pass, &key, &cert, NULL) || !key) { Rf_error("%s", ERR_error_string(ERR_get_error(), NULL)); } return wrap_EVP_PKEY(key); }
static LUA_FUNCTION(openssl_pkcs12_read) { PKCS12 * p12 = NULL; EVP_PKEY * pkey = NULL; X509 * cert = NULL; STACK_OF(X509) * ca = NULL; int ret = 0; int base64 = 0; int olb64 = 0; BIO * b64 = NULL; BIO * bio_in = load_bio_object(L, 1); const char *pass = luaL_checkstring(L, 2); if (!lua_isnoneornil(L, 3)) base64 = auxiliar_checkboolean(L, 3); if (!lua_isnoneornil(L, 4)) olb64 = auxiliar_checkboolean(L, 4); if (base64) { if ((b64 = BIO_new(BIO_f_base64())) == NULL) return 0; if (olb64) BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); bio_in = BIO_push(b64, bio_in); } if (d2i_PKCS12_bio(bio_in, &p12) && PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { lua_newtable(L); AUXILIAR_SETOBJECT(L, cert, "openssl.x509" , -1, "cert"); AUXILIAR_SETOBJECT(L, pkey, "openssl.evp_pkey" , -1, "pkey"); AUXILIAR_SETOBJECT(L, ca, "openssl.stack_of_x509" , -1, "extracerts"); ret = 1; } if (b64) BIO_free(b64); BIO_free(bio_in); PKCS12_free(p12); return ret; }
/* * call-seq: * PKCS12.new -> pkcs12 * PKCS12.new(str) -> pkcs12 * PKCS12.new(str, pass) -> pkcs12 * * === Parameters * * +str+ - Must be a DER encoded PKCS12 string. * * +pass+ - string */ static VALUE ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) { BIO *in; VALUE arg, pass, pkey, cert, ca; char *passphrase; EVP_PKEY *key; X509 *x509; STACK_OF(X509) *x509s = NULL; int st = 0; PKCS12 *pkcs = DATA_PTR(self); if(rb_scan_args(argc, argv, "02", &arg, &pass) == 0) return self; passphrase = NIL_P(pass) ? NULL : StringValuePtr(pass); in = ossl_obj2bio(arg); d2i_PKCS12_bio(in, &pkcs); DATA_PTR(self) = pkcs; BIO_free(in); pkey = cert = ca = Qnil; if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s)) ossl_raise(ePKCS12Error, "PKCS12_parse"); pkey = rb_protect((VALUE(*)_((VALUE)))ossl_pkey_new, (VALUE)key, &st); /* NO DUP */ if(st) goto err; cert = rb_protect((VALUE(*)_((VALUE)))ossl_x509_new, (VALUE)x509, &st); if(st) goto err; if(x509s){ ca = rb_protect((VALUE(*)_((VALUE)))ossl_x509_sk2ary, (VALUE)x509s, &st); if(st) goto err; } err: X509_free(x509); sk_X509_pop_free(x509s, X509_free); ossl_pkcs12_set_key(self, pkey); ossl_pkcs12_set_cert(self, cert); ossl_pkcs12_set_ca_certs(self, ca); if(st) rb_jump_tag(st); return self; }
static int loadPkcs12( const char *fn, const char* pw) { /* you are lost in a maze of twisty crypto algorithms... */ PKCS12 *p12; X509 *x509; EVP_PKEY *pkey; FILE *fp; int ret; fp = fopen(fn, "r"); if (fp == NULL) { printf("Could not open file `%s\n", fn); return -1; } p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (p12 == NULL) { printf("Could not read certificate from file `%s\n",fn); return -1; } /* we need some more for the P12 decoding */ OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); ret = PKCS12_parse(p12, getenv(pw),&pkey, &x509, NULL); saveCertificateHome(x509, true); savePKeyHome( x509, pkey); PKCS12_free(p12); if (ret != 1) { printf("Error parsing certificate (incorrect password?): %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } return 0; }
void Pkcs12::parse(string password) throw(Pkcs12Exception) { EVP_PKEY* pkey = NULL; X509* cert = NULL; STACK_OF(X509)* ca = NULL; unsigned long opensslError = 0; X509* tmp = NULL; //Limpa fila de erros e carrega tabelas ERR_clear_error(); //OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); if(!PKCS12_parse(this->pkcs12, password.c_str(), &pkey, &cert, &ca)) { opensslError = ERR_get_error(); switch(ERR_GET_REASON(opensslError)) { case PKCS12_R_MAC_VERIFY_FAILURE : throw Pkcs12Exception(Pkcs12Exception::PARSE_ERROR, "Pkcs12::parse"); break; case PKCS12_R_PARSE_ERROR : throw Pkcs12Exception(Pkcs12Exception::MAC_VERIFY_FAILURE, "Pkcs12::parse"); break; } } this->privKey = new PrivateKey(pkey); this->cert = new Certificate(cert); for(int i = 0 ; i < sk_X509_num(ca) ; i ++) { tmp = sk_X509_value(ca, i); this->ca.push_back(new Certificate(tmp)); } sk_X509_free(ca); }
bool OpenSSLContext::setClientCertificate(CertificateWithKey::ref certificate) { boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate); if (!pkcs12Certificate || pkcs12Certificate->isNull()) { return false; } // Create a PKCS12 structure BIO* bio = BIO_new(BIO_s_mem()); BIO_write(bio, vecptr(pkcs12Certificate->getData()), pkcs12Certificate->getData().size()); boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free); BIO_free(bio); if (!pkcs12) { return false; } // Parse PKCS12 X509 *certPtr = 0; EVP_PKEY* privateKeyPtr = 0; STACK_OF(X509)* caCertsPtr = 0; int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr); if (result != 1) { return false; } boost::shared_ptr<X509> cert(certPtr, X509_free); boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free); boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack); // Use the key & certificates if (SSL_CTX_use_certificate(context_, cert.get()) != 1) { return false; } if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) { return false; } for (int i = 0; i < sk_X509_num(caCerts.get()); ++i) { SSL_CTX_add_extra_chain_cert(context_, sk_X509_value(caCerts.get(), i)); } return true; }
static X509 *_load_certificate_from_mem(int format, uint8_t *buffer, uint32_t length, char *password) { X509 *x509 = NULL; BIO *mem = NULL; mem = BIO_new_mem_buf(buffer, length); if (mem != NULL) { switch (format) { case 0 : x509 = d2i_X509_bio(mem, NULL); break; case 1 : x509 = PEM_read_bio_X509(mem, NULL, NULL, NULL); break; case 2 : { PKCS12 *p12 = d2i_PKCS12_bio(mem, NULL); PKCS12_parse(p12, password, NULL, &x509, NULL); PKCS12_free(p12); } break; } BIO_free(mem); } else { DEBUG_ERR_MSG("X509_LOOKUP_load_file failed"); } return x509; }
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size, const char *cert_pwd, uint8_t **signature, int32_t *signature_size) { PKCS12 *p12 = NULL; EVP_PKEY *evp_pkey = NULL; BUF_MEM *buf_mem = NULL; BIO *cert_bio = NULL; BIO *message_bio = NULL; BIO *signature_bio = NULL; CMS_ContentInfo *cms = NULL; CMS_SignerInfo *signer_info = NULL; STACK_OF(X509) *ca_stack = NULL; X509 *cert = NULL; int32_t result = 0; int32_t err = MZ_OK; if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL) return MZ_PARAM_ERROR; mz_crypt_init(); *signature = NULL; *signature_size = 0; cert_bio = BIO_new_mem_buf(cert_data, cert_data_size); if (d2i_PKCS12_bio(cert_bio, &p12) == NULL) err = MZ_SIGN_ERROR; if (err == MZ_OK) result = PKCS12_parse(p12, cert_pwd, &evp_pkey, &cert, &ca_stack); if (result) { cms = CMS_sign(NULL, NULL, ca_stack, NULL, CMS_BINARY | CMS_PARTIAL); if (cms) signer_info = CMS_add1_signer(cms, cert, evp_pkey, EVP_sha256(), 0); if (signer_info == NULL) { err = MZ_SIGN_ERROR; } else { message_bio = BIO_new_mem_buf(message, message_size); signature_bio = BIO_new(BIO_s_mem()); result = CMS_final(cms, message_bio, NULL, CMS_BINARY); if (result) result = i2d_CMS_bio(signature_bio, cms); if (result) { BIO_flush(signature_bio); BIO_get_mem_ptr(signature_bio, &buf_mem); *signature_size = buf_mem->length; *signature = MZ_ALLOC(buf_mem->length); memcpy(*signature, buf_mem->data, buf_mem->length); } #if 0 BIO *yy = BIO_new_file("xyz", "wb"); BIO_write(yy, *signature, *signature_size); BIO_flush(yy); BIO_free(yy); #endif } } if (!result) err = MZ_SIGN_ERROR; if (cms) CMS_ContentInfo_free(cms); if (signature_bio) BIO_free(signature_bio); if (cert_bio) BIO_free(cert_bio); if (message_bio) BIO_free(message_bio); if (p12) PKCS12_free(p12); if (err != MZ_OK && *signature != NULL) { MZ_FREE(*signature); *signature = NULL; *signature_size = 0; } return err; }
static int load_pkcs12_certificate(struct openconnect_info *vpninfo, PKCS12 *p12) { EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *ca; int ret = 0; char *pass; pass = vpninfo->cert_password; vpninfo->cert_password = NULL; retrypass: /* We do this every time round the loop, to work around a bug in OpenSSL < 1.0.0-beta2 -- where the stack at *ca will be freed when PKCS12_parse() returns an error, but *ca is left pointing to the freed memory. */ ca = NULL; if (!pass && request_passphrase(vpninfo, "openconnect_pkcs12", &pass, _("Enter PKCS#12 pass phrase:")) < 0) { PKCS12_free(p12); return -EINVAL; } if (!PKCS12_parse(p12, pass, &pkey, &cert, &ca)) { unsigned long err = ERR_peek_error(); openconnect_report_ssl_errors(vpninfo); if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && ERR_GET_FUNC(err) == PKCS12_F_PKCS12_PARSE && ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (wrong passphrase?)\n")); free(pass); pass = NULL; goto retrypass; } vpn_progress(vpninfo, PRG_ERR, _("Parse PKCS#12 failed (see above errors)\n")); PKCS12_free(p12); free(pass); return -EINVAL; } free(pass); if (cert) { char buf[200]; vpninfo->cert_x509 = cert; SSL_CTX_use_certificate(vpninfo->https_ctx, cert); X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_INFO, _("Using client certificate '%s'\n"), buf); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no certificate!")); ret = -EINVAL; } if (pkey) { SSL_CTX_use_PrivateKey(vpninfo->https_ctx, pkey); EVP_PKEY_free(pkey); } else { vpn_progress(vpninfo, PRG_ERR, _("PKCS#12 contained no private key!")); ret = -EINVAL; } /* Only include supporting certificates which are actually necessary */ if (ca) { int i; next: for (i = 0; i < sk_X509_num(ca); i++) { X509 *cert2 = sk_X509_value(ca, i); if (X509_check_issued(cert2, cert) == X509_V_OK) { char buf[200]; if (cert2 == cert) break; if (X509_check_issued(cert2, cert2) == X509_V_OK) break; X509_NAME_oneline(X509_get_subject_name(cert2), buf, sizeof(buf)); vpn_progress(vpninfo, PRG_DEBUG, _("Extra cert from PKCS#12: '%s'\n"), buf); CRYPTO_add(&cert2->references, 1, CRYPTO_LOCK_X509); SSL_CTX_add_extra_chain_cert(vpninfo->https_ctx, cert2); cert = cert2; goto next; } } sk_X509_pop_free(ca, X509_free); } PKCS12_free(p12); return ret; }
int main(int argc, char **argv) { BIO* in=NULL; BIO* out=NULL; char * outfile = NULL; char * infile = NULL ; int tabLength=100; char *binaryptr; char* mimetype; char* mimetypeaccept=NULL; char* contenttype; const char** pp; unsigned char* hostporturl = NULL; BIO * p12bio ; char **args = argv + 1; unsigned char * serverurl; sslctxparm p; char *response; CURLcode res; struct curl_slist * headers=NULL; int badarg=0; binaryptr = malloc(tabLength); p.verbose = 0; p.errorbio = BIO_new_fp (stderr, BIO_NOCLOSE); curl_global_init(CURL_GLOBAL_DEFAULT); /* we need some more for the P12 decoding */ OpenSSL_add_all_ciphers(); OpenSSL_add_all_digests(); ERR_load_crypto_strings(); while (*args && *args[0] == '-') { if (!strcmp (*args, "-in")) { if (args[1]) { infile=*(++args); } else badarg=1; } else if (!strcmp (*args, "-out")) { if (args[1]) { outfile=*(++args); } else badarg=1; } else if (!strcmp (*args, "-p12")) { if (args[1]) { p.p12file = *(++args); } else badarg=1; } else if (strcmp(*args,"-envpass") == 0) { if (args[1]) { p.pst = getenv(*(++args)); } else badarg=1; } else if (strcmp(*args,"-connect") == 0) { if (args[1]) { hostporturl = *(++args); } else badarg=1; } else if (strcmp(*args,"-mimetype") == 0) { if (args[1]) { mimetype = *(++args); } else badarg=1; } else if (strcmp(*args,"-acceptmime") == 0) { if (args[1]) { mimetypeaccept = *(++args); } else badarg=1; } else if (strcmp(*args,"-accesstype") == 0) { if (args[1]) { if ((p.accesstype = OBJ_obj2nid(OBJ_txt2obj(*++args,0))) == 0) badarg=1; } else badarg=1; } else if (strcmp(*args,"-verbose") == 0) { p.verbose++; } else badarg=1; args++; } if (mimetype==NULL || mimetypeaccept == NULL) badarg = 1; if (badarg) { for (pp=curlx_usage; (*pp != NULL); pp++) BIO_printf(p.errorbio,"%s\n",*pp); BIO_printf(p.errorbio,"\n"); goto err; } /* set input */ if ((in=BIO_new(BIO_s_file())) == NULL) { BIO_printf(p.errorbio, "Error setting input bio\n"); goto err; } else if (infile == NULL) BIO_set_fp(in,stdin,BIO_NOCLOSE|BIO_FP_TEXT); else if (BIO_read_filename(in,infile) <= 0) { BIO_printf(p.errorbio, "Error opening input file %s\n", infile); BIO_free(in); goto err; } /* set output */ if ((out=BIO_new(BIO_s_file())) == NULL) { BIO_printf(p.errorbio, "Error setting output bio.\n"); goto err; } else if (outfile == NULL) BIO_set_fp(out,stdout,BIO_NOCLOSE|BIO_FP_TEXT); else if (BIO_write_filename(out,outfile) <= 0) { BIO_printf(p.errorbio, "Error opening output file %s\n", outfile); BIO_free(out); goto err; } p.errorbio = BIO_new_fp (stderr, BIO_NOCLOSE); if (!(p.curl = curl_easy_init())) { BIO_printf(p.errorbio, "Cannot init curl lib\n"); goto err; } if (!(p12bio = BIO_new_file(p.p12file , "rb"))) { BIO_printf(p.errorbio, "Error opening P12 file %s\n", p.p12file); goto err; } if (!(p.p12 = d2i_PKCS12_bio (p12bio, NULL))) { BIO_printf(p.errorbio, "Cannot decode P12 structure %s\n", p.p12file); goto err; } p.ca= NULL; if (!(PKCS12_parse (p.p12, p.pst, &(p.pkey), &(p.usercert), &(p.ca) ) )) { BIO_printf(p.errorbio,"Invalid P12 structure in %s\n", p.p12file); goto err; } if (sk_X509_num(p.ca) <= 0) { BIO_printf(p.errorbio,"No trustworthy CA given.%s\n", p.p12file); goto err; } if (p.verbose > 1) X509_print_ex(p.errorbio,p.usercert,0,0); /* determine URL to go */ if (hostporturl) { serverurl = malloc(9+strlen(hostporturl)); sprintf(serverurl,"https://%s",hostporturl); } else if (p.accesstype != 0) /* see whether we can find an AIA or SIA for a given access type */ { if (!(serverurl = my_get_ext(p.usercert,p.accesstype,NID_info_access))) { int j=0; BIO_printf(p.errorbio,"no service URL in user cert " "cherching in others certificats\n"); for (j=0; j<sk_X509_num(p.ca); j++) { if ((serverurl = my_get_ext(sk_X509_value(p.ca,j),p.accesstype, NID_info_access))) break; if ((serverurl = my_get_ext(sk_X509_value(p.ca,j),p.accesstype, NID_sinfo_access))) break; } } } if (!serverurl) { BIO_printf(p.errorbio, "no service URL in certificats," " check '-accesstype (AD_DVCS | ad_timestamping)'" " or use '-connect'\n"); goto err; } if (p.verbose) BIO_printf(p.errorbio, "Service URL: <%s>\n", serverurl); curl_easy_setopt(p.curl, CURLOPT_URL, serverurl); /* Now specify the POST binary data */ curl_easy_setopt(p.curl, CURLOPT_POSTFIELDS, binaryptr); curl_easy_setopt(p.curl, CURLOPT_POSTFIELDSIZE,(long)tabLength); /* pass our list of custom made headers */ contenttype = malloc(15+strlen(mimetype)); sprintf(contenttype,"Content-type: %s",mimetype); headers = curl_slist_append(headers,contenttype); curl_easy_setopt(p.curl, CURLOPT_HTTPHEADER, headers); if (p.verbose) BIO_printf(p.errorbio, "Service URL: <%s>\n", serverurl); { FILE *outfp; BIO_get_fp(out,&outfp); curl_easy_setopt(p.curl, CURLOPT_WRITEDATA, outfp); } res = curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun) ; if (res != CURLE_OK) BIO_printf(p.errorbio,"%d %s=%d %d\n", __LINE__, "CURLOPT_SSL_CTX_FUNCTION",CURLOPT_SSL_CTX_FUNCTION,res); curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p); { int lu; int i=0; while ((lu = BIO_read (in,&binaryptr[i],tabLength-i)) >0 ) { i+=lu; if (i== tabLength) { tabLength+=100; binaryptr=realloc(binaryptr,tabLength); /* should be more careful */ } } tabLength = i; } /* Now specify the POST binary data */ curl_easy_setopt(p.curl, CURLOPT_POSTFIELDS, binaryptr); curl_easy_setopt(p.curl, CURLOPT_POSTFIELDSIZE,(long)tabLength); /* Perform the request, res will get the return code */ BIO_printf(p.errorbio,"%d %s %d\n", __LINE__, "curl_easy_perform", res = curl_easy_perform(p.curl)); { int result =curl_easy_getinfo(p.curl,CURLINFO_CONTENT_TYPE,&response); if( mimetypeaccept && p.verbose) if(!strcmp(mimetypeaccept,response)) BIO_printf(p.errorbio,"the response has a correct mimetype : %s\n", response); else BIO_printf(p.errorbio,"the reponse doesn\'t has an acceptable " "mime type, it is %s instead of %s\n", response,mimetypeaccept); } /*** code d'erreur si accept mime ***, egalement code return HTTP != 200 ***/ /* free the header list*/ curl_slist_free_all(headers); /* always cleanup */ curl_easy_cleanup(p.curl); BIO_free(in); BIO_free(out); return (EXIT_SUCCESS); err: BIO_printf(p.errorbio,"error"); exit(1); }
DVT_STATUS CERTIFICATE_FILE_CLASS::importPkcs12(const char* filename, bool certificatesOnly, const char* password) // DESCRIPTION : Import certificates from a PKCS#12 formated file. // PRECONDITIONS : // POSTCONDITIONS : // EXCEPTIONS : // NOTES : Returns MSG_OK, MSG_ERROR, MSG_FILE_NOT_EXIST, MSG_NO_VALUE, MSG_INVALID_PASSWORD //<<=========================================================================== { DVT_STATUS status = MSG_ERROR; BIO* bio_ptr = NULL; PKCS12 *p12_ptr = NULL; EVP_PKEY *pkey_ptr = NULL; X509 *cert_ptr = NULL; STACK_OF(X509) *ca_ptr = NULL; const char* password_ptr = NULL; int count = 0; // clear the error queue ERR_clear_error(); // open the file bio_ptr = BIO_new(BIO_s_file_internal()); if (bio_ptr == NULL) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "setting up to read PKCS#12 file"); status = MSG_ERROR; goto end; } if (BIO_read_filename(bio_ptr, filename) <= 0) { unsigned long err; err = ERR_peek_error(); if ((ERR_GET_LIB(err) == ERR_LIB_SYS) && (ERR_GET_REASON(err) == ERROR_FILE_NOT_FOUND)) { // file does not exist ERR_clear_error(); // eat any errors status = MSG_FILE_NOT_EXIST; } else { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "opening PKCS#12 file for reading"); status = MSG_ERROR; } goto end; } // read the file p12_ptr = d2i_PKCS12_bio(bio_ptr, NULL); if (!p12_ptr) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "reading PKCS#12 file"); status = MSG_ERROR; goto end; } // see if we have a password that will work if (PKCS12_verify_mac(p12_ptr, NULL, 0)) { password_ptr = NULL; } else if(PKCS12_verify_mac(p12_ptr, "", 0)) { password_ptr = ""; } else if(PKCS12_verify_mac(p12_ptr, password, strlen(password))) { password_ptr = password; } else { status = MSG_INVALID_PASSWORD; goto end; } // parse the data if (!PKCS12_parse(p12_ptr, password_ptr, &pkey_ptr, &cert_ptr, &ca_ptr)) { openSslM_ptr->printError(loggerM_ptr, LOG_ERROR, "parsing PKCS#12 file"); status = MSG_ERROR; ca_ptr = NULL; // this is freed by PKCS12_parse(), but not set to NULL goto end; } if ((pkey_ptr != NULL) && !certificatesOnly) { // save the private key if (!push(pkey_ptr)) { status = MSG_ERROR; goto end; } count++; } if (cert_ptr != NULL) { // save the certificate if (!push(cert_ptr)) { status = MSG_ERROR; goto end; } count++; } if ((ca_ptr != NULL) && (sk_X509_num(ca_ptr) > 0)) { X509* x509_ptr; // save each of the certificates while ((x509_ptr = sk_X509_shift(ca_ptr)) != NULL) { if (!push(x509_ptr)) { status = MSG_ERROR; goto end; } count++; } } if (count == 0) { status = MSG_NO_VALUE; } else { status = MSG_OK; } end: if (bio_ptr != NULL) BIO_free(bio_ptr); if (p12_ptr != NULL) PKCS12_free(p12_ptr); if (pkey_ptr != NULL) EVP_PKEY_free(pkey_ptr); if (cert_ptr != NULL) X509_free(cert_ptr); if (ca_ptr != NULL) sk_X509_pop_free(ca_ptr, X509_free); return status; }
/* * PKCS#12 decoder. It operates by decoding all of the blob content, * extracting all the interesting data from it and storing them internally, * then serving them one piece at a time. */ static OSSL_STORE_INFO *try_decode_PKCS12(const char *pem_name, const char *pem_header, const unsigned char *blob, size_t len, void **pctx, int *matchcount, const UI_METHOD *ui_method, void *ui_data) { OSSL_STORE_INFO *store_info = NULL; STACK_OF(OSSL_STORE_INFO) *ctx = *pctx; if (ctx == NULL) { /* Initial parsing */ PKCS12 *p12; int ok = 0; if (pem_name != NULL) /* No match, there is no PEM PKCS12 tag */ return NULL; if ((p12 = d2i_PKCS12(NULL, &blob, len)) != NULL) { char *pass = NULL; char tpass[PEM_BUFSIZE]; EVP_PKEY *pkey = NULL; X509 *cert = NULL; STACK_OF(X509) *chain = NULL; *matchcount = 1; if (PKCS12_verify_mac(p12, "", 0) || PKCS12_verify_mac(p12, NULL, 0)) { pass = ""; } else { if ((pass = file_get_pass(ui_method, tpass, PEM_BUFSIZE, "PKCS12 import password", ui_data)) == NULL) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12, OSSL_STORE_R_PASSPHRASE_CALLBACK_ERROR); goto p12_end; } if (!PKCS12_verify_mac(p12, pass, strlen(pass))) { OSSL_STOREerr(OSSL_STORE_F_TRY_DECODE_PKCS12, OSSL_STORE_R_ERROR_VERIFYING_PKCS12_MAC); goto p12_end; } } if (PKCS12_parse(p12, pass, &pkey, &cert, &chain)) { OSSL_STORE_INFO *osi_pkey = NULL; OSSL_STORE_INFO *osi_cert = NULL; OSSL_STORE_INFO *osi_ca = NULL; if ((ctx = sk_OSSL_STORE_INFO_new_null()) != NULL && (osi_pkey = OSSL_STORE_INFO_new_PKEY(pkey)) != NULL && sk_OSSL_STORE_INFO_push(ctx, osi_pkey) != 0 && (osi_cert = OSSL_STORE_INFO_new_CERT(cert)) != NULL && sk_OSSL_STORE_INFO_push(ctx, osi_cert) != 0) { ok = 1; osi_pkey = NULL; osi_cert = NULL; while(sk_X509_num(chain) > 0) { X509 *ca = sk_X509_value(chain, 0); if ((osi_ca = OSSL_STORE_INFO_new_CERT(ca)) == NULL || sk_OSSL_STORE_INFO_push(ctx, osi_ca) == 0) { ok = 0; break; } osi_ca = NULL; (void)sk_X509_shift(chain); } } if (!ok) { OSSL_STORE_INFO_free(osi_ca); OSSL_STORE_INFO_free(osi_cert); OSSL_STORE_INFO_free(osi_pkey); sk_OSSL_STORE_INFO_pop_free(ctx, OSSL_STORE_INFO_free); EVP_PKEY_free(pkey); X509_free(cert); sk_X509_pop_free(chain, X509_free); ctx = NULL; } *pctx = ctx; } } p12_end: PKCS12_free(p12); if (!ok) return NULL; } if (ctx != NULL) { *matchcount = 1; store_info = sk_OSSL_STORE_INFO_shift(ctx); } return store_info; }
int tls_ctx_load_pkcs12(struct tls_root_ctx *ctx, const char *pkcs12_file, const char *pkcs12_file_inline, bool load_ca_file ) { FILE *fp; EVP_PKEY *pkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; int i; char password[256]; ASSERT(NULL != ctx); if (!strcmp (pkcs12_file, INLINE_FILE_TAG) && pkcs12_file_inline) { BIO *b64 = BIO_new(BIO_f_base64()); BIO *bio = BIO_new_mem_buf((void *) pkcs12_file_inline, (int) strlen(pkcs12_file_inline)); ASSERT(b64 && bio); BIO_push(b64, bio); p12 = d2i_PKCS12_bio(b64, NULL); if (!p12) msg(M_SSLERR, "Error reading inline PKCS#12 file"); BIO_free(b64); BIO_free(bio); } else { /* Load the PKCS #12 file */ if (!(fp = platform_fopen(pkcs12_file, "rb"))) msg(M_SSLERR, "Error opening file %s", pkcs12_file); p12 = d2i_PKCS12_fp(fp, NULL); fclose(fp); if (!p12) msg(M_SSLERR, "Error reading PKCS#12 file %s", pkcs12_file); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, "", &pkey, &cert, &ca)) { pem_password_callback (password, sizeof(password) - 1, 0, NULL); /* Reparse the PKCS #12 file with password */ ca = NULL; if (!PKCS12_parse(p12, password, &pkey, &cert, &ca)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == PKCS12_R_MAC_VERIFY_FAILURE)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif PKCS12_free(p12); return 1; } } PKCS12_free(p12); /* Load Certificate */ if (!SSL_CTX_use_certificate (ctx->ctx, cert)) msg (M_SSLERR, "Cannot use certificate"); /* Load Private Key */ if (!SSL_CTX_use_PrivateKey (ctx->ctx, pkey)) msg (M_SSLERR, "Cannot use private key"); warn_if_group_others_accessible (pkcs12_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ctx->ctx)) msg (M_SSLERR, "Private key does not match the certificate"); /* Set Certificate Verification chain */ if (load_ca_file) { if (ca && sk_X509_num(ca)) { for (i = 0; i < sk_X509_num(ca); i++) { if (!X509_STORE_add_cert(ctx->ctx->cert_store,sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to certificate chain (X509_STORE_add_cert)"); if (!SSL_CTX_add_client_CA(ctx->ctx, sk_X509_value(ca, i))) msg (M_SSLERR, "Cannot add certificate to client CA list (SSL_CTX_add_client_CA)"); } } } return 0; }
/* ChangePasswordPKCS12() returns: * -1 Wrong password * 0 Changing password failed for unknown reason * 1 Password changed successfully */ int ChangePasswordPKCS12(HWND hwndDlg) { char keyfile[MAX_PATH]; char oldpsw[50]; char newpsw[50]; WCHAR oldpsw_unicode[50]; WCHAR newpsw_unicode[50]; FILE *fp; EVP_PKEY *privkey; X509 *cert; STACK_OF(X509) *ca = NULL; PKCS12 *p12; PKCS12 *new_p12; char *alias; /* Get filename, old_psw and new_psw from Dialog */ GetDlgItemText(hwndDlg, TEXT_KEYFILE, keyfile, sizeof(keyfile) - 1); GetDlgItemTextW(hwndDlg, EDIT_PSW_CURRENT, oldpsw_unicode, sizeof(oldpsw_unicode)/2 - 1); GetDlgItemTextW(hwndDlg, EDIT_PSW_NEW, newpsw_unicode, sizeof(newpsw_unicode)/2 - 1); /* Convert Unicode to ASCII (CP850) */ ConvertUnicode2Ascii(oldpsw_unicode, oldpsw, sizeof(oldpsw)); if (!ConvertUnicode2Ascii(newpsw_unicode, newpsw, sizeof(newpsw))) { ShowLocalizedMsg(GUI_NAME, ERR_INVALID_CHARS_IN_PSW, ""); return(-1); } /* Load the PKCS #12 file */ if (!(fp = fopen(keyfile, "rb"))) { /* error opening file */ ShowLocalizedMsg(GUI_NAME, ERR_OPEN_PRIVATE_KEY_FILE, keyfile); return(0); } p12 = d2i_PKCS12_fp(fp, NULL); fclose (fp); if (!p12) { /* error reading PKCS #12 */ ShowLocalizedMsg(GUI_NAME, ERR_READ_PKCS12, keyfile); return(0); } /* Parse the PKCS #12 file */ if (!PKCS12_parse(p12, oldpsw, &privkey, &cert, &ca)) { /* old password incorrect */ ShowLocalizedMsg(GUI_NAME, ERR_OLD_PWD_INCORRECT, ""); PKCS12_free(p12); return(-1); } /* Free old PKCS12 object */ PKCS12_free(p12); /* Get FriendlyName of old cert */ alias = X509_alias_get0(cert, NULL); /* Create new PKCS12 object */ p12 = PKCS12_create(newpsw, alias, privkey, cert, ca, 0,0,0,0,0); if (!p12) { /* create failed */ //ShowMsg(GUI_NAME, ERR_error_string(ERR_peek_last_error(), NULL)); ShowLocalizedMsg(GUI_NAME, ERR_CREATE_PKCS12, ""); return(0); } /* Free old key, cert and ca */ EVP_PKEY_free(privkey); X509_free(cert); sk_X509_pop_free(ca, X509_free); /* Open keyfile for writing */ if (!(fp = fopen(keyfile, "wb"))) { ShowLocalizedMsg(GUI_NAME, ERR_OPEN_WRITE_KEY, keyfile); PKCS12_free(p12); return(0); } /* Write new key to file */ i2d_PKCS12_fp(fp, p12); PKCS12_free(p12); fclose(fp); /* signal success to user */ ShowLocalizedMsg(GUI_NAME, INFO_PWD_CHANGED, ""); return(1); }
static int cert_stuff(struct connectdata *conn, SSL_CTX* ctx, char *cert_file, const char *cert_type, char *key_file, const char *key_type) { struct SessionHandle *data = conn->data; int file_type; if(cert_file != NULL) { SSL *ssl; X509 *x509; int cert_done = 0; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ size_t len = strlen(data->set.key_passwd); if(len < sizeof(global_passwd)) memcpy(global_passwd, data->set.key_passwd, len+1); #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata(ctx, data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } file_type = do_file_type(cert_type); #define SSL_CLIENT_CERT_ERR \ "unable to use client certificate (no key found or wrong pass phrase?)" switch(file_type) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ if(SSL_CTX_use_certificate_chain_file(ctx, cert_file) != 1) { failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; case SSL_FILETYPE_ASN1: /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but we use the case above for PEM so this can only be performed with ASN1 files. */ if(SSL_CTX_use_certificate_file(ctx, cert_file, file_type) != 1) { failf(data, SSL_CLIENT_CERT_ERR); return 0; } break; case SSL_FILETYPE_ENGINE: failf(data, "file type ENG for certificate not implemented"); return 0; case SSL_FILETYPE_PKCS12: { #ifdef HAVE_PKCS12_SUPPORT FILE *f; PKCS12 *p12; EVP_PKEY *pri; f = fopen(cert_file,"rb"); if (!f) { failf(data, "could not open PKCS12 file '%s'", cert_file); return 0; } p12 = d2i_PKCS12_fp(f, NULL); fclose(f); PKCS12_PBE_add(); if (!PKCS12_parse(p12, data->set.key_passwd, &pri, &x509, NULL)) { failf(data, "could not parse PKCS12 file, check password, OpenSSL error %s", ERR_error_string(ERR_get_error(), NULL) ); return 0; } PKCS12_free(p12); if(SSL_CTX_use_certificate(ctx, x509) != 1) { failf(data, SSL_CLIENT_CERT_ERR); EVP_PKEY_free(pri); X509_free(x509); return 0; } if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { failf(data, "unable to use private key from PKCS12 file '%s'", cert_file); EVP_PKEY_free(pri); X509_free(x509); return 0; } EVP_PKEY_free(pri); X509_free(x509); cert_done = 1; break; #else failf(data, "file type P12 for certificate not supported"); return 0; #endif } default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; } file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(cert_done) break; if(key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file: '%s' type %s\n", key_file, key_type?key_type:"PEM"); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if(conn && conn->data && conn->data->state.engine) { #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS UI_METHOD *ui_method = UI_OpenSSL(); #endif if(!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key(conn->data->state.engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif data->set.key_passwd); if(!priv_key) { failf(data, "failed to load private key from crypto engine\n"); return 0; } if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { failf(data, "unable to set private key\n"); EVP_PKEY_free(priv_key); return 0; } EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ } else { failf(data, "crypto engine not set, can't load private key\n"); return 0; } } break; #else failf(data, "file type ENG for private key not supported\n"); return 0; #endif case SSL_FILETYPE_PKCS12: if(!cert_done) { failf(data, "file type P12 for private key not supported\n"); return 0; } break; default: failf(data, "not supported file type for private key\n"); return 0; } ssl=SSL_new(ctx); if (NULL == ssl) { failf(data,"unable to create an SSL structure\n"); return 0; } x509=SSL_get_certificate(ssl); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl)); EVP_PKEY_free(pktmp); } SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if(!SSL_CTX_check_private_key(ctx)) { failf(data, "Private key does not match the certificate public key"); return(0); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset(global_passwd, 0, sizeof(global_passwd)); #endif } return(1); }
/* * Constructor for PKCS12 objects, never called by Python code directly. * The strategy for this object is to create all the Python objects * corresponding to the cert/key/CA certs right away * * Arguments: p12 - A "real" PKCS12 object or NULL * passphrase - Passphrase to use when decrypting the PKCS12 object * Returns: The newly created PKCS12 object */ crypto_PKCS12Obj * crypto_PKCS12_New(PKCS12 *p12, char *passphrase) { crypto_PKCS12Obj *self = NULL; PyObject *cacertobj = NULL; unsigned char *alias_str; int alias_len; X509 *cert = NULL; EVP_PKEY *pkey = NULL; STACK_OF(X509) *cacerts = NULL; int i, cacert_count = 0; /* allocate space for the CA cert stack */ if((cacerts = sk_X509_new_null()) == NULL) { goto error; /* out of memory? */ } /* parse the PKCS12 lump */ if (p12) { if (!PKCS12_parse(p12, passphrase, &pkey, &cert, &cacerts)) { /* * If PKCS12_parse fails, and it allocated cacerts, it seems to * free cacerts, but not re-NULL the pointer. Zounds! Make sure * it is re-set to NULL here, else we'll have a double-free below. */ cacerts = NULL; exception_from_error_queue(crypto_Error); goto error; } else { /* * OpenSSL 1.0.0 sometimes leaves an X509_check_private_key error in * the queue for no particular reason. This error isn't interesting * to anyone outside this function. It's not even interesting to * us. Get rid of it. */ flush_error_queue(); } } if (!(self = PyObject_GC_New(crypto_PKCS12Obj, &crypto_PKCS12_Type))) { goto error; } /* client certificate and friendlyName */ if (cert == NULL) { Py_INCREF(Py_None); self->cert = Py_None; Py_INCREF(Py_None); self->friendlyname = Py_None; } else { if ((self->cert = (PyObject *)crypto_X509_New(cert, 1)) == NULL) { goto error; } /* Now we need to extract the friendlyName of the PKCS12 * that was stored by PKCS_parse() in the alias of the * certificate. */ alias_str = X509_alias_get0(cert, &alias_len); if (alias_str) { self->friendlyname = Py_BuildValue(BYTESTRING_FMT "#", alias_str, alias_len); if (!self->friendlyname) { /* * XXX Untested */ goto error; } /* success */ } else { Py_INCREF(Py_None); self->friendlyname = Py_None; } } /* private key */ if (pkey == NULL) { Py_INCREF(Py_None); self->key = Py_None; } else { if ((self->key = (PyObject *)crypto_PKey_New(pkey, 1)) == NULL) goto error; } /* CA certs */ cacert_count = sk_X509_num(cacerts); if (cacert_count <= 0) { Py_INCREF(Py_None); self->cacerts = Py_None; } else { if ((self->cacerts = PyTuple_New(cacert_count)) == NULL) { goto error; } for (i = 0; i < cacert_count; i++) { cert = sk_X509_value(cacerts, i); if ((cacertobj = (PyObject *)crypto_X509_New(cert, 1)) == NULL) { goto error; } PyTuple_SET_ITEM(self->cacerts, i, cacertobj); } } sk_X509_free(cacerts); /* Don't free the certs, just the container. */ PyObject_GC_Track(self); return self; error: sk_X509_free(cacerts); /* NULL safe. Free just the container. */ if (self) { crypto_PKCS12_clear(self); PyObject_GC_Del(self); } return NULL; }
X509* ssl_parse_certificate(void* pCert, size_t certLen, LPCSTR pwd, EVP_PKEY** privateKey) { X509 *x=NULL; PKCS12* p12 = NULL; if(privateKey != NULL) { *privateKey = NULL; } //check for PEM BASE64 header BIO *certBio = NULL; if ((certBio=BIO_new(BIO_s_mem())) != NULL) { BIO_write(certBio, (const char*)pCert, certLen); x = PEM_read_bio_X509(certBio, NULL, 0, NULL); if(x != NULL) { BIO_reset(certBio); BIO_write(certBio, (const char*)pCert, certLen); if(privateKey != NULL) { *privateKey = PEM_read_bio_PrivateKey(certBio, NULL, password_cb, (void*)pwd); } } if(x == NULL) { BIO_reset(certBio); BIO_write(certBio, (const char*)pCert, certLen); p12 = d2i_PKCS12_bio(certBio, NULL); if(p12 != NULL) { if(privateKey == NULL) { PKCS12_parse(p12, pwd, NULL, &x, NULL); } else { PKCS12_parse(p12, pwd, privateKey, &x, NULL); } PKCS12_free(p12); } } BIO_free(certBio); } if(x == NULL) { const UINT8* tmp = (const UINT8*)pCert; x = d2i_X509(NULL, &tmp, certLen); if(x != NULL && privateKey != NULL) { X509_PKEY* pKey; tmp = (const UINT8*)pCert; pKey = d2i_X509_PKEY(NULL, &tmp, certLen); if(pKey != NULL) { *privateKey = pKey->dec_pkey; } } } return x; }
/*============================================================================ * OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile *===========================================================================*/ OpcUa_StatusCode OpcUa_P_OpenSSL_RSA_LoadPrivateKeyFromFile( OpcUa_StringA a_privateKeyFile, OpcUa_P_FileFormat a_fileFormat, OpcUa_StringA a_password, /* optional: just needed encrypted PEM */ OpcUa_ByteString* a_pPrivateKey) { BIO* pPrivateKeyFile = OpcUa_Null; RSA* pRsaPrivateKey = OpcUa_Null; EVP_PKEY* pEvpKey = OpcUa_Null; unsigned char* pData; OpcUa_InitializeStatus(OpcUa_Module_P_OpenSSL, "RSA_LoadPrivateKeyFromFile"); /* check parameters */ OpcUa_ReturnErrorIfArgumentNull(a_privateKeyFile); OpcUa_ReturnErrorIfArgumentNull(a_pPrivateKey); if(a_fileFormat == OpcUa_Crypto_Encoding_Invalid) { return OpcUa_BadInvalidArgument; } OpcUa_ReferenceParameter(a_password); /* open file */ pPrivateKeyFile = BIO_new_file((const char*)a_privateKeyFile, "rb"); OpcUa_ReturnErrorIfArgumentNull(pPrivateKeyFile); /* read and convert file */ switch(a_fileFormat) { case OpcUa_Crypto_Encoding_PEM: { /* read from file */ pEvpKey = PEM_read_bio_PrivateKey( pPrivateKeyFile, /* file */ NULL, /* key struct */ 0, /* password callback */ a_password); /* default passphrase or arbitrary handle */ OpcUa_GotoErrorIfNull(pEvpKey, OpcUa_Bad); break; } case OpcUa_Crypto_Encoding_PKCS12: { int iResult = 0; /* read from file. */ PKCS12* pPkcs12 = d2i_PKCS12_bio(pPrivateKeyFile, NULL); if (pPkcs12 == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* parse the certificate. */ iResult = PKCS12_parse(pPkcs12, a_password, &pEvpKey, NULL, NULL); if (iResult == 0) { OpcUa_GotoErrorWithStatus(OpcUa_BadEncodingError); } /* free certificate. */ PKCS12_free(pPkcs12); pPkcs12 = NULL; break; } case OpcUa_Crypto_Encoding_DER: default: { uStatus = OpcUa_BadNotSupported; OpcUa_GotoError; } } /* convert to intermediary openssl struct */ pRsaPrivateKey = EVP_PKEY_get1_RSA(pEvpKey); EVP_PKEY_free(pEvpKey); OpcUa_GotoErrorIfNull(pRsaPrivateKey, OpcUa_Bad); /* get required length */ a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, OpcUa_Null); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); /* allocate target buffer */ a_pPrivateKey->Data = (OpcUa_Byte*)OpcUa_P_Memory_Alloc(a_pPrivateKey->Length); OpcUa_GotoErrorIfAllocFailed(a_pPrivateKey->Data); /* do real conversion */ pData = a_pPrivateKey->Data; a_pPrivateKey->Length = i2d_RSAPrivateKey(pRsaPrivateKey, &pData); OpcUa_GotoErrorIfTrue((a_pPrivateKey->Length <= 0), OpcUa_Bad); RSA_free(pRsaPrivateKey); BIO_free(pPrivateKeyFile); OpcUa_ReturnStatusCode; OpcUa_BeginErrorHandling; if(pEvpKey) { EVP_PKEY_free(pEvpKey); } if(a_pPrivateKey != OpcUa_Null) { if(a_pPrivateKey->Data != OpcUa_Null) { OpcUa_P_Memory_Free(a_pPrivateKey->Data); a_pPrivateKey->Data = OpcUa_Null; a_pPrivateKey->Length = -1; } } if(pPrivateKeyFile != NULL) { BIO_free(pPrivateKeyFile); } if(pRsaPrivateKey != NULL) { RSA_free(pRsaPrivateKey); } OpcUa_FinishErrorHandling; }
static int ssl_need_client_cert(SSL *ssl, X509 **cert, EVP_PKEY **pkey) { serf_ssl_context_t *ctx = SSL_get_app_data(ssl); apr_status_t status; if (ctx->cached_cert) { *cert = ctx->cached_cert; *pkey = ctx->cached_cert_pw; return 1; } while (ctx->cert_callback) { const char *cert_path; apr_file_t *cert_file; BIO *bio; PKCS12 *p12; int i; int retrying_success = 0; if (ctx->cert_file_success) { status = APR_SUCCESS; cert_path = ctx->cert_file_success; ctx->cert_file_success = NULL; retrying_success = 1; } else { status = ctx->cert_callback(ctx->cert_userdata, &cert_path); } if (status || !cert_path) { break; } /* Load the x.509 cert file stored in PKCS12 */ status = apr_file_open(&cert_file, cert_path, APR_READ, APR_OS_DEFAULT, ctx->pool); if (status) { continue; } bio = BIO_new(&bio_file_method); bio->ptr = cert_file; ctx->cert_path = cert_path; p12 = d2i_PKCS12_bio(bio, NULL); apr_file_close(cert_file); i = PKCS12_parse(p12, NULL, pkey, cert, NULL); if (i == 1) { PKCS12_free(p12); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { const char *c; c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path); apr_pool_userdata_setn(c, "serf:ssl:cert", apr_pool_cleanup_null, ctx->cert_cache_pool); } return 1; } else { int err = ERR_get_error(); ERR_clear_error(); if (ERR_GET_LIB(err) == ERR_LIB_PKCS12 && ERR_GET_REASON(err) == PKCS12_R_MAC_VERIFY_FAILURE) { if (ctx->cert_pw_callback) { const char *password; if (ctx->cert_pw_success) { status = APR_SUCCESS; password = ctx->cert_pw_success; ctx->cert_pw_success = NULL; } else { status = ctx->cert_pw_callback(ctx->cert_pw_userdata, ctx->cert_path, &password); } if (!status && password) { i = PKCS12_parse(p12, password, pkey, cert, NULL); if (i == 1) { PKCS12_free(p12); ctx->cached_cert = *cert; ctx->cached_cert_pw = *pkey; if (!retrying_success && ctx->cert_cache_pool) { const char *c; c = apr_pstrdup(ctx->cert_cache_pool, ctx->cert_path); apr_pool_userdata_setn(c, "serf:ssl:cert", apr_pool_cleanup_null, ctx->cert_cache_pool); } if (!retrying_success && ctx->cert_pw_cache_pool) { const char *c; c = apr_pstrdup(ctx->cert_pw_cache_pool, password); apr_pool_userdata_setn(c, "serf:ssl:certpw", apr_pool_cleanup_null, ctx->cert_pw_cache_pool); } return 1; } } } PKCS12_free(p12); return 0; } else { printf("OpenSSL cert error: %d %d %d\n", ERR_GET_LIB(err), ERR_GET_FUNC(err), ERR_GET_REASON(err)); PKCS12_free(p12); } } } return 0; }