diff options
author | rsleevi <rsleevi@chromium.org> | 2014-09-23 20:12:55 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-24 03:13:10 +0000 |
commit | 25e2bc0a95354727342757ba71582bf4de638fe8 (patch) | |
tree | 769e510b3a3566a92e098baecd86bc272fef3b67 /content/browser/browser_main_runner.cc | |
parent | 6fb1f2e798c05bc01f3feeb8ae17dbb34f482f86 (diff) | |
download | chromium_src-25e2bc0a95354727342757ba71582bf4de638fe8.zip chromium_src-25e2bc0a95354727342757ba71582bf4de638fe8.tar.gz chromium_src-25e2bc0a95354727342757ba71582bf4de638fe8.tar.bz2 |
Use sidestep to detour CertVerifyCertificateSignatureEx on Windows versions earlier than Vista (excluding XP SP3), adding in SHA-256 support by deferring to NSS.
The canonical path to supporting SHA-256 is to install XP SP3 or the appropriate hotfixes for XP x64 / Windows Server 2003. However, as not all users may do so, and there's enough of a usability hurdle, provide an interception hook until we fully drop support for these systems.
XP is already outside of MSFT EOL (April 2014). Windows Server 2003 is EOL'd July 2015.
BUG=401365
Review URL: https://codereview.chromium.org/561613002
Cr-Commit-Position: refs/heads/master@{#296335}
Diffstat (limited to 'content/browser/browser_main_runner.cc')
-rw-r--r-- | content/browser/browser_main_runner.cc | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/content/browser/browser_main_runner.cc b/content/browser/browser_main_runner.cc index a06f18a..7acd62d 100644 --- a/content/browser/browser_main_runner.cc +++ b/content/browser/browser_main_runner.cc @@ -20,7 +20,10 @@ #include "ui/base/ime/input_method_initializer.h" #if defined(OS_WIN) +#include "base/win/win_util.h" #include "base/win/windows_version.h" +#include "net/cert/sha256_legacy_support_win.h" +#include "sandbox/win/src/sidestep/preamble_patcher.h" #include "ui/base/win/scoped_ole_initializer.h" #endif @@ -28,6 +31,89 @@ bool g_exited_main_message_loop = false; namespace content { +#if defined(OS_WIN) +namespace { + +// Pointer to the original CryptVerifyCertificateSignatureEx function. +net::sha256_interception::CryptVerifyCertificateSignatureExFunc + g_real_crypt_verify_signature_stub = NULL; + +// Stub function that is called whenever the Crypt32 function +// CryptVerifyCertificateSignatureEx is called. It just defers to net to perform +// the actual verification. +BOOL WINAPI CryptVerifyCertificateSignatureExStub( + HCRYPTPROV_LEGACY provider, + DWORD encoding_type, + DWORD subject_type, + void* subject_data, + DWORD issuer_type, + void* issuer_data, + DWORD flags, + void* extra) { + return net::sha256_interception::CryptVerifyCertificateSignatureExHook( + g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type, + subject_data, issuer_type, issuer_data, flags, extra); +} + +// If necessary, install an interception +void InstallSha256LegacyHooks() { +#if defined(_WIN64) + // Interception on x64 is not supported. + return; +#else + if (base::win::MaybeHasSHA256Support()) + return; + + net::sha256_interception::CryptVerifyCertificateSignatureExFunc + cert_verify_signature_ptr = reinterpret_cast< + net::sha256_interception::CryptVerifyCertificateSignatureExFunc>( + ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"), + "CryptVerifyCertificateSignatureEx")); + CHECK(cert_verify_signature_ptr); + + DWORD old_protect = 0; + if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE, + &old_protect)) { + return; + } + + g_real_crypt_verify_signature_stub = + reinterpret_cast< + net::sha256_interception::CryptVerifyCertificateSignatureExFunc>( + VirtualAllocEx(::GetCurrentProcess(), NULL, + sidestep::kMaxPreambleStubSize, MEM_COMMIT, + PAGE_EXECUTE_READWRITE)); + if (g_real_crypt_verify_signature_stub == NULL) { + CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, + &old_protect)); + return; + } + + sidestep::SideStepError patch_result = + sidestep::PreamblePatcher::Patch( + cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub, + g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize); + if (patch_result != sidestep::SIDESTEP_SUCCESS) { + CHECK(::VirtualFreeEx(::GetCurrentProcess(), + g_real_crypt_verify_signature_stub, 0, + MEM_RELEASE)); + CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, + &old_protect)); + return; + } + + DWORD dummy = 0; + CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy)); + CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub, + sidestep::kMaxPreambleStubSize, old_protect, + &old_protect)); +#endif // _WIN64 +} + +} // namespace + +#endif // OS_WIN + class BrowserMainRunnerImpl : public BrowserMainRunner { public: BrowserMainRunnerImpl() @@ -64,6 +150,7 @@ class BrowserMainRunnerImpl : public BrowserMainRunner { // Win32 API here directly. ImmDisableTextFrameService(static_cast<DWORD>(-1)); } + InstallSha256LegacyHooks(); #endif // OS_WIN base::StatisticsRecorder::Initialize(); |