From f7b0fbbf532bdce896b1f2a1bdf3bdd0acdb88e6 Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Sun, 22 Sep 2013 12:14:51 +0200 Subject: Teach Libssl backend to load .p12 files --- src/LibsslTLSContext.cc | 92 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) (limited to 'src/LibsslTLSContext.cc') diff --git a/src/LibsslTLSContext.cc b/src/LibsslTLSContext.cc index c0507227..6f59a5d4 100644 --- a/src/LibsslTLSContext.cc +++ b/src/LibsslTLSContext.cc @@ -34,12 +34,30 @@ /* copyright --> */ #include "LibsslTLSContext.h" +#include + #include +#include +#include #include "LogFactory.h" #include "Logger.h" #include "fmt.h" #include "message.h" +#include "BufferedFile.h" + +namespace { + struct bio_deleter { + void operator()(BIO *b) { + if (b) BIO_free(b); + } + }; + struct p12_deleter { + void operator()(PKCS12 *p) { + if (p) PKCS12_free(p); + } + }; +} // namespace namespace aria2 { @@ -88,6 +106,9 @@ bool OpenSSLTLSContext::good() const bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile, const std::string& keyfile) { + if (keyfile.empty()) { + return addP12CredentialFile(certfile); + } if(SSL_CTX_use_PrivateKey_file(sslCtx_, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) { A2_LOG_ERROR(fmt("Failed to load private key from %s. Cause: %s", @@ -106,6 +127,77 @@ bool OpenSSLTLSContext::addCredentialFile(const std::string& certfile, keyfile.c_str())); return true; } +bool OpenSSLTLSContext::addP12CredentialFile(const std::string& p12file) +{ + // Need this to "decrypt" p12 files. + OpenSSL_add_all_algorithms(); + + std::stringstream ss; + BufferedFile(p12file.c_str(), "rb").transfer(ss); + + void *ptr = const_cast(ss.str().c_str()); + size_t len = ss.str().length(); + std::unique_ptr bio(BIO_new_mem_buf(ptr, len)); + A2_LOG_DEBUG(fmt("p12 size: %" PRIu64, len)); + + if (!bio) { + A2_LOG_ERROR("Failed to open p12 file: no memory"); + return false; + } + std::unique_ptr p12(d2i_PKCS12_bio(bio.get(), nullptr)); + if (!p12) { + A2_LOG_ERROR(fmt("Failed to open p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + EVP_PKEY *pkey; + X509 *cert; + STACK_OF(X509) *ca = 0; + if (!PKCS12_parse(p12.get(), "", &pkey, &cert, &ca)) { + A2_LOG_ERROR(fmt("Failed to parse p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + return false; + } + + bool rv = false; + if (pkey && cert) { + rv = SSL_CTX_use_PrivateKey(sslCtx_, pkey); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file pkey: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + if (rv) { + rv = SSL_CTX_use_certificate(sslCtx_, cert); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file cert: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + } + if (rv && ca && sk_X509_num(ca)) { + rv = SSL_CTX_add_extra_chain_cert(sslCtx_, ca); + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file chain: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + } + } + else { + A2_LOG_ERROR(fmt("Failed to use p12 file: no pkey or cert %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + if (pkey) EVP_PKEY_free(pkey); + if (cert) X509_free(cert); + if (ca) sk_X509_pop_free(ca, X509_free); + + if (!rv) { + A2_LOG_ERROR(fmt("Failed to use p12 file: %s", + ERR_error_string(ERR_get_error(), nullptr))); + } + else { + A2_LOG_INFO("Using certificate and key from p12 file"); + } + return rv; +} bool OpenSSLTLSContext::addSystemTrustedCACerts() { -- cgit