Use injected clock when injecting clock for testing into SSL adapter Bug: webrtc:42223992 Change-Id: I763f56d4d56ee569283f1d7c01c3a7abb7aa99a3 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/466060 Reviewed-by: Evan Shrubsole <eshr@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/main@{#47563}
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 90f907c..92555c2 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn
@@ -1678,21 +1678,24 @@ ":stream", ":stringutils", ":threading", - ":timeutils", "../api:field_trials_view", "../api:sequence_checker", "../api/environment", "../api/task_queue", "../api/task_queue:pending_task_safety_flag", "../api/units:time_delta", + "../api/units:timestamp", + "../system_wrappers", + "synchronization:mutex", "system:rtc_export", "task_utils:repeating_task", "//third_party/abseil-cpp/absl/base:core_headers", + "//third_party/abseil-cpp/absl/base:no_destructor", "//third_party/abseil-cpp/absl/base:nullability", "//third_party/abseil-cpp/absl/functional:any_invocable", "//third_party/abseil-cpp/absl/memory", - "//third_party/abseil-cpp/absl/strings", "//third_party/abseil-cpp/absl/strings:str_format", + "//third_party/abseil-cpp/absl/strings:string_view", ] # If we are building the SSL library ourselves, we know it's BoringSSL.
diff --git a/rtc_base/openssl_stream_adapter.cc b/rtc_base/openssl_stream_adapter.cc index 403f4ca..ccc8823 100644 --- a/rtc_base/openssl_stream_adapter.cc +++ b/rtc_base/openssl_stream_adapter.cc
@@ -26,6 +26,7 @@ #include <utility> #include <vector> +#include "absl/base/no_destructor.h" #include "absl/functional/any_invocable.h" #include "absl/strings/str_format.h" #include "absl/strings/string_view.h" @@ -35,6 +36,7 @@ #include "api/task_queue/pending_task_safety_flag.h" #include "api/task_queue/task_queue_base.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "rtc_base/buffer.h" #include "rtc_base/checks.h" #include "rtc_base/logging.h" @@ -47,8 +49,9 @@ #include "rtc_base/ssl_stream_adapter.h" #include "rtc_base/stream.h" #include "rtc_base/string_encode.h" +#include "rtc_base/synchronization/mutex.h" #include "rtc_base/task_utils/repeating_task.h" -#include "rtc_base/time_utils.h" +#include "system_wrappers/include/clock.h" #ifdef OPENSSL_IS_BORINGSSL #include <openssl/digest.h> @@ -92,12 +95,12 @@ #ifdef OPENSSL_IS_BORINGSSL // Enabled by EnableTimeCallbackForTesting. Should never be set in production // code. -bool g_use_time_callback_for_testing = false; -// Not used in production code. Actual time should be relative to Jan 1, 1970. -void TimeCallbackForTesting(const SSL* ssl, struct timeval* out_clock) { - int64_t time = TimeNanos(); - out_clock->tv_sec = time / kNumNanosecsPerSec; - out_clock->tv_usec = (time % kNumNanosecsPerSec) / kNumNanosecsPerMicrosec; +constinit bool g_use_time_callback_for_testing = false; +constinit size_t g_num_clock_for_testing_users = 0; +constinit Clock* g_clock_for_testing = nullptr; +Mutex& GlobalClockMutex() { + static absl::NoDestructor<Mutex> m; + return *m; } #endif @@ -1105,6 +1108,36 @@ timeout_task_.Stop(); } +#ifdef OPENSSL_IS_BORINGSSL +OpenSSLStreamAdapter::ScopedClockForTesting::ScopedClockForTesting( + SSL_CTX* ctx, + Clock* clock) { + MutexLock lock(&GlobalClockMutex()); + if (g_num_clock_for_testing_users == 0) { + g_clock_for_testing = clock; + } else { + RTC_CHECK(g_clock_for_testing == clock) + << "Multiple SSL clocks for testing is not implemented"; + } + ++g_num_clock_for_testing_users; + + // Not used in production code. Actual time should be relative to Jan 1, 1970. + SSL_CTX_set_current_time_cb( + ctx, +[](const SSL*, timeval* out_clock) { + Timestamp time = g_clock_for_testing->CurrentTime(); + out_clock->tv_sec = time.us() / TimeDelta::Seconds(1).us(); + out_clock->tv_usec = time.us() % TimeDelta::Seconds(1).us(); + }); +} +OpenSSLStreamAdapter::ScopedClockForTesting::~ScopedClockForTesting() { + MutexLock lock(&GlobalClockMutex()); + --g_num_clock_for_testing_users; + if (g_num_clock_for_testing_users == 0) { + g_clock_for_testing = nullptr; + } +} +#endif + SSL_CTX* OpenSSLStreamAdapter::SetupSSLContext() { #ifdef OPENSSL_IS_BORINGSSL // If X509 objects aren't used, we can use these methods to avoid @@ -1130,7 +1163,9 @@ #ifdef OPENSSL_IS_BORINGSSL // SSL_CTX_set_current_time_cb is only supported in BoringSSL. if (g_use_time_callback_for_testing) { - SSL_CTX_set_current_time_cb(ctx, &TimeCallbackForTesting); + // Clock should be injected to set one for testing. + RTC_CHECK(env_.has_value()); + clock_for_testing_.emplace(ctx, &env_->clock()); } SSL_CTX_set0_buffer_pool(ctx, openssl::GetBufferPool()); #endif
diff --git a/rtc_base/openssl_stream_adapter.h b/rtc_base/openssl_stream_adapter.h index 6aa5fd1..46335a7 100644 --- a/rtc_base/openssl_stream_adapter.h +++ b/rtc_base/openssl_stream_adapter.h
@@ -32,6 +32,7 @@ #include "rtc_base/ssl_stream_adapter.h" #include "rtc_base/stream.h" #include "rtc_base/task_utils/repeating_task.h" +#include "system_wrappers/include/clock.h" #ifdef OPENSSL_IS_BORINGSSL #include "rtc_base/boringssl_identity.h" @@ -273,6 +274,15 @@ // Kill switch (from field-trial) flag to disable the use of // SSL_set_group_ids. const bool disable_ssl_group_ids_ = false; + +#ifdef OPENSSL_IS_BORINGSSL + class ScopedClockForTesting { + public: + ScopedClockForTesting(SSL_CTX* ctx, Clock* clock); + ~ScopedClockForTesting(); + }; + std::optional<ScopedClockForTesting> clock_for_testing_; +#endif }; /////////////////////////////////////////////////////////////////////////////