#include "rtc_base/openssl_stream_adapter.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/stack.h>
#include <openssl/tls1.h>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "api/array_view.h"
#include "api/sequence_checker.h"
#include "api/task_queue/pending_task_safety_flag.h"
#include "api/units/time_delta.h"
#include "rtc_base/buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/numerics/safe_conversions.h"
#include "rtc_base/openssl_adapter.h"
#include "rtc_base/openssl_digest.h"
#include "rtc_base/ssl_identity.h"
#include "rtc_base/ssl_stream_adapter.h"
#include "rtc_base/task_utils/repeating_task.h"
#ifdef OPENSSL_IS_BORINGSSL
#include <openssl/base.h>
#include <openssl/digest.h>
#include <openssl/dtls1.h>
#include <openssl/pool.h>
#include <openssl/ssl.h>
#include "rtc_base/boringssl_certificate.h"
#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/string_encode.h"
#include "rtc_base/thread.h"
#include "rtc_base/time_utils.h"
#include "system_wrappers/include/field_trial.h"
#if (OPENSSL_VERSION_NUMBER < 0x10100000L)
#error "webrtc requires at least OpenSSL version 1.1.0, to support DTLS-SRTP"
#endif
#define DEFINE_CIPHER_ENTRY_SSL3(name) …
#define DEFINE_CIPHER_ENTRY_TLS1(name) …
namespace rtc {
namespace {
SafeTask;
struct SrtpCipherMapEntry { … };
struct SslCipherMapEntry { … };
constexpr SrtpCipherMapEntry kSrtpCipherMap[] = …;
#ifndef OPENSSL_IS_BORINGSSL
constexpr SslCipherMapEntry kSslCipherMap[] = {
DEFINE_CIPHER_ENTRY_SSL3(RSA_RC4_128_SHA),
{SSL3_CK_RSA_DES_192_CBC3_SHA, "TLS_RSA_WITH_3DES_EDE_CBC_SHA"},
{TLS1_CK_RSA_WITH_AES_128_SHA, "TLS_RSA_WITH_AES_128_CBC_SHA"},
{TLS1_CK_DHE_RSA_WITH_AES_128_SHA, "TLS_DHE_RSA_WITH_AES_128_CBC_SHA"},
{TLS1_CK_RSA_WITH_AES_256_SHA, "TLS_RSA_WITH_AES_256_CBC_SHA"},
{TLS1_CK_DHE_RSA_WITH_AES_256_SHA, "TLS_DHE_RSA_WITH_AES_256_CBC_SHA"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_RC4_128_SHA),
{TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA,
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_RC4_128_SHA),
{TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA,
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_CBC_SHA),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_CBC_SHA),
{TLS1_CK_RSA_WITH_AES_128_SHA256, "TLS_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_RSA_WITH_AES_256_SHA256, "TLS_RSA_WITH_AES_256_CBC_SHA256"},
{TLS1_CK_DHE_RSA_WITH_AES_128_SHA256,
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_DHE_RSA_WITH_AES_256_SHA256,
"TLS_DHE_RSA_WITH_AES_256_CBC_SHA256"},
DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(RSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(DHE_RSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(DH_RSA_WITH_AES_256_GCM_SHA384),
{TLS1_CK_ECDHE_ECDSA_WITH_AES_128_SHA256,
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_ECDHE_ECDSA_WITH_AES_256_SHA384,
"TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384"},
{TLS1_CK_ECDHE_RSA_WITH_AES_128_SHA256,
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256"},
{TLS1_CK_ECDHE_RSA_WITH_AES_256_SHA384,
"TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384"},
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_ECDSA_WITH_AES_256_GCM_SHA384),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_128_GCM_SHA256),
DEFINE_CIPHER_ENTRY_TLS1(ECDHE_RSA_WITH_AES_256_GCM_SHA384),
{0, nullptr}};
#endif
#ifdef OPENSSL_IS_BORINGSSL
bool g_use_time_callback_for_testing = …;
void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) { … }
#endif
}
static int stream_write(BIO* h, const char* buf, int num);
static int stream_read(BIO* h, char* buf, int size);
static int stream_puts(BIO* h, const char* str);
static long stream_ctrl(BIO* h, int cmd, long arg1, void* arg2);
static int stream_new(BIO* h);
static int stream_free(BIO* data);
static BIO_METHOD* BIO_stream_method() { … }
static BIO* BIO_new_stream(StreamInterface* stream) { … }
static int stream_new(BIO* b) { … }
static int stream_free(BIO* b) { … }
static int stream_read(BIO* b, char* out, int outl) { … }
static int stream_write(BIO* b, const char* in, int inl) { … }
static int stream_puts(BIO* b, const char* str) { … }
static long stream_ctrl(BIO* b, int cmd, long num, void* ptr) { … }
OpenSSLStreamAdapter::OpenSSLStreamAdapter(
std::unique_ptr<StreamInterface> stream,
absl::AnyInvocable<void(SSLHandshakeError)> handshake_error)
: … { … }
OpenSSLStreamAdapter::~OpenSSLStreamAdapter() { … }
void OpenSSLStreamAdapter::SetIdentity(std::unique_ptr<SSLIdentity> identity) { … }
SSLIdentity* OpenSSLStreamAdapter::GetIdentityForTesting() const { … }
void OpenSSLStreamAdapter::SetServerRole(SSLRole role) { … }
bool OpenSSLStreamAdapter::SetPeerCertificateDigest(
absl::string_view digest_alg,
const unsigned char* digest_val,
size_t digest_len,
SSLPeerCertificateDigestError* error) { … }
std::string OpenSSLStreamAdapter::SslCipherSuiteToName(int cipher_suite) { … }
bool OpenSSLStreamAdapter::GetSslCipherSuite(int* cipher_suite) { … }
SSLProtocolVersion OpenSSLStreamAdapter::GetSslVersion() const { … }
bool OpenSSLStreamAdapter::GetSslVersionBytes(int* version) const { … }
bool OpenSSLStreamAdapter::ExportKeyingMaterial(absl::string_view label,
const uint8_t* context,
size_t context_len,
bool use_context,
uint8_t* result,
size_t result_len) { … }
uint16_t OpenSSLStreamAdapter::GetPeerSignatureAlgorithm() const { … }
bool OpenSSLStreamAdapter::SetDtlsSrtpCryptoSuites(
const std::vector<int>& ciphers) { … }
bool OpenSSLStreamAdapter::GetDtlsSrtpCryptoSuite(int* crypto_suite) { … }
bool OpenSSLStreamAdapter::IsTlsConnected() { … }
int OpenSSLStreamAdapter::StartSSL() { … }
void OpenSSLStreamAdapter::SetMode(SSLMode mode) { … }
void OpenSSLStreamAdapter::SetMaxProtocolVersion(SSLProtocolVersion version) { … }
void OpenSSLStreamAdapter::SetInitialRetransmissionTimeout(int timeout_ms) { … }
StreamResult OpenSSLStreamAdapter::Write(rtc::ArrayView<const uint8_t> data,
size_t& written,
int& error) { … }
StreamResult OpenSSLStreamAdapter::Read(rtc::ArrayView<uint8_t> data,
size_t& read,
int& error) { … }
void OpenSSLStreamAdapter::FlushInput(unsigned int left) { … }
void OpenSSLStreamAdapter::Close() { … }
StreamState OpenSSLStreamAdapter::GetState() const { … }
void OpenSSLStreamAdapter::OnEvent(int events, int err) { … }
void OpenSSLStreamAdapter::PostEvent(int events, int err) { … }
void OpenSSLStreamAdapter::SetTimeout(int delay_ms) { … }
int OpenSSLStreamAdapter::BeginSSL() { … }
int OpenSSLStreamAdapter::ContinueSSL() { … }
void OpenSSLStreamAdapter::Error(absl::string_view context,
int err,
uint8_t alert,
bool signal) { … }
void OpenSSLStreamAdapter::Cleanup(uint8_t alert) { … }
SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { … }
bool OpenSSLStreamAdapter::VerifyPeerCertificate() { … }
std::unique_ptr<SSLCertChain> OpenSSLStreamAdapter::GetPeerSSLCertChain()
const { … }
#ifdef OPENSSL_IS_BORINGSSL
enum ssl_verify_result_t OpenSSLStreamAdapter::SSLVerifyCallback(
SSL* ssl,
uint8_t* out_alert) { … }
#else
int OpenSSLStreamAdapter::SSLVerifyCallback(X509_STORE_CTX* store, void* arg) {
SSL* ssl = reinterpret_cast<SSL*>(
X509_STORE_CTX_get_ex_data(store, SSL_get_ex_data_X509_STORE_CTX_idx()));
OpenSSLStreamAdapter* stream =
reinterpret_cast<OpenSSLStreamAdapter*>(SSL_get_app_data(ssl));
X509* cert = X509_STORE_CTX_get0_cert(store);
stream->peer_cert_chain_.reset(
new SSLCertChain(std::make_unique<OpenSSLCertificate>(cert)));
if (stream->peer_certificate_digest_algorithm_.empty()) {
RTC_DLOG(LS_INFO) << "Waiting to verify certificate until digest is known.";
return 1;
}
if (!stream->VerifyPeerCertificate()) {
X509_STORE_CTX_set_error(store, X509_V_ERR_CERT_REJECTED);
return 0;
}
return 1;
}
#endif
bool OpenSSLStreamAdapter::IsBoringSsl() { … }
#define CDEF …
struct cipher_list { … };
static const cipher_list OK_RSA_ciphers[] = …;
static const cipher_list OK_ECDSA_ciphers[] = …;
#undef CDEF
bool OpenSSLStreamAdapter::IsAcceptableCipher(int cipher, KeyType key_type) { … }
bool OpenSSLStreamAdapter::IsAcceptableCipher(absl::string_view cipher,
KeyType key_type) { … }
void OpenSSLStreamAdapter::EnableTimeCallbackForTesting() { … }
}