Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(461)

Side by Side Diff: chrome/browser/safe_browsing/signature_util_win.cc

Issue 8528043: Get all of the certificate data for downloads from the WinVerifyTrust result. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address review comments Created 9 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/signature_util_win_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/safe_browsing/signature_util.h" 5 #include "chrome/browser/safe_browsing/signature_util.h"
6 6
7 #include <windows.h> 7 #include <windows.h>
8 #include <softpub.h> 8 #include <softpub.h>
9 #include <wincrypt.h>
10 #include <wintrust.h> 9 #include <wintrust.h>
11 10
12 #include "base/file_path.h" 11 #include "base/file_path.h"
13 #include "base/logging.h" 12 #include "base/logging.h"
14 #include "base/scoped_ptr.h"
15 #include "crypto/scoped_capi_types.h"
16 #include "chrome/common/safe_browsing/csd.pb.h" 13 #include "chrome/common/safe_browsing/csd.pb.h"
17 14
18 #pragma comment(lib, "crypt32.lib")
19 #pragma comment(lib, "wintrust.lib") 15 #pragma comment(lib, "wintrust.lib")
20 16
21 namespace safe_browsing { 17 namespace safe_browsing {
22 namespace {
23 using crypto::ScopedCAPIHandle;
24 using crypto::CAPIDestroyer;
25 using crypto::CAPIDestroyerWithFlags;
26 18
27 // Free functors for scoped_ptr_malloc. 19 SignatureUtil::SignatureUtil() {}
28 class FreeConstCertContext {
29 public:
30 void operator()(const CERT_CONTEXT* cert_context) const {
31 if (cert_context) {
32 CertFreeCertificateContext(cert_context);
33 }
34 }
35 };
36 20
37 class FreeConstCertChainContext { 21 SignatureUtil::~SignatureUtil() {}
38 public:
39 void operator()(const CERT_CHAIN_CONTEXT* cert_chain_context) const {
40 if (cert_chain_context) {
41 CertFreeCertificateChain(cert_chain_context);
42 }
43 }
44 };
45 22
46 // Tries to extract the signing certificate from |file_path|. On success, 23 void SignatureUtil::CheckSignature(
47 // the |certificate_contents| field of |signature_info| is populated with the
48 // DER-encoded X.509 certificate.
49 void GetCertificateContents(
50 const FilePath& file_path, 24 const FilePath& file_path,
51 ClientDownloadRequest_SignatureInfo* signature_info) { 25 ClientDownloadRequest_SignatureInfo* signature_info) {
52 // Largely based on http://support.microsoft.com/kb/323809 26 VLOG(2) << "Checking signature for " << file_path.value();
53 // Get message handle and store handle from the signed file.
54 typedef CAPIDestroyer<HCRYPTMSG, CryptMsgClose> CryptMsgDestroyer;
55 ScopedCAPIHandle<HCRYPTMSG, CryptMsgDestroyer> crypt_msg;
56 typedef CAPIDestroyerWithFlags<
57 HCERTSTORE, CertCloseStore, 0> CertStoreDestroyer;
58 ScopedCAPIHandle<HCERTSTORE, CertStoreDestroyer> cert_store;
59 27
60 VLOG(2) << "Looking for signature in: " << file_path.value();
61 if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE,
62 file_path.value().c_str(),
63 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED,
64 CERT_QUERY_FORMAT_FLAG_BINARY,
65 0, // flags
66 NULL, // encoding
67 NULL, // content type
68 NULL, // format type
69 cert_store.receive(),
70 crypt_msg.receive(),
71 NULL)) { // context
72 VLOG(2) << "No signature found.";
73 return;
74 }
75
76 // Get the signer information size.
77 DWORD signer_info_size;
78 if (!CryptMsgGetParam(crypt_msg.get(),
79 CMSG_SIGNER_INFO_PARAM,
80 0, // index
81 NULL, // no buffer when checking the size
82 &signer_info_size)) {
83 VLOG(2) << "Failed to get signer info size";
84 return;
85 }
86
87 // Get the signer information.
88 scoped_array<BYTE> signer_info_buffer(new BYTE[signer_info_size]);
89 CMSG_SIGNER_INFO* signer_info =
90 reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get());
91 if (!CryptMsgGetParam(crypt_msg.get(),
92 CMSG_SIGNER_INFO_PARAM,
93 0, // index
94 signer_info,
95 &signer_info_size)) {
96 VLOG(2) << "Failed to get signer info";
97 return;
98 }
99
100 // Search for the signer certificate in the temporary certificate store.
101 CERT_INFO cert_info;
102 cert_info.Issuer = signer_info->Issuer;
103 cert_info.SerialNumber = signer_info->SerialNumber;
104
105 scoped_ptr_malloc<const CERT_CONTEXT, FreeConstCertContext> cert_context(
106 CertFindCertificateInStore(
107 cert_store.get(),
108 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
109 0, // flags
110 CERT_FIND_SUBJECT_CERT,
111 &cert_info,
112 NULL)); // no previous context
113 if (!cert_context.get()) {
114 VLOG(2) << "Failed to get CERT_CONTEXT";
115 return;
116 }
117
118 // Follow the chain of certificates to a trusted root.
119 CERT_CHAIN_PARA cert_chain_params;
120 memset(&cert_chain_params, 0, sizeof(cert_chain_params));
121 cert_chain_params.cbSize = sizeof(cert_chain_params);
122
123 const CERT_CHAIN_CONTEXT* cert_chain_context = NULL;
124 if (!CertGetCertificateChain(NULL, // default chain engine
125 cert_context.get(),
126 // TODO(bryner): should this verify at the
127 // executable's embedded timestamp?
128 NULL, // verify at the current time
129 NULL, // no additional store
130 &cert_chain_params,
131 0, // default flags
132 NULL, // reserved parameter
133 &cert_chain_context)) {
134 VLOG(2) << "Failed to get certificate chain.";
135 return;
136 }
137
138 typedef scoped_ptr_malloc<const CERT_CHAIN_CONTEXT,
139 FreeConstCertChainContext> ScopedCertChainContext;
140 ScopedCertChainContext scoped_cert_chain_context(cert_chain_context);
141 for (size_t i = 0; i < cert_chain_context->cChain; ++i) {
142 CERT_SIMPLE_CHAIN* simple_chain = cert_chain_context->rgpChain[i];
143 ClientDownloadRequest_CertificateChain* chain =
144 signature_info->add_certificate_chain();
145 for (size_t j = 0; j < simple_chain->cElement; ++j) {
146 CERT_CHAIN_ELEMENT* element = simple_chain->rgpElement[j];
147 chain->add_element()->set_certificate(
148 element->pCertContext->pbCertEncoded,
149 element->pCertContext->cbCertEncoded);
150 }
151 }
152 }
153
154 bool CheckTrust(const FilePath& file_path) {
155 WINTRUST_FILE_INFO file_info; 28 WINTRUST_FILE_INFO file_info;
156 file_info.cbStruct = sizeof(file_info); 29 file_info.cbStruct = sizeof(file_info);
157 file_info.pcwszFilePath = file_path.value().c_str(); 30 file_info.pcwszFilePath = file_path.value().c_str();
158 file_info.hFile = NULL; 31 file_info.hFile = NULL;
159 file_info.pgKnownSubject = NULL; 32 file_info.pgKnownSubject = NULL;
160 33
161 WINTRUST_DATA wintrust_data; 34 WINTRUST_DATA wintrust_data;
162 wintrust_data.cbStruct = sizeof(wintrust_data); 35 wintrust_data.cbStruct = sizeof(wintrust_data);
163 wintrust_data.pPolicyCallbackData = NULL; 36 wintrust_data.pPolicyCallbackData = NULL;
164 wintrust_data.pSIPClientData = NULL; 37 wintrust_data.pSIPClientData = NULL;
165 wintrust_data.dwUIChoice = WTD_UI_NONE; 38 wintrust_data.dwUIChoice = WTD_UI_NONE;
166 wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE; 39 wintrust_data.fdwRevocationChecks = WTD_REVOKE_NONE;
167 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE; 40 wintrust_data.dwUnionChoice = WTD_CHOICE_FILE;
168 wintrust_data.pFile = &file_info; 41 wintrust_data.pFile = &file_info;
169 wintrust_data.dwStateAction = WTD_STATEACTION_IGNORE; 42 wintrust_data.dwStateAction = WTD_STATEACTION_VERIFY;
170 wintrust_data.hWVTStateData = NULL; 43 wintrust_data.hWVTStateData = NULL;
171 wintrust_data.pwszURLReference = NULL; 44 wintrust_data.pwszURLReference = NULL;
172 wintrust_data.dwProvFlags = 0; // don't set any flags 45 // Disallow revocation checks over the network.
46 wintrust_data.dwProvFlags = WTD_CACHE_ONLY_URL_RETRIEVAL;
173 wintrust_data.dwUIContext = WTD_UICONTEXT_EXECUTE; 47 wintrust_data.dwUIContext = WTD_UICONTEXT_EXECUTE;
174 48
175 // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate 49 // The WINTRUST_ACTION_GENERIC_VERIFY_V2 policy verifies that the certificate
176 // chains up to a trusted root CA, and that it has appropriate permission to 50 // chains up to a trusted root CA, and that it has appropriate permission to
177 // sign code. 51 // sign code.
178 GUID policy_guid = WINTRUST_ACTION_GENERIC_VERIFY_V2; 52 GUID policy_guid = WINTRUST_ACTION_GENERIC_VERIFY_V2;
179 53
180 return (WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE), 54 LONG result = WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
181 &policy_guid, 55 &policy_guid,
182 &wintrust_data) == ERROR_SUCCESS); 56 &wintrust_data);
183 }
184 } // namespace
185 57
186 SignatureUtil::SignatureUtil() {} 58 CRYPT_PROVIDER_DATA* prov_data = WTHelperProvDataFromStateData(
59 wintrust_data.hWVTStateData);
60 if (prov_data) {
61 if (prov_data->csSigners > 0) {
62 signature_info->set_trusted(result == ERROR_SUCCESS);
63 }
64 for (DWORD i = 0; i < prov_data->csSigners; ++i) {
65 const CERT_CHAIN_CONTEXT* cert_chain_context =
66 prov_data->pasSigners[i].pChainContext;
67 for (DWORD j = 0; j < cert_chain_context->cChain; ++j) {
68 CERT_SIMPLE_CHAIN* simple_chain = cert_chain_context->rgpChain[j];
69 ClientDownloadRequest_CertificateChain* chain =
70 signature_info->add_certificate_chain();
71 for (DWORD k = 0; k < simple_chain->cElement; ++k) {
72 CERT_CHAIN_ELEMENT* element = simple_chain->rgpElement[k];
73 chain->add_element()->set_certificate(
74 element->pCertContext->pbCertEncoded,
75 element->pCertContext->cbCertEncoded);
76 }
77 }
78 }
187 79
188 SignatureUtil::~SignatureUtil() {} 80 // Free the provider data.
189 81 wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
190 void SignatureUtil::CheckSignature( 82 WinVerifyTrust(static_cast<HWND>(INVALID_HANDLE_VALUE),
191 const FilePath& file_path, 83 &policy_guid, &wintrust_data);
192 ClientDownloadRequest_SignatureInfo* signature_info) { 84 }
193 GetCertificateContents(file_path, signature_info);
194 signature_info->set_trusted(CheckTrust(file_path));
195 } 85 }
196 86
197 } // namespace safe_browsing 87 } // namespace safe_browsing
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/safe_browsing/signature_util_win_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698