From 7e6290d1d25e3e113e95f87dd62d8e16e51d59de Mon Sep 17 00:00:00 2001 From: Sam Zackrisson Date: Thu, 10 Dec 2020 07:55:28 +0000 Subject: [PATCH] Revert "Use CRYPTO_BUFFER APIs instead of X509 when building with BoringSSL." This reverts commit 72f638a9a279e7abb5534fa66a0ade2cf18ec1a7. Reason for revert: downstream build failures Original change's description: > 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 > Reviewed-by: David Benjamin > Reviewed-by: Harald Alvestrand > Commit-Queue: Taylor > Cr-Commit-Position: refs/heads/master@{#32811} TBR=deadbeef@webrtc.org,mbonadei@webrtc.org,davidben@webrtc.org,hta@webrtc.org Change-Id: Ib5e55cb5798a2f3d25a4460f5311d2e650d3fa82 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: webrtc:11410 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/196742 Reviewed-by: Sam Zackrisson Commit-Queue: Sam Zackrisson Cr-Commit-Position: refs/heads/master@{#32812} --- pc/test/fake_rtc_certificate_generator.h | 2 +- rtc_base/BUILD.gn | 22 +- rtc_base/boringssl_certificate.cc | 410 --------------------- rtc_base/boringssl_certificate.h | 80 ---- rtc_base/boringssl_identity.cc | 215 ----------- rtc_base/boringssl_identity.h | 76 ---- rtc_base/openssl_adapter.cc | 150 ++------ rtc_base/openssl_adapter.h | 19 - rtc_base/openssl_identity.cc | 171 ++++++++- rtc_base/openssl_identity.h | 33 +- rtc_base/openssl_key_pair.cc | 192 ---------- rtc_base/openssl_key_pair.h | 60 --- rtc_base/openssl_session_cache_unittest.cc | 30 +- rtc_base/openssl_stream_adapter.cc | 80 +--- rtc_base/openssl_stream_adapter.h | 17 +- rtc_base/openssl_utility.cc | 148 +------- rtc_base/openssl_utility.h | 17 - rtc_base/openssl_utility_unittest.cc | 42 +-- rtc_base/rtc_certificate_generator.cc | 2 +- rtc_base/ssl_certificate.cc | 11 +- rtc_base/ssl_identity.cc | 36 +- rtc_base/ssl_identity_unittest.cc | 17 +- rtc_base/ssl_stream_adapter_unittest.cc | 63 +--- webrtc.gni | 4 - 24 files changed, 278 insertions(+), 1619 deletions(-) delete mode 100644 rtc_base/boringssl_certificate.cc delete mode 100644 rtc_base/boringssl_certificate.h delete mode 100644 rtc_base/boringssl_identity.cc delete mode 100644 rtc_base/boringssl_identity.h delete mode 100644 rtc_base/openssl_key_pair.cc delete mode 100644 rtc_base/openssl_key_pair.h diff --git a/pc/test/fake_rtc_certificate_generator.h b/pc/test/fake_rtc_certificate_generator.h index b591c4c4ab..b726a4c0ba 100644 --- a/pc/test/fake_rtc_certificate_generator.h +++ b/pc/test/fake_rtc_certificate_generator.h @@ -83,7 +83,7 @@ static const rtc::RTCCertificatePEM kRsaPems[] = { // ECDSA with EC_NIST_P256. // These PEM strings were created by generating an identity with -// |SSLIdentity::Create| and invoking |identity->PrivateKeyToPEMString()|, +// |SSLIdentity::Generate| and invoking |identity->PrivateKeyToPEMString()|, // |identity->PublicKeyToPEMString()| and // |identity->certificate().ToPEMString()|. static const rtc::RTCCertificatePEM kEcdsaPems[] = { diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 8762bfbeb1..8b920908f3 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -911,10 +911,12 @@ rtc_library("rtc_base") { "openssl.h", "openssl_adapter.cc", "openssl_adapter.h", + "openssl_certificate.cc", + "openssl_certificate.h", "openssl_digest.cc", "openssl_digest.h", - "openssl_key_pair.cc", - "openssl_key_pair.h", + "openssl_identity.cc", + "openssl_identity.h", "openssl_session_cache.cc", "openssl_session_cache.h", "openssl_stream_adapter.cc", @@ -960,22 +962,6 @@ rtc_library("rtc_base") { "unique_id_generator.h", ] - if (rtc_openssl_is_boringssl) { - sources += [ - "boringssl_certificate.cc", - "boringssl_certificate.h", - "boringssl_identity.cc", - "boringssl_identity.h", - ] - } else { - sources += [ - "openssl_certificate.cc", - "openssl_certificate.h", - "openssl_identity.cc", - "openssl_identity.h", - ] - } - if (build_with_chromium) { include_dirs = [ "../../boringssl/src/include" ] public_configs += [ ":rtc_base_chromium_config" ] diff --git a/rtc_base/boringssl_certificate.cc b/rtc_base/boringssl_certificate.cc deleted file mode 100644 index c9713c2c8c..0000000000 --- a/rtc_base/boringssl_certificate.cc +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Copyright 2020 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "rtc_base/boringssl_certificate.h" - -#if defined(WEBRTC_WIN) -// Must be included first before openssl headers. -#include "rtc_base/win32.h" // NOLINT -#endif // WEBRTC_WIN - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "rtc_base/checks.h" -#include "rtc_base/helpers.h" -#include "rtc_base/logging.h" -#include "rtc_base/message_digest.h" -#include "rtc_base/openssl_digest.h" -#include "rtc_base/openssl_identity.h" -#include "rtc_base/openssl_utility.h" - -namespace rtc { -namespace { - -// List of OIDs of signature algorithms accepted by WebRTC. -// Taken from openssl/nid.h. -static const uint8_t kMD5WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x03}; -static const uint8_t kMD5WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x04}; -static const uint8_t kECDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce, - 0x3d, 0x04, 0x01}; -static const uint8_t kDSAWithSHA1[] = {0x2a, 0x86, 0x48, 0xce, - 0x38, 0x04, 0x03}; -static const uint8_t kDSAWithSHA1_2[] = {0x2b, 0x0e, 0x03, 0x02, 0x1b}; -static const uint8_t kSHA1WithRSA[] = {0x2b, 0x0e, 0x03, 0x02, 0x1d}; -static const uint8_t kSHA1WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x05}; -static const uint8_t kECDSAWithSHA224[] = {0x2a, 0x86, 0x48, 0xce, - 0x3d, 0x04, 0x03, 0x01}; -static const uint8_t kSHA224WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0e}; -static const uint8_t kDSAWithSHA224[] = {0x60, 0x86, 0x48, 0x01, 0x65, - 0x03, 0x04, 0x03, 0x01}; -static const uint8_t kECDSAWithSHA256[] = {0x2a, 0x86, 0x48, 0xce, - 0x3d, 0x04, 0x03, 0x02}; -static const uint8_t kSHA256WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0b}; -static const uint8_t kDSAWithSHA256[] = {0x60, 0x86, 0x48, 0x01, 0x65, - 0x03, 0x04, 0x03, 0x028}; -static const uint8_t kECDSAWithSHA384[] = {0x2a, 0x86, 0x48, 0xce, - 0x3d, 0x04, 0x03, 0x03}; -static const uint8_t kSHA384WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0c}; -static const uint8_t kECDSAWithSHA512[] = {0x2a, 0x86, 0x48, 0xce, - 0x3d, 0x04, 0x03, 0x04}; -static const uint8_t kSHA512WithRSAEncryption[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x0d}; - -#if !defined(NDEBUG) -// Print a certificate to the log, for debugging. -static void PrintCert(BoringSSLCertificate* cert) { - // Since we're using CRYPTO_BUFFER, we can't use X509_print_ex, so we'll just - // print the PEM string. - RTC_DLOG(LS_VERBOSE) << "PEM representation of certificate:\n" - << cert->ToPEMString(); -} -#endif - -bool AddSHA256SignatureAlgorithm(CBB* cbb, KeyType key_type) { - // An AlgorithmIdentifier is described in RFC 5280, 4.1.1.2. - CBB sequence, oid, params; - if (!CBB_add_asn1(cbb, &sequence, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1(&sequence, &oid, CBS_ASN1_OBJECT)) { - return false; - } - - switch (key_type) { - case KT_RSA: - if (!CBB_add_bytes(&oid, kSHA256WithRSAEncryption, - sizeof(kSHA256WithRSAEncryption)) || - !CBB_add_asn1(&sequence, ¶ms, CBS_ASN1_NULL)) { - return false; - } - break; - case KT_ECDSA: - if (!CBB_add_bytes(&oid, kECDSAWithSHA256, sizeof(kECDSAWithSHA256))) { - return false; - } - break; - default: - RTC_NOTREACHED(); - return false; - } - if (!CBB_flush(cbb)) { - return false; - } - return true; -} - -// Adds an X.509 Common Name to |cbb|. -bool AddCommonName(CBB* cbb, const std::string& common_name) { - // See RFC 4519. - static const uint8_t kCommonName[] = {0x55, 0x04, 0x03}; - - if (common_name.empty()) { - RTC_LOG(LS_ERROR) << "Common name cannot be empty."; - return false; - } - - // See RFC 5280, section 4.1.2.4. - CBB rdns; - if (!CBB_add_asn1(cbb, &rdns, CBS_ASN1_SEQUENCE)) { - return false; - } - - CBB rdn, attr, type, value; - if (!CBB_add_asn1(&rdns, &rdn, CBS_ASN1_SET) || - !CBB_add_asn1(&rdn, &attr, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1(&attr, &type, CBS_ASN1_OBJECT) || - !CBB_add_bytes(&type, kCommonName, sizeof(kCommonName)) || - !CBB_add_asn1(&attr, &value, CBS_ASN1_UTF8STRING) || - !CBB_add_bytes(&value, - reinterpret_cast(common_name.c_str()), - common_name.size()) || - !CBB_flush(cbb)) { - return false; - } - - return true; -} - -bool AddTime(CBB* cbb, time_t time) { - bssl::UniquePtr asn1_time(ASN1_TIME_new()); - if (!asn1_time) { - return false; - } - - if (!ASN1_TIME_set(asn1_time.get(), time)) { - return false; - } - - unsigned tag; - switch (asn1_time->type) { - case V_ASN1_UTCTIME: - tag = CBS_ASN1_UTCTIME; - break; - case V_ASN1_GENERALIZEDTIME: - tag = CBS_ASN1_GENERALIZEDTIME; - break; - default: - return false; - } - - CBB child; - if (!CBB_add_asn1(cbb, &child, tag) || - !CBB_add_bytes(&child, asn1_time->data, asn1_time->length) || - !CBB_flush(cbb)) { - return false; - } - - return true; -} - -// Generate a self-signed certificate, with the public key from the -// given key pair. Caller is responsible for freeing the returned object. -static bssl::UniquePtr MakeCertificate( - EVP_PKEY* pkey, - const SSLIdentityParams& params) { - RTC_LOG(LS_INFO) << "Making certificate for " << params.common_name; - - // See RFC 5280, section 4.1. First, construct the TBSCertificate. - bssl::ScopedCBB cbb; - CBB tbs_cert, version, validity; - uint8_t* tbs_cert_bytes; - size_t tbs_cert_len; - uint64_t serial_number; - if (!CBB_init(cbb.get(), 64) || - !CBB_add_asn1(cbb.get(), &tbs_cert, CBS_ASN1_SEQUENCE) || - !CBB_add_asn1(&tbs_cert, &version, - CBS_ASN1_CONTEXT_SPECIFIC | CBS_ASN1_CONSTRUCTED | 0) || - !CBB_add_asn1_uint64(&version, 2) || - !RAND_bytes(reinterpret_cast(&serial_number), - sizeof(serial_number)) || - !CBB_add_asn1_uint64(&tbs_cert, serial_number) || - !AddSHA256SignatureAlgorithm(&tbs_cert, params.key_params.type()) || - !AddCommonName(&tbs_cert, params.common_name) || // issuer - !CBB_add_asn1(&tbs_cert, &validity, CBS_ASN1_SEQUENCE) || - !AddTime(&validity, params.not_before) || - !AddTime(&validity, params.not_after) || - !AddCommonName(&tbs_cert, params.common_name) || // subject - !EVP_marshal_public_key(&tbs_cert, pkey) || // subjectPublicKeyInfo - !CBB_finish(cbb.get(), &tbs_cert_bytes, &tbs_cert_len)) { - return nullptr; - } - - bssl::UniquePtr delete_tbs_cert_bytes(tbs_cert_bytes); - - // Sign the TBSCertificate and write the entire certificate. - CBB cert, signature; - bssl::ScopedEVP_MD_CTX ctx; - uint8_t* sig_out; - size_t sig_len; - uint8_t* cert_bytes; - size_t cert_len; - if (!CBB_init(cbb.get(), tbs_cert_len) || - !CBB_add_asn1(cbb.get(), &cert, CBS_ASN1_SEQUENCE) || - !CBB_add_bytes(&cert, tbs_cert_bytes, tbs_cert_len) || - !AddSHA256SignatureAlgorithm(&cert, params.key_params.type()) || - !CBB_add_asn1(&cert, &signature, CBS_ASN1_BITSTRING) || - !CBB_add_u8(&signature, 0 /* no unused bits */) || - !EVP_DigestSignInit(ctx.get(), nullptr, EVP_sha256(), nullptr, pkey) || - // Compute the maximum signature length. - !EVP_DigestSign(ctx.get(), nullptr, &sig_len, tbs_cert_bytes, - tbs_cert_len) || - !CBB_reserve(&signature, &sig_out, sig_len) || - // Actually sign the TBSCertificate. - !EVP_DigestSign(ctx.get(), sig_out, &sig_len, tbs_cert_bytes, - tbs_cert_len) || - !CBB_did_write(&signature, sig_len) || - !CBB_finish(cbb.get(), &cert_bytes, &cert_len)) { - return nullptr; - } - bssl::UniquePtr delete_cert_bytes(cert_bytes); - - RTC_LOG(LS_INFO) << "Returning certificate"; - return bssl::UniquePtr( - CRYPTO_BUFFER_new(cert_bytes, cert_len, openssl::GetBufferPool())); -} - -} // namespace - -BoringSSLCertificate::BoringSSLCertificate( - bssl::UniquePtr cert_buffer) - : cert_buffer_(std::move(cert_buffer)) { - RTC_DCHECK(cert_buffer_ != nullptr); -} - -std::unique_ptr BoringSSLCertificate::Generate( - OpenSSLKeyPair* key_pair, - const SSLIdentityParams& params) { - SSLIdentityParams actual_params(params); - if (actual_params.common_name.empty()) { - // Use a random string, arbitrarily 8 chars long. - actual_params.common_name = CreateRandomString(8); - } - bssl::UniquePtr cert_buffer = - MakeCertificate(key_pair->pkey(), actual_params); - if (!cert_buffer) { - openssl::LogSSLErrors("Generating certificate"); - return nullptr; - } - auto ret = std::make_unique(std::move(cert_buffer)); -#if !defined(NDEBUG) - PrintCert(ret.get()); -#endif - return ret; -} - -std::unique_ptr BoringSSLCertificate::FromPEMString( - const std::string& pem_string) { - std::string der; - if (!SSLIdentity::PemToDer(kPemTypeCertificate, pem_string, &der)) { - return nullptr; - } - bssl::UniquePtr cert_buffer( - CRYPTO_BUFFER_new(reinterpret_cast(der.c_str()), - der.length(), openssl::GetBufferPool())); - if (!cert_buffer) { - return nullptr; - } - return std::make_unique(std::move(cert_buffer)); -} - -#define OID_MATCHES(oid, oid_other) \ - (CBS_len(&oid) == sizeof(oid_other) && \ - 0 == memcmp(CBS_data(&oid), oid_other, sizeof(oid_other))) - -bool BoringSSLCertificate::GetSignatureDigestAlgorithm( - std::string* algorithm) const { - CBS oid; - if (!openssl::ParseCertificate(cert_buffer_.get(), &oid, nullptr)) { - RTC_LOG(LS_ERROR) << "Failed to parse certificate."; - return false; - } - if (OID_MATCHES(oid, kMD5WithRSA) || - OID_MATCHES(oid, kMD5WithRSAEncryption)) { - *algorithm = DIGEST_MD5; - return true; - } - if (OID_MATCHES(oid, kECDSAWithSHA1) || OID_MATCHES(oid, kDSAWithSHA1) || - OID_MATCHES(oid, kDSAWithSHA1_2) || OID_MATCHES(oid, kSHA1WithRSA) || - OID_MATCHES(oid, kSHA1WithRSAEncryption)) { - *algorithm = DIGEST_SHA_1; - return true; - } - if (OID_MATCHES(oid, kECDSAWithSHA224) || - OID_MATCHES(oid, kSHA224WithRSAEncryption) || - OID_MATCHES(oid, kDSAWithSHA224)) { - *algorithm = DIGEST_SHA_224; - return true; - } - if (OID_MATCHES(oid, kECDSAWithSHA256) || - OID_MATCHES(oid, kSHA256WithRSAEncryption) || - OID_MATCHES(oid, kDSAWithSHA256)) { - *algorithm = DIGEST_SHA_256; - return true; - } - if (OID_MATCHES(oid, kECDSAWithSHA384) || - OID_MATCHES(oid, kSHA384WithRSAEncryption)) { - *algorithm = DIGEST_SHA_384; - return true; - } - if (OID_MATCHES(oid, kECDSAWithSHA512) || - OID_MATCHES(oid, kSHA512WithRSAEncryption)) { - *algorithm = DIGEST_SHA_512; - return true; - } - // Unknown algorithm. There are several unhandled options that are less - // common and more complex. - RTC_LOG(LS_ERROR) << "Unknown signature algorithm."; - algorithm->clear(); - return false; -} - -bool BoringSSLCertificate::ComputeDigest(const std::string& algorithm, - unsigned char* digest, - size_t size, - size_t* length) const { - return ComputeDigest(cert_buffer_.get(), algorithm, digest, size, length); -} - -bool BoringSSLCertificate::ComputeDigest(const CRYPTO_BUFFER* cert_buffer, - const std::string& algorithm, - unsigned char* digest, - size_t size, - size_t* length) { - const EVP_MD* md = nullptr; - unsigned int n = 0; - if (!OpenSSLDigest::GetDigestEVP(algorithm, &md)) { - return false; - } - if (size < static_cast(EVP_MD_size(md))) { - return false; - } - if (!EVP_Digest(CRYPTO_BUFFER_data(cert_buffer), - CRYPTO_BUFFER_len(cert_buffer), digest, &n, md, nullptr)) { - return false; - } - *length = n; - return true; -} - -BoringSSLCertificate::~BoringSSLCertificate() {} - -std::unique_ptr BoringSSLCertificate::Clone() const { - return std::make_unique( - bssl::UpRef(cert_buffer_.get())); -} - -std::string BoringSSLCertificate::ToPEMString() const { - return OpenSSLIdentity::DerToPem(kPemTypeCertificate, - CRYPTO_BUFFER_data(cert_buffer_.get()), - CRYPTO_BUFFER_len(cert_buffer_.get())); -} - -void BoringSSLCertificate::ToDER(Buffer* der_buffer) const { - der_buffer->SetData(CRYPTO_BUFFER_data(cert_buffer_.get()), - CRYPTO_BUFFER_len(cert_buffer_.get())); -} - -bool BoringSSLCertificate::operator==(const BoringSSLCertificate& other) const { - return CRYPTO_BUFFER_len(cert_buffer_.get()) == - CRYPTO_BUFFER_len(other.cert_buffer_.get()) && - 0 == memcmp(CRYPTO_BUFFER_data(cert_buffer_.get()), - CRYPTO_BUFFER_data(other.cert_buffer_.get()), - CRYPTO_BUFFER_len(cert_buffer_.get())); -} - -bool BoringSSLCertificate::operator!=(const BoringSSLCertificate& other) const { - return !(*this == other); -} - -int64_t BoringSSLCertificate::CertificateExpirationTime() const { - int64_t ret; - if (!openssl::ParseCertificate(cert_buffer_.get(), nullptr, &ret)) { - RTC_LOG(LS_ERROR) << "Failed to parse certificate."; - return -1; - } - return ret; -} - -} // namespace rtc diff --git a/rtc_base/boringssl_certificate.h b/rtc_base/boringssl_certificate.h deleted file mode 100644 index 740763dc69..0000000000 --- a/rtc_base/boringssl_certificate.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2020 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef RTC_BASE_BORINGSSL_CERTIFICATE_H_ -#define RTC_BASE_BORINGSSL_CERTIFICATE_H_ - -#include -#include -#include - -#include -#include - -#include "rtc_base/buffer.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/ssl_certificate.h" -#include "rtc_base/ssl_identity.h" - -namespace rtc { - -class OpenSSLKeyPair; - -// BoringSSLCertificate encapsulates a BoringSSL CRYPTO_BUFFER object holding a -// certificate, which is also reference counted inside the BoringSSL library. -// This offers binary size and memory improvements over the OpenSSL X509 -// object. -class BoringSSLCertificate final : public SSLCertificate { - public: - explicit BoringSSLCertificate(bssl::UniquePtr cert_buffer); - - static std::unique_ptr Generate( - OpenSSLKeyPair* key_pair, - const SSLIdentityParams& params); - static std::unique_ptr FromPEMString( - const std::string& pem_string); - - ~BoringSSLCertificate() override; - - std::unique_ptr Clone() const override; - - CRYPTO_BUFFER* cert_buffer() const { return cert_buffer_.get(); } - - std::string ToPEMString() const override; - void ToDER(Buffer* der_buffer) const override; - bool operator==(const BoringSSLCertificate& other) const; - bool operator!=(const BoringSSLCertificate& other) const; - - // Compute the digest of the certificate given |algorithm|. - bool ComputeDigest(const std::string& algorithm, - unsigned char* digest, - size_t size, - size_t* length) const override; - - // Compute the digest of a certificate as a CRYPTO_BUFFER. - static bool ComputeDigest(const CRYPTO_BUFFER* cert_buffer, - const std::string& algorithm, - unsigned char* digest, - size_t size, - size_t* length); - - bool GetSignatureDigestAlgorithm(std::string* algorithm) const override; - - int64_t CertificateExpirationTime() const override; - - private: - // A handle to the DER encoded certificate data. - bssl::UniquePtr cert_buffer_; - RTC_DISALLOW_COPY_AND_ASSIGN(BoringSSLCertificate); -}; - -} // namespace rtc - -#endif // RTC_BASE_BORINGSSL_CERTIFICATE_H_ diff --git a/rtc_base/boringssl_identity.cc b/rtc_base/boringssl_identity.cc deleted file mode 100644 index d22c8ce529..0000000000 --- a/rtc_base/boringssl_identity.cc +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2020 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "rtc_base/boringssl_identity.h" - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "absl/memory/memory.h" -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/numerics/safe_conversions.h" -#include "rtc_base/openssl.h" -#include "rtc_base/openssl_utility.h" - -namespace rtc { - -BoringSSLIdentity::BoringSSLIdentity( - std::unique_ptr key_pair, - std::unique_ptr certificate) - : key_pair_(std::move(key_pair)) { - RTC_DCHECK(key_pair_ != nullptr); - RTC_DCHECK(certificate != nullptr); - std::vector> certs; - certs.push_back(std::move(certificate)); - cert_chain_.reset(new SSLCertChain(std::move(certs))); -} - -BoringSSLIdentity::BoringSSLIdentity(std::unique_ptr key_pair, - std::unique_ptr cert_chain) - : key_pair_(std::move(key_pair)), cert_chain_(std::move(cert_chain)) { - RTC_DCHECK(key_pair_ != nullptr); - RTC_DCHECK(cert_chain_ != nullptr); -} - -BoringSSLIdentity::~BoringSSLIdentity() = default; - -std::unique_ptr BoringSSLIdentity::CreateInternal( - const SSLIdentityParams& params) { - auto key_pair = OpenSSLKeyPair::Generate(params.key_params); - if (key_pair) { - std::unique_ptr certificate( - BoringSSLCertificate::Generate(key_pair.get(), params)); - if (certificate != nullptr) { - return absl::WrapUnique( - new BoringSSLIdentity(std::move(key_pair), std::move(certificate))); - } - } - RTC_LOG(LS_ERROR) << "Identity generation failed."; - return nullptr; -} - -// static -std::unique_ptr BoringSSLIdentity::CreateWithExpiration( - const std::string& common_name, - const KeyParams& key_params, - time_t certificate_lifetime) { - SSLIdentityParams params; - params.key_params = key_params; - params.common_name = common_name; - time_t now = time(nullptr); - params.not_before = now + kCertificateWindowInSeconds; - params.not_after = now + certificate_lifetime; - if (params.not_before > params.not_after) - return nullptr; - return CreateInternal(params); -} - -std::unique_ptr BoringSSLIdentity::CreateForTest( - const SSLIdentityParams& params) { - return CreateInternal(params); -} - -std::unique_ptr BoringSSLIdentity::CreateFromPEMStrings( - const std::string& private_key, - const std::string& certificate) { - std::unique_ptr cert( - BoringSSLCertificate::FromPEMString(certificate)); - if (!cert) { - RTC_LOG(LS_ERROR) - << "Failed to create BoringSSLCertificate from PEM string."; - return nullptr; - } - - auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); - if (!key_pair) { - RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string."; - return nullptr; - } - - return absl::WrapUnique( - new BoringSSLIdentity(std::move(key_pair), std::move(cert))); -} - -std::unique_ptr BoringSSLIdentity::CreateFromPEMChainStrings( - const std::string& private_key, - const std::string& certificate_chain) { - bssl::UniquePtr bio( - BIO_new_mem_buf(certificate_chain.data(), - rtc::dchecked_cast(certificate_chain.size()))); - if (!bio) { - return nullptr; - } - BIO_set_mem_eof_return(bio.get(), 0); - std::vector> certs; - while (true) { - char* name; - char* header; - unsigned char* data; - long len; // NOLINT - int ret = PEM_read_bio(bio.get(), &name, &header, &data, &len); - if (ret == 0) { - uint32_t err = ERR_peek_error(); - if (ERR_GET_LIB(err) == ERR_LIB_PEM && - ERR_GET_REASON(err) == PEM_R_NO_START_LINE) { - break; - } - RTC_LOG(LS_ERROR) << "Failed to parse certificate from PEM string."; - return nullptr; - } - bssl::UniquePtr owned_name(name); - bssl::UniquePtr owned_header(header); - bssl::UniquePtr owned_data(data); - if (strcmp(owned_name.get(), PEM_STRING_X509) != 0) { - RTC_LOG(LS_ERROR) - << "Non-certificate found while parsing certificate chain: " - << owned_name.get(); - return nullptr; - } - bssl::UniquePtr crypto_buffer( - CRYPTO_BUFFER_new(data, len, openssl::GetBufferPool())); - if (!crypto_buffer) { - return nullptr; - } - certs.emplace_back(new BoringSSLCertificate(std::move(crypto_buffer))); - } - if (certs.empty()) { - RTC_LOG(LS_ERROR) << "Found no certificates in PEM string."; - return nullptr; - } - - auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); - if (!key_pair) { - RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string."; - return nullptr; - } - - return absl::WrapUnique(new BoringSSLIdentity( - std::move(key_pair), std::make_unique(std::move(certs)))); -} - -const BoringSSLCertificate& BoringSSLIdentity::certificate() const { - return *static_cast(&cert_chain_->Get(0)); -} - -const SSLCertChain& BoringSSLIdentity::cert_chain() const { - return *cert_chain_.get(); -} - -std::unique_ptr BoringSSLIdentity::CloneInternal() const { - // We cannot use std::make_unique here because the referenced - // BoringSSLIdentity constructor is private. - return absl::WrapUnique( - new BoringSSLIdentity(key_pair_->Clone(), cert_chain_->Clone())); -} - -bool BoringSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { - std::vector cert_buffers; - for (size_t i = 0; i < cert_chain_->GetSize(); ++i) { - cert_buffers.push_back( - static_cast(&cert_chain_->Get(i)) - ->cert_buffer()); - } - // 1 is the documented success return code. - if (1 != SSL_CTX_set_chain_and_key(ctx, &cert_buffers[0], cert_buffers.size(), - key_pair_->pkey(), nullptr)) { - openssl::LogSSLErrors("Configuring key and certificate"); - return false; - } - return true; -} - -std::string BoringSSLIdentity::PrivateKeyToPEMString() const { - return key_pair_->PrivateKeyToPEMString(); -} - -std::string BoringSSLIdentity::PublicKeyToPEMString() const { - return key_pair_->PublicKeyToPEMString(); -} - -bool BoringSSLIdentity::operator==(const BoringSSLIdentity& other) const { - return *this->key_pair_ == *other.key_pair_ && - this->certificate() == other.certificate(); -} - -bool BoringSSLIdentity::operator!=(const BoringSSLIdentity& other) const { - return !(*this == other); -} - -} // namespace rtc diff --git a/rtc_base/boringssl_identity.h b/rtc_base/boringssl_identity.h deleted file mode 100644 index 71b29b486d..0000000000 --- a/rtc_base/boringssl_identity.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2020 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef RTC_BASE_BORINGSSL_IDENTITY_H_ -#define RTC_BASE_BORINGSSL_IDENTITY_H_ - -#include - -#include -#include -#include - -#include "rtc_base/boringssl_certificate.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/openssl_key_pair.h" -#include "rtc_base/ssl_certificate.h" -#include "rtc_base/ssl_identity.h" - -namespace rtc { - -// Holds a keypair and certificate together, and a method to generate them -// consistently. Uses CRYPTO_BUFFER instead of X509, which offers binary size -// and memory improvements. -class BoringSSLIdentity final : public SSLIdentity { - public: - static std::unique_ptr CreateWithExpiration( - const std::string& common_name, - const KeyParams& key_params, - time_t certificate_lifetime); - static std::unique_ptr CreateForTest( - const SSLIdentityParams& params); - static std::unique_ptr CreateFromPEMStrings( - const std::string& private_key, - const std::string& certificate); - static std::unique_ptr CreateFromPEMChainStrings( - const std::string& private_key, - const std::string& certificate_chain); - ~BoringSSLIdentity() override; - - const BoringSSLCertificate& certificate() const override; - const SSLCertChain& cert_chain() const override; - - // Configure an SSL context object to use our key and certificate. - bool ConfigureIdentity(SSL_CTX* ctx); - - std::string PrivateKeyToPEMString() const override; - std::string PublicKeyToPEMString() const override; - bool operator==(const BoringSSLIdentity& other) const; - bool operator!=(const BoringSSLIdentity& other) const; - - private: - BoringSSLIdentity(std::unique_ptr key_pair, - std::unique_ptr certificate); - BoringSSLIdentity(std::unique_ptr key_pair, - std::unique_ptr cert_chain); - std::unique_ptr CloneInternal() const override; - - static std::unique_ptr CreateInternal( - const SSLIdentityParams& params); - - std::unique_ptr key_pair_; - std::unique_ptr cert_chain_; - - RTC_DISALLOW_COPY_AND_ASSIGN(BoringSSLIdentity); -}; - -} // namespace rtc - -#endif // RTC_BASE_BORINGSSL_IDENTITY_H_ diff --git a/rtc_base/openssl_adapter.cc b/rtc_base/openssl_adapter.cc index e5c2c42761..8fd882c2b3 100644 --- a/rtc_base/openssl_adapter.cc +++ b/rtc_base/openssl_adapter.cc @@ -13,9 +13,6 @@ #include #include #include -#ifdef OPENSSL_IS_BORINGSSL -#include -#endif #include #include #include @@ -23,24 +20,13 @@ #include -// Use CRYPTO_BUFFER APIs if available and we have no dependency on X509 -// objects. -#if defined(OPENSSL_IS_BORINGSSL) && \ - defined(WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS) -#define WEBRTC_USE_CRYPTO_BUFFER_CALLBACK -#endif - #include "absl/memory/memory.h" #include "rtc_base/checks.h" #include "rtc_base/location.h" #include "rtc_base/logging.h" #include "rtc_base/numerics/safe_conversions.h" #include "rtc_base/openssl.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else -#include "rtc_base/openssl_identity.h" -#endif +#include "rtc_base/openssl_certificate.h" #include "rtc_base/openssl_utility.h" #include "rtc_base/string_encode.h" #include "rtc_base/thread.h" @@ -237,13 +223,8 @@ void OpenSSLAdapter::SetCertVerifier( void OpenSSLAdapter::SetIdentity(std::unique_ptr identity) { RTC_DCHECK(!identity_); -#ifdef OPENSSL_IS_BORINGSSL - identity_ = - absl::WrapUnique(static_cast(identity.release())); -#else identity_ = absl::WrapUnique(static_cast(identity.release())); -#endif } void OpenSSLAdapter::SetRole(SSLRole role) { @@ -816,70 +797,7 @@ void OpenSSLAdapter::SSLInfoCallback(const SSL* s, int where, int ret) { #endif -#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK -// static -enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyCallback(SSL* ssl, - uint8_t* out_alert) { - // Get our stream pointer from the SSL context. - OpenSSLAdapter* stream = - reinterpret_cast(SSL_get_app_data(ssl)); - - ssl_verify_result_t ret = stream->SSLVerifyInternal(ssl, out_alert); - - // Should only be used for debugging and development. - if (ret != ssl_verify_ok && stream->ignore_bad_cert_) { - RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; - return ssl_verify_ok; - } - - return ret; -} - -enum ssl_verify_result_t OpenSSLAdapter::SSLVerifyInternal(SSL* ssl, - uint8_t* out_alert) { - if (ssl_cert_verifier_ == nullptr) { - RTC_LOG(LS_WARNING) << "Built-in trusted root certificates disabled but no " - "SSL verify callback provided."; - return ssl_verify_invalid; - } - - RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback."; - const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl); - if (sk_CRYPTO_BUFFER_num(chain) == 0) { - RTC_LOG(LS_ERROR) << "Peer certificate chain empty?"; - return ssl_verify_invalid; - } - - BoringSSLCertificate cert(bssl::UpRef(sk_CRYPTO_BUFFER_value(chain, 0))); - if (!ssl_cert_verifier_->Verify(cert)) { - RTC_LOG(LS_WARNING) << "Failed to verify certificate using custom callback"; - return ssl_verify_invalid; - } - - custom_cert_verifier_status_ = true; - RTC_LOG(LS_INFO) << "Validated certificate using custom callback"; - return ssl_verify_ok; -} -#else // WEBRTC_USE_CRYPTO_BUFFER_CALLBACK int OpenSSLAdapter::SSLVerifyCallback(int ok, X509_STORE_CTX* store) { - // Get our stream pointer from the store - SSL* ssl = reinterpret_cast( - X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx())); - - OpenSSLAdapter* stream = - reinterpret_cast(SSL_get_app_data(ssl)); - ok = stream->SSLVerifyInternal(ok, ssl, store); - - // Should only be used for debugging and development. - if (!ok && stream->ignore_bad_cert_) { - RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; - return 1; - } - - return ok; -} - -int OpenSSLAdapter::SSLVerifyInternal(int ok, SSL* ssl, X509_STORE_CTX* store) { #if !defined(NDEBUG) if (!ok) { char data[256]; @@ -896,40 +814,33 @@ int OpenSSLAdapter::SSLVerifyInternal(int ok, SSL* ssl, X509_STORE_CTX* store) { << X509_verify_cert_error_string(err); } #endif - if (ssl_cert_verifier_ == nullptr) { - return ok; + // Get our stream pointer from the store + SSL* ssl = reinterpret_cast( + X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx())); + + OpenSSLAdapter* stream = + reinterpret_cast(SSL_get_app_data(ssl)); + + if (!ok && stream->ssl_cert_verifier_ != nullptr) { + RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback."; + const OpenSSLCertificate cert(X509_STORE_CTX_get_current_cert(store)); + if (stream->ssl_cert_verifier_->Verify(cert)) { + stream->custom_cert_verifier_status_ = true; + RTC_LOG(LS_INFO) << "Validated certificate using custom callback"; + ok = true; + } else { + RTC_LOG(LS_INFO) << "Failed to verify certificate using custom callback"; + } } - RTC_LOG(LS_INFO) << "Invoking SSL Verify Callback."; -#ifdef OPENSSL_IS_BORINGSSL - // Convert X509 to CRYPTO_BUFFER. - uint8_t* data = nullptr; - int length = i2d_X509(X509_STORE_CTX_get_current_cert(store), &data); - if (length < 0) { - RTC_LOG(LS_ERROR) << "Failed to encode X509."; - return ok; - } - bssl::UniquePtr owned_data(data); - bssl::UniquePtr crypto_buffer( - CRYPTO_BUFFER_new(data, length, openssl::GetBufferPool())); - if (!crypto_buffer) { - RTC_LOG(LS_ERROR) << "Failed to allocate CRYPTO_BUFFER."; - return ok; - } - const BoringSSLCertificate cert(std::move(crypto_buffer)); -#else - const OpenSSLCertificate cert(X509_STORE_CTX_get_current_cert(store)); -#endif - if (!ssl_cert_verifier_->Verify(cert)) { - RTC_LOG(LS_INFO) << "Failed to verify certificate using custom callback"; - return ok; + // Should only be used for debugging and development. + if (!ok && stream->ignore_bad_cert_) { + RTC_DLOG(LS_WARNING) << "Ignoring cert error while verifying cert chain"; + ok = 1; } - custom_cert_verifier_status_ = true; - RTC_LOG(LS_INFO) << "Validated certificate using custom callback"; - return 1; + return ok; } -#endif // !defined(WEBRTC_USE_CRYPTO_BUFFER_CALLBACK) int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) { OpenSSLAdapter* stream = @@ -941,15 +852,8 @@ int OpenSSLAdapter::NewSSLSessionCallback(SSL* ssl, SSL_SESSION* session) { } SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) { -#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK - // If X509 objects aren't used, we can use these methods to avoid - // linking the sizable crypto/x509 code. - SSL_CTX* ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_with_buffers_method() - : TLS_with_buffers_method()); -#else SSL_CTX* ctx = SSL_CTX_new(mode == SSL_MODE_DTLS ? DTLS_method() : TLS_method()); -#endif if (ctx == nullptr) { unsigned long error = ERR_get_error(); // NOLINT: type used by OpenSSL. RTC_LOG(LS_WARNING) << "SSL_CTX creation failed: " << '"' @@ -973,16 +877,8 @@ SSL_CTX* OpenSSLAdapter::CreateContext(SSLMode mode, bool enable_cache) { SSL_CTX_set_info_callback(ctx, SSLInfoCallback); #endif -#ifdef OPENSSL_IS_BORINGSSL - SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool()); -#endif - -#ifdef WEBRTC_USE_CRYPTO_BUFFER_CALLBACK - SSL_CTX_set_custom_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback); -#else SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, SSLVerifyCallback); SSL_CTX_set_verify_depth(ctx, 4); -#endif // Use defaults, but disable HMAC-SHA256 and HMAC-SHA384 ciphers // (note that SHA256 and SHA384 only select legacy CBC ciphers). // Additionally disable HMAC-SHA1 ciphers in ECDSA. These are the remaining diff --git a/rtc_base/openssl_adapter.h b/rtc_base/openssl_adapter.h index 76b003a7dd..6f1f7dccab 100644 --- a/rtc_base/openssl_adapter.h +++ b/rtc_base/openssl_adapter.h @@ -11,7 +11,6 @@ #ifndef RTC_BASE_OPENSSL_ADAPTER_H_ #define RTC_BASE_OPENSSL_ADAPTER_H_ -#include #include #include @@ -22,11 +21,7 @@ #include "rtc_base/async_socket.h" #include "rtc_base/buffer.h" #include "rtc_base/message_handler.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else #include "rtc_base/openssl_identity.h" -#endif #include "rtc_base/openssl_session_cache.h" #include "rtc_base/socket.h" #include "rtc_base/socket_address.h" @@ -114,16 +109,7 @@ class OpenSSLAdapter final : public SSLAdapter, // In debug builds, logs info about the state of the SSL connection. static void SSLInfoCallback(const SSL* ssl, int where, int ret); #endif - -#if defined(OPENSSL_IS_BORINGSSL) && \ - defined(WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS) - static enum ssl_verify_result_t SSLVerifyCallback(SSL* ssl, - uint8_t* out_alert); - enum ssl_verify_result_t SSLVerifyInternal(SSL* ssl, uint8_t* out_alert); -#else static int SSLVerifyCallback(int ok, X509_STORE_CTX* store); - int SSLVerifyInternal(int ok, SSL* ssl, X509_STORE_CTX* store); -#endif friend class OpenSSLStreamAdapter; // for custom_verify_callback_; // If the SSL_CTX was created with |enable_cache| set to true, this callback @@ -137,12 +123,7 @@ class OpenSSLAdapter final : public SSLAdapter, SSLCertificateVerifier* ssl_cert_verifier_ = nullptr; // The current connection state of the (d)TLS connection. SSLState state_; - -#ifdef OPENSSL_IS_BORINGSSL - std::unique_ptr identity_; -#else std::unique_ptr identity_; -#endif // Indicates whethere this is a client or a server. SSLRole role_; bool ssl_read_needs_write_; diff --git a/rtc_base/openssl_identity.cc b/rtc_base/openssl_identity.cc index 3794d981ce..c94df40bfb 100644 --- a/rtc_base/openssl_identity.cc +++ b/rtc_base/openssl_identity.cc @@ -20,8 +20,10 @@ #endif // WEBRTC_WIN #include +#include #include #include +#include #include #include "absl/memory/memory.h" @@ -33,6 +35,160 @@ namespace rtc { +// We could have exposed a myriad of parameters for the crypto stuff, +// but keeping it simple seems best. + +// Generate a key pair. Caller is responsible for freeing the returned object. +static EVP_PKEY* MakeKey(const KeyParams& key_params) { + RTC_LOG(LS_INFO) << "Making key pair"; + EVP_PKEY* pkey = EVP_PKEY_new(); + if (key_params.type() == KT_RSA) { + int key_length = key_params.rsa_params().mod_size; + BIGNUM* exponent = BN_new(); + RSA* rsa = RSA_new(); + if (!pkey || !exponent || !rsa || + !BN_set_word(exponent, key_params.rsa_params().pub_exp) || + !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) || + !EVP_PKEY_assign_RSA(pkey, rsa)) { + EVP_PKEY_free(pkey); + BN_free(exponent); + RSA_free(rsa); + RTC_LOG(LS_ERROR) << "Failed to make RSA key pair"; + return nullptr; + } + // ownership of rsa struct was assigned, don't free it. + BN_free(exponent); + } else if (key_params.type() == KT_ECDSA) { + if (key_params.ec_curve() == EC_NIST_P256) { + EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + + // Ensure curve name is included when EC key is serialized. + // Without this call, OpenSSL versions before 1.1.0 will create + // certificates that don't work for TLS. + // This is a no-op for BoringSSL and OpenSSL 1.1.0+ + EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); + + if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) || + !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) { + EVP_PKEY_free(pkey); + EC_KEY_free(ec_key); + RTC_LOG(LS_ERROR) << "Failed to make EC key pair"; + return nullptr; + } + // ownership of ec_key struct was assigned, don't free it. + } else { + // Add generation of any other curves here. + EVP_PKEY_free(pkey); + RTC_LOG(LS_ERROR) << "ECDSA key requested for unknown curve"; + return nullptr; + } + } else { + EVP_PKEY_free(pkey); + RTC_LOG(LS_ERROR) << "Key type requested not understood"; + return nullptr; + } + + RTC_LOG(LS_INFO) << "Returning key pair"; + return pkey; +} + +OpenSSLKeyPair* OpenSSLKeyPair::Generate(const KeyParams& key_params) { + EVP_PKEY* pkey = MakeKey(key_params); + if (!pkey) { + openssl::LogSSLErrors("Generating key pair"); + return nullptr; + } + return new OpenSSLKeyPair(pkey); +} + +OpenSSLKeyPair* OpenSSLKeyPair::FromPrivateKeyPEMString( + const std::string& pem_string) { + BIO* bio = BIO_new_mem_buf(const_cast(pem_string.c_str()), -1); + if (!bio) { + RTC_LOG(LS_ERROR) << "Failed to create a new BIO buffer."; + return nullptr; + } + BIO_set_mem_eof_return(bio, 0); + EVP_PKEY* pkey = + PEM_read_bio_PrivateKey(bio, nullptr, nullptr, const_cast("\0")); + BIO_free(bio); // Frees the BIO, but not the pointed-to string. + if (!pkey) { + RTC_LOG(LS_ERROR) << "Failed to create the private key from PEM string."; + return nullptr; + } + if (EVP_PKEY_missing_parameters(pkey) != 0) { + RTC_LOG(LS_ERROR) + << "The resulting key pair is missing public key parameters."; + EVP_PKEY_free(pkey); + return nullptr; + } + return new OpenSSLKeyPair(pkey); +} + +OpenSSLKeyPair::~OpenSSLKeyPair() { + EVP_PKEY_free(pkey_); +} + +OpenSSLKeyPair* OpenSSLKeyPair::GetReference() { + AddReference(); + return new OpenSSLKeyPair(pkey_); +} + +void OpenSSLKeyPair::AddReference() { + EVP_PKEY_up_ref(pkey_); +} + +std::string OpenSSLKeyPair::PrivateKeyToPEMString() const { + BIO* temp_memory_bio = BIO_new(BIO_s_mem()); + if (!temp_memory_bio) { + RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; + RTC_NOTREACHED(); + return ""; + } + if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0, + nullptr, nullptr)) { + RTC_LOG_F(LS_ERROR) << "Failed to write private key"; + BIO_free(temp_memory_bio); + RTC_NOTREACHED(); + return ""; + } + BIO_write(temp_memory_bio, "\0", 1); + char* buffer; + BIO_get_mem_data(temp_memory_bio, &buffer); + std::string priv_key_str = buffer; + BIO_free(temp_memory_bio); + return priv_key_str; +} + +std::string OpenSSLKeyPair::PublicKeyToPEMString() const { + BIO* temp_memory_bio = BIO_new(BIO_s_mem()); + if (!temp_memory_bio) { + RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; + RTC_NOTREACHED(); + return ""; + } + if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) { + RTC_LOG_F(LS_ERROR) << "Failed to write public key"; + BIO_free(temp_memory_bio); + RTC_NOTREACHED(); + return ""; + } + BIO_write(temp_memory_bio, "\0", 1); + char* buffer; + BIO_get_mem_data(temp_memory_bio, &buffer); + std::string pub_key_str = buffer; + BIO_free(temp_memory_bio); + return pub_key_str; +} + +bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const { + return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1; +} + +bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const { + return !(*this == other); +} + OpenSSLIdentity::OpenSSLIdentity( std::unique_ptr key_pair, std::unique_ptr certificate) @@ -55,7 +211,8 @@ OpenSSLIdentity::~OpenSSLIdentity() = default; std::unique_ptr OpenSSLIdentity::CreateInternal( const SSLIdentityParams& params) { - auto key_pair = OpenSSLKeyPair::Generate(params.key_params); + std::unique_ptr key_pair( + OpenSSLKeyPair::Generate(params.key_params)); if (key_pair) { std::unique_ptr certificate( OpenSSLCertificate::Generate(key_pair.get(), params)); @@ -64,7 +221,7 @@ std::unique_ptr OpenSSLIdentity::CreateInternal( new OpenSSLIdentity(std::move(key_pair), std::move(certificate))); } } - RTC_LOG(LS_ERROR) << "Identity generation failed"; + RTC_LOG(LS_INFO) << "Identity generation failed"; return nullptr; } @@ -99,7 +256,8 @@ std::unique_ptr OpenSSLIdentity::CreateFromPEMStrings( return nullptr; } - auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); + std::unique_ptr key_pair( + OpenSSLKeyPair::FromPrivateKeyPEMString(private_key)); if (!key_pair) { RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string."; return nullptr; @@ -140,7 +298,8 @@ std::unique_ptr OpenSSLIdentity::CreateFromPEMChainStrings( return nullptr; } - auto key_pair = OpenSSLKeyPair::FromPrivateKeyPEMString(private_key); + std::unique_ptr key_pair( + OpenSSLKeyPair::FromPrivateKeyPEMString(private_key)); if (!key_pair) { RTC_LOG(LS_ERROR) << "Failed to create key pair from PEM string."; return nullptr; @@ -161,8 +320,8 @@ const SSLCertChain& OpenSSLIdentity::cert_chain() const { std::unique_ptr OpenSSLIdentity::CloneInternal() const { // We cannot use std::make_unique here because the referenced OpenSSLIdentity // constructor is private. - return absl::WrapUnique( - new OpenSSLIdentity(key_pair_->Clone(), cert_chain_->Clone())); + return absl::WrapUnique(new OpenSSLIdentity( + absl::WrapUnique(key_pair_->GetReference()), cert_chain_->Clone())); } bool OpenSSLIdentity::ConfigureIdentity(SSL_CTX* ctx) { diff --git a/rtc_base/openssl_identity.h b/rtc_base/openssl_identity.h index 00d6c74922..a2ac87cf45 100644 --- a/rtc_base/openssl_identity.h +++ b/rtc_base/openssl_identity.h @@ -17,14 +17,45 @@ #include #include +#include "rtc_base/checks.h" #include "rtc_base/constructor_magic.h" #include "rtc_base/openssl_certificate.h" -#include "rtc_base/openssl_key_pair.h" #include "rtc_base/ssl_certificate.h" #include "rtc_base/ssl_identity.h" namespace rtc { +// OpenSSLKeyPair encapsulates an OpenSSL EVP_PKEY* keypair object, +// which is reference counted inside the OpenSSL library. +class OpenSSLKeyPair final { + public: + explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) { + RTC_DCHECK(pkey_ != nullptr); + } + + static OpenSSLKeyPair* Generate(const KeyParams& key_params); + // Constructs a key pair from the private key PEM string. This must not result + // in missing public key parameters. Returns null on error. + static OpenSSLKeyPair* FromPrivateKeyPEMString(const std::string& pem_string); + + virtual ~OpenSSLKeyPair(); + + virtual OpenSSLKeyPair* GetReference(); + + EVP_PKEY* pkey() const { return pkey_; } + std::string PrivateKeyToPEMString() const; + std::string PublicKeyToPEMString() const; + bool operator==(const OpenSSLKeyPair& other) const; + bool operator!=(const OpenSSLKeyPair& other) const; + + private: + void AddReference(); + + EVP_PKEY* pkey_; + + RTC_DISALLOW_COPY_AND_ASSIGN(OpenSSLKeyPair); +}; + // Holds a keypair and certificate together, and a method to generate // them consistently. class OpenSSLIdentity final : public SSLIdentity { diff --git a/rtc_base/openssl_key_pair.cc b/rtc_base/openssl_key_pair.cc deleted file mode 100644 index 911a751cbe..0000000000 --- a/rtc_base/openssl_key_pair.cc +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2004 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#include "rtc_base/openssl_key_pair.h" - -#include -#include - -#if defined(WEBRTC_WIN) -// Must be included first before openssl headers. -#include "rtc_base/win32.h" // NOLINT -#endif // WEBRTC_WIN - -#include -#include -#include -#include - -#include "rtc_base/checks.h" -#include "rtc_base/logging.h" -#include "rtc_base/openssl.h" -#include "rtc_base/openssl_utility.h" - -namespace rtc { - -// We could have exposed a myriad of parameters for the crypto stuff, -// but keeping it simple seems best. - -// Generate a key pair. Caller is responsible for freeing the returned object. -static EVP_PKEY* MakeKey(const KeyParams& key_params) { - RTC_LOG(LS_INFO) << "Making key pair"; - EVP_PKEY* pkey = EVP_PKEY_new(); - if (key_params.type() == KT_RSA) { - int key_length = key_params.rsa_params().mod_size; - BIGNUM* exponent = BN_new(); - RSA* rsa = RSA_new(); - if (!pkey || !exponent || !rsa || - !BN_set_word(exponent, key_params.rsa_params().pub_exp) || - !RSA_generate_key_ex(rsa, key_length, exponent, nullptr) || - !EVP_PKEY_assign_RSA(pkey, rsa)) { - EVP_PKEY_free(pkey); - BN_free(exponent); - RSA_free(rsa); - RTC_LOG(LS_ERROR) << "Failed to make RSA key pair"; - return nullptr; - } - // ownership of rsa struct was assigned, don't free it. - BN_free(exponent); - } else if (key_params.type() == KT_ECDSA) { - if (key_params.ec_curve() == EC_NIST_P256) { - EC_KEY* ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); - if (!ec_key) { - EVP_PKEY_free(pkey); - RTC_LOG(LS_ERROR) << "Failed to allocate EC key"; - return nullptr; - } - - // Ensure curve name is included when EC key is serialized. - // Without this call, OpenSSL versions before 1.1.0 will create - // certificates that don't work for TLS. - // This is a no-op for BoringSSL and OpenSSL 1.1.0+ - EC_KEY_set_asn1_flag(ec_key, OPENSSL_EC_NAMED_CURVE); - - if (!pkey || !ec_key || !EC_KEY_generate_key(ec_key) || - !EVP_PKEY_assign_EC_KEY(pkey, ec_key)) { - EVP_PKEY_free(pkey); - EC_KEY_free(ec_key); - RTC_LOG(LS_ERROR) << "Failed to make EC key pair"; - return nullptr; - } - // ownership of ec_key struct was assigned, don't free it. - } else { - // Add generation of any other curves here. - EVP_PKEY_free(pkey); - RTC_LOG(LS_ERROR) << "ECDSA key requested for unknown curve"; - return nullptr; - } - } else { - EVP_PKEY_free(pkey); - RTC_LOG(LS_ERROR) << "Key type requested not understood"; - return nullptr; - } - - RTC_LOG(LS_INFO) << "Returning key pair"; - return pkey; -} - -std::unique_ptr OpenSSLKeyPair::Generate( - const KeyParams& key_params) { - EVP_PKEY* pkey = MakeKey(key_params); - if (!pkey) { - openssl::LogSSLErrors("Generating key pair"); - return nullptr; - } - return std::make_unique(pkey); -} - -std::unique_ptr OpenSSLKeyPair::FromPrivateKeyPEMString( - const std::string& pem_string) { - BIO* bio = - BIO_new_mem_buf(const_cast(pem_string.data()), pem_string.size()); - if (!bio) { - RTC_LOG(LS_ERROR) << "Failed to create a new BIO buffer."; - return nullptr; - } - BIO_set_mem_eof_return(bio, 0); - EVP_PKEY* pkey = PEM_read_bio_PrivateKey(bio, nullptr, nullptr, nullptr); - BIO_free(bio); // Frees the BIO, but not the pointed-to string. - if (!pkey) { - RTC_LOG(LS_ERROR) << "Failed to create the private key from PEM string."; - return nullptr; - } - if (EVP_PKEY_missing_parameters(pkey) != 0) { - RTC_LOG(LS_ERROR) - << "The resulting key pair is missing public key parameters."; - EVP_PKEY_free(pkey); - return nullptr; - } - return std::make_unique(pkey); -} - -OpenSSLKeyPair::~OpenSSLKeyPair() { - EVP_PKEY_free(pkey_); -} - -std::unique_ptr OpenSSLKeyPair::Clone() { - AddReference(); - return std::make_unique(pkey_); -} - -void OpenSSLKeyPair::AddReference() { - EVP_PKEY_up_ref(pkey_); -} - -std::string OpenSSLKeyPair::PrivateKeyToPEMString() const { - BIO* temp_memory_bio = BIO_new(BIO_s_mem()); - if (!temp_memory_bio) { - RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; - RTC_NOTREACHED(); - return ""; - } - if (!PEM_write_bio_PrivateKey(temp_memory_bio, pkey_, nullptr, nullptr, 0, - nullptr, nullptr)) { - RTC_LOG_F(LS_ERROR) << "Failed to write private key"; - BIO_free(temp_memory_bio); - RTC_NOTREACHED(); - return ""; - } - char* buffer; - size_t len = BIO_get_mem_data(temp_memory_bio, &buffer); - std::string priv_key_str(buffer, len); - BIO_free(temp_memory_bio); - return priv_key_str; -} - -std::string OpenSSLKeyPair::PublicKeyToPEMString() const { - BIO* temp_memory_bio = BIO_new(BIO_s_mem()); - if (!temp_memory_bio) { - RTC_LOG_F(LS_ERROR) << "Failed to allocate temporary memory bio"; - RTC_NOTREACHED(); - return ""; - } - if (!PEM_write_bio_PUBKEY(temp_memory_bio, pkey_)) { - RTC_LOG_F(LS_ERROR) << "Failed to write public key"; - BIO_free(temp_memory_bio); - RTC_NOTREACHED(); - return ""; - } - BIO_write(temp_memory_bio, "\0", 1); - char* buffer; - BIO_get_mem_data(temp_memory_bio, &buffer); - std::string pub_key_str = buffer; - BIO_free(temp_memory_bio); - return pub_key_str; -} - -bool OpenSSLKeyPair::operator==(const OpenSSLKeyPair& other) const { - return EVP_PKEY_cmp(this->pkey_, other.pkey_) == 1; -} - -bool OpenSSLKeyPair::operator!=(const OpenSSLKeyPair& other) const { - return !(*this == other); -} - -} // namespace rtc diff --git a/rtc_base/openssl_key_pair.h b/rtc_base/openssl_key_pair.h deleted file mode 100644 index a84c43b6bd..0000000000 --- a/rtc_base/openssl_key_pair.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 The WebRTC Project Authors. All rights reserved. - * - * Use of this source code is governed by a BSD-style license - * that can be found in the LICENSE file in the root of the source - * tree. An additional intellectual property rights grant can be found - * in the file PATENTS. All contributing project authors may - * be found in the AUTHORS file in the root of the source tree. - */ - -#ifndef RTC_BASE_OPENSSL_KEY_PAIR_H_ -#define RTC_BASE_OPENSSL_KEY_PAIR_H_ - -#include - -#include -#include - -#include "rtc_base/checks.h" -#include "rtc_base/constructor_magic.h" -#include "rtc_base/ssl_identity.h" - -namespace rtc { - -// OpenSSLKeyPair encapsulates an OpenSSL EVP_PKEY* keypair object, -// which is reference counted inside the OpenSSL library. -class OpenSSLKeyPair final { - public: - // Takes ownership of the key. - explicit OpenSSLKeyPair(EVP_PKEY* pkey) : pkey_(pkey) { - RTC_DCHECK(pkey_ != nullptr); - } - - static std::unique_ptr Generate(const KeyParams& key_params); - // Constructs a key pair from the private key PEM string. This must not result - // in missing public key parameters. Returns null on error. - static std::unique_ptr FromPrivateKeyPEMString( - const std::string& pem_string); - - ~OpenSSLKeyPair(); - - std::unique_ptr Clone(); - - EVP_PKEY* pkey() const { return pkey_; } - std::string PrivateKeyToPEMString() const; - std::string PublicKeyToPEMString() const; - bool operator==(const OpenSSLKeyPair& other) const; - bool operator!=(const OpenSSLKeyPair& other) const; - - private: - void AddReference(); - - EVP_PKEY* pkey_; - - RTC_DISALLOW_COPY_AND_ASSIGN(OpenSSLKeyPair); -}; - -} // namespace rtc - -#endif // RTC_BASE_OPENSSL_KEY_PAIR_H_ diff --git a/rtc_base/openssl_session_cache_unittest.cc b/rtc_base/openssl_session_cache_unittest.cc index 0441d5c012..1d3084bbc5 100644 --- a/rtc_base/openssl_session_cache_unittest.cc +++ b/rtc_base/openssl_session_cache_unittest.cc @@ -19,28 +19,10 @@ #include "rtc_base/gunit.h" #include "rtc_base/openssl.h" -namespace { -// Use methods that avoid X509 objects if possible. -SSL_CTX* NewDtlsContext() { -#ifdef OPENSSL_IS_BORINGSSL - return SSL_CTX_new(DTLS_with_buffers_method()); -#else - return SSL_CTX_new(DTLS_method()); -#endif -} -SSL_CTX* NewTlsContext() { -#ifdef OPENSSL_IS_BORINGSSL - return SSL_CTX_new(TLS_with_buffers_method()); -#else - return SSL_CTX_new(TLS_method()); -#endif -} -} // namespace - namespace rtc { TEST(OpenSSLSessionCache, DTLSModeSetCorrectly) { - SSL_CTX* ssl_ctx = NewDtlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx); EXPECT_EQ(session_cache.GetSSLMode(), SSL_MODE_DTLS); @@ -49,7 +31,7 @@ TEST(OpenSSLSessionCache, DTLSModeSetCorrectly) { } TEST(OpenSSLSessionCache, TLSModeSetCorrectly) { - SSL_CTX* ssl_ctx = NewTlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(TLSv1_2_client_method()); OpenSSLSessionCache session_cache(SSL_MODE_TLS, ssl_ctx); EXPECT_EQ(session_cache.GetSSLMode(), SSL_MODE_TLS); @@ -58,7 +40,7 @@ TEST(OpenSSLSessionCache, TLSModeSetCorrectly) { } TEST(OpenSSLSessionCache, SSLContextSetCorrectly) { - SSL_CTX* ssl_ctx = NewDtlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx); EXPECT_EQ(session_cache.GetSSLContext(), ssl_ctx); @@ -67,7 +49,7 @@ TEST(OpenSSLSessionCache, SSLContextSetCorrectly) { } TEST(OpenSSLSessionCache, InvalidLookupReturnsNullptr) { - SSL_CTX* ssl_ctx = NewDtlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx); EXPECT_EQ(session_cache.LookupSession("Invalid"), nullptr); @@ -78,7 +60,7 @@ TEST(OpenSSLSessionCache, InvalidLookupReturnsNullptr) { } TEST(OpenSSLSessionCache, SimpleValidSessionLookup) { - SSL_CTX* ssl_ctx = NewDtlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); SSL_SESSION* ssl_session = SSL_SESSION_new(ssl_ctx); OpenSSLSessionCache session_cache(SSL_MODE_DTLS, ssl_ctx); @@ -89,7 +71,7 @@ TEST(OpenSSLSessionCache, SimpleValidSessionLookup) { } TEST(OpenSSLSessionCache, AddToExistingReplacesPrevious) { - SSL_CTX* ssl_ctx = NewDtlsContext(); + SSL_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); SSL_SESSION* ssl_session_1 = SSL_SESSION_new(ssl_ctx); SSL_SESSION* ssl_session_2 = SSL_SESSION_new(ssl_ctx); diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc index 63b8069e0e..f59b4edf18 100644 --- a/rtc_base/openssl_stream_adapter.cc +++ b/rtc_base/openssl_stream_adapter.cc @@ -32,12 +32,7 @@ #include "rtc_base/openssl.h" #include "rtc_base/openssl_adapter.h" #include "rtc_base/openssl_digest.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else #include "rtc_base/openssl_identity.h" -#endif -#include "rtc_base/openssl_utility.h" #include "rtc_base/ssl_certificate.h" #include "rtc_base/stream.h" #include "rtc_base/task_utils/to_queued_task.h" @@ -309,14 +304,10 @@ OpenSSLStreamAdapter::~OpenSSLStreamAdapter() { void OpenSSLStreamAdapter::SetIdentity(std::unique_ptr identity) { RTC_DCHECK(!identity_); -#ifdef OPENSSL_IS_BORINGSSL - identity_.reset(static_cast(identity.release())); -#else identity_.reset(static_cast(identity.release())); -#endif } -SSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const { +OpenSSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const { return identity_.get(); } @@ -1003,16 +994,8 @@ void OpenSSLStreamAdapter::Cleanup(uint8_t alert) { } SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { -#ifdef OPENSSL_IS_BORINGSSL - // If X509 objects aren't used, we can use these methods to avoid - // linking the sizable crypto/x509 code, using CRYPTO_BUFFER instead. - SSL_CTX* ctx = - SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_with_buffers_method() - : TLS_with_buffers_method()); -#else SSL_CTX* ctx = SSL_CTX_new(ssl_mode_ == SSL_MODE_DTLS ? DTLS_method() : TLS_method()); -#endif if (ctx == nullptr) { return nullptr; } @@ -1050,7 +1033,6 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { if (g_use_time_callback_for_testing) { SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting); } - SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool()); #endif if (identity_ && !identity_->ConfigureIdentity(ctx)) { @@ -1071,16 +1053,11 @@ SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { } // Configure a custom certificate verification callback to check the peer - // certificate digest. -#ifdef OPENSSL_IS_BORINGSSL - // Use CRYPTO_BUFFER version of the callback if building with BoringSSL. - SSL_CTX_set_custom_verify(ctx, mode, SSLVerifyCallback); -#else - // Note the second argument to SSL_CTX_set_verify is to override individual - // errors in the default verification logic, which is not what we want here. + // certificate digest. Note the second argument to SSL_CTX_set_verify is to + // override individual errors in the default verification logic, which is not + // what we want here. SSL_CTX_set_verify(ctx, mode, nullptr); SSL_CTX_set_cert_verify_callback(ctx, SSLVerifyCallback, nullptr); -#endif // Select list of available ciphers. Note that !SHA256 and !SHA384 only // remove HMAC-SHA256 and HMAC-SHA384 cipher suites, not GCM cipher suites @@ -1105,12 +1082,14 @@ bool OpenSSLStreamAdapter::VerifyPeerCertificate() { RTC_LOG(LS_WARNING) << "Missing digest or peer certificate."; return false; } + const OpenSSLCertificate* leaf_cert = + static_cast(&peer_cert_chain_->Get(0)); unsigned char digest[EVP_MAX_MD_SIZE]; size_t digest_length; - if (!peer_cert_chain_->Get(0).ComputeDigest( - peer_certificate_digest_algorithm_, digest, sizeof(digest), - &digest_length)) { + if (!OpenSSLCertificate::ComputeDigest( + leaf_cert->x509(), peer_certificate_digest_algorithm_, digest, + sizeof(digest), &digest_length)) { RTC_LOG(LS_WARNING) << "Failed to compute peer cert digest."; return false; } @@ -1134,36 +1113,6 @@ std::unique_ptr OpenSSLStreamAdapter::GetPeerSSLCertChain() return peer_cert_chain_ ? peer_cert_chain_->Clone() : nullptr; } -#ifdef OPENSSL_IS_BORINGSSL -enum ssl_verify_result_t OpenSSLStreamAdapter::SSLVerifyCallback( - SSL* ssl, - uint8_t* out_alert) { - // Get our OpenSSLStreamAdapter from the context. - OpenSSLStreamAdapter* stream = - reinterpret_cast(SSL_get_app_data(ssl)); - const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl); - // Creates certificate chain. - std::vector> cert_chain; - for (CRYPTO_BUFFER* cert : chain) { - cert_chain.emplace_back(new BoringSSLCertificate(bssl::UpRef(cert))); - } - stream->peer_cert_chain_.reset(new SSLCertChain(std::move(cert_chain))); - - // If the peer certificate digest isn't known yet, we'll wait to verify - // until it's known, and for now just return a success status. - if (stream->peer_certificate_digest_algorithm_.empty()) { - RTC_LOG(LS_INFO) << "Waiting to verify certificate until digest is known."; - // TODO(deadbeef): Use ssl_verify_retry? - return ssl_verify_ok; - } - - if (!stream->VerifyPeerCertificate()) { - return ssl_verify_invalid; - } - - return ssl_verify_ok; -} -#else // OPENSSL_IS_BORINGSSL int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) { // Get our SSL structure and OpenSSLStreamAdapter from the store. SSL* ssl = reinterpret_cast( @@ -1171,10 +1120,20 @@ int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) { OpenSSLStreamAdapter* stream = reinterpret_cast(SSL_get_app_data(ssl)); +#if defined(OPENSSL_IS_BORINGSSL) + STACK_OF(X509)* chain = SSL_get_peer_full_cert_chain(ssl); + // Creates certificate chain. + std::vector> cert_chain; + for (X509* cert : chain) { + cert_chain.emplace_back(new OpenSSLCertificate(cert)); + } + stream->peer_cert_chain_.reset(new SSLCertChain(std::move(cert_chain))); +#else // Record the peer's certificate. X509* cert = X509_STORE_CTX_get0_cert(store); stream->peer_cert_chain_.reset( new SSLCertChain(std::make_unique(cert))); +#endif // If the peer certificate digest isn't known yet, we'll wait to verify // until it's known, and for now just return a success status. @@ -1190,7 +1149,6 @@ int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) { return 1; } -#endif // !OPENSSL_IS_BORINGSSL bool OpenSSLStreamAdapter::IsBoringSsl() { #ifdef OPENSSL_IS_BORINGSSL diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h index a09737c024..fbfccd6844 100644 --- a/rtc_base/openssl_stream_adapter.h +++ b/rtc_base/openssl_stream_adapter.h @@ -21,11 +21,7 @@ #include "absl/types/optional.h" #include "rtc_base/buffer.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else #include "rtc_base/openssl_identity.h" -#endif #include "rtc_base/ssl_identity.h" #include "rtc_base/ssl_stream_adapter.h" #include "rtc_base/stream.h" @@ -75,7 +71,7 @@ class OpenSSLStreamAdapter final : public SSLStreamAdapter { ~OpenSSLStreamAdapter() override; void SetIdentity(std::unique_ptr identity) override; - SSLIdentity* GetIdentityForTesting() const override; + OpenSSLIdentity* GetIdentityForTesting() const override; // Default argument is for compatibility void SetServerRole(SSLRole role = SSL_SERVER) override; @@ -183,16 +179,9 @@ class OpenSSLStreamAdapter final : public SSLStreamAdapter { SSL_CTX* SetupSSLContext(); // Verify the peer certificate matches the signaled digest. bool VerifyPeerCertificate(); - -#ifdef OPENSSL_IS_BORINGSSL - // SSL certificate verification callback. See SSL_CTX_set_custom_verify. - static enum ssl_verify_result_t SSLVerifyCallback(SSL* ssl, - uint8_t* out_alert); -#else // SSL certificate verification callback. See // SSL_CTX_set_cert_verify_callback. static int SSLVerifyCallback(X509_STORE_CTX* store, void* arg); -#endif bool WaitingToVerifyPeerCertificate() const { return GetClientAuthEnabled() && !peer_certificate_verified_; @@ -219,11 +208,7 @@ class OpenSSLStreamAdapter final : public SSLStreamAdapter { SSL_CTX* ssl_ctx_; // Our key and certificate. -#ifdef OPENSSL_IS_BORINGSSL - std::unique_ptr identity_; -#else std::unique_ptr identity_; -#endif // The certificate chain that the peer presented. Initially null, until the // connection is established. std::unique_ptr peer_cert_chain_; diff --git a/rtc_base/openssl_utility.cc b/rtc_base/openssl_utility.cc index f91e8d9203..1984eb0706 100644 --- a/rtc_base/openssl_utility.cc +++ b/rtc_base/openssl_utility.cc @@ -14,9 +14,6 @@ #include "rtc_base/win32.h" // NOLINT #endif // WEBRTC_WIN -#ifdef OPENSSL_IS_BORINGSSL -#include -#endif #include #include #include @@ -36,10 +33,6 @@ namespace openssl { // Holds various helper methods. namespace { - -// TODO(crbug.com/webrtc/11710): When OS certificate verification is available, -// and we don't need VerifyPeerCertMatchesHost, don't compile this in order to -// avoid a dependency on OpenSSL X509 objects (see crbug.com/webrtc/11410). void LogCertificates(SSL* ssl, X509* certificate) { // Logging certificates is extremely verbose. So it is disabled by default. #ifdef LOG_CERTIFICATES @@ -72,118 +65,6 @@ void LogCertificates(SSL* ssl, X509* certificate) { } } // namespace -#ifdef OPENSSL_IS_BORINGSSL -bool ParseCertificate(CRYPTO_BUFFER* cert_buffer, - CBS* signature_algorithm_oid, - int64_t* expiration_time) { - CBS cbs; - CRYPTO_BUFFER_init_CBS(cert_buffer, &cbs); - - // Certificate ::= SEQUENCE { - CBS certificate; - if (!CBS_get_asn1(&cbs, &certificate, CBS_ASN1_SEQUENCE)) { - return false; - } - // tbsCertificate TBSCertificate, - CBS tbs_certificate; - if (!CBS_get_asn1(&certificate, &tbs_certificate, CBS_ASN1_SEQUENCE)) { - return false; - } - // signatureAlgorithm AlgorithmIdentifier, - CBS signature_algorithm; - if (!CBS_get_asn1(&certificate, &signature_algorithm, CBS_ASN1_SEQUENCE)) { - return false; - } - if (!CBS_get_asn1(&signature_algorithm, signature_algorithm_oid, - CBS_ASN1_OBJECT)) { - return false; - } - // signatureValue BIT STRING } - if (!CBS_get_asn1(&certificate, nullptr, CBS_ASN1_BITSTRING)) { - return false; - } - if (CBS_len(&certificate)) { - return false; - } - - // Now parse the inner TBSCertificate. - // version [0] EXPLICIT Version DEFAULT v1, - if (!CBS_get_optional_asn1( - &tbs_certificate, nullptr, nullptr, - CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)) { - return false; - } - // serialNumber CertificateSerialNumber, - if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_INTEGER)) { - return false; - } - // signature AlgorithmIdentifier - if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) { - return false; - } - // issuer Name, - if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) { - return false; - } - // validity Validity, - CBS validity; - if (!CBS_get_asn1(&tbs_certificate, &validity, CBS_ASN1_SEQUENCE)) { - return false; - } - // Skip over notBefore. - if (!CBS_get_any_asn1_element(&validity, nullptr, nullptr, nullptr)) { - return false; - } - // Parse notAfter. - CBS not_after; - unsigned not_after_tag; - if (!CBS_get_any_asn1(&validity, ¬_after, ¬_after_tag)) { - return false; - } - bool long_format; - if (not_after_tag == CBS_ASN1_UTCTIME) { - long_format = false; - } else if (not_after_tag == CBS_ASN1_GENERALIZEDTIME) { - long_format = true; - } else { - return false; - } - if (expiration_time) { - *expiration_time = - ASN1TimeToSec(CBS_data(¬_after), CBS_len(¬_after), long_format); - } - // subject Name, - if (!CBS_get_asn1_element(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) { - return false; - } - // subjectPublicKeyInfo SubjectPublicKeyInfo, - if (!CBS_get_asn1(&tbs_certificate, nullptr, CBS_ASN1_SEQUENCE)) { - return false; - } - // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL - if (!CBS_get_optional_asn1(&tbs_certificate, nullptr, nullptr, - 0x01 | CBS_ASN1_CONTEXT_SPECIFIC)) { - return false; - } - // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL - if (!CBS_get_optional_asn1(&tbs_certificate, nullptr, nullptr, - 0x02 | CBS_ASN1_CONTEXT_SPECIFIC)) { - return false; - } - // extensions [3] EXPLICIT Extensions OPTIONAL - if (!CBS_get_optional_asn1( - &tbs_certificate, nullptr, nullptr, - 0x03 | CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC)) { - return false; - } - if (CBS_len(&tbs_certificate)) { - return false; - } - - return true; -} -#endif // OPENSSL_IS_BORINGSSL - bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host) { if (host.empty()) { RTC_DLOG(LS_ERROR) << "Hostname is empty. Cannot verify peer certificate."; @@ -195,28 +76,9 @@ bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host) { return false; } -#ifdef OPENSSL_IS_BORINGSSL - // We can't grab a X509 object directly, as the SSL context may have been - // initialized with TLS_with_buffers_method. - const STACK_OF(CRYPTO_BUFFER)* chain = SSL_get0_peer_certificates(ssl); - if (chain == nullptr || sk_CRYPTO_BUFFER_num(chain) == 0) { - RTC_LOG(LS_ERROR) - << "SSL_get0_peer_certificates failed. This should never happen."; - return false; - } - CRYPTO_BUFFER* leaf = sk_CRYPTO_BUFFER_value(chain, 0); - bssl::UniquePtr x509(X509_parse_from_buffer(leaf)); - if (!x509) { - RTC_LOG(LS_ERROR) << "Failed to parse certificate to X509 object."; - return false; - } - LogCertificates(ssl, x509.get()); - return X509_check_host(x509.get(), host.c_str(), host.size(), 0, nullptr) == - 1; -#else // OPENSSL_IS_BORINGSSL X509* certificate = SSL_get_peer_certificate(ssl); if (certificate == nullptr) { - RTC_LOG(LS_ERROR) + RTC_DLOG(LS_ERROR) << "SSL_get_peer_certificate failed. This should never happen."; return false; } @@ -227,7 +89,6 @@ bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host) { X509_check_host(certificate, host.c_str(), host.size(), 0, nullptr) == 1; X509_free(certificate); return is_valid_cert_name; -#endif // !defined(OPENSSL_IS_BORINGSSL) } void LogSSLErrors(const std::string& prefix) { @@ -262,12 +123,5 @@ bool LoadBuiltinSSLRootCertificates(SSL_CTX* ctx) { } #endif // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS -#ifdef OPENSSL_IS_BORINGSSL -CRYPTO_BUFFER_POOL* GetBufferPool() { - static CRYPTO_BUFFER_POOL* instance = CRYPTO_BUFFER_POOL_new(); - return instance; -} -#endif - } // namespace openssl } // namespace rtc diff --git a/rtc_base/openssl_utility.h b/rtc_base/openssl_utility.h index ee29ccd602..022294d4bb 100644 --- a/rtc_base/openssl_utility.h +++ b/rtc_base/openssl_utility.h @@ -20,21 +20,8 @@ namespace rtc { // to OpenSSL that are commonly used and don't require global state should be // placed here. namespace openssl { - -#ifdef OPENSSL_IS_BORINGSSL -// Does minimal parsing of a certificate (only verifying the presence of major -// fields), primarily for the purpose of extracting the relevant out -// parameters. Any that the caller is uninterested in can be null. -bool ParseCertificate(CRYPTO_BUFFER* cert_buffer, - CBS* signature_algorithm_oid, - int64_t* expiration_time); -#endif - // Verifies that the hostname provided matches that in the peer certificate // attached to this SSL state. -// TODO(crbug.com/webrtc/11710): When OS certificate verification is available, -// skip compiling this as it adds a dependency on OpenSSL X509 objects, which we -// are trying to avoid in favor of CRYPTO_BUFFERs (see crbug.com/webrtc/11410). bool VerifyPeerCertMatchesHost(SSL* ssl, const std::string& host); // Logs all the errors in the OpenSSL errror queue from the current thread. A @@ -48,10 +35,6 @@ void LogSSLErrors(const std::string& prefix); bool LoadBuiltinSSLRootCertificates(SSL_CTX* ssl_ctx); #endif // WEBRTC_EXCLUDE_BUILT_IN_SSL_ROOT_CERTS -#ifdef OPENSSL_IS_BORINGSSL -CRYPTO_BUFFER_POOL* GetBufferPool(); -#endif - } // namespace openssl } // namespace rtc diff --git a/rtc_base/openssl_utility_unittest.cc b/rtc_base/openssl_utility_unittest.cc index d090524cde..9c9b9717ab 100644 --- a/rtc_base/openssl_utility_unittest.cc +++ b/rtc_base/openssl_utility_unittest.cc @@ -24,12 +24,8 @@ #include #include #include -#ifdef OPENSSL_IS_BORINGSSL -#include -#else #include #include -#endif #include "rtc_base/arraysize.h" #include "rtc_base/checks.h" @@ -173,17 +169,14 @@ 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(cert_len)); // NOLINT + RTC_CHECK(x509); const unsigned char* key_ptr = kFakeSSLPrivateKey; EVP_PKEY* key = d2i_PrivateKey( @@ -191,33 +184,14 @@ SSL* CreateSSLWithPeerCertificate(const unsigned char* cert, size_t cert_len) { checked_cast(arraysize(kFakeSSLPrivateKey))); // NOLINT RTC_CHECK(key); -#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_CTX* ctx = SSL_CTX_new(SSLv23_method()); 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 cert_buffer(CRYPTO_BUFFER_new( - static_cast(cert), cert_len, openssl::GetBufferPool())); - RTC_CHECK(cert_buffer); - std::vector 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(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; @@ -247,19 +221,13 @@ 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) { -#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_CTX* ssl_ctx = SSL_CTX_new(DTLSv1_2_client_method()); SSL* ssl = SSL_new(ssl_ctx); EXPECT_FALSE(openssl::VerifyPeerCertMatchesHost(ssl, "webrtc.org")); diff --git a/rtc_base/rtc_certificate_generator.cc b/rtc_base/rtc_certificate_generator.cc index 5e1fdcac30..d95b645396 100644 --- a/rtc_base/rtc_certificate_generator.cc +++ b/rtc_base/rtc_certificate_generator.cc @@ -51,7 +51,7 @@ scoped_refptr RTCCertificateGenerator::GenerateCertificate( expires_s = std::min(expires_s, kYearInSeconds); // TODO(torbjorng): Stop using |time_t|, its type is unspecified. It it safe // to assume it can hold up to a year's worth of seconds (and more), but - // |SSLIdentity::Create| should stop relying on |time_t|. + // |SSLIdentity::Generate| should stop relying on |time_t|. // See bugs.webrtc.org/5720. time_t cert_lifetime_s = static_cast(expires_s); identity = SSLIdentity::Create(kIdentityName, key_params, cert_lifetime_s); diff --git a/rtc_base/ssl_certificate.cc b/rtc_base/ssl_certificate.cc index 3f7013ee11..db9097b9a3 100644 --- a/rtc_base/ssl_certificate.cc +++ b/rtc_base/ssl_certificate.cc @@ -16,12 +16,7 @@ #include "absl/algorithm/container.h" #include "rtc_base/checks.h" -#include "rtc_base/openssl.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else -#include "rtc_base/openssl_identity.h" -#endif +#include "rtc_base/openssl_certificate.h" #include "rtc_base/ssl_fingerprint.h" #include "rtc_base/third_party/base64/base64.h" @@ -122,11 +117,7 @@ std::unique_ptr SSLCertChain::GetStats() const { // static std::unique_ptr SSLCertificate::FromPEMString( const std::string& pem_string) { -#ifdef OPENSSL_IS_BORINGSSL - return BoringSSLCertificate::FromPEMString(pem_string); -#else return OpenSSLCertificate::FromPEMString(pem_string); -#endif } } // namespace rtc diff --git a/rtc_base/ssl_identity.cc b/rtc_base/ssl_identity.cc index 8d93ecfe23..09d25d228e 100644 --- a/rtc_base/ssl_identity.cc +++ b/rtc_base/ssl_identity.cc @@ -11,16 +11,12 @@ // Handling of certificates and keypairs for SSLStreamAdapter's peer mode. #include "rtc_base/ssl_identity.h" -#include #include #include +#include #include "rtc_base/checks.h" -#ifdef OPENSSL_IS_BORINGSSL -#include "rtc_base/boringssl_identity.h" -#else #include "rtc_base/openssl_identity.h" -#endif #include "rtc_base/ssl_certificate.h" #include "rtc_base/strings/string_builder.h" #include "rtc_base/third_party/base64/base64.h" @@ -217,36 +213,28 @@ std::string SSLIdentity::DerToPem(const std::string& pem_type, std::unique_ptr SSLIdentity::Create(const std::string& common_name, const KeyParams& key_param, time_t certificate_lifetime) { -#ifdef OPENSSL_IS_BORINGSSL - return BoringSSLIdentity::CreateWithExpiration(common_name, key_param, - certificate_lifetime); -#else return OpenSSLIdentity::CreateWithExpiration(common_name, key_param, certificate_lifetime); -#endif } // static std::unique_ptr SSLIdentity::Create(const std::string& common_name, const KeyParams& key_param) { - return Create(common_name, key_param, kDefaultCertificateLifetimeInSeconds); + return OpenSSLIdentity::CreateWithExpiration( + common_name, key_param, kDefaultCertificateLifetimeInSeconds); } // static std::unique_ptr SSLIdentity::Create(const std::string& common_name, KeyType key_type) { - return Create(common_name, KeyParams(key_type), - kDefaultCertificateLifetimeInSeconds); + return OpenSSLIdentity::CreateWithExpiration( + common_name, KeyParams(key_type), kDefaultCertificateLifetimeInSeconds); } // static std::unique_ptr SSLIdentity::CreateForTest( const SSLIdentityParams& params) { -#ifdef OPENSSL_IS_BORINGSSL - return BoringSSLIdentity::CreateForTest(params); -#else return OpenSSLIdentity::CreateForTest(params); -#endif } // Construct an identity from a private key and a certificate. @@ -254,11 +242,7 @@ std::unique_ptr SSLIdentity::CreateForTest( std::unique_ptr SSLIdentity::CreateFromPEMStrings( const std::string& private_key, const std::string& certificate) { -#ifdef OPENSSL_IS_BORINGSSL - return BoringSSLIdentity::CreateFromPEMStrings(private_key, certificate); -#else return OpenSSLIdentity::CreateFromPEMStrings(private_key, certificate); -#endif } // Construct an identity from a private key and a certificate chain. @@ -266,23 +250,13 @@ std::unique_ptr SSLIdentity::CreateFromPEMStrings( std::unique_ptr SSLIdentity::CreateFromPEMChainStrings( const std::string& private_key, const std::string& certificate_chain) { -#ifdef OPENSSL_IS_BORINGSSL - return BoringSSLIdentity::CreateFromPEMChainStrings(private_key, - certificate_chain); -#else return OpenSSLIdentity::CreateFromPEMChainStrings(private_key, certificate_chain); -#endif } bool operator==(const SSLIdentity& a, const SSLIdentity& b) { -#ifdef OPENSSL_IS_BORINGSSL - return static_cast(a) == - static_cast(b); -#else return static_cast(a) == static_cast(b); -#endif } bool operator!=(const SSLIdentity& a, const SSLIdentity& b) { return !(a == b); diff --git a/rtc_base/ssl_identity_unittest.cc b/rtc_base/ssl_identity_unittest.cc index a907bfc3ed..0d9d0fd859 100644 --- a/rtc_base/ssl_identity_unittest.cc +++ b/rtc_base/ssl_identity_unittest.cc @@ -65,7 +65,7 @@ const unsigned char kTestCertSha512[] = { 0x35, 0xce, 0x26, 0x58, 0x4a, 0x33, 0x6d, 0xbc, 0xb6}; // These PEM strings were created by generating an identity with -// |SSLIdentity::Create| and invoking |identity->PrivateKeyToPEMString()|, +// |SSLIdentity::Generate| and invoking |identity->PrivateKeyToPEMString()|, // |identity->PublicKeyToPEMString()| and // |identity->certificate().ToPEMString()|. If the crypto library is updated, // and the update changes the string form of the keys, these will have to be @@ -406,21 +406,6 @@ TEST_F(SSLIdentityTest, FromPEMStringsEC) { EXPECT_EQ(kECDSA_CERT_PEM, identity->certificate().ToPEMString()); } -TEST_F(SSLIdentityTest, FromPEMChainStrings) { - // This doesn't form a valid certificate chain, but that doesn't matter for - // the purposes of the test - std::string chain(kRSA_CERT_PEM); - chain.append(kTestCertificate); - std::unique_ptr identity( - SSLIdentity::CreateFromPEMChainStrings(kRSA_PRIVATE_KEY_PEM, chain)); - EXPECT_TRUE(identity); - EXPECT_EQ(kRSA_PRIVATE_KEY_PEM, identity->PrivateKeyToPEMString()); - EXPECT_EQ(kRSA_PUBLIC_KEY_PEM, identity->PublicKeyToPEMString()); - ASSERT_EQ(2u, identity->cert_chain().GetSize()); - EXPECT_EQ(kRSA_CERT_PEM, identity->cert_chain().Get(0).ToPEMString()); - EXPECT_EQ(kTestCertificate, identity->cert_chain().Get(1).ToPEMString()); -} - TEST_F(SSLIdentityTest, CloneIdentityRSA) { TestCloningIdentity(*identity_rsa1_); TestCloningIdentity(*identity_rsa2_); diff --git a/rtc_base/ssl_stream_adapter_unittest.cc b/rtc_base/ssl_stream_adapter_unittest.cc index c580d835c5..379acace6e 100644 --- a/rtc_base/ssl_stream_adapter_unittest.cc +++ b/rtc_base/ssl_stream_adapter_unittest.cc @@ -508,9 +508,8 @@ class SSLStreamAdapterTestBase : public ::testing::Test, } } - // This tests that the handshake can complete before the identity is verified, - // and the identity will be verified after the fact. It also verifies that - // packets can't be read or written before the identity has been verified. + // This tests that the handshake can complete before the identity is + // verified, and the identity will be verified after the fact. void TestHandshakeWithDelayedIdentity(bool valid_identity) { server_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); client_ssl_->SetMode(dtls_ ? rtc::SSL_MODE_DTLS : rtc::SSL_MODE_TLS); @@ -525,9 +524,14 @@ class SSLStreamAdapterTestBase : public ::testing::Test, } // Start the handshake + int rv; + server_ssl_->SetServerRole(); - ASSERT_EQ(0, server_ssl_->StartSSL()); - ASSERT_EQ(0, client_ssl_->StartSSL()); + rv = server_ssl_->StartSSL(); + ASSERT_EQ(0, rv); + + rv = client_ssl_->StartSSL(); + ASSERT_EQ(0, rv); // Now run the handshake. EXPECT_TRUE_WAIT( @@ -543,57 +547,16 @@ class SSLStreamAdapterTestBase : public ::testing::Test, EXPECT_EQ(rtc::SR_BLOCK, client_ssl_->Write(&packet, 1, &sent, 0)); EXPECT_EQ(rtc::SR_BLOCK, server_ssl_->Write(&packet, 1, &sent, 0)); - // Collect both of the certificate digests; needs to be done before calling - // SetPeerCertificateDigest as that may reset the identity. - unsigned char server_digest[20]; - size_t server_digest_len; - unsigned char client_digest[20]; - size_t client_digest_len; - bool rv; - - rv = server_identity()->certificate().ComputeDigest( - rtc::DIGEST_SHA_1, server_digest, 20, &server_digest_len); - ASSERT_TRUE(rv); - rv = client_identity()->certificate().ComputeDigest( - rtc::DIGEST_SHA_1, client_digest, 20, &client_digest_len); - ASSERT_TRUE(rv); - - if (!valid_identity) { - RTC_LOG(LS_INFO) << "Setting bogus digest for client/server certs"; - client_digest[0]++; - server_digest[0]++; - } - - // Set the peer certificate digest for the client. - rtc::SSLPeerCertificateDigestError err; - rtc::SSLPeerCertificateDigestError expected_err = - valid_identity - ? rtc::SSLPeerCertificateDigestError::NONE - : rtc::SSLPeerCertificateDigestError::VERIFICATION_FAILED; - rv = client_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, server_digest, - server_digest_len, &err); - EXPECT_EQ(expected_err, err); - EXPECT_EQ(valid_identity, rv); + // If we set an invalid identity at this point, SetPeerCertificateDigest + // should return false. + SetPeerIdentitiesByDigest(valid_identity, valid_identity); // State should then transition to SS_OPEN or SS_CLOSED based on validation // of the identity. if (valid_identity) { EXPECT_EQ(rtc::SS_OPEN, client_ssl_->GetState()); - // If the client sends a packet while the server still hasn't verified the - // client identity, the server should continue to return SR_BLOCK. - EXPECT_EQ(rtc::SR_SUCCESS, client_ssl_->Write(&packet, 1, &sent, 0)); - EXPECT_EQ(rtc::SR_BLOCK, server_ssl_->Read(&packet, 1, 0, 0)); - } else { - EXPECT_EQ(rtc::SS_CLOSED, client_ssl_->GetState()); - } - - // Set the peer certificate digest for the server. - rv = server_ssl_->SetPeerCertificateDigest(rtc::DIGEST_SHA_1, client_digest, - client_digest_len, &err); - EXPECT_EQ(expected_err, err); - EXPECT_EQ(valid_identity, rv); - if (valid_identity) { EXPECT_EQ(rtc::SS_OPEN, server_ssl_->GetState()); } else { + EXPECT_EQ(rtc::SS_CLOSED, client_ssl_->GetState()); EXPECT_EQ(rtc::SS_CLOSED, server_ssl_->GetState()); } } diff --git a/webrtc.gni b/webrtc.gni index 2f6e77d1bf..05a230c4f1 100644 --- a/webrtc.gni +++ b/webrtc.gni @@ -227,10 +227,6 @@ declare_args() { rtc_libvpx_build_vp9 = !build_with_mozilla rtc_build_opus = !build_with_mozilla rtc_build_ssl = !build_with_mozilla - - # Can be set to true if rtc_build_ssl is false, but externally provided - # openssl library is boringssl, to enable the use of boringssl-specific code. - rtc_openssl_is_boringssl = !build_with_mozilla rtc_build_usrsctp = !build_with_mozilla # Enable libevent task queues on platforms that support it.