diff options
-rw-r--r-- | content/browser/browser_main_runner.cc | 87 | ||||
-rw-r--r-- | net/cert/sha256_legacy_support_win.cc | 195 | ||||
-rw-r--r-- | net/cert/sha256_legacy_support_win.h | 48 | ||||
-rw-r--r-- | net/cert/sha256_legacy_support_win_unittest.cc | 52 | ||||
-rw-r--r-- | net/data/ssl/certificates/README | 5 | ||||
-rw-r--r-- | net/data/ssl/certificates/sha256.pem | 70 | ||||
-rw-r--r-- | net/net.gypi | 3 |
7 files changed, 460 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(); diff --git a/net/cert/sha256_legacy_support_win.cc b/net/cert/sha256_legacy_support_win.cc new file mode 100644 index 0000000..656edd73 --- /dev/null +++ b/net/cert/sha256_legacy_support_win.cc @@ -0,0 +1,195 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/sha256_legacy_support_win.h" + +#include <windows.h> +#include <wincrypt.h> + +#include <cert.h> +#include <keyhi.h> +#include <secoid.h> + +#include "base/lazy_instance.h" +#include "base/logging.h" +#include "base/strings/string_piece.h" +#include "base/win/windows_version.h" +#include "crypto/scoped_nss_types.h" + +namespace net { + +namespace sha256_interception { + +namespace { + +bool IsSupportedSubjectType(DWORD subject_type) { + switch (subject_type) { + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB: + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT: + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL: + return true; + } + return false; +} + +bool IsSupportedIssuerType(DWORD issuer_type) { + switch (issuer_type) { + case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY: + case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT: + case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: + return true; + } + return false; +} + +base::StringPiece GetSubjectSignature(DWORD subject_type, + void* subject_data) { + switch (subject_type) { + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_BLOB: { + CRYPT_DATA_BLOB* data_blob = + reinterpret_cast<CRYPT_DATA_BLOB*>(subject_data); + return base::StringPiece(reinterpret_cast<char*>(data_blob->pbData), + data_blob->cbData); + } + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT: { + PCCERT_CONTEXT subject_cert = + reinterpret_cast<PCCERT_CONTEXT>(subject_data); + return base::StringPiece( + reinterpret_cast<char*>(subject_cert->pbCertEncoded), + subject_cert->cbCertEncoded); + } + case CRYPT_VERIFY_CERT_SIGN_SUBJECT_CRL: { + PCCRL_CONTEXT subject_crl = + reinterpret_cast<PCCRL_CONTEXT>(subject_data); + return base::StringPiece( + reinterpret_cast<char*>(subject_crl->pbCrlEncoded), + subject_crl->cbCrlEncoded); + } + } + return base::StringPiece(); +} + +PCERT_PUBLIC_KEY_INFO GetIssuerPublicKey(DWORD issuer_type, + void* issuer_data) { + switch (issuer_type) { + case CRYPT_VERIFY_CERT_SIGN_ISSUER_PUBKEY: + return reinterpret_cast<PCERT_PUBLIC_KEY_INFO>(issuer_data); + case CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT: { + PCCERT_CONTEXT cert = reinterpret_cast<PCCERT_CONTEXT>(issuer_data); + return &cert->pCertInfo->SubjectPublicKeyInfo; + } + case CRYPT_VERIFY_CERT_SIGN_ISSUER_CHAIN: { + PCCERT_CHAIN_CONTEXT chain = + reinterpret_cast<PCCERT_CHAIN_CONTEXT>(issuer_data); + PCCERT_CONTEXT cert = chain->rgpChain[0]->rgpElement[0]->pCertContext; + return &cert->pCertInfo->SubjectPublicKeyInfo; + } + } + return NULL; +} + +} // namespace + +BOOL CryptVerifyCertificateSignatureExHook( + CryptVerifyCertificateSignatureExFunc original_func, + HCRYPTPROV_LEGACY provider, + DWORD encoding_type, + DWORD subject_type, + void* subject_data, + DWORD issuer_type, + void* issuer_data, + DWORD flags, + void* extra) { + CHECK(original_func); + + // Only intercept if the arguments are supported. + if (provider != NULL || (encoding_type != X509_ASN_ENCODING) || + !IsSupportedSubjectType(subject_type) || subject_data == NULL || + !IsSupportedIssuerType(issuer_type) || issuer_data == NULL) { + return original_func(provider, encoding_type, subject_type, subject_data, + issuer_type, issuer_data, flags, extra); + } + + base::StringPiece subject_signature = + GetSubjectSignature(subject_type, subject_data); + bool should_intercept = false; + + crypto::ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); + CERTSignedData signed_data; + memset(&signed_data, 0, sizeof(signed_data)); + + // Attempt to decode the subject using the generic "Signed Data" template, + // which all of the supported subject types match. If the signature + // algorithm is RSA with one of the SHA-2 algorithms supported by NSS + // (excluding SHA-224, which is pointless), then defer to the NSS + // implementation. Otherwise, fall back and let the OS handle it (e.g. + // in case there are any algorithm policies in effect). + if (!subject_signature.empty()) { + SECItem subject_sig_item; + subject_sig_item.data = const_cast<unsigned char*>( + reinterpret_cast<const unsigned char*>(subject_signature.data())); + subject_sig_item.len = subject_signature.size(); + SECStatus rv = SEC_QuickDERDecodeItem( + arena.get(), &signed_data, SEC_ASN1_GET(CERT_SignedDataTemplate), + &subject_sig_item); + if (rv == SECSuccess) { + SECOidTag signature_alg = + SECOID_GetAlgorithmTag(&signed_data.signatureAlgorithm); + if (signature_alg == SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION || + signature_alg == SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION || + signature_alg == SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION) { + should_intercept = true; + } + } + } + + if (!should_intercept) { + return original_func(provider, encoding_type, subject_type, subject_data, + issuer_type, issuer_data, flags, extra); + } + + // Rather than attempting to synthesize a CERTSubjectPublicKeyInfo by hand, + // just force the OS to do an ASN.1 encoding and then decode it back into + // NSS. This is silly for performance, but safest for consistency. + PCERT_PUBLIC_KEY_INFO issuer_public_key = + GetIssuerPublicKey(issuer_type, issuer_data); + if (!issuer_public_key) { + SetLastError(static_cast<DWORD>(NTE_BAD_ALGID)); + return FALSE; + } + + unsigned char* issuer_spki_data = NULL; + DWORD issuer_spki_len = 0; + if (!CryptEncodeObjectEx(X509_ASN_ENCODING, X509_PUBLIC_KEY_INFO, + issuer_public_key, CRYPT_ENCODE_ALLOC_FLAG, NULL, + &issuer_spki_data, &issuer_spki_len)) { + return FALSE; + } + + SECItem nss_issuer_spki; + nss_issuer_spki.data = issuer_spki_data; + nss_issuer_spki.len = issuer_spki_len; + CERTSubjectPublicKeyInfo* spki = + SECKEY_DecodeDERSubjectPublicKeyInfo(&nss_issuer_spki); + ::LocalFree(issuer_spki_data); + if (!spki) { + SetLastError(static_cast<DWORD>(NTE_BAD_ALGID)); + return FALSE; + } + + // Attempt to actually verify the signed data. If it fails, synthesize the + // failure as a generic "bad signature" and let CryptoAPI handle the rest. + SECStatus rv = CERT_VerifySignedDataWithPublicKeyInfo( + &signed_data, spki, NULL); + SECKEY_DestroySubjectPublicKeyInfo(spki); + if (rv != SECSuccess) { + SetLastError(static_cast<DWORD>(NTE_BAD_SIGNATURE)); + return FALSE; + } + return TRUE; +} + +} // namespace sha256_interception + +} // namespace net
\ No newline at end of file diff --git a/net/cert/sha256_legacy_support_win.h b/net/cert/sha256_legacy_support_win.h new file mode 100644 index 0000000..c98414c --- /dev/null +++ b/net/cert/sha256_legacy_support_win.h @@ -0,0 +1,48 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_CERT_SHA256_LEGACY_SUPPORT_WIN_H_ +#define NET_CERT_SHA256_LEGACY_SUPPORT_WIN_H_ + +#include <windows.h> +#include <wincrypt.h> + +#include "net/base/net_export.h" + +namespace net { + +namespace sha256_interception { + +typedef BOOL (WINAPI* CryptVerifyCertificateSignatureExFunc)( + HCRYPTPROV_LEGACY provider, + DWORD encoding_type, + DWORD subject_type, + void* subject_data, + DWORD issuer_type, + void* issuer_data, + DWORD flags, + void* extra); + +// Interception function meant to be called whenever +// CryptVerifyCertificateSignatureEx is called. Note that the calling +// conventions do not match, as the caller is expected to ensure that their +// interposed function handles the calling conventions and provides a pointer +// to the original CryptVerifyCertificateSignatureEx (e.g. to handle parameters +// and keys that are not supported). +NET_EXPORT BOOL CryptVerifyCertificateSignatureExHook( + CryptVerifyCertificateSignatureExFunc original_func, + HCRYPTPROV_LEGACY provider, + DWORD encoding_type, + DWORD subject_type, + void* subject_data, + DWORD issuer_type, + void* issuer_data, + DWORD flags, + void* extra); + +} // namespace sha256_interception + +} // namespace net + +#endif // NET_CERT_SHA256_LEGACY_SUPPORT_WIN_H_
\ No newline at end of file diff --git a/net/cert/sha256_legacy_support_win_unittest.cc b/net/cert/sha256_legacy_support_win_unittest.cc new file mode 100644 index 0000000..0496ca3 --- /dev/null +++ b/net/cert/sha256_legacy_support_win_unittest.cc @@ -0,0 +1,52 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "net/cert/sha256_legacy_support_win.h" + +#include "base/memory/ref_counted.h" +#include "net/base/test_data_directory.h" +#include "net/cert/x509_certificate.h" +#include "net/test/cert_test_util.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace net { + +namespace sha256_interception { + +namespace { + +// Verifies that SHA-256 signatures can be validated through the interception. +// Although this is only needed on legacy platforms, the test is run on all +// Windows platforms to make sure that the CryptoAPI<->NSS integration does not +// regress. +TEST(Sha256Interception, HandlesSHA2) { + base::FilePath certs_dir = GetTestCertsDirectory(); + + scoped_refptr<X509Certificate> server_cert = + ImportCertFromFile(certs_dir, "sha256.pem"); + ASSERT_NE(static_cast<X509Certificate*>(NULL), server_cert.get()); + + CryptVerifyCertificateSignatureExFunc cert_verify_signature_ptr = + reinterpret_cast<CryptVerifyCertificateSignatureExFunc>( + ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"), + "CryptVerifyCertificateSignatureEx")); + ASSERT_TRUE(cert_verify_signature_ptr); + + BOOL rv = CryptVerifyCertificateSignatureExHook( + cert_verify_signature_ptr, NULL, X509_ASN_ENCODING, + CRYPT_VERIFY_CERT_SIGN_SUBJECT_CERT, + const_cast<void*>(reinterpret_cast<const void*>( + server_cert->os_cert_handle())), + CRYPT_VERIFY_CERT_SIGN_ISSUER_CERT, + const_cast<void*>(reinterpret_cast<const void*>( + server_cert->os_cert_handle())), + 0, NULL); + EXPECT_EQ(TRUE, rv); +} + +} // namespace + +} // namespace sha256_interception + +} // namespace net
\ No newline at end of file diff --git a/net/data/ssl/certificates/README b/net/data/ssl/certificates/README index 17247f3..a3a94c8 100644 --- a/net/data/ssl/certificates/README +++ b/net/data/ssl/certificates/README @@ -112,6 +112,11 @@ unit tests. - ocsp-test-root.pem : A root certificate for the code in net/tools/testserver/minica.py +- sha256.pem: Used to test the handling of SHA-256 certs on Windows. + Generated by using the command: + "openssl req -x509 -days 3650 -sha256 -newkey rsa:2048 -text \ + -config ../scripts/ee.cnf -out sha256.pem" + - spdy_pooling.pem : Used to test the handling of spdy IP connection pooling Generated by using the command "openssl req -x509 -days 3650 -sha1 -extensions req_spdy_pooling \ diff --git a/net/data/ssl/certificates/sha256.pem b/net/data/ssl/certificates/sha256.pem new file mode 100644 index 0000000..507ff04 --- /dev/null +++ b/net/data/ssl/certificates/sha256.pem @@ -0,0 +1,70 @@ +Certificate: + Data: + Version: 1 (0x0) + Serial Number: + 90:23:b2:54:1d:1a:a1:b4 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1 + Validity + Not Before: Sep 11 19:19:22 2014 GMT + Not After : Sep 8 19:19:22 2024 GMT + Subject: C=US, ST=California, L=Mountain View, O=Test CA, CN=127.0.0.1 + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + RSA Public Key: (2048 bit) + Modulus (2048 bit): + 00:d2:41:24:4c:b5:a5:83:ad:b9:64:5b:90:e2:d1: + e5:17:14:fe:ee:d0:6a:d8:d0:74:3c:98:35:d1:6b: + 2a:81:32:9e:e4:a2:77:5b:f2:81:2c:ae:c1:cc:ca: + f0:45:dd:8e:21:d3:4c:a6:7a:69:1b:08:3e:83:31: + 0e:cc:5a:f8:a4:b6:05:10:68:ec:a0:a2:44:b6:95: + e9:c5:e3:7c:a2:fa:a0:72:de:b3:49:e7:ac:cc:dc: + ce:f3:7c:af:9f:05:46:e4:c2:31:54:a4:2b:cc:bf: + ab:c3:e2:a6:9d:30:24:f4:2b:4d:44:eb:63:5f:35: + 0f:c5:ec:e9:77:40:0d:3d:35:6c:88:e7:18:c3:01: + 95:4c:c1:d4:14:96:88:66:98:fd:8e:0f:0e:a1:50: + d3:f9:13:e1:b6:5d:5a:8a:1c:8d:55:e1:43:3d:ca: + c6:31:95:9c:0a:00:68:38:1a:b7:24:ce:cd:34:d6: + 8d:f5:11:79:64:7b:01:b3:0f:76:fd:cf:ca:73:33: + 96:03:e4:1a:2e:98:8b:54:4d:0b:b9:62:27:8f:0d: + 9a:2c:1f:5d:b5:6a:e4:3a:27:33:02:eb:7f:0d:30: + 6a:6f:ea:61:c9:78:fe:7a:9f:08:7b:61:cd:b8:b2: + 04:98:24:37:d5:f7:ce:ec:34:29:b3:bc:26:ca:6f: + 54:53 + Exponent: 65537 (0x10001) + Signature Algorithm: sha256WithRSAEncryption + 73:89:72:15:fa:cf:c9:6a:4d:a5:1a:66:0d:da:03:13:2e:31: + 6b:6f:df:f1:4f:dd:54:8d:bd:87:1e:e9:b1:b2:84:4a:da:8e: + fa:76:b8:66:f0:2d:d6:f4:72:2d:55:ef:99:d4:e1:99:7c:79: + 98:b7:b9:bc:9c:f8:69:47:6d:10:03:4b:41:59:ea:84:7c:04: + 97:67:37:d4:a8:75:53:4a:f3:f9:9a:cb:bb:09:fb:dd:d7:b0: + d5:35:48:04:f3:58:78:bc:fb:26:d7:dc:e2:bf:cb:64:22:3d: + f7:bb:a4:5e:a3:98:5f:aa:29:46:aa:c6:a9:7c:8c:04:ac:21: + 21:97:b1:94:da:eb:ee:49:03:9d:46:e0:a0:22:e4:dd:e4:2b: + 3d:0d:0e:af:1b:59:39:41:e8:47:43:b8:58:36:82:86:c6:0e: + d6:d3:c0:92:da:2b:a4:5a:5a:f8:4f:20:93:32:a7:74:21:13: + 9d:b7:7b:68:20:71:81:4a:1a:32:b7:5e:e7:45:de:f7:e4:04: + dd:c1:7b:89:3e:a2:cb:47:20:fa:36:a6:bc:17:5a:19:56:97: + 1e:3c:fa:a7:fc:1e:d9:ad:dc:62:6b:ef:52:88:c8:d3:09:6c: + 6f:ff:d4:28:4b:7d:1e:9d:bb:0c:08:12:f3:f8:fd:24:35:57: + a2:3a:26:e2 +-----BEGIN CERTIFICATE----- +MIIDPDCCAiQCCQCQI7JUHRqhtDANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJV +UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQ +MA4GA1UECgwHVGVzdCBDQTESMBAGA1UEAwwJMTI3LjAuMC4xMB4XDTE0MDkxMTE5 +MTkyMloXDTI0MDkwODE5MTkyMlowYDELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNh +bGlmb3JuaWExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxEDAOBgNVBAoMB1Rlc3Qg +Q0ExEjAQBgNVBAMMCTEyNy4wLjAuMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANJBJEy1pYOtuWRbkOLR5RcU/u7QatjQdDyYNdFrKoEynuSid1vygSyu +wczK8EXdjiHTTKZ6aRsIPoMxDsxa+KS2BRBo7KCiRLaV6cXjfKL6oHLes0nnrMzc +zvN8r58FRuTCMVSkK8y/q8Pipp0wJPQrTUTrY181D8Xs6XdADT01bIjnGMMBlUzB +1BSWiGaY/Y4PDqFQ0/kT4bZdWoocjVXhQz3KxjGVnAoAaDgatyTOzTTWjfUReWR7 +AbMPdv3PynMzlgPkGi6Yi1RNC7liJ48NmiwfXbVq5DonMwLrfw0wam/qYcl4/nqf +CHthzbiyBJgkN9X3zuw0KbO8JspvVFMCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA +c4lyFfrPyWpNpRpmDdoDEy4xa2/f8U/dVI29hx7psbKEStqO+na4ZvAt1vRyLVXv +mdThmXx5mLe5vJz4aUdtEANLQVnqhHwEl2c31Kh1U0rz+ZrLuwn73dew1TVIBPNY +eLz7Jtfc4r/LZCI997ukXqOYX6opRqrGqXyMBKwhIZexlNrr7kkDnUbgoCLk3eQr +PQ0OrxtZOUHoR0O4WDaChsYO1tPAktorpFpa+E8gkzKndCETnbd7aCBxgUoaMrde +50Xe9+QE3cF7iT6iy0cg+jamvBdaGVaXHjz6p/we2a3cYmvvUojI0wlsb//UKEt9 +Hp27DAgS8/j9JDVXojom4g== +-----END CERTIFICATE----- diff --git a/net/net.gypi b/net/net.gypi index fe7cff3..35ec25e 100644 --- a/net/net.gypi +++ b/net/net.gypi @@ -77,6 +77,8 @@ 'cert/ct_verify_result.h', 'cert/pem_tokenizer.cc', 'cert/pem_tokenizer.h', + 'cert/sha256_legacy_support_win.cc', + 'cert/sha256_legacy_support_win.h', 'cert/signed_certificate_timestamp.cc', 'cert/signed_certificate_timestamp.h', 'cert/single_request_cert_verifier.cc', @@ -1299,6 +1301,7 @@ 'cert/nss_cert_database_unittest.cc', 'cert/nss_profile_filter_chromeos_unittest.cc', 'cert/pem_tokenizer_unittest.cc', + 'cert/sha256_legacy_support_win_unittest.cc', 'cert/signed_certificate_timestamp_unittest.cc', 'cert/test_root_certs_unittest.cc', 'cert/x509_cert_types_unittest.cc', |