1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <windows.h> 6 #include <atlstr.h> 7 #include <wincrypt.h> 8 #include <wintrust.h> 9 10 #include "base/base_paths.h" 11 #include "base/basictypes.h" 12 #include "base/compiler_specific.h" 13 #include "base/files/file_path.h" 14 #include "base/files/file_util.h" 15 #include "base/logging.h" 16 #include "base/path_service.h" 17 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_piece.h" 19 #include "base/strings/string_util.h" 20 #include "chrome/app/signature_validator_win.h" 21 #include "crypto/sha2.h" 22 #include "net/cert/test_root_certs.h" 23 #include "testing/gtest/include/gtest/gtest.h" 24 25 namespace { 26 27 const char kGoogleCertIssuer[] = "Google Inc"; 28 const int CERT_BUFFER_SIZE = 1024; 29 30 const base::FilePath::CharType kCertificateRelativePath[] = 31 FILE_PATH_LITERAL("chrome\\app\\test_data\\certificates\\"); 32 const base::FilePath::CharType kDLLRelativePath[] = 33 FILE_PATH_LITERAL("chrome\\app\\test_data\\dlls\\"); 34 35 class SignatureValidatorTest : public testing::Test { 36 protected: 37 SignatureValidatorTest() {} 38 39 void SetUp() OVERRIDE { 40 test_roots_ = net::TestRootCerts::GetInstance(); 41 base::FilePath cert_path = 42 GetTestCertsDirectory().Append(L"AuthorityCert.cer"); 43 base::FilePath other_cert_path = 44 GetTestCertsDirectory().Append(L"OtherAuthorityCert.cer"); 45 test_roots_->AddFromFile(cert_path); 46 test_roots_->AddFromFile(other_cert_path); 47 EXPECT_FALSE(test_roots_->IsEmpty()); 48 49 SetExpectedHash(GetTestCertsDirectory().Append(L"ValidCert.cer")); 50 } 51 52 void TearDown() OVERRIDE { 53 test_roots_->Clear(); 54 EXPECT_TRUE(test_roots_->IsEmpty()); 55 } 56 57 base::FilePath GetTestCertsDirectory() { 58 base::FilePath src_root; 59 PathService::Get(base::DIR_SOURCE_ROOT, &src_root); 60 return src_root.Append(kCertificateRelativePath); 61 } 62 63 base::FilePath GetTestDLLsDirectory() { 64 base::FilePath src_root; 65 PathService::Get(base::DIR_SOURCE_ROOT, &src_root); 66 return src_root.Append(kDLLRelativePath); 67 } 68 69 void SetExpectedHash(const base::FilePath& cert_path) { 70 char cert_buffer[CERT_BUFFER_SIZE]; 71 base::ReadFile(cert_path, cert_buffer, CERT_BUFFER_SIZE); 72 73 PCCERT_CONTEXT cert = CertCreateCertificateContext(X509_ASN_ENCODING, 74 reinterpret_cast<byte*>(&cert_buffer), 75 CERT_BUFFER_SIZE); 76 77 CRYPT_BIT_BLOB blob = cert->pCertInfo->SubjectPublicKeyInfo.PublicKey; 78 size_t public_key_length = blob.cbData; 79 uint8* public_key = blob.pbData; 80 81 uint8 hash[crypto::kSHA256Length] = {0}; 82 83 base::StringPiece key_bytes(reinterpret_cast<char*>(public_key), 84 public_key_length); 85 crypto::SHA256HashString(key_bytes, hash, crypto::kSHA256Length); 86 87 std::string public_key_hash = 88 base::StringToLowerASCII(base::HexEncode(hash, arraysize(hash))); 89 expected_hashes_.push_back(public_key_hash); 90 } 91 92 void RunTest(const wchar_t* dll_filename, bool isValid, bool isGoogle) { 93 base::FilePath full_dll_path = GetTestDLLsDirectory().Append(dll_filename); 94 ASSERT_EQ(isValid, VerifyAuthenticodeSignature(full_dll_path)); 95 ASSERT_EQ(isGoogle, VerifySignerIsGoogle(full_dll_path, kGoogleCertIssuer, 96 expected_hashes_)); 97 } 98 99 private: 100 net::TestRootCerts* test_roots_; 101 std::vector<std::string> expected_hashes_; 102 }; 103 104 } // namespace 105 106 TEST_F(SignatureValidatorTest, ValidSigTest) { 107 RunTest(L"valid_sig.dll", true, true); 108 } 109 110 TEST_F(SignatureValidatorTest, SelfSignedTest) { 111 RunTest(L"self_signed.dll", false, false); 112 } 113 114 TEST_F(SignatureValidatorTest, NotSignedTest) { 115 RunTest(L"not_signed.dll", false, false); 116 } 117 118 TEST_F(SignatureValidatorTest, NotGoogleTest) { 119 RunTest(L"not_google.dll", true, false); 120 } 121 122 TEST_F(SignatureValidatorTest, CertPinningTest) { 123 RunTest(L"different_hash.dll", true, false); 124 } 125 126 TEST_F(SignatureValidatorTest, ExpiredCertTest) { 127 //TODO(caitkp): Figure out how to sign a dll with an expired cert. 128 RunTest(L"expired.dll", false, false); 129 } 130 131 132