blob: 9f22c3b98f7fc9dbacf9d421eb57a4b67780c1f8 [file] [log] [blame]
// Copyright 2002-2009 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
#ifndef OMAHA_COMMON_SIGNATUREVALIDATOR_H__
#define OMAHA_COMMON_SIGNATUREVALIDATOR_H__
#include <windows.h>
#include <wincrypt.h>
#include <atlstr.h>
#pragma warning(push)
// C4548: expression before comma has no effect
#pragma warning(disable : 4548)
#include <vector>
#pragma warning(pop)
namespace omaha {
// Class: CertInfo
//
// CertInfo holds all sensible details of a certificate. During verification of
// a signature, one CertInfo object is made for each certificate encountered in
// the signature.
class CertInfo {
public:
// certificate issuing company name e.g. "Google Inc".
CString issuing_company_name_;
// a company may own multiple certificates.
// so this tells which dept owns this certificate.
CString issuing_dept_name_;
// trust-authority (or trust-provider) name. e.g. "Verisign, Inc.".
CString trust_authority_name_;
// validity period start-date
FILETIME not_valid_before_;
// validity period end-date
FILETIME not_valid_after_;
// CERT_CONTEXT structure, defined by Crypto API, contains all the info about
// the certificate.
const CERT_CONTEXT *cert_context_;
explicit CertInfo(const CERT_CONTEXT* given_cert_context);
~CertInfo();
// IsValidNow() functions returns true if this certificate is valid at this
// moment, based on the validity period specified in the certificate.
bool IsValidNow() const;
// AsString() is a utility function that's used for printing CertInfo details.
CString AsString() const {
CString cert_info_str =
_T("Issuing Company: \"") + issuing_company_name_ +
_T("\" Dept: \"") + issuing_dept_name_ +
_T("\" Trust Provider: \"") + trust_authority_name_ +
_T("\" Valid From: \"") + this->FileTimeToString(&not_valid_before_) +
_T("\" Valid To: \"") + this->FileTimeToString(&not_valid_after_) +
_T("\"");
return cert_info_str;
}
// FileTimeToString() is just a convenience function to print FILETIME.
static CString FileTimeToString(const FILETIME* ft);
// Given a cerificate context, this function extracts the subject/signee
// company name and its dept name(orgnanizational-unit-name, as they call it).
// Optionally, you could also retrieve trust-authority name.
static bool ExtractIssuerInfo(const CERT_CONTEXT* cert_context,
CString* orgn_name,
CString* orgn_dept_name,
CString* trust_authority = NULL);
private:
// we expect the input string to contain field <name, value> pairs
// separated by semi-colons. i.e.
// <field-name>=<field-value>;<field-name=<field-value>;
// N O T E: If more than field exists with the same name, this function
// returns the value of the first field.
static bool ExtractField(const TCHAR* str,
const TCHAR* field_name,
CString* field_value);
};
// CertList is a container for a list of certificates. It is used to hold all
// the certificates found in the signature of a signed file. In addition, it
// also provides interface to fetch certificates matching to a particular
// criterion.
//
// Internally, CertList contains basically a vector of CertInfo* pointers.
// The only reason why CertList is created as opposed to simply putting all
// the certificates in a vector<CertInfo*> is to avoid memory-leaks. CertList
// contains a list of CertInfo pointers and users don't have to worry about
// freeing those pointers. On the other hand, if you use vector<CertInfo>
// instead, it results in unwanted copying of CertInfo objects around.
class CertList {
public:
// Constructor
CertList() {}
// Destructor
~CertList() {
for (unsigned int inx = 0; inx < cert_list_.size(); ++inx)
delete cert_list_[inx];
cert_list_.clear();
}
// size() returns the number of certificates in this CertList
size_t size() {
return cert_list_.size();
}
// AddCertificate() is used to add a certificate to CertList.
// NOTE that once a certificate is added, CertList takes ownership of that
// CertInfo object.
void AddCertificate(CertInfo* cert) {
cert_list_.push_back(cert);
}
// FindFirstCert() finds the first certificate that matches given criteria.
// If allow_test_variant is true, the company name will also be deemed valid
// if it equals company_name_to_match + " (TEST)".
void FindFirstCert(CertInfo** result_cert_info,
const CString &company_name_to_match,
const CString &orgn_unit_to_match,
const CString &trust_authority_to_match,
bool allow_test_variant,
bool check_timestamp);
typedef std::vector<CertInfo*> CertInfoList;
// FindAllCerts() finds all certificates that match given criteria.
void FindAllCerts(CertInfoList* result_cert_info_list,
CString company_name_to_match,
CString orgn_unit_to_match,
CString trust_authority_to_match,
bool check_timestamp);
private:
CertInfoList cert_list_;
};
// ExtractAllCertificatesFromSignature() takes in a signed file, extracts all
// the certificates related to its signature and returns them in a CertList
// object.
void ExtractAllCertificatesFromSignature(const wchar_t* signed_file,
CertList* cert_list);
// TODO(omaha): the time check verification algorithm below seems weak if not
// completely wrong. The time stamp check should be done against the time
// stamp signature instead of the current time. For example, modifying the
// system time allows the test to pass or fail. See the documentation for
// WinVerifyTrust and WTD_LIFETIME_SIGNING_FLAG.
//
// VerifySigneeIsGoogle() tries to verify the signee is Google by matching
// the subject name on the certificate to "Google Inc" and its corresponding
// dept name on the certificate to "Engineering". If matched, this returns true
// otherwise it returns false. The time validity of the certicate is checked.
bool VerifySigneeIsGoogle(const wchar_t* signed_file);
// Verifies the signee but not the time stamp of the certificate.
bool VerifySigneeIsGoogleNoTimestampCheck(const wchar_t* signed_file);
// Returns S_OK if a given signed file contains a signature
// that could be successfully verified using one of the trust providers
// IE relies on. This means that, whoever signed the file, they should've signed
// using certificate issued by a well-known (to IE) trust provider like
// Verisign, Inc.
HRESULT VerifySignature(const wchar_t* signed_file, bool allow_network_check);
// Returns true if a given signed file contains a valid signature.
inline bool SignatureIsValid(const wchar_t* signed_file,
bool allow_network_check) {
return VerifySignature(signed_file, allow_network_check) == S_OK;
}
// Gets the timestamp for the file's signature.
HRESULT GetSigningTime(const wchar_t* signed_file, SYSTEMTIME* signing_time);
// Verifies that the file was signed within the specified number of days.
HRESULT VerifyFileSignedWithinDays(const wchar_t* signed_file, int days);
} // namespace omaha
#endif // OMAHA_COMMON_SIGNATUREVALIDATOR_H__