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(
NET_EXPORT bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
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 net
......
......@@ -8,12 +8,14 @@
#include <algorithm>
#include <memory>
#include <vector>
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "crypto/ec_private_key.h"
#include "crypto/openssl_util.h"
#include "crypto/rsa_private_key.h"
......@@ -26,6 +28,7 @@
#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/pool.h"
#include "third_party/boringssl/src/include/openssl/stack.h"
namespace net {
......@@ -392,6 +395,33 @@ bssl::UniquePtr<CRYPTO_BUFFER> CreateCryptoBuffer(
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 net
......@@ -198,44 +198,6 @@ int GetBufferSize(const char* field_trial) {
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(
const void* bytes,
size_t len,
......@@ -1244,7 +1206,8 @@ int SSLClientSocketImpl::DoChannelIDLookupComplete(int result) {
int SSLClientSocketImpl::DoVerifyCert(int result) {
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
// implementation could not. This is treated as a fatal SSL-level protocol
......@@ -1659,44 +1622,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
return -1;
}
#if BUILDFLAG(USE_BYTE_CERTS)
std::vector<CRYPTO_BUFFER*> chain_raw;
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";
if (!SetSSLChainAndKey(ssl_.get(), ssl_config_.client_cert.get(), nullptr,
&SSLContext::kPrivateKeyMethod)) {
OpenSSLPutNetError(FROM_HERE, ERR_SSL_CLIENT_AUTH_CERT_BAD_FORMAT);
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 =
ssl_config_.client_private_key->GetDigestPreferences();
......@@ -1726,8 +1656,11 @@ int SSLClientSocketImpl::ClientCertRequestCallback(SSL* ssl) {
SSL_set_private_key_digest_prefs(ssl_.get(), digests.data(),
digests.size());
net_log_.AddEvent(NetLogEventType::SSL_CLIENT_CERT_PROVIDED,
NetLog::IntCallback("cert_count", chain_raw.size()));
net_log_.AddEvent(
NetLogEventType::SSL_CLIENT_CERT_PROVIDED,
NetLog::IntCallback(
"cert_count",
1 + ssl_config_.client_cert->GetIntermediateCertificates().size()));
return 1;
}
#endif // defined(OS_IOS)
......
This diff is collapsed.
......@@ -29,6 +29,8 @@ class SSLServerContextImpl : public SSLServerContext {
std::unique_ptr<StreamSocket> socket) override;
private:
class SocketImpl;
bssl::UniquePtr<SSL_CTX> ssl_ctx_;
// Options for the SSL socket.
......
......@@ -12,8 +12,10 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/values.h"
#include "build/build_config.h"
#include "crypto/openssl_util.h"
#include "net/base/net_errors.h"
#include "net/cert/x509_util.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/ssl.h"
......@@ -138,6 +140,16 @@ std::unique_ptr<base::Value> NetLogOpenSSLErrorCallback(
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
void OpenSSLPutNetError(const tracked_objects::Location& location, int err) {
......@@ -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
......@@ -78,6 +78,13 @@ NetLogParametersCallback CreateNetLogOpenSSLErrorCallback(
// this SSL connection.
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
#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