[safe browsing] Binary golden file for prefix set test.
[chromium-blink-merge.git] / chrome / app / signature_validator_win.cc
blobab93a4f2e96ce9c94b9c790cd574d18bd0fa1f2c
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.
5 #include "chrome/app/signature_validator_win.h"
7 #include <atlstr.h>
8 #include <softpub.h>
9 #include <wincrypt.h>
10 #include <windows.h>
11 #include <wintrust.h>
13 #include <algorithm>
15 #include "base/files/file_path.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/time/time.h"
20 #include "base/win/scoped_handle.h"
21 #include "crypto/sha2.h"
23 namespace {
25 bool ExtractPublicKeyHash(const CERT_CONTEXT* cert_context,
26 std::string* public_key_hash) {
27 public_key_hash->clear();
29 CRYPT_BIT_BLOB crypt_blob =
30 cert_context->pCertInfo->SubjectPublicKeyInfo.PublicKey;
32 // Key blobs that are not an integral number of bytes are unsupported.
33 if (crypt_blob.cUnusedBits != 0)
34 return false;
36 uint8 hash[crypto::kSHA256Length] = {};
38 base::StringPiece key_bytes(reinterpret_cast<char*>(
39 crypt_blob.pbData), crypt_blob.cbData);
40 crypto::SHA256HashString(key_bytes, hash, crypto::kSHA256Length);
42 *public_key_hash = StringToLowerASCII(base::HexEncode(hash, arraysize(hash)));
43 return true;
46 // The traits class for HCERTSTORE handles that can be closed via
47 // CertCloseStore() API.
48 class CertStoreHandleTraits {
49 public:
50 typedef HCERTSTORE Handle;
52 // Closes the handle.
53 static bool CloseHandle(HCERTSTORE handle) {
54 return CertCloseStore(handle, 0) != FALSE;
57 // Returns true if the handle value is valid.
58 static bool IsHandleValid(HCERTSTORE handle) {
59 return handle != NULL;
62 // Returns NULL handle value.
63 static HANDLE NullHandle() {
64 return NULL;
67 private:
68 DISALLOW_IMPLICIT_CONSTRUCTORS(CertStoreHandleTraits);
71 typedef base::win::GenericScopedHandle<CertStoreHandleTraits,
72 base::win::DummyVerifierTraits> ScopedCertStoreHandle;
74 // Class: CertInfo
76 // CertInfo holds all sensible details of a certificate. During verification of
77 // a signature, one CertInfo object is made for each certificate encountered in
78 // the signature.
79 class CertInfo {
80 public:
81 explicit CertInfo(const CERT_CONTEXT* given_cert_context)
82 : cert_context_(NULL) {
83 if (given_cert_context) {
84 // CertDuplicateCertificateContext just increases reference count of a
85 // given CERT_CONTEXT.
86 cert_context_ = CertDuplicateCertificateContext(given_cert_context);
87 not_valid_before_ = cert_context_->pCertInfo->NotBefore;
88 not_valid_after_ = cert_context_->pCertInfo->NotAfter;
90 ExtractPublicKeyHash(cert_context_, &public_key_hash_);
94 ~CertInfo() { // Decrement reference count, if needed.
95 if (cert_context_) {
96 CertFreeCertificateContext(cert_context_);
97 cert_context_ = NULL;
101 // IsValidNow() functions returns true if this certificate is valid at this
102 // moment, based on the validity period specified in the certificate.
103 bool IsValidNow() const {
104 // we cannot directly get current time in FILETIME format.
105 // so first get it in SYSTEMTIME format and convert it into FILETIME.
106 base::Time now = base::Time::NowFromSystemTime();
107 FILETIME filetime_now = now.ToFileTime();
108 // CompareFileTime() is a windows function
109 return ((CompareFileTime(&filetime_now, &not_valid_before_) > 0) &&
110 (CompareFileTime(&filetime_now, &not_valid_after_) < 0));
113 std::string public_key_hash() const {
114 return public_key_hash_;
117 private:
118 // cert_context structure, defined by Crypto API, contains all the info
119 // about the certificate.
120 const CERT_CONTEXT* cert_context_;
122 // Lower-case hex SHA-256 hash of the certificate subject's public key.
123 std::string public_key_hash_;
125 // Validity period start-date
126 FILETIME not_valid_before_;
128 // Validity period end-date
129 FILETIME not_valid_after_;
132 } // namespace
134 bool VerifyAuthenticodeSignature(const base::FilePath& signed_file) {
135 // Don't pop up any windows
136 const HWND window_mode = reinterpret_cast<HWND>(INVALID_HANDLE_VALUE);
138 // Verify file & certificates using the Microsoft Authenticode Policy
139 // Provider.
140 GUID verification_type = WINTRUST_ACTION_GENERIC_VERIFY_V2;
142 // Info for the file we're going to verify.
143 WINTRUST_FILE_INFO file_info = {};
144 file_info.cbStruct = sizeof(file_info);
145 file_info.pcwszFilePath = signed_file.value().c_str();
147 // Info for request to WinVerifyTrust.
148 WINTRUST_DATA trust_data = {};
149 trust_data.cbStruct = sizeof(trust_data);
150 trust_data.dwUIChoice = WTD_UI_NONE; // no graphics
151 trust_data.fdwRevocationChecks = WTD_REVOKE_NONE; // no revocation checking
152 trust_data.dwUnionChoice = WTD_CHOICE_FILE; // check a file
153 trust_data.pFile = &file_info; // check this file
154 trust_data.dwProvFlags = WTD_REVOCATION_CHECK_NONE;
156 // From the WinVerifyTrust documentation:
157 // http://msdn2.microsoft.com/en-us/library/aa388208.aspx:
158 // "If the trust provider verifies that the subject is trusted
159 // for the specified action, the return value is zero. No other
160 // value besides zero should be considered a successful return."
161 LONG result = WinVerifyTrust(window_mode, &verification_type, &trust_data);
162 return !result;
165 bool VerifySignerIsGoogle(const base::FilePath& signed_file,
166 const std::string& subject_name,
167 const std::vector<std::string>& expected_hashes) {
168 if (signed_file.empty())
169 return false;
171 // If successful, cert_store will be populated by a store containing all the
172 // certificates related to the file signature.
173 HCERTSTORE cert_store = NULL;
175 BOOL succeeded = CryptQueryObject(
176 CERT_QUERY_OBJECT_FILE,
177 signed_file.value().c_str(),
178 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
179 CERT_QUERY_FORMAT_FLAG_ALL,
180 0, // Reserved: must be 0.
181 NULL,
182 NULL,
183 NULL,
184 &cert_store,
185 NULL, // Do not return the message.
186 NULL); // Do not return additional context.
188 ScopedCertStoreHandle scoped_cert_store(cert_store);
190 if (!succeeded || !scoped_cert_store.IsValid())
191 return false;
193 PCCERT_CONTEXT cert_context_ptr = NULL;
194 cert_context_ptr = CertFindCertificateInStore(
195 cert_store,
196 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
198 CERT_FIND_SUBJECT_STR,
199 base::UTF8ToWide(subject_name).c_str(),
200 cert_context_ptr);
202 // No cert found with this subject, so stop here.
203 if (!cert_context_ptr)
204 return false;
206 CertInfo cert_info(cert_context_ptr);
208 CertFreeCertificateContext(cert_context_ptr);
209 cert_context_ptr = NULL;
211 // Check the hashes to make sure subject isn't being faked, and the time
212 // to make sure the cert is current.
213 std::vector<std::string>::const_iterator it = std::find(
214 expected_hashes.begin(),
215 expected_hashes.end(),
216 cert_info.public_key_hash());
217 if (it == expected_hashes.end() || !cert_info.IsValidNow())
218 return false;
220 return true;