Use CRYPTO_BUFFER APIs instead of X509 when building with BoringSSL.

Using CRYPTO_BUFFERs instead of legacy X509 objects offers memory and
security gains, and will provide binary size improvements as well once
the default list of built-in certificates can be removed; the code
dealing with them still depends on the X509 API.

Implemented by splitting openssl_identity and openssl_certificate
into BoringSSL and vanilla OpenSSL implementations.

Bug: webrtc:11410
Change-Id: Idc043462faac5e4ab1b75bedab2057197f80aba6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/174120
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: David Benjamin <davidben@webrtc.org>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Taylor <deadbeef@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32811}
This commit is contained in:
Taylor Brandstetter
2020-11-15 13:01:15 -08:00
committed by Commit Bot
parent 20ecd8f777
commit 72f638a9a2
24 changed files with 1619 additions and 278 deletions

View File

@ -24,8 +24,12 @@
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/ssl.h>
#ifdef OPENSSL_IS_BORINGSSL
#include <openssl/pool.h>
#else
#include <openssl/x509.h>
#include <openssl/x509v3.h>
#endif
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
@ -169,14 +173,17 @@ const unsigned char kFakeSSLCertificateLegacy[] = {
0x84, 0x0b, 0xc7, 0x15, 0x86, 0xc3, 0xfc, 0x48, 0x55, 0xb5, 0x81, 0x94,
0x73, 0xbd, 0x18, 0xcd, 0x9d, 0x92, 0x47, 0xaa, 0xfd, 0x18};
#ifdef OPENSSL_IS_BORINGSSL
enum ssl_verify_result_t DummyVerifyCallback(SSL* ssl, uint8_t* out_alert) {
return ssl_verify_ok;
}
#endif
// Creates a client SSL that has completed handshaking with a server that uses
// the specified certificate (which must have private key kFakeSSLPrivateKey).
// The server is deallocated. This client will have a peer certificate available
// and is thus suitable for testing VerifyPeerCertMatchesHost.
SSL* CreateSSLWithPeerCertificate(const unsigned char* cert, size_t cert_len) {
X509* x509 =
d2i_X509(nullptr, &cert, checked_cast<long>(cert_len)); // NOLINT
RTC_CHECK(x509);
const unsigned char* key_ptr = kFakeSSLPrivateKey;
EVP_PKEY* key = d2i_PrivateKey(
@ -184,14 +191,33 @@ SSL* CreateSSLWithPeerCertificate(const unsigned char* cert, size_t cert_len) {
checked_cast<long>(arraysize(kFakeSSLPrivateKey))); // NOLINT
RTC_CHECK(key);
SSL_CTX* ctx = SSL_CTX_new(SSLv23_method());
#ifdef OPENSSL_IS_BORINGSSL
SSL_CTX* ctx = SSL_CTX_new(TLS_with_buffers_method());
#else
SSL_CTX* ctx = SSL_CTX_new(TLS_method());
#endif
SSL* client = SSL_new(ctx);
SSL* server = SSL_new(ctx);
SSL_set_connect_state(client);
SSL_set_accept_state(server);
#ifdef OPENSSL_IS_BORINGSSL
bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer(CRYPTO_BUFFER_new(
static_cast<const uint8_t*>(cert), cert_len, openssl::GetBufferPool()));
RTC_CHECK(cert_buffer);
std::vector<CRYPTO_BUFFER*> cert_buffers;
cert_buffers.push_back(cert_buffer.get());
RTC_CHECK(1 == SSL_set_chain_and_key(server, cert_buffers.data(),
cert_buffers.size(), key, nullptr));
// When using crypto buffers we don't get any built-in verification.
SSL_set_custom_verify(client, SSL_VERIFY_PEER, DummyVerifyCallback);
#else
X509* x509 =
d2i_X509(nullptr, &cert, checked_cast<long>(cert_len)); // NOLINT
RTC_CHECK(x509);
RTC_CHECK(SSL_use_certificate(server, x509));
RTC_CHECK(SSL_use_PrivateKey(server, key));
#endif
BIO* bio1;
BIO* bio2;
@ -221,13 +247,19 @@ SSL* CreateSSLWithPeerCertificate(const unsigned char* cert, size_t cert_len) {
SSL_free(server);
SSL_CTX_free(ctx);
EVP_PKEY_free(key);
#ifndef OPENSSL_IS_BORINGSSL
X509_free(x509);
#endif
return client;
}
} // namespace
TEST(OpenSSLUtilityTest, VerifyPeerCertMatchesHostFailsOnNoPeerCertificate) {
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method());
#ifdef OPENSSL_IS_BORINGSSL
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLS_with_buffers_method());
#else
SSL_CTX* ssl_ctx = SSL_CTX_new(DTLS_method());
#endif
SSL* ssl = SSL_new(ssl_ctx);
EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "webrtc.org"));