Commit b8ab3858 authored by David Benjamin's avatar David Benjamin Committed by Commit Bot

Switch SSLServerSocket to CRYPTO_BUFFER.

This also allows us to support asynchronous client certificate
verification, but this CL leaves it as a TODO for now.

Bug: 706445
Change-Id: I792eb91a854bb15a67317d7ea4d04a80ba5ca4da
Reviewed-on: https://chromium-review.googlesource.com/586431Reviewed-by: default avatarSteven Valdez <svaldez@chromium.org>
Reviewed-by: default avatarMatt Mueller <mattm@chromium.org>
Commit-Queue: David Benjamin <davidben@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491886}
parent dac798e2
...@@ -103,6 +103,11 @@ NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer( ...@@ -103,6 +103,11 @@ NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer( NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
const char* invalid_data); const char* invalid_data);
// Creates a new X509Certificate from the chain in |buffers|, which must have at
// least one element.
scoped_refptr<X509Certificate> CreateX509CertificateFromBuffers(
STACK_OF(CRYPTO_BUFFER) * buffers);
} // namespace x509_util } // namespace x509_util
} // namespace net } // namespace net
......
...@@ -8,12 +8,14 @@ ...@@ -8,12 +8,14 @@
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
#include <vector>
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "build/build_config.h"
#include "crypto/ec_private_key.h" #include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h" #include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h" #include "crypto/rsa_private_key.h"
...@@ -26,6 +28,7 @@ ...@@ -26,6 +28,7 @@
#include "third_party/boringssl/src/include/openssl/digest.h" #include "third_party/boringssl/src/include/openssl/digest.h"
#include "third_party/boringssl/src/include/openssl/mem.h" #include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/pool.h" #include "third_party/boringssl/src/include/openssl/pool.h"
#include "third_party/boringssl/src/include/openssl/stack.h"
namespace net { namespace net {
...@@ -392,6 +395,33 @@ bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer( ...@@ -392,6 +395,33 @@ bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
data.size(), GetBufferPool())); data.size(), GetBufferPool()));
} }
scoped_refptr<X509Certificate> CreateX509CertificateFromBuffers(
STACK_OF(CRYPTO_BUFFER) * buffers) {
if (sk_CRYPTO_BUFFER_num(buffers) == 0) {
NOTREACHED();
return nullptr;
}
#if BUILDFLAG(USE_BYTE_CERTS)
std::vector<CRYPTO_BUFFER*> intermediate_chain;
for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(buffers); ++i)
intermediate_chain.push_back(sk_CRYPTO_BUFFER_value(buffers, i));
return X509Certificate::CreateFromHandle(sk_CRYPTO_BUFFER_value(buffers, 0),
intermediate_chain);
#else
// Convert the certificate chains to a platform certificate handle.
std::vector<base::StringPiece> der_chain;
der_chain.reserve(sk_CRYPTO_BUFFER_num(buffers));
for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(buffers); ++i) {
const CRYPTO_BUFFER* cert = sk_CRYPTO_BUFFER_value(buffers, i);
der_chain.push_back(base::StringPiece(
reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)),
CRYPTO_BUFFER_len(cert)));
}
return X509Certificate::CreateFromDERCertChain(der_chain);
#endif
}
} // namespace x509_util } // namespace x509_util
} // namespace net } // namespace net
...@@ -198,44 +198,6 @@ int GetBufferSize(const char* field_trial) { ...@@ -198,44 +198,6 @@ int GetBufferSize(const char* field_trial) {
return buffer_size; return buffer_size;
} }
scoped_refptr<X509Certificate> OSChainFromBuffers(STACK_OF(CRYPTO_BUFFER) *
openssl_chain) {
if (sk_CRYPTO_BUFFER_num(openssl_chain) == 0) {
NOTREACHED();
return nullptr;
}
#if BUILDFLAG(USE_BYTE_CERTS)
std::vector<CRYPTO_BUFFER*> intermediate_chain;
for (size_t i = 1; i < sk_CRYPTO_BUFFER_num(openssl_chain); ++i)
intermediate_chain.push_back(sk_CRYPTO_BUFFER_value(openssl_chain, i));
return X509Certificate::CreateFromHandle(
sk_CRYPTO_BUFFER_value(openssl_chain, 0), intermediate_chain);
#else
// Convert the certificate chains to a platform certificate handle.
std::vector<base::StringPiece> der_chain;
der_chain.reserve(sk_CRYPTO_BUFFER_num(openssl_chain));
for (size_t i = 0; i < sk_CRYPTO_BUFFER_num(openssl_chain); ++i) {
const CRYPTO_BUFFER* cert = sk_CRYPTO_BUFFER_value(openssl_chain, i);
base::StringPiece der;
der_chain.push_back(base::StringPiece(
reinterpret_cast<const char*>(CRYPTO_BUFFER_data(cert)),
CRYPTO_BUFFER_len(cert)));
}
return X509Certificate::CreateFromDERCertChain(der_chain);
#endif
}
#if !defined(OS_IOS) && !BUILDFLAG(USE_BYTE_CERTS)
bssl::UniquePtr<CRYPTO_BUFFER> OSCertHandleToBuffer(
X509Certificate::OSCertHandle os_handle) {
std::string der_encoded;
if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded))
return nullptr;
return x509_util::CreateCryptoBuffer(der_encoded);
}
#endif
std::unique_ptr<base::Value> NetLogSSLAlertCallback( std::unique_ptr<base::Value> NetLogSSLAlertCallback(
const void* bytes, const void* bytes,
size_t len, size_t len,
...@@ -1244,7 +1206,8 @@ int SSLClientSocketImpl::DoChannelIDLookupComplete(int result) { ...@@ -1244,7 +1206,8 @@ int SSLClientSocketImpl::DoChannelIDLookupComplete(int result) {
int SSLClientSocketImpl::DoVerifyCert(int result) { int SSLClientSocketImpl::DoVerifyCert(int result) {
DCHECK(start_cert_verification_time_.is_null()); DCHECK(start_cert_verification_time_.is_null());
server_cert_ = OSChainFromBuffers(SSL_get0_peer_certificates(ssl_.get())); server_cert_ = x509_util::CreateX509CertificateFromBuffers(
SSL_get0_peer_certificates(ssl_.get()));
// OpenSSL decoded the certificate, but the platform certificate // OpenSSL decoded the certificate, but the platform certificate
// implementation could not. This is treated as a fatal SSL-level protocol // implementation could not. This is treated as a fatal SSL-level protocol
...@@ -1659,44 +1622,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { ...@@ -1659,44 +1622,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
return -1; return -1;
} }
#if BUILDFLAG(USE_BYTE_CERTS) if (!SetSSLChainAndKey(ssl_.get(), ssl_config_.client_cert.get(), nullptr,
std::vector<CRYPTO_BUFFER*> chain_raw; &SSLContext::kPrivateKeyMethod)) {
chain_raw.push_back(ssl_config_.client_cert->os_cert_handle());
for (X509Certificate::OSCertHandle cert :
ssl_config_.client_cert->GetIntermediateCertificates()) {
chain_raw.push_back(cert);
}
#else
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> chain;
std::vector<CRYPTO_BUFFER*> chain_raw;
bssl::UniquePtr<CRYPTO_BUFFER> buf =
OSCertHandleToBuffer(ssl_config_.client_cert->os_cert_handle());
if (!buf) {
LOG(WARNING) << "Failed to import certificate";
OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT); OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT);
return -1; return -1;
} }
chain_raw.push_back(buf.get());
chain.push_back(std::move(buf));
for (X509Certificate::OSCertHandle cert :
ssl_config_.client_cert->GetIntermediateCertificates()) {
bssl::UniquePtr<CRYPTO_BUFFER> buf = OSCertHandleToBuffer(cert);
if (!buf) {
LOG(WARNING) << "Failed to import intermediate";
OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT);
return -1;
}
chain_raw.push_back(buf.get());
chain.push_back(std::move(buf));
}
#endif
if (!SSL_set_chain_and_key(ssl_.get(), chain_raw.data(), chain_raw.size(),
nullptr, &SSLContext::kPrivateKeyMethod)) {
LOG(WARNING) << "Failed to set client certificate";
return -1;
}
std::vector<SSLPrivateKey::Hash> digest_prefs = std::vector<SSLPrivateKey::Hash> digest_prefs =
ssl_config_.client_private_key->GetDigestPreferences(); ssl_config_.client_private_key->GetDigestPreferences();
...@@ -1726,8 +1656,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) { ...@@ -1726,8 +1656,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
SSL_set_private_key_digest_prefs(ssl_.get(), digests.data(), SSL_set_private_key_digest_prefs(ssl_.get(), digests.data(),
digests.size()); digests.size());
net_log_.AddEvent(NetLogEventType::SSL_CLIENT_CERT_PROVIDED, net_log_.AddEvent(
NetLog::IntCallback("cert_count", chain_raw.size())); NetLogEventType::SSL_CLIENT_CERT_PROVIDED,
NetLog::IntCallback(
"cert_count",
1 + ssl_config_.client_cert->GetIntermediateCertificates().size()));
return 1; return 1;
} }
#endif // defined(OS_IOS) #endif // defined(OS_IOS)
......
This diff is collapsed.
...@@ -29,6 +29,8 @@ class SSLServerContextImpl : public SSLServerContext { ...@@ -29,6 +29,8 @@ class SSLServerContextImpl : public SSLServerContext {
std::unique_ptr<StreamSocket> socket) override; std::unique_ptr<StreamSocket> socket) override;
private: private:
class SocketImpl;
bssl::UniquePtr<SSL_CTX> ssl_ctx_; bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// Options for the SSL socket. // Options for the SSL socket.
......
...@@ -12,8 +12,10 @@ ...@@ -12,8 +12,10 @@
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/values.h" #include "base/values.h"
#include "build/build_config.h"
#include "crypto/openssl_util.h" #include "crypto/openssl_util.h"
#include "net/base/net_errors.h" #include "net/base/net_errors.h"
#include "net/cert/x509_util.h"
#include "net/ssl/ssl_connection_status_flags.h" #include "net/ssl/ssl_connection_status_flags.h"
#include "third_party/boringssl/src/include/openssl/err.h" #include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/ssl.h" #include "third_party/boringssl/src/include/openssl/ssl.h"
...@@ -138,6 +140,16 @@ std::unique_ptr<base::Value> NetLogOpenSSLErrorCallback( ...@@ -138,6 +140,16 @@ std::unique_ptr<base::Value> NetLogOpenSSLErrorCallback(
return std::move(dict); return std::move(dict);
} }
#if !BUILDFLAG(USE_BYTE_CERTS)
bssl::UniquePtr<CRYPTO_BUFFER> OSCertHandleToBuffer(
X509Certificate::OSCertHandle os_handle) {
std::string der_encoded;
if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded))
return nullptr;
return x509_util::CreateCryptoBuffer(der_encoded);
}
#endif
} // namespace } // namespace
void OpenSSLPutNetError(const tracked_objects::Location& location, int err) { void OpenSSLPutNetError(const tracked_objects::Location& location, int err) {
...@@ -224,4 +236,48 @@ int GetNetSSLVersion(SSL* ssl) { ...@@ -224,4 +236,48 @@ int GetNetSSLVersion(SSL* ssl) {
} }
} }
bool SetSSLChainAndKey(SSL* ssl,
X509Certificate* cert,
EVP_PKEY* pkey,
const SSL_PRIVATE_KEY_METHOD* custom_key) {
#if BUILDFLAG(USE_BYTE_CERTS)
std::vector<CRYPTO_BUFFER*> chain_raw;
chain_raw.push_back(cert->os_cert_handle());
for (X509Certificate::OSCertHandle handle :
cert->GetIntermediateCertificates()) {
chain_raw.push_back(handle);
}
#else
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> chain;
std::vector<CRYPTO_BUFFER*> chain_raw;
bssl::UniquePtr<CRYPTO_BUFFER> buf =
OSCertHandleToBuffer(cert->os_cert_handle());
if (!buf) {
LOG(WARNING) << "Failed to import certificate";
return false;
}
chain_raw.push_back(buf.get());
chain.push_back(std::move(buf));
for (X509Certificate::OSCertHandle handle :
cert->GetIntermediateCertificates()) {
bssl::UniquePtr<CRYPTO_BUFFER> buf = OSCertHandleToBuffer(handle);
if (!buf) {
LOG(WARNING) << "Failed to import intermediate";
return false;
}
chain_raw.push_back(buf.get());
chain.push_back(std::move(buf));
}
#endif
if (!SSL_set_chain_and_key(ssl, chain_raw.data(), chain_raw.size(), pkey,
custom_key)) {
LOG(WARNING) << "Failed to set client certificate";
return false;
}
return true;
}
} // namespace net } // namespace net
...@@ -78,6 +78,13 @@ NetLogParametersCallback CreateNetLogOpenSSLErrorCallback( ...@@ -78,6 +78,13 @@ NetLogParametersCallback CreateNetLogOpenSSLErrorCallback(
// this SSL connection. // this SSL connection.
int GetNetSSLVersion(SSL* ssl); int GetNetSSLVersion(SSL* ssl);
// Configures |ssl| to send the specified certificate and either |pkey| or
// |custom_key|. This is a wrapper over |SSL_set_chain_and_key|.
bool SetSSLChainAndKey(SSL* ssl,
X509Certificate* cert,
EVP_PKEY* pkey,
const SSL_PRIVATE_KEY_METHOD* custom_key);
} // namespace net } // namespace net
#endif // NET_SSL_OPENSSL_SSL_UTIL_H_ #endif // NET_SSL_OPENSSL_SSL_UTIL_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment