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 25namespace { 26 27const char kGoogleCertIssuer[] = "Google Inc"; 28const int CERT_BUFFER_SIZE = 1024; 29 30const base::FilePath::CharType kCertificateRelativePath[] = 31 FILE_PATH_LITERAL("chrome\\app\\test_data\\certificates\\"); 32const base::FilePath::CharType kDLLRelativePath[] = 33 FILE_PATH_LITERAL("chrome\\app\\test_data\\dlls\\"); 34 35class 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 106TEST_F(SignatureValidatorTest, ValidSigTest) { 107 RunTest(L"valid_sig.dll", true, true); 108} 109 110TEST_F(SignatureValidatorTest, SelfSignedTest) { 111 RunTest(L"self_signed.dll", false, false); 112} 113 114TEST_F(SignatureValidatorTest, NotSignedTest) { 115 RunTest(L"not_signed.dll", false, false); 116} 117 118TEST_F(SignatureValidatorTest, NotGoogleTest) { 119 RunTest(L"not_google.dll", true, false); 120} 121 122TEST_F(SignatureValidatorTest, CertPinningTest) { 123 RunTest(L"different_hash.dll", true, false); 124} 125 126TEST_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