Home | History | Annotate | Download | only in app
      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