From aa0a4410f447df4bbe14cd8cbc017ba04915a63b Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Thu, 26 Aug 2021 15:34:48 +0000 Subject: [PATCH] [vm/certs/win] When adding root certificates consider not_before and not_after properties, only add valid ones. boringssl seems to be confused when expired certificates are present in trusted root, only picks up the first matching one which could be expired and ignores still-valid-ones. TEST=secure_socket_utils_test Fixes https://github.com/dart-lang/sdk/issues/46370 Change-Id: I5bbc0a1a3331ce4dcda46eee41b02b5b6e835b2a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/211160 Reviewed-by: Siva Annamalai Commit-Queue: Alexander Aprelev --- runtime/bin/BUILD.gn | 1 + runtime/bin/builtin_impl_sources.gni | 2 +- runtime/bin/io_impl_sources.gni | 7 +- runtime/bin/secure_socket_utils.cc | 16 +++ runtime/bin/secure_socket_utils.h | 2 + runtime/bin/secure_socket_utils_test.cc | 152 ++++++++++++++++++++++++ runtime/bin/security_context_win.cc | 8 ++ 7 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 runtime/bin/secure_socket_utils_test.cc diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 355d3ba9affc..ba9c4bb61354 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -909,6 +909,7 @@ executable("run_vm_tests") { ":dart_snapshot_cc", ":standalone_dart_io", "..:libdart_precompiler", + "//third_party/boringssl", # for secure_socket_utils_test "//third_party/zlib", ] include_dirs = [ diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni index d1f7d9583b7b..9c14afbe00f8 100644 --- a/runtime/bin/builtin_impl_sources.gni +++ b/runtime/bin/builtin_impl_sources.gni @@ -4,7 +4,7 @@ # This file contains all C++ sources for the dart:_builtin library and # some of the C++ sources for the dart:io library. The rest are in -# io_impl_sources.gypi. +# io_impl_sources.gni. builtin_impl_sources = [ "crypto.cc", diff --git a/runtime/bin/io_impl_sources.gni b/runtime/bin/io_impl_sources.gni index 846c775cb40b..8c368bb4e290 100644 --- a/runtime/bin/io_impl_sources.gni +++ b/runtime/bin/io_impl_sources.gni @@ -3,7 +3,7 @@ # BSD-style license that can be found in the LICENSE file. # This file contains some C++ sources for the dart:io library. The other -# implementation files are in builtin_impl_sources.gypi. +# implementation files are in builtin_impl_sources.gni. io_impl_sources = [ "console.h", "console_posix.cc", @@ -109,4 +109,7 @@ io_impl_sources = [ "typed_data_utils.h", ] -io_impl_tests = [ "platform_macos_test.cc" ] +io_impl_tests = [ + "platform_macos_test.cc", + "secure_socket_utils_test.cc", +] diff --git a/runtime/bin/secure_socket_utils.cc b/runtime/bin/secure_socket_utils.cc index ce38f8fc5b57..ad738e976871 100644 --- a/runtime/bin/secure_socket_utils.cc +++ b/runtime/bin/secure_socket_utils.cc @@ -89,6 +89,22 @@ void SecureSocketUtils::CheckStatus(int status, SecureSocketUtils::CheckStatusSSL(status, type, message, NULL); } +bool SecureSocketUtils::IsCurrentTimeInsideCertValidDateRange(X509* root_cert) { + ASN1_TIME* not_before = X509_get_notBefore(root_cert); + ASN1_TIME* not_after = X509_get_notAfter(root_cert); + int days_since_valid = 0; + int secs_since_valid = 0; + int days_before_invalid = 0; + int secs_before_invalid = 0; + // nullptr indicates current date/time + ASN1_TIME_diff(&days_since_valid, &secs_since_valid, not_before, + /*to=*/nullptr); + ASN1_TIME_diff(&days_before_invalid, &secs_before_invalid, + /*from=*/nullptr, not_after); + return days_since_valid >= 0 && secs_since_valid >= 0 && + days_before_invalid >= 0 && secs_before_invalid >= 0; +} + } // namespace bin } // namespace dart diff --git a/runtime/bin/secure_socket_utils.h b/runtime/bin/secure_socket_utils.h index ddbd2b675ae4..e8e306ef6a79 100644 --- a/runtime/bin/secure_socket_utils.h +++ b/runtime/bin/secure_socket_utils.h @@ -39,6 +39,8 @@ class SecureSocketUtils : public AllStatic { static void CheckStatus(int status, const char* type, const char* message); + static bool IsCurrentTimeInsideCertValidDateRange(X509* root_cert); + static bool NoPEMStartLine() { uint32_t last_error = ERR_peek_last_error(); return (ERR_GET_LIB(last_error) == ERR_LIB_PEM) && diff --git a/runtime/bin/secure_socket_utils_test.cc b/runtime/bin/secure_socket_utils_test.cc new file mode 100644 index 000000000000..89bbb12d874e --- /dev/null +++ b/runtime/bin/secure_socket_utils_test.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#if !defined(DART_IO_SECURE_SOCKET_DISABLED) + +#include +#include +#include + +#include "bin/secure_socket_utils.h" +#include "platform/globals.h" +#include "vm/unit_test.h" + +namespace dart { +namespace bin { + +TEST_CASE(SecureSocketUtils_CertNotYetValid) { + const char* valid_after_2121 = + "-----BEGIN CERTIFICATE-----\n" + "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\n" + "q8uu\n" + "-----END CERTIFICATE-----\n"; + size_t len = strlen(valid_after_2121); + BIO* cert_bio = BIO_new(BIO_s_mem()); + BIO_write(cert_bio, valid_after_2121, len); + X509* cert_X509 = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); + EXPECT(cert_X509 != nullptr); + EXPECT(!SecureSocketUtils::IsCurrentTimeInsideCertValidDateRange(cert_X509)); + BIO_free(cert_bio); + X509_free(cert_X509); +} + +TEST_CASE(SecureSocketUtils_CertValid) { + const char* valid_in_2021 = + "-----BEGIN CERTIFICATE-----\n" + "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\n" + "dw==\n" + "-----END CERTIFICATE-----\n"; + size_t len = strlen(valid_in_2021); + BIO* cert_bio = BIO_new(BIO_s_mem()); + BIO_write(cert_bio, valid_in_2021, len); + X509* cert_X509 = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); + EXPECT(cert_X509 != nullptr); + EXPECT(SecureSocketUtils::IsCurrentTimeInsideCertValidDateRange(cert_X509)); + BIO_free(cert_bio); + X509_free(cert_X509); +} + +TEST_CASE(SecureSocketUtils_CertAlreadyExpired) { + const char* valid_before_2021 = + "-----BEGIN CERTIFICATE-----\n" + "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\n" + "-----END CERTIFICATE-----\n"; + size_t len = strlen(valid_before_2021); + BIO* cert_bio = BIO_new(BIO_s_mem()); + BIO_write(cert_bio, valid_before_2021, len); + X509* cert_X509 = PEM_read_bio_X509(cert_bio, NULL, NULL, NULL); + EXPECT(cert_X509 != nullptr); + EXPECT(!SecureSocketUtils::IsCurrentTimeInsideCertValidDateRange(cert_X509)); + BIO_free(cert_bio); + X509_free(cert_X509); +} + +} // namespace bin +} // namespace dart + +#endif // !defined(DART_IO_SECURE_SOCKET_DISABLED) diff --git a/runtime/bin/security_context_win.cc b/runtime/bin/security_context_win.cc index f61ae55433c9..2be09d48a3f6 100644 --- a/runtime/bin/security_context_win.cc +++ b/runtime/bin/security_context_win.cc @@ -111,6 +111,14 @@ static bool AddCertificatesFromNamedSystemStore(const wchar_t* name, Syslog::Print("\n"); } + if (!SecureSocketUtils::IsCurrentTimeInsideCertValidDateRange(root_cert)) { + if (SSL_LOG_STATUS) { + Syslog::Print("...certificate is outside of its valid date range\n"); + } + X509_free(root_cert); + continue; + } + int status = X509_STORE_add_cert(store, root_cert); if (status == 0) { int error = ERR_get_error();