Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 <wincrypt.h> | 8 #include <wincrypt.h> |
|
mattm
2011/11/04 22:14:18
nit: missing blank line
Brian Ryner
2011/11/04 22:20:30
Done.
| |
| 9 #include "base/file_path.h" | 9 #include "base/file_path.h" |
| 10 #include "base/logging.h" | |
| 11 #include "base/scoped_ptr.h" | |
| 12 #include "crypto/scoped_capi_types.h" | |
| 13 #include "chrome/common/safe_browsing/csd.pb.h" | |
| 10 | 14 |
| 11 namespace safe_browsing { | 15 namespace safe_browsing { |
| 12 namespace signature_util { | 16 namespace { |
| 17 using crypto::ScopedCAPIHandle; | |
| 18 using crypto::CAPIDestroyer; | |
| 19 using crypto::CAPIDestroyerWithFlags; | |
| 13 | 20 |
| 14 bool IsSigned(const FilePath& file_path) { | 21 // Free functor for scoped_ptr_malloc. |
| 22 class FreeConstCertContext { | |
| 23 public: | |
| 24 void operator()(const CERT_CONTEXT* cert_context) const { | |
| 25 CertFreeCertificateContext(cert_context); | |
| 26 } | |
| 27 }; | |
| 28 | |
| 29 // Tries to extract the signing certificate from |file_path|. On success, | |
| 30 // the |certificate_contents| field of |signature_info| is populated with the | |
| 31 // DER-encoded X.509 certificate. | |
| 32 void GetCertificateContents( | |
| 33 const FilePath& file_path, | |
| 34 ClientDownloadRequest_SignatureInfo* signature_info) { | |
| 35 // Largely based on http://support.microsoft.com/kb/323809 | |
| 15 // Get message handle and store handle from the signed file. | 36 // Get message handle and store handle from the signed file. |
| 16 BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE, | 37 typedef CAPIDestroyer<HCRYPTMSG, CryptMsgClose> CryptMsgDestroyer; |
| 17 file_path.value().c_str(), | 38 ScopedCAPIHandle<HCRYPTMSG, CryptMsgDestroyer> crypt_msg; |
| 18 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, | 39 typedef CAPIDestroyerWithFlags< |
| 19 CERT_QUERY_FORMAT_FLAG_BINARY, | 40 HCERTSTORE, CertCloseStore, 0> CertStoreDestroyer; |
| 20 0, // flags | 41 ScopedCAPIHandle<HCERTSTORE, CertStoreDestroyer> cert_store; |
| 21 NULL, // encoding | 42 |
| 22 NULL, // content type | 43 VLOG(2) << "Looking for signature in: " << file_path.value(); |
| 23 NULL, // format type | 44 if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE, |
| 24 NULL, // HCERTSTORE | 45 file_path.value().c_str(), |
| 25 NULL, // HCRYPTMSG | 46 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, |
| 26 NULL); // context | 47 CERT_QUERY_FORMAT_FLAG_BINARY, |
| 27 return result == TRUE; | 48 0, // flags |
| 49 NULL, // encoding | |
| 50 NULL, // content type | |
| 51 NULL, // format type | |
| 52 cert_store.receive(), | |
| 53 crypt_msg.receive(), | |
| 54 NULL)) { // context | |
| 55 VLOG(2) << "No signature found."; | |
| 56 return; | |
| 57 } | |
| 58 | |
| 59 // Get the signer information size. | |
| 60 DWORD signer_info_size; | |
| 61 if (!CryptMsgGetParam(crypt_msg.get(), | |
| 62 CMSG_SIGNER_INFO_PARAM, | |
| 63 0, // index | |
| 64 NULL, // no buffer when checking the size | |
| 65 &signer_info_size)) { | |
| 66 VLOG(2) << "Failed to get signer info size"; | |
| 67 return; | |
| 68 } | |
| 69 | |
| 70 // Get the signer information. | |
| 71 scoped_array<BYTE> signer_info_buffer(new BYTE[signer_info_size]); | |
| 72 CMSG_SIGNER_INFO* signer_info = | |
| 73 reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get()); | |
| 74 if (!CryptMsgGetParam(crypt_msg.get(), | |
| 75 CMSG_SIGNER_INFO_PARAM, | |
| 76 0, // index | |
| 77 signer_info, | |
| 78 &signer_info_size)) { | |
| 79 VLOG(2) << "Failed to get signer info"; | |
| 80 return; | |
| 81 } | |
| 82 | |
| 83 // Search for the signer certificate in the temporary certificate store. | |
| 84 CERT_INFO cert_info; | |
| 85 cert_info.Issuer = signer_info->Issuer; | |
| 86 cert_info.SerialNumber = signer_info->SerialNumber; | |
| 87 | |
| 88 scoped_ptr_malloc<const CERT_CONTEXT, FreeConstCertContext> cert_context( | |
| 89 CertFindCertificateInStore( | |
| 90 cert_store.get(), | |
| 91 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | |
| 92 0, // flags | |
| 93 CERT_FIND_SUBJECT_CERT, | |
| 94 &cert_info, | |
| 95 NULL)); // no previous context | |
| 96 if (!cert_context.get()) { | |
| 97 VLOG(2) << "Failed to get CERT_CONTEXT"; | |
| 98 return; | |
| 99 } | |
| 100 | |
| 101 signature_info->set_certificate_contents(cert_context->pbCertEncoded, | |
| 102 cert_context->cbCertEncoded); | |
| 103 VLOG(2) << "Successfully extracted cert"; | |
| 104 } | |
| 105 } // namespace | |
| 106 | |
| 107 SignatureUtil::SignatureUtil() {} | |
| 108 | |
| 109 SignatureUtil::~SignatureUtil() {} | |
| 110 | |
| 111 void SignatureUtil::CheckSignature( | |
| 112 const FilePath& file_path, | |
| 113 ClientDownloadRequest_SignatureInfo* signature_info) { | |
| 114 GetCertificateContents(file_path, signature_info); | |
| 115 // TODO(bryner): Populate is_trusted. | |
| 28 } | 116 } |
| 29 | 117 |
| 30 } // namespace signature_util | |
| 31 } // namespace safe_browsing | 118 } // namespace safe_browsing |
| OLD | NEW |