Chromium Code Reviews| Index: chrome/browser/safe_browsing/signature_util_win.cc |
| =================================================================== |
| --- chrome/browser/safe_browsing/signature_util_win.cc (revision 108613) |
| +++ chrome/browser/safe_browsing/signature_util_win.cc (working copy) |
| @@ -7,25 +7,112 @@ |
| #include <windows.h> |
| #include <wincrypt.h> |
|
mattm
2011/11/04 22:14:18
nit: missing blank line
Brian Ryner
2011/11/04 22:20:30
Done.
|
| #include "base/file_path.h" |
| +#include "base/logging.h" |
| +#include "base/scoped_ptr.h" |
| +#include "crypto/scoped_capi_types.h" |
| +#include "chrome/common/safe_browsing/csd.pb.h" |
| namespace safe_browsing { |
| -namespace signature_util { |
| +namespace { |
| +using crypto::ScopedCAPIHandle; |
| +using crypto::CAPIDestroyer; |
| +using crypto::CAPIDestroyerWithFlags; |
| -bool IsSigned(const FilePath& file_path) { |
| +// Free functor for scoped_ptr_malloc. |
| +class FreeConstCertContext { |
| + public: |
| + void operator()(const CERT_CONTEXT* cert_context) const { |
| + CertFreeCertificateContext(cert_context); |
| + } |
| +}; |
| + |
| +// Tries to extract the signing certificate from |file_path|. On success, |
| +// the |certificate_contents| field of |signature_info| is populated with the |
| +// DER-encoded X.509 certificate. |
| +void GetCertificateContents( |
| + const FilePath& file_path, |
| + ClientDownloadRequest_SignatureInfo* signature_info) { |
| + // Largely based on http://support.microsoft.com/kb/323809 |
| // Get message handle and store handle from the signed file. |
| - BOOL result = CryptQueryObject(CERT_QUERY_OBJECT_FILE, |
| - file_path.value().c_str(), |
| - CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, |
| - CERT_QUERY_FORMAT_FLAG_BINARY, |
| - 0, // flags |
| - NULL, // encoding |
| - NULL, // content type |
| - NULL, // format type |
| - NULL, // HCERTSTORE |
| - NULL, // HCRYPTMSG |
| - NULL); // context |
| - return result == TRUE; |
| + typedef CAPIDestroyer<HCRYPTMSG, CryptMsgClose> CryptMsgDestroyer; |
| + ScopedCAPIHandle<HCRYPTMSG, CryptMsgDestroyer> crypt_msg; |
| + typedef CAPIDestroyerWithFlags< |
| + HCERTSTORE, CertCloseStore, 0> CertStoreDestroyer; |
| + ScopedCAPIHandle<HCERTSTORE, CertStoreDestroyer> cert_store; |
| + |
| + VLOG(2) << "Looking for signature in: " << file_path.value(); |
| + if (!CryptQueryObject(CERT_QUERY_OBJECT_FILE, |
| + file_path.value().c_str(), |
| + CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED, |
| + CERT_QUERY_FORMAT_FLAG_BINARY, |
| + 0, // flags |
| + NULL, // encoding |
| + NULL, // content type |
| + NULL, // format type |
| + cert_store.receive(), |
| + crypt_msg.receive(), |
| + NULL)) { // context |
| + VLOG(2) << "No signature found."; |
| + return; |
| + } |
| + |
| + // Get the signer information size. |
| + DWORD signer_info_size; |
| + if (!CryptMsgGetParam(crypt_msg.get(), |
| + CMSG_SIGNER_INFO_PARAM, |
| + 0, // index |
| + NULL, // no buffer when checking the size |
| + &signer_info_size)) { |
| + VLOG(2) << "Failed to get signer info size"; |
| + return; |
| + } |
| + |
| + // Get the signer information. |
| + scoped_array<BYTE> signer_info_buffer(new BYTE[signer_info_size]); |
| + CMSG_SIGNER_INFO* signer_info = |
| + reinterpret_cast<CMSG_SIGNER_INFO*>(signer_info_buffer.get()); |
| + if (!CryptMsgGetParam(crypt_msg.get(), |
| + CMSG_SIGNER_INFO_PARAM, |
| + 0, // index |
| + signer_info, |
| + &signer_info_size)) { |
| + VLOG(2) << "Failed to get signer info"; |
| + return; |
| + } |
| + |
| + // Search for the signer certificate in the temporary certificate store. |
| + CERT_INFO cert_info; |
| + cert_info.Issuer = signer_info->Issuer; |
| + cert_info.SerialNumber = signer_info->SerialNumber; |
| + |
| + scoped_ptr_malloc<const CERT_CONTEXT, FreeConstCertContext> cert_context( |
| + CertFindCertificateInStore( |
| + cert_store.get(), |
| + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
| + 0, // flags |
| + CERT_FIND_SUBJECT_CERT, |
| + &cert_info, |
| + NULL)); // no previous context |
| + if (!cert_context.get()) { |
| + VLOG(2) << "Failed to get CERT_CONTEXT"; |
| + return; |
| + } |
| + |
| + signature_info->set_certificate_contents(cert_context->pbCertEncoded, |
| + cert_context->cbCertEncoded); |
| + VLOG(2) << "Successfully extracted cert"; |
| } |
| +} // namespace |
| -} // namespace signature_util |
| +SignatureUtil::SignatureUtil() {} |
| + |
| +SignatureUtil::~SignatureUtil() {} |
| + |
| +void SignatureUtil::CheckSignature( |
| + const FilePath& file_path, |
| + ClientDownloadRequest_SignatureInfo* signature_info) { |
| + GetCertificateContents(file_path, signature_info); |
| + // TODO(bryner): Populate is_trusted. |
| +} |
| + |
| } // namespace safe_browsing |