diff options
Diffstat (limited to 'net/base')
30 files changed, 218 insertions, 491 deletions
diff --git a/net/base/cert_test_util.cc b/net/base/cert_test_util.cc index 7815872..cdfd6b0 100644 --- a/net/base/cert_test_util.cc +++ b/net/base/cert_test_util.cc @@ -53,7 +53,7 @@ scoped_refptr<X509Certificate> ImportCertFromFile( } ScopedTestEVPolicy::ScopedTestEVPolicy(EVRootCAMetadata* ev_root_ca_metadata, - const SHA1HashValue& fingerprint, + const SHA1Fingerprint& fingerprint, const char* policy) : fingerprint_(fingerprint), ev_root_ca_metadata_(ev_root_ca_metadata) { diff --git a/net/base/cert_test_util.h b/net/base/cert_test_util.h index eb9e7eb..ee370e7 100644 --- a/net/base/cert_test_util.h +++ b/net/base/cert_test_util.h @@ -40,12 +40,12 @@ scoped_refptr<X509Certificate> ImportCertFromFile(const FilePath& certs_dir, class ScopedTestEVPolicy { public: ScopedTestEVPolicy(EVRootCAMetadata* ev_root_ca_metadata, - const SHA1HashValue& fingerprint, + const SHA1Fingerprint& fingerprint, const char* policy); ~ScopedTestEVPolicy(); private: - SHA1HashValue fingerprint_; + SHA1Fingerprint fingerprint_; EVRootCAMetadata* const ev_root_ca_metadata_; }; diff --git a/net/base/cert_verify_proc.cc b/net/base/cert_verify_proc.cc index 31b13bf..420a8a5 100644 --- a/net/base/cert_verify_proc.cc +++ b/net/base/cert_verify_proc.cc @@ -217,9 +217,8 @@ bool CertVerifyProc::IsBlacklisted(X509Certificate* cert) { } // static -// NOTE: This implementation assumes and enforces that the hashes are SHA1. bool CertVerifyProc::IsPublicKeyBlacklisted( - const std::vector<HashValueVector>& public_key_hashes) { + const std::vector<SHA1Fingerprint>& public_key_hashes) { static const unsigned kNumHashes = 9; static const uint8 kHashes[kNumHashes][base::kSHA1Length] = { // Subject: CN=DigiNotar Root CA @@ -264,14 +263,11 @@ bool CertVerifyProc::IsPublicKeyBlacklisted( 0xd1, 0x72, 0xbd, 0x53, 0xe0, 0xd3, 0x07, 0x83, 0x4b, 0xd1}, }; - const HashValueVector& sha1_hashes = public_key_hashes[HASH_VALUE_SHA1]; for (unsigned i = 0; i < kNumHashes; i++) { - for (HashValueVector::const_iterator j = sha1_hashes.begin(); - j != sha1_hashes.end(); ++j) { - if (j->tag == HASH_VALUE_SHA1 && - memcmp(j->data(), kHashes[i], base::kSHA1Length) == 0) { + for (std::vector<SHA1Fingerprint>::const_iterator + j = public_key_hashes.begin(); j != public_key_hashes.end(); ++j) { + if (memcmp(j->data, kHashes[i], base::kSHA1Length) == 0) return true; - } } } diff --git a/net/base/cert_verify_proc.h b/net/base/cert_verify_proc.h index 790847f..a4801cfd 100644 --- a/net/base/cert_verify_proc.h +++ b/net/base/cert_verify_proc.h @@ -75,9 +75,9 @@ class NET_EXPORT CertVerifyProc static bool IsBlacklisted(X509Certificate* cert); // IsPublicKeyBlacklisted returns true iff one of |public_key_hashes| (which - // are hashes of SubjectPublicKeyInfo structures) is explicitly blocked. + // are SHA1 hashes of SubjectPublicKeyInfo structures) is explicitly blocked. static bool IsPublicKeyBlacklisted( - const std::vector<HashValueVector>& public_key_hashes); + const std::vector<SHA1Fingerprint>& public_key_hashes); }; } // namespace net diff --git a/net/base/cert_verify_proc_mac.cc b/net/base/cert_verify_proc_mac.cc index f38c5b1..49798b5 100644 --- a/net/base/cert_verify_proc_mac.cc +++ b/net/base/cert_verify_proc_mac.cc @@ -8,9 +8,6 @@ #include <CoreServices/CoreServices.h> #include <Security/Security.h> -#include <string> -#include <vector> - #include "base/logging.h" #include "base/mac/mac_logging.h" #include "base/mac/scoped_cftyperef.h" @@ -234,7 +231,7 @@ void GetCertChainInfo(CFArrayRef cert_chain, } void AppendPublicKeyHashes(CFArrayRef chain, - std::vector<HashValueVector>* hashes) { + std::vector<SHA1Fingerprint>* hashes) { const CFIndex n = CFArrayGetCount(chain); for (CFIndex i = 0; i < n; i++) { SecCertificateRef cert = reinterpret_cast<SecCertificateRef>( @@ -249,15 +246,9 @@ void AppendPublicKeyHashes(CFArrayRef chain, if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) continue; - HashValue sha1; - sha1.tag = HASH_VALUE_SHA1; - CC_SHA1(spki_bytes.data(), spki_bytes.size(), sha1.data()); - (*hashes)[HASH_VALUE_SHA1].push_back(sha1); - - HashValue sha256; - sha256.tag = HASH_VALUE_SHA256; - CC_SHA256(spki_bytes.data(), spki_bytes.size(), sha256.data()); - (*hashes)[HASH_VALUE_SHA256].push_back(sha256); + SHA1Fingerprint hash; + CC_SHA1(spki_bytes.data(), spki_bytes.size(), hash.data); + hashes->push_back(hash); } } @@ -334,7 +325,7 @@ bool IsIssuedByKnownRoot(CFArrayRef chain) { return false; SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( const_cast<void*>(CFArrayGetValueAtIndex(chain, n - 1))); - SHA1HashValue hash = X509Certificate::CalculateFingerprint(root_ref); + SHA1Fingerprint hash = X509Certificate::CalculateFingerprint(root_ref); return IsSHA1HashInSortedArray( hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes)); } diff --git a/net/base/cert_verify_proc_nss.cc b/net/base/cert_verify_proc_nss.cc index db9b34a..3108555 100644 --- a/net/base/cert_verify_proc_nss.cc +++ b/net/base/cert_verify_proc_nss.cc @@ -4,9 +4,6 @@ #include "net/base/cert_verify_proc_nss.h" -#include <string> -#include <vector> - #include <cert.h> #include <nss.h> #include <prerror.h> @@ -600,19 +597,9 @@ bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle, return false; } -HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { - HashValue hash; - hash.tag = HASH_VALUE_SHA1; - SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), - cert->derPublicKey.data, cert->derPublicKey.len); - DCHECK_EQ(rv, SECSuccess); - return hash; -} - -HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { - HashValue hash; - hash.tag = HASH_VALUE_SHA256; - SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), +SHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) { + SHA1Fingerprint hash; + SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data, cert->derPublicKey.data, cert->derPublicKey.len); DCHECK_EQ(rv, SECSuccess); return hash; @@ -620,18 +607,14 @@ HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { void AppendPublicKeyHashes(CERTCertList* cert_list, CERTCertificate* root_cert, - std::vector<HashValueVector>* hashes) { - // TODO(palmer): Generalize this to handle any and all HashValueTags. + std::vector<SHA1Fingerprint>* hashes) { for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); !CERT_LIST_END(node, cert_list); node = CERT_LIST_NEXT(node)) { - (*hashes)[HASH_VALUE_SHA1].push_back(CertPublicKeyHashSHA1(node->cert)); - (*hashes)[HASH_VALUE_SHA256].push_back(CertPublicKeyHashSHA256(node->cert)); - } - if (root_cert) { - (*hashes)[HASH_VALUE_SHA1].push_back(CertPublicKeyHashSHA1(root_cert)); - (*hashes)[HASH_VALUE_SHA256].push_back(CertPublicKeyHashSHA256(root_cert)); + hashes->push_back(CertPublicKeyHash(node->cert)); } + if (root_cert) + hashes->push_back(CertPublicKeyHash(root_cert)); } // Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp @@ -684,7 +667,7 @@ bool VerifyEV(CERTCertificate* cert_handle, int flags, CRLSet* crl_set) { return false; } - SHA1HashValue fingerprint = + SHA1Fingerprint fingerprint = X509Certificate::CalculateFingerprint(root_ca); std::vector<SECOidTag> ev_policy_tags; if (!metadata->GetPolicyOIDsForCA(fingerprint, &ev_policy_tags)) diff --git a/net/base/cert_verify_proc_openssl.cc b/net/base/cert_verify_proc_openssl.cc index 0c02249..9b467c5 100644 --- a/net/base/cert_verify_proc_openssl.cc +++ b/net/base/cert_verify_proc_openssl.cc @@ -6,13 +6,9 @@ #include <openssl/x509v3.h> -#include <string> -#include <vector> - #include "base/logging.h" #include "base/sha1.h" #include "crypto/openssl_util.h" -#include "crypto/sha2.h" #include "net/base/asn1_util.h" #include "net/base/cert_status_flags.h" #include "net/base/cert_verify_result.h" @@ -135,7 +131,7 @@ void GetCertChainInfo(X509_STORE_CTX* store_ctx, } void AppendPublicKeyHashes(X509_STORE_CTX* store_ctx, - std::vector<HashValueVector>* hashes) { + std::vector<SHA1Fingerprint>* hashes) { STACK_OF(X509)* chain = X509_STORE_CTX_get_chain(store_ctx); for (int i = 0; i < sk_X509_num(chain); ++i) { X509* cert = sk_X509_value(chain, i); @@ -149,16 +145,10 @@ void AppendPublicKeyHashes(X509_STORE_CTX* store_ctx, if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) continue; - HashValue sha1; - sha1.tag = HASH_VALUE_SHA1; + SHA1Fingerprint hash; base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), - spki_bytes.size(), sha1.data()); - (*hashes)[HASH_VALUE_SHA1].push_back(sha1); - - HashValue sha256; - sha256.tag = HASH_VALUE_SHA256; - crypto::SHA256HashString(spki_bytes, sha1.data(), crypto::kSHA256Length); - (*hashes)[HASH_VALUE_SHA256].push_back(sha256); + spki_bytes.size(), hash.data); + hashes->push_back(hash); } } diff --git a/net/base/cert_verify_proc_unittest.cc b/net/base/cert_verify_proc_unittest.cc index 317aacc5..6898a5b 100644 --- a/net/base/cert_verify_proc_unittest.cc +++ b/net/base/cert_verify_proc_unittest.cc @@ -120,7 +120,7 @@ TEST_F(CertVerifyProcTest, PaypalNullCertParsing) { ASSERT_NE(static_cast<X509Certificate*>(NULL), paypal_null_cert); - const SHA1HashValue& fingerprint = + const SHA1Fingerprint& fingerprint = paypal_null_cert->fingerprint(); for (size_t i = 0; i < 20; ++i) EXPECT_EQ(paypal_null_fingerprint[i], fingerprint.data[i]); @@ -397,13 +397,11 @@ TEST_F(CertVerifyProcTest, DigiNotarCerts) { std::string spki_sha1 = base::SHA1HashString(spki.as_string()); - std::vector<HashValueVector> public_keys(HASH_VALUE_TAGS_COUNT); - public_keys[HASH_VALUE_SHA1] = HashValueVector(); - HashValue fingerprint; - fingerprint.tag = HASH_VALUE_SHA1; - ASSERT_EQ(fingerprint.size(), spki_sha1.size()); - memcpy(fingerprint.data(), spki_sha1.data(), spki_sha1.size()); - public_keys[HASH_VALUE_SHA1].push_back(fingerprint); + std::vector<SHA1Fingerprint> public_keys; + SHA1Fingerprint fingerprint; + ASSERT_EQ(sizeof(fingerprint.data), spki_sha1.size()); + memcpy(fingerprint.data, spki_sha1.data(), spki_sha1.size()); + public_keys.push_back(fingerprint); EXPECT_TRUE(CertVerifyProc::IsPublicKeyBlacklisted(public_keys)) << "Public key not blocked for " << kDigiNotarFilenames[i]; @@ -455,14 +453,10 @@ TEST_F(CertVerifyProcTest, PublicKeyHashes) { int error = Verify(cert_chain, "cert.se", flags, NULL, &verify_result); EXPECT_EQ(OK, error); EXPECT_EQ(0U, verify_result.cert_status); - ASSERT_LE(static_cast<size_t>(HASH_VALUE_TAGS_COUNT), - verify_result.public_key_hashes.size()); - const HashValueVector& sha1_hashes = - verify_result.public_key_hashes[HASH_VALUE_SHA1]; - ASSERT_LE(3u, sha1_hashes.size()); - for (unsigned i = 0; i < 3; ++i) { + ASSERT_LE(3u, verify_result.public_key_hashes.size()); + for (unsigned i = 0; i < 3; i++) { EXPECT_EQ(HexEncode(kCertSESPKIs[i], base::kSHA1Length), - HexEncode(sha1_hashes[i].data(), base::kSHA1Length)); + HexEncode(verify_result.public_key_hashes[i].data, base::kSHA1Length)); } } diff --git a/net/base/cert_verify_proc_win.cc b/net/base/cert_verify_proc_win.cc index cedba2c..045ea16 100644 --- a/net/base/cert_verify_proc_win.cc +++ b/net/base/cert_verify_proc_win.cc @@ -4,9 +4,6 @@ #include "net/base/cert_verify_proc_win.h" -#include <string> -#include <vector> - #include "base/memory/scoped_ptr.h" #include "base/sha1.h" #include "base/string_util.h" @@ -285,7 +282,7 @@ bool IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context) { PCERT_CHAIN_ELEMENT* element = first_chain->rgpElement; PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext; - SHA1HashValue hash = X509Certificate::CalculateFingerprint(cert); + SHA1Fingerprint hash = X509Certificate::CalculateFingerprint(cert); return IsSHA1HashInSortedArray( hash, &kKnownRootCertSHA1Hashes[0][0], sizeof(kKnownRootCertSHA1Hashes)); } @@ -444,7 +441,7 @@ bool CheckRevocationWithCRLSet(PCCERT_CHAIN_CONTEXT chain, } void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain, - std::vector<HashValueVector>* hashes) { + std::vector<SHA1Fingerprint>* hashes) { if (chain->cChain == 0) return; @@ -462,16 +459,10 @@ void AppendPublicKeyHashes(PCCERT_CHAIN_CONTEXT chain, if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) continue; - HashValue sha1; - sha1.tag = HASH_VALUE_SHA1; + SHA1Fingerprint hash; base::SHA1HashBytes(reinterpret_cast<const uint8*>(spki_bytes.data()), - spki_bytes.size(), sha1.data()); - (*hashes)[HASH_VALUE_SHA1].push_back(sha1); - - HashValue sha256; - sha256.tag = HASH_VALUE_SHA256; - crypto::SHA256HashString(spki_bytes, sha1.data(), crypto::kSHA256Length); - (*hashes)[HASH_VALUE_SHA256].push_back(sha256); + spki_bytes.size(), hash.data); + hashes->push_back(hash); } } @@ -512,7 +503,7 @@ bool CheckEV(PCCERT_CHAIN_CONTEXT chain_context, // Look up the EV policy OID of the root CA. PCCERT_CONTEXT root_cert = element[num_elements - 1]->pCertContext; - SHA1HashValue fingerprint = + SHA1Fingerprint fingerprint = X509Certificate::CalculateFingerprint(root_cert); EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); return metadata->HasEVPolicyOID(fingerprint, policy_oid); diff --git a/net/base/cert_verify_result.cc b/net/base/cert_verify_result.cc index 86735d4..d51566b 100644 --- a/net/base/cert_verify_result.cc +++ b/net/base/cert_verify_result.cc @@ -24,13 +24,7 @@ void CertVerifyResult::Reset() { has_md5_ca = false; has_md2_ca = false; is_issued_by_known_root = false; - public_key_hashes.clear(); - public_key_hashes.reserve(HASH_VALUE_TAGS_COUNT); - HashValueVector sha1s; - public_key_hashes.push_back(sha1s); - HashValueVector sha256s; - public_key_hashes.push_back(sha256s); } -} // namespace net +} // namespace net diff --git a/net/base/cert_verify_result.h b/net/base/cert_verify_result.h index 0d33ed9..06baad2 100644 --- a/net/base/cert_verify_result.h +++ b/net/base/cert_verify_result.h @@ -45,15 +45,10 @@ class NET_EXPORT CertVerifyResult { bool has_md5_ca; bool has_md2_ca; - // If the certificate was successfully verified then this contains the - // fingerprints, in several hash algorithms, of the SubjectPublicKeyInfos - // of the chain. The fingerprint from the leaf certificate will be the - // first element of each sub-vector. - // - // This is a vector of vectors: Index the outer vector with - // FingerprintTag, and then the inner HashValueVectors will be - // fingerprints made with the algorithm named by the FingerprintTag. - std::vector<HashValueVector> public_key_hashes; + // If the certificate was successfully verified then this contains the SHA1 + // fingerprints of the SubjectPublicKeyInfos of the chain. The fingerprint + // from the leaf certificate will be the first element of the vector. + std::vector<SHA1Fingerprint> public_key_hashes; // is_issued_by_known_root is true if we recognise the root CA as a standard // root. If it isn't then it's probably the case that this certificate was diff --git a/net/base/ev_root_ca_metadata.cc b/net/base/ev_root_ca_metadata.cc index 2ccce80..301732f 100644 --- a/net/base/ev_root_ca_metadata.cc +++ b/net/base/ev_root_ca_metadata.cc @@ -33,7 +33,7 @@ struct EVMetadata { // The SHA-1 fingerprint of the root CA certificate, used as a unique // identifier for a root CA certificate. - SHA1HashValue fingerprint; + SHA1Fingerprint fingerprint; // The EV policy OIDs of the root CA. const char policy_oids[kMaxOIDsPerCA][kMaxOIDLength]; @@ -73,7 +73,7 @@ static const EVMetadata ev_root_ca_metadata[] = { // https://premiumecc.affirmtrust.com:4433/ { { { 0xb8, 0x23, 0x6b, 0x00, 0x2f, 0x1d, 0x16, 0x86, 0x53, 0x01, 0x55, 0x6c, 0x11, 0xa4, 0x37, 0xca, 0xeb, 0xff, 0xc3, 0xbb } }, - {"1.3.6.1.4.1.34697.2.4", ""}, + {"1.3.6.1.4.1.34697.2.4", ""}, }, // CertPlus Class 2 Primary CA (KEYNECTIS) // https://www.keynectis.com/ @@ -322,7 +322,7 @@ EVRootCAMetadata* EVRootCAMetadata::GetInstance() { #if defined(USE_NSS) bool EVRootCAMetadata::GetPolicyOIDsForCA( - const SHA1HashValue& fingerprint, + const SHA1Fingerprint& fingerprint, std::vector<PolicyOID>* policy_oids) const { PolicyOIDMap::const_iterator iter = ev_policy_.find(fingerprint); if (iter == ev_policy_.end()) @@ -342,7 +342,7 @@ int EVRootCAMetadata::NumPolicyOIDs() const { return policy_oids_.size(); } -bool EVRootCAMetadata::AddEVCA(const SHA1HashValue& fingerprint, +bool EVRootCAMetadata::AddEVCA(const SHA1Fingerprint& fingerprint, const char* policy) { if (ev_policy_.find(fingerprint) != ev_policy_.end()) return false; @@ -357,7 +357,7 @@ bool EVRootCAMetadata::AddEVCA(const SHA1HashValue& fingerprint, return true; } -bool EVRootCAMetadata::RemoveEVCA(const SHA1HashValue& fingerprint) { +bool EVRootCAMetadata::RemoveEVCA(const SHA1Fingerprint& fingerprint) { PolicyOIDMap::iterator it = ev_policy_.find(fingerprint); if (it == ev_policy_.end()) return false; @@ -416,7 +416,7 @@ bool EVRootCAMetadata::IsEVPolicyOID(PolicyOID policy_oid) const { return false; } -bool EVRootCAMetadata::HasEVPolicyOID(const SHA1HashValue& fingerprint, +bool EVRootCAMetadata::HasEVPolicyOID(const SHA1Fingerprint& fingerprint, PolicyOID policy_oid) const { for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) { if (!fingerprint.Equals(ev_root_ca_metadata[i].fingerprint)) @@ -434,7 +434,7 @@ bool EVRootCAMetadata::HasEVPolicyOID(const SHA1HashValue& fingerprint, return it != extra_cas_.end() && it->second == policy_oid; } -bool EVRootCAMetadata::AddEVCA(const SHA1HashValue& fingerprint, +bool EVRootCAMetadata::AddEVCA(const SHA1Fingerprint& fingerprint, const char* policy) { for (size_t i = 0; i < arraysize(ev_root_ca_metadata); i++) { if (fingerprint.Equals(ev_root_ca_metadata[i].fingerprint)) @@ -448,7 +448,7 @@ bool EVRootCAMetadata::AddEVCA(const SHA1HashValue& fingerprint, return true; } -bool EVRootCAMetadata::RemoveEVCA(const SHA1HashValue& fingerprint) { +bool EVRootCAMetadata::RemoveEVCA(const SHA1Fingerprint& fingerprint) { ExtraEVCAMap::iterator it = extra_cas_.find(fingerprint); if (it == extra_cas_.end()) return false; @@ -461,12 +461,12 @@ bool EVRootCAMetadata::RemoveEVCA(const SHA1HashValue& fingerprint) { // These are just stub functions for platforms where we don't use this EV // metadata. -bool EVRootCAMetadata::AddEVCA(const SHA1HashValue& fingerprint, +bool EVRootCAMetadata::AddEVCA(const SHA1Fingerprint& fingerprint, const char* policy) { return true; } -bool EVRootCAMetadata::RemoveEVCA(const SHA1HashValue& fingerprint) { +bool EVRootCAMetadata::RemoveEVCA(const SHA1Fingerprint& fingerprint) { return true; } diff --git a/net/base/ev_root_ca_metadata.h b/net/base/ev_root_ca_metadata.h index 864e120..ab76c49 100644 --- a/net/base/ev_root_ca_metadata.h +++ b/net/base/ev_root_ca_metadata.h @@ -12,7 +12,6 @@ #endif #include <map> -#include <string> #include <vector> #include "net/base/net_export.h" @@ -40,7 +39,7 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata { #if defined(USE_NSS) // If the root CA cert has an EV policy OID, returns true and appends the // policy OIDs to |*policy_oids|. Otherwise, returns false. - bool GetPolicyOIDsForCA(const SHA1HashValue& fingerprint, + bool GetPolicyOIDsForCA(const SHA1Fingerprint& fingerprint, std::vector<PolicyOID>* policy_oids) const; const PolicyOID* GetPolicyOIDs() const; int NumPolicyOIDs() const; @@ -50,18 +49,18 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata { // Returns true if the root CA with the given certificate fingerprint has // the EV policy OID policy_oid. - bool HasEVPolicyOID(const SHA1HashValue& fingerprint, + bool HasEVPolicyOID(const SHA1Fingerprint& fingerprint, PolicyOID policy_oid) const; #endif // AddEVCA adds an EV CA to the list of known EV CAs with the given policy. // |policy| is expressed as a string of dotted numbers. It returns true on // success. - bool AddEVCA(const SHA1HashValue& fingerprint, const char* policy); + bool AddEVCA(const SHA1Fingerprint& fingerprint, const char* policy); // RemoveEVCA removes an EV CA that was previously added by AddEVCA. It // returns true on success. - bool RemoveEVCA(const SHA1HashValue& fingerprint); + bool RemoveEVCA(const SHA1Fingerprint& fingerprint); private: friend struct base::DefaultLazyInstanceTraits<EVRootCAMetadata>; @@ -70,8 +69,8 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata { ~EVRootCAMetadata(); #if defined(USE_NSS) - typedef std::map<SHA1HashValue, std::vector<PolicyOID>, - SHA1HashValueLessThan> PolicyOIDMap; + typedef std::map<SHA1Fingerprint, std::vector<PolicyOID>, + SHA1FingerprintLessThan> PolicyOIDMap; // RegisterOID registers |policy|, a policy OID in dotted string form, and // writes the memoized form to |*out|. It returns true on success. @@ -80,8 +79,8 @@ class NET_EXPORT_PRIVATE EVRootCAMetadata { PolicyOIDMap ev_policy_; std::vector<PolicyOID> policy_oids_; #elif defined(OS_WIN) - typedef std::map<SHA1HashValue, std::string, - SHA1HashValueLessThan> ExtraEVCAMap; + typedef std::map<SHA1Fingerprint, std::string, + SHA1FingerprintLessThan> ExtraEVCAMap; // extra_cas_ contains any EV CA metadata that was added at runtime. ExtraEVCAMap extra_cas_; diff --git a/net/base/ev_root_ca_metadata_unittest.cc b/net/base/ev_root_ca_metadata_unittest.cc index 6b022ea..1a1ef35 100644 --- a/net/base/ev_root_ca_metadata_unittest.cc +++ b/net/base/ev_root_ca_metadata_unittest.cc @@ -13,10 +13,10 @@ namespace net { static const char kVerisignPolicy[] = "2.16.840.1.113733.1.7.23.6"; static const char kThawtePolicy[] = "2.16.840.1.113733.1.7.48.1"; static const char kFakePolicy[] = "2.16.840.1.42"; -static const SHA1HashValue kVerisignFingerprint = +static const SHA1Fingerprint kVerisignFingerprint = { { 0x74, 0x2c, 0x31, 0x92, 0xe6, 0x07, 0xe4, 0x24, 0xeb, 0x45, 0x49, 0x54, 0x2b, 0xe1, 0xbb, 0xc5, 0x3e, 0x61, 0x74, 0xe2 } }; -static const SHA1HashValue kFakeFingerprint = +static const SHA1Fingerprint kFakeFingerprint = { { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99 } }; @@ -89,6 +89,6 @@ TEST(EVRootCAMetadataTest, AddRemove) { kFakePolicy)); } -#endif // defined(OS_WIN) +#endif // defined(OS_WIN) } // namespace net diff --git a/net/base/multi_threaded_cert_verifier.h b/net/base/multi_threaded_cert_verifier.h index 5b1278c..1ef04ab 100644 --- a/net/base/multi_threaded_cert_verifier.h +++ b/net/base/multi_threaded_cert_verifier.h @@ -66,8 +66,8 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier // Input parameters of a certificate verification request. struct RequestParams { - RequestParams(const SHA1HashValue& cert_fingerprint_arg, - const SHA1HashValue& ca_fingerprint_arg, + RequestParams(const SHA1Fingerprint& cert_fingerprint_arg, + const SHA1Fingerprint& ca_fingerprint_arg, const std::string& hostname_arg, int flags_arg) : cert_fingerprint(cert_fingerprint_arg), @@ -92,8 +92,8 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier return hostname < other.hostname; } - SHA1HashValue cert_fingerprint; - SHA1HashValue ca_fingerprint; + SHA1Fingerprint cert_fingerprint; + SHA1Fingerprint ca_fingerprint; std::string hostname; int flags; }; diff --git a/net/base/multi_threaded_cert_verifier_unittest.cc b/net/base/multi_threaded_cert_verifier_unittest.cc index b25ea88..945cd7a 100644 --- a/net/base/multi_threaded_cert_verifier_unittest.cc +++ b/net/base/multi_threaded_cert_verifier_unittest.cc @@ -243,10 +243,10 @@ TEST_F(MultiThreadedCertVerifierTest, CancelRequestThenQuit) { } TEST_F(MultiThreadedCertVerifierTest, RequestParamsComparators) { - SHA1HashValue a_key; + SHA1Fingerprint a_key; memset(a_key.data, 'a', sizeof(a_key.data)); - SHA1HashValue z_key; + SHA1Fingerprint z_key; memset(z_key.data, 'z', sizeof(z_key.data)); struct { diff --git a/net/base/ssl_info.cc b/net/base/ssl_info.cc index 55ef1de..db4ac67 100644 --- a/net/base/ssl_info.cc +++ b/net/base/ssl_info.cc @@ -30,7 +30,6 @@ SSLInfo& SSLInfo::operator=(const SSLInfo& info) { channel_id_sent = info.channel_id_sent; handshake_type = info.handshake_type; public_key_hashes = info.public_key_hashes; - return *this; } @@ -43,13 +42,7 @@ void SSLInfo::Reset() { client_cert_sent = false; channel_id_sent = false; handshake_type = HANDSHAKE_UNKNOWN; - public_key_hashes.clear(); - public_key_hashes.reserve(HASH_VALUE_TAGS_COUNT); - HashValueVector sha1s; - public_key_hashes.push_back(sha1s); - HashValueVector sha256s; - public_key_hashes.push_back(sha256s); } void SSLInfo::SetCertError(int error) { diff --git a/net/base/ssl_info.h b/net/base/ssl_info.h index e9c6ea5..b3c37d2 100644 --- a/net/base/ssl_info.h +++ b/net/base/ssl_info.h @@ -71,11 +71,8 @@ class NET_EXPORT SSLInfo { HandshakeType handshake_type; - // The hashes of the SubjectPublicKeyInfos from each certificate in the - // chain. This is a vector of vectors: Index the outer vector with - // FingerprintTag, and then the inner HashValueVectors will be - // fingerprints made with the algorithm named by the FingerprintTag. - std::vector<HashValueVector> public_key_hashes; + // The hashes of the SubjectPublicKeyInfos from each certificate in the chain. + std::vector<SHA1Fingerprint> public_key_hashes; }; } // namespace net diff --git a/net/base/transport_security_state.cc b/net/base/transport_security_state.cc index 61cdb40..747dc7e 100644 --- a/net/base/transport_security_state.cc +++ b/net/base/transport_security_state.cc @@ -33,7 +33,6 @@ #include "googleurl/src/gurl.h" #include "net/base/dns_util.h" #include "net/base/ssl_info.h" -#include "net/base/x509_cert_types.h" #include "net/base/x509_certificate.h" #include "net/http/http_util.h" @@ -219,78 +218,69 @@ static StringPair Split(const std::string& source, char delimiter) { return pair; } +// TODO(palmer): Support both sha256 and sha1. This will require additional +// infrastructure code changes and can come in a later patch. +// // static bool TransportSecurityState::ParsePin(const std::string& value, - HashValue* out) { + SHA1Fingerprint* out) { StringPair slash = Split(Strip(value), '/'); - - if (slash.first == "sha1") - out->tag = HASH_VALUE_SHA1; - else if (slash.first == "sha256") - out->tag = HASH_VALUE_SHA256; - else + if (slash.first != "sha1") return false; std::string decoded; if (!base::Base64Decode(slash.second, &decoded) || - decoded.size() != out->size()) { + decoded.size() != arraysize(out->data)) { return false; } - memcpy(out->data(), decoded.data(), out->size()); + memcpy(out->data, decoded.data(), arraysize(out->data)); return true; } static bool ParseAndAppendPin(const std::string& value, - HashValueVector* fingerprints) { + FingerprintVector* fingerprints) { // The base64'd fingerprint MUST be a quoted-string. 20 bytes base64'd is 28 - // characters; 32 bytes base64'd is 44 characters. + // characters; 32 bytes base64'd is 44 characters. TODO(palmer): Support + // SHA256. size_t size = value.size(); - if ((size != 30 && size != 46) || value[0] != '"' || value[size - 1] != '"') + if (size != 30 || value[0] != '"' || value[size - 1] != '"') return false; std::string unquoted = HttpUtil::Unquote(value); std::string decoded; - HashValue fp; - - // This code has to assume that 32 bytes is SHA-256 and 20 bytes is SHA-1. - // Currently, those are the only two possibilities, so the assumption is - // valid. - if (!base::Base64Decode(unquoted, &decoded)) - return false; + SHA1Fingerprint fp; - if (decoded.size() == 20) - fp.tag = HASH_VALUE_SHA1; - else if (decoded.size() == 32) - fp.tag = HASH_VALUE_SHA256; - else + if (!base::Base64Decode(unquoted, &decoded) || + decoded.size() != arraysize(fp.data)) { return false; + } - memcpy(fp.data(), decoded.data(), fp.size()); + memcpy(fp.data, decoded.data(), arraysize(fp.data)); fingerprints->push_back(fp); return true; } -struct HashValuesEqualPredicate { - explicit HashValuesEqualPredicate(const HashValue& fingerprint) : +struct FingerprintsEqualPredicate { + explicit FingerprintsEqualPredicate(const SHA1Fingerprint& fingerprint) : fingerprint_(fingerprint) {} - bool operator()(const HashValue& other) const { + bool operator()(const SHA1Fingerprint& other) const { return fingerprint_.Equals(other); } - const HashValue& fingerprint_; + const SHA1Fingerprint& fingerprint_; }; // Returns true iff there is an item in |pins| which is not present in // |from_cert_chain|. Such an SPKI hash is called a "backup pin". -static bool IsBackupPinPresent(const HashValueVector& pins, - const HashValueVector& from_cert_chain) { - for (HashValueVector::const_iterator +static bool IsBackupPinPresent(const FingerprintVector& pins, + const FingerprintVector& from_cert_chain) { + for (FingerprintVector::const_iterator i = pins.begin(); i != pins.end(); ++i) { - HashValueVector::const_iterator j = + FingerprintVector::const_iterator j = std::find_if(from_cert_chain.begin(), from_cert_chain.end(), - HashValuesEqualPredicate(*i)); + FingerprintsEqualPredicate(*i)); if (j == from_cert_chain.end()) return true; } @@ -298,12 +288,12 @@ static bool IsBackupPinPresent(const HashValueVector& pins, return false; } -static bool HashesIntersect(const HashValueVector& a, - const HashValueVector& b) { - for (HashValueVector::const_iterator +static bool HashesIntersect(const FingerprintVector& a, + const FingerprintVector& b) { + for (FingerprintVector::const_iterator i = a.begin(); i != a.end(); ++i) { - HashValueVector::const_iterator j = - std::find_if(b.begin(), b.end(), HashValuesEqualPredicate(*i)); + FingerprintVector::const_iterator j = + std::find_if(b.begin(), b.end(), FingerprintsEqualPredicate(*i)); if (j != b.end()) return true; } @@ -316,30 +306,17 @@ static bool HashesIntersect(const HashValueVector& a, // backup pin is a pin intended for disaster recovery, not day-to-day use, and // thus must be absent from the certificate chain. The Public-Key-Pins header // specification requires both. -static bool IsPinListValid(const HashValueVector& pins, +static bool IsPinListValid(const FingerprintVector& pins, const SSLInfo& ssl_info) { - // Fast fail: 1 live + 1 backup = at least 2 pins. (Check for actual - // liveness and backupness below.) if (pins.size() < 2) return false; - // Site operators might pin a key using either the SHA-1 or SHA-256 hash - // of the SPKI. So check for success using either hash function. - // - // TODO(palmer): Make this generic so that it works regardless of what - // HashValueTags are defined in the future. - const HashValueVector& from_cert_chain_sha1 = - ssl_info.public_key_hashes[HASH_VALUE_SHA1]; - const HashValueVector& from_cert_chain_sha256 = - ssl_info.public_key_hashes[HASH_VALUE_SHA256]; - - if (from_cert_chain_sha1.empty() && from_cert_chain_sha256.empty()) + const FingerprintVector& from_cert_chain = ssl_info.public_key_hashes; + if (from_cert_chain.empty()) return false; - return (IsBackupPinPresent(pins, from_cert_chain_sha1) || - IsBackupPinPresent(pins, from_cert_chain_sha256)) && - (HashesIntersect(pins, from_cert_chain_sha1) || - HashesIntersect(pins, from_cert_chain_sha256)); + return IsBackupPinPresent(pins, from_cert_chain) && + HashesIntersect(pins, from_cert_chain); } // "Public-Key-Pins" ":" @@ -351,7 +328,7 @@ bool TransportSecurityState::DomainState::ParsePinsHeader( const SSLInfo& ssl_info) { bool parsed_max_age = false; int max_age_candidate = 0; - HashValueVector pins; + FingerprintVector pins; std::string source = value; @@ -372,10 +349,11 @@ bool TransportSecurityState::DomainState::ParsePinsHeader( if (max_age_candidate > kMaxHSTSAgeSecs) max_age_candidate = kMaxHSTSAgeSecs; parsed_max_age = true; - } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1") || - LowerCaseEqualsASCII(equals.first, "pin-sha256")) { + } else if (LowerCaseEqualsASCII(equals.first, "pin-sha1")) { if (!ParseAndAppendPin(equals.second, &pins)) return false; + } else if (LowerCaseEqualsASCII(equals.first, "pin-sha256")) { + // TODO(palmer) } else { // Silently ignore unknown directives for forward compatibility. } @@ -391,7 +369,7 @@ bool TransportSecurityState::DomainState::ParsePinsHeader( dynamic_spki_hashes.clear(); if (max_age_candidate > 0) { - for (HashValueVector::const_iterator i = pins.begin(); + for (FingerprintVector::const_iterator i = pins.begin(); i != pins.end(); ++i) { dynamic_spki_hashes.push_back(*i); } @@ -498,8 +476,8 @@ bool TransportSecurityState::DomainState::ParseSTSHeader( } static bool AddHash(const std::string& type_and_base64, - HashValueVector* out) { - HashValue hash; + FingerprintVector* out) { + SHA1Fingerprint hash; if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) return false; @@ -765,13 +743,13 @@ void TransportSecurityState::AddOrUpdateForcedHosts( } static std::string HashesToBase64String( - const HashValueVector& hashes) { + const FingerprintVector& hashes) { std::vector<std::string> hashes_strs; - for (HashValueVector::const_iterator + for (FingerprintVector::const_iterator i = hashes.begin(); i != hashes.end(); i++) { std::string s; - const std::string hash_str(reinterpret_cast<const char*>(i->data()), - i->size()); + const std::string hash_str(reinterpret_cast<const char*>(i->data), + sizeof(i->data)); base::Base64Encode(hash_str, &s); hashes_strs.push_back(s); } @@ -789,43 +767,24 @@ TransportSecurityState::DomainState::~DomainState() { } bool TransportSecurityState::DomainState::IsChainOfPublicKeysPermitted( - const std::vector<HashValueVector>& hashes) const { - // Validate that hashes is not empty. By the time this code is called (in - // production), that should never happen, but it's good to be defensive. - // And, hashes *can* be empty in some test scenarios. - bool empty = true; - for (size_t i = 0; i < hashes.size(); ++i) { - if (hashes[i].size()) { - empty = false; - break; - } - } - if (empty) { - LOG(ERROR) << "Rejecting empty certificate chain for public key pinned " - "domain " << domain; + const FingerprintVector& hashes) const { + if (HashesIntersect(bad_static_spki_hashes, hashes)) { + LOG(ERROR) << "Rejecting public key chain for domain " << domain + << ". Validated chain: " << HashesToBase64String(hashes) + << ", matches one or more bad hashes: " + << HashesToBase64String(bad_static_spki_hashes); return false; } - for (size_t i = 0; i < hashes.size(); ++i) { - if (HashesIntersect(bad_static_spki_hashes, hashes[i])) { - LOG(ERROR) << "Rejecting public key chain for domain " << domain - << ". Validated chain: " << HashesToBase64String(hashes[i]) - << ", matches one or more bad hashes: " - << HashesToBase64String(bad_static_spki_hashes); - return false; - } - - if (!(dynamic_spki_hashes.empty() && static_spki_hashes.empty()) && - hashes[i].size() > 0 && - !HashesIntersect(dynamic_spki_hashes, hashes[i]) && - !HashesIntersect(static_spki_hashes, hashes[i])) { - LOG(ERROR) << "Rejecting public key chain for domain " << domain - << ". Validated chain: " << HashesToBase64String(hashes[i]) - << ", expected: " << HashesToBase64String(dynamic_spki_hashes) - << " or: " << HashesToBase64String(static_spki_hashes); + if (!(dynamic_spki_hashes.empty() && static_spki_hashes.empty()) && + !HashesIntersect(dynamic_spki_hashes, hashes) && + !HashesIntersect(static_spki_hashes, hashes)) { + LOG(ERROR) << "Rejecting public key chain for domain " << domain + << ". Validated chain: " << HashesToBase64String(hashes) + << ", expected: " << HashesToBase64String(dynamic_spki_hashes) + << " or: " << HashesToBase64String(static_spki_hashes); - return false; - } + return false; } return true; diff --git a/net/base/transport_security_state.h b/net/base/transport_security_state.h index 4500583..2e4b42e 100644 --- a/net/base/transport_security_state.h +++ b/net/base/transport_security_state.h @@ -91,10 +91,9 @@ class NET_EXPORT TransportSecurityState // // |bad_static_spki_hashes| contains public keys that we don't want to // trust. - bool IsChainOfPublicKeysPermitted( - const std::vector<HashValueVector>& hashes) const; + bool IsChainOfPublicKeysPermitted(const FingerprintVector& hashes) const; - // Returns true if any of the HashValueVectors |static_spki_hashes|, + // Returns true if any of the FingerprintVectors |static_spki_hashes|, // |bad_static_spki_hashes|, or |dynamic_spki_hashes| contains any // items. bool HasPins() const; @@ -132,10 +131,10 @@ class NET_EXPORT TransportSecurityState // |dynamic_spki_hashes| take precedence over |static_spki_hashes|. // That is, |IsChainOfPublicKeysPermitted| first checks dynamic pins and // then checks static pins. - HashValueVector static_spki_hashes; + FingerprintVector static_spki_hashes; // Optional; hashes of dynamically pinned SubjectPublicKeyInfos. - HashValueVector dynamic_spki_hashes; + FingerprintVector dynamic_spki_hashes; // The absolute time (UTC) when the |dynamic_spki_hashes| expire. base::Time dynamic_spki_hashes_expiry; @@ -143,7 +142,7 @@ class NET_EXPORT TransportSecurityState // Optional; hashes of static known-bad SubjectPublicKeyInfos which // MUST NOT intersect with the set of SPKIs in the TLS server's // certificate chain. - HashValueVector bad_static_spki_hashes; + FingerprintVector bad_static_spki_hashes; // The following members are not valid when stored in |enabled_hosts_|: @@ -256,7 +255,7 @@ class NET_EXPORT TransportSecurityState // Decodes a pin string |value| (e.g. "sha1/hvfkN/qlp/zhXR3cuerq6jd2Z7g="). // If parsing succeeded, updates |*out| and returns true; otherwise returns // false without updating |*out|. - static bool ParsePin(const std::string& value, HashValue* out); + static bool ParsePin(const std::string& value, Fingerprint* out); // The maximum number of seconds for which we'll cache an HSTS request. static const long int kMaxHSTSAgeSecs; diff --git a/net/base/transport_security_state_unittest.cc b/net/base/transport_security_state_unittest.cc index 2840413..ec20313 100644 --- a/net/base/transport_security_state_unittest.cc +++ b/net/base/transport_security_state_unittest.cc @@ -6,13 +6,11 @@ #include <algorithm> #include <string> -#include <vector> #include "base/base64.h" #include "base/file_path.h" #include "base/sha1.h" #include "base/string_piece.h" -#include "crypto/sha2.h" #include "net/base/asn1_util.h" #include "net/base/cert_test_util.h" #include "net/base/cert_verifier.h" @@ -22,7 +20,6 @@ #include "net/base/ssl_info.h" #include "net/base/test_completion_callback.h" #include "net/base/test_root_certs.h" -#include "net/base/x509_cert_types.h" #include "net/base/x509_certificate.h" #include "net/http/http_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -94,8 +91,7 @@ TEST_F(TransportSecurityStateTest, BogusHeaders) { } static bool GetPublicKeyHash(const net::X509Certificate::OSCertHandle& cert, - HashValue* fingerprint, - HashValueTag tag) { + SHA1Fingerprint* fingerprint) { std::string der_bytes; if (!net::X509Certificate::GetDEREncoded(cert, &der_bytes)) return false; @@ -104,52 +100,28 @@ static bool GetPublicKeyHash(const net::X509Certificate::OSCertHandle& cert, if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki)) return false; - fingerprint->tag = tag; - switch (tag) { - case HASH_VALUE_SHA1: - base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(spki.data()), - spki.size(), fingerprint->data()); - break; - case HASH_VALUE_SHA256: - crypto::SHA256HashString(spki, fingerprint->data(), - crypto::kSHA256Length); - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - } - + base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(spki.data()), + spki.size(), fingerprint->data); return true; } -static std::string GetPinFromCert(X509Certificate* cert, HashValueTag tag) { - HashValue spki_hash; - EXPECT_TRUE(GetPublicKeyHash(cert->os_cert_handle(), &spki_hash, tag)); +static std::string GetPinFromCert(X509Certificate* cert) { + SHA1Fingerprint spki_hash; + EXPECT_TRUE(GetPublicKeyHash(cert->os_cert_handle(), &spki_hash)); std::string base64; - base::Base64Encode(base::StringPiece( - reinterpret_cast<char*>(spki_hash.data()), spki_hash.size()), &base64); - - std::string label; - switch (tag) { - case HASH_VALUE_SHA1: - label = "pin-sha1="; - break; - case HASH_VALUE_SHA256: - label = "pin-sha256="; - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - } - - return label + HttpUtil::Quote(base64); + base::Base64Encode(base::StringPiece(reinterpret_cast<char*>(spki_hash.data), + sizeof(spki_hash.data)), + &base64); + return "pin-sha1=" + HttpUtil::Quote(base64); } -static void TestBogusPinsHeaders(HashValueTag tag) { +TEST_F(TransportSecurityStateTest, BogusPinsHeaders) { TransportSecurityState::DomainState state; SSLInfo ssl_info; ssl_info.cert = ImportCertFromFile(GetTestCertsDirectory(), "test_mail_google_com.pem"); - std::string good_pin = GetPinFromCert(ssl_info.cert, tag); + std::string good_pin = GetPinFromCert(ssl_info.cert); base::Time now = base::Time::Now(); // The backup pin is fake --- it just has to not be in the chain. @@ -208,14 +180,6 @@ static void TestBogusPinsHeaders(HashValueTag tag) { EXPECT_FALSE(state.include_subdomains); } -TEST_F(TransportSecurityStateTest, BogusPinsHeadersSHA1) { - TestBogusPinsHeaders(HASH_VALUE_SHA1); -} - -TEST_F(TransportSecurityStateTest, BogusPinsHeadersSHA256) { - TestBogusPinsHeaders(HASH_VALUE_SHA256); -} - TEST_F(TransportSecurityStateTest, ValidSTSHeaders) { TransportSecurityState::DomainState state; base::Time expiry; @@ -276,7 +240,7 @@ TEST_F(TransportSecurityStateTest, ValidSTSHeaders) { EXPECT_TRUE(state.include_subdomains); } -static void TestValidPinsHeaders(HashValueTag tag) { +TEST_F(TransportSecurityStateTest, ValidPinsHeaders) { TransportSecurityState::DomainState state; base::Time expiry; base::Time now = base::Time::Now(); @@ -316,8 +280,7 @@ static void TestValidPinsHeaders(HashValueTag tag) { // Normally, ssl_client_socket_nss would do this, but for a unit test we // fake it. ssl_info.public_key_hashes = result.public_key_hashes; - std::string good_pin = GetPinFromCert(ssl_info.cert, /*tag*/HASH_VALUE_SHA1); - DLOG(WARNING) << "good pin: " << good_pin; + std::string good_pin = GetPinFromCert(ssl_info.cert); // The backup pin is fake --- we just need an SPKI hash that does not match // the hash of any SPKI in the certificate chain. @@ -393,14 +356,6 @@ static void TestValidPinsHeaders(HashValueTag tag) { EXPECT_EQ(expiry, state.dynamic_spki_hashes_expiry); } -TEST_F(TransportSecurityStateTest, ValidPinsHeadersSHA1) { - TestValidPinsHeaders(HASH_VALUE_SHA1); -} - -TEST_F(TransportSecurityStateTest, ValidPinsHeadersSHA256) { - TestValidPinsHeaders(HASH_VALUE_SHA256); -} - TEST_F(TransportSecurityStateTest, SimpleMatches) { TransportSecurityState state; TransportSecurityState::DomainState domain_state; @@ -828,7 +783,7 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) { EXPECT_TRUE(state.GetDomainState("chrome.google.com", true, &domain_state)); EXPECT_TRUE(HasPins("chrome.google.com")); - std::vector<HashValueVector> hashes; + FingerprintVector hashes; // Checks that a built-in list does exist. EXPECT_FALSE(domain_state.IsChainOfPublicKeysPermitted(hashes)); EXPECT_FALSE(HasPins("www.paypal.com")); @@ -874,17 +829,20 @@ TEST_F(TransportSecurityStateTest, BuiltinCertPins) { } static bool AddHash(const std::string& type_and_base64, - HashValueVector* out) { - HashValue hash; - - if (!TransportSecurityState::ParsePin(type_and_base64, &hash)) - return false; - - out->push_back(hash); - return true; + FingerprintVector* out) { + std::string hash_str; + if (type_and_base64.find("sha1/") == 0 && + base::Base64Decode(type_and_base64.substr(5, type_and_base64.size() - 5), + &hash_str) && + hash_str.size() == base::kSHA1Length) { + SHA1Fingerprint hash; + memcpy(hash.data, hash_str.data(), sizeof(hash.data)); + out->push_back(hash); + return true; + } + return false; } - TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { // kGoodPath is plus.google.com via Google Internet Authority. static const char* kGoodPath[] = { @@ -904,7 +862,7 @@ TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { NULL, }; - HashValueVector good_hashes, bad_hashes; + std::vector<net::SHA1Fingerprint> good_hashes, bad_hashes; for (size_t i = 0; kGoodPath[i]; i++) { EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); @@ -918,13 +876,8 @@ TEST_F(TransportSecurityStateTest, PinValidationWithRejectedCerts) { EXPECT_TRUE(state.GetDomainState("plus.google.com", true, &domain_state)); EXPECT_TRUE(domain_state.HasPins()); - std::vector<HashValueVector> good; - good.push_back(good_hashes); - EXPECT_TRUE(domain_state.IsChainOfPublicKeysPermitted(good)); - - std::vector<HashValueVector> bad; - bad.push_back(bad_hashes); - EXPECT_FALSE(domain_state.IsChainOfPublicKeysPermitted(bad)); + EXPECT_TRUE(domain_state.IsChainOfPublicKeysPermitted(good_hashes)); + EXPECT_FALSE(domain_state.IsChainOfPublicKeysPermitted(bad_hashes)); } TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { @@ -945,7 +898,7 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { NULL, }; - HashValueVector good_hashes, bad_hashes; + std::vector<net::SHA1Fingerprint> good_hashes, bad_hashes; for (size_t i = 0; kGoodPath[i]; i++) { EXPECT_TRUE(AddHash(kGoodPath[i], &good_hashes)); @@ -959,13 +912,8 @@ TEST_F(TransportSecurityStateTest, PinValidationWithoutRejectedCerts) { EXPECT_TRUE(state.GetDomainState("blog.torproject.org", true, &domain_state)); EXPECT_TRUE(domain_state.HasPins()); - std::vector<HashValueVector> good; - good.push_back(good_hashes); - EXPECT_TRUE(domain_state.IsChainOfPublicKeysPermitted(good)); - - std::vector<HashValueVector> bad; - bad.push_back(bad_hashes); - EXPECT_FALSE(domain_state.IsChainOfPublicKeysPermitted(bad)); + EXPECT_TRUE(domain_state.IsChainOfPublicKeysPermitted(good_hashes)); + EXPECT_FALSE(domain_state.IsChainOfPublicKeysPermitted(bad_hashes)); } TEST_F(TransportSecurityStateTest, OptionalHSTSCertPins) { diff --git a/net/base/x509_cert_types.cc b/net/base/x509_cert_types.cc index d7d4e08..174000a 100644 --- a/net/base/x509_cert_types.cc +++ b/net/base/x509_cert_types.cc @@ -38,7 +38,7 @@ int CompareSHA1Hashes(const void* a, const void* b) { } // namespace // static -bool IsSHA1HashInSortedArray(const SHA1HashValue& hash, +bool IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, const uint8* array, size_t array_byte_len) { DCHECK_EQ(0u, array_byte_len % base::kSHA1Length); diff --git a/net/base/x509_cert_types.h b/net/base/x509_cert_types.h index 91983cc..cfde622 100644 --- a/net/base/x509_cert_types.h +++ b/net/base/x509_cert_types.h @@ -7,12 +7,10 @@ #include <string.h> -#include <algorithm> #include <set> #include <string> #include <vector> -#include "base/logging.h" #include "base/string_piece.h" #include "build/build_config.h" #include "net/base/net_export.h" @@ -30,132 +28,32 @@ namespace net { class X509Certificate; // SHA-1 fingerprint (160 bits) of a certificate. -struct NET_EXPORT SHA1HashValue { - bool Equals(const SHA1HashValue& other) const { +struct NET_EXPORT SHA1Fingerprint { + bool Equals(const SHA1Fingerprint& other) const { return memcmp(data, other.data, sizeof(data)) == 0; } unsigned char data[20]; }; -class NET_EXPORT SHA1HashValueLessThan { - public: - bool operator() (const SHA1HashValue& lhs, - const SHA1HashValue& rhs) const { - return memcmp(lhs.data, rhs.data, sizeof(lhs.data)) < 0; - } -}; - -struct NET_EXPORT SHA256HashValue { - bool Equals(const SHA256HashValue& other) const { - return memcmp(data, other.data, sizeof(data)) == 0; - } +// In the future there will be a generic Fingerprint type, with at least two +// implementations: SHA1 and SHA256. See http://crbug.com/117914. Until that +// work is done (in a separate patch) this typedef bridges the gap. +typedef SHA1Fingerprint Fingerprint; - unsigned char data[32]; -}; +typedef std::vector<Fingerprint> FingerprintVector; -class NET_EXPORT SHA256HashValueLessThan { +class NET_EXPORT SHA1FingerprintLessThan { public: - bool operator() (const SHA256HashValue& lhs, - const SHA256HashValue& rhs) const { + bool operator() (const SHA1Fingerprint& lhs, + const SHA1Fingerprint& rhs) const { return memcmp(lhs.data, rhs.data, sizeof(lhs.data)) < 0; } }; -enum HashValueTag { - HASH_VALUE_SHA1, - HASH_VALUE_SHA256, - - // This must always be last. - HASH_VALUE_TAGS_COUNT -}; - -struct NET_EXPORT HashValue { - bool Equals(const HashValue& other) const { - if (tag != other.tag) - return false; - switch (tag) { - case HASH_VALUE_SHA1: - return fingerprint.sha1.Equals(other.fingerprint.sha1); - break; - case HASH_VALUE_SHA256: - return fingerprint.sha256.Equals(other.fingerprint.sha256); - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - return false; - } - } - - size_t size() const { - switch (tag) { - case HASH_VALUE_SHA1: - return sizeof(fingerprint.sha1.data); - break; - case HASH_VALUE_SHA256: - return sizeof(fingerprint.sha256.data); - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - return sizeof(fingerprint.sha1.data); - } - } - - unsigned char* data() { - switch (tag) { - case HASH_VALUE_SHA1: - return fingerprint.sha1.data; - break; - case HASH_VALUE_SHA256: - return fingerprint.sha256.data; - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - return NULL; - } - } - - const unsigned char* data() const { - switch (tag) { - case HASH_VALUE_SHA1: - return fingerprint.sha1.data; - break; - case HASH_VALUE_SHA256: - return fingerprint.sha256.data; - break; - default: - NOTREACHED() << "Unknown HashValueTag " << tag; - return NULL; - } - } - - HashValueTag tag; - - union { - SHA1HashValue sha1; - SHA256HashValue sha256; - } fingerprint; -}; - -class NET_EXPORT HashValueLessThan { - public: - bool operator() (const HashValue& lhs, - const HashValue& rhs) const { - size_t lhs_size = lhs.size(); - size_t rhs_size = rhs.size(); - int r = memcmp(lhs.data(), rhs.data(), std::min(lhs_size, rhs_size)); - - if (r == 0 && lhs_size != rhs_size) - return lhs_size < rhs_size; - return r < 0; - } -}; - -typedef std::vector<HashValue> HashValueVector; - // IsSHA1HashInSortedArray returns true iff |hash| is in |array|, a sorted // array of SHA1 hashes. -bool NET_EXPORT IsSHA1HashInSortedArray(const SHA1HashValue& hash, +bool NET_EXPORT IsSHA1HashInSortedArray(const SHA1Fingerprint& hash, const uint8* array, size_t array_byte_len); @@ -232,10 +130,10 @@ class NET_EXPORT CertPolicy { private: // The set of fingerprints of allowed certificates. - std::set<SHA1HashValue, SHA1HashValueLessThan> allowed_; + std::set<SHA1Fingerprint, SHA1FingerprintLessThan> allowed_; // The set of fingerprints of denied certificates. - std::set<SHA1HashValue, SHA1HashValueLessThan> denied_; + std::set<SHA1Fingerprint, SHA1FingerprintLessThan> denied_; }; #if defined(OS_MACOSX) && !defined(OS_IOS) diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 29b11a8..7f1c41e 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -91,7 +91,7 @@ class X509CertificateCache { // the cached OS certificate handle will be freed. int ref_count; }; - typedef std::map<SHA1HashValue, Entry, SHA1HashValueLessThan> CertMap; + typedef std::map<SHA1Fingerprint, Entry, SHA1FingerprintLessThan> CertMap; // Obtain an instance of X509CertificateCache via a LazyInstance. X509CertificateCache() {} @@ -114,7 +114,7 @@ base::LazyInstance<X509CertificateCache>::Leaky void X509CertificateCache::InsertOrUpdate( X509Certificate::OSCertHandle* cert_handle) { DCHECK(cert_handle); - SHA1HashValue fingerprint = + SHA1Fingerprint fingerprint = X509Certificate::CalculateFingerprint(*cert_handle); X509Certificate::OSCertHandle old_handle = NULL; @@ -160,7 +160,7 @@ void X509CertificateCache::InsertOrUpdate( } void X509CertificateCache::Remove(X509Certificate::OSCertHandle cert_handle) { - SHA1HashValue fingerprint = + SHA1Fingerprint fingerprint = X509Certificate::CalculateFingerprint(cert_handle); base::AutoLock lock(lock_); diff --git a/net/base/x509_certificate.h b/net/base/x509_certificate.h index debdb44..4055f0a 100644 --- a/net/base/x509_certificate.h +++ b/net/base/x509_certificate.h @@ -247,10 +247,10 @@ class NET_EXPORT X509Certificate const base::Time& valid_expiry() const { return valid_expiry_; } // The fingerprint of this certificate. - const SHA1HashValue& fingerprint() const { return fingerprint_; } + const SHA1Fingerprint& fingerprint() const { return fingerprint_; } // The fingerprint of the intermediate CA certificates. - const SHA1HashValue& ca_fingerprint() const { + const SHA1Fingerprint& ca_fingerprint() const { return ca_fingerprint_; } @@ -425,11 +425,11 @@ class NET_EXPORT X509Certificate // Calculates the SHA-1 fingerprint of the certificate. Returns an empty // (all zero) fingerprint on failure. - static SHA1HashValue CalculateFingerprint(OSCertHandle cert_handle); + static SHA1Fingerprint CalculateFingerprint(OSCertHandle cert_handle); // Calculates the SHA-1 fingerprint of the intermediate CA certificates. // Returns an empty (all zero) fingerprint on failure. - static SHA1HashValue CalculateCAFingerprint( + static SHA1Fingerprint CalculateCAFingerprint( const OSCertHandles& intermediates); private: @@ -495,10 +495,10 @@ class NET_EXPORT X509Certificate base::Time valid_expiry_; // The fingerprint of this certificate. - SHA1HashValue fingerprint_; + SHA1Fingerprint fingerprint_; // The fingerprint of the intermediate CA certificates. - SHA1HashValue ca_fingerprint_; + SHA1Fingerprint ca_fingerprint_; // The serial number of this certificate, DER encoded. std::string serial_number_; diff --git a/net/base/x509_certificate_mac.cc b/net/base/x509_certificate_mac.cc index 645d737..c694579 100644 --- a/net/base/x509_certificate_mac.cc +++ b/net/base/x509_certificate_mac.cc @@ -577,9 +577,9 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { } // static -SHA1HashValue X509Certificate::CalculateFingerprint( +SHA1Fingerprint X509Certificate::CalculateFingerprint( OSCertHandle cert) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); CSSM_DATA cert_data; @@ -596,9 +596,9 @@ SHA1HashValue X509Certificate::CalculateFingerprint( } // static -SHA1HashValue X509Certificate::CalculateCAFingerprint( +SHA1Fingerprint X509Certificate::CalculateCAFingerprint( const OSCertHandles& intermediates) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); // The CC_SHA(3cc) man page says all CC_SHA1_xxx routines return 1, so @@ -720,7 +720,7 @@ bool X509Certificate::GetSSLClientCertificates( continue; // Skip duplicates (a cert may be in multiple keychains). - const SHA1HashValue& fingerprint = cert->fingerprint(); + const SHA1Fingerprint& fingerprint = cert->fingerprint(); unsigned i; for (i = 0; i < certs->size(); ++i) { if ((*certs)[i]->fingerprint().Equals(fingerprint)) diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc index 060f4f7..eddab65 100644 --- a/net/base/x509_certificate_nss.cc +++ b/net/base/x509_certificate_nss.cc @@ -384,9 +384,9 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { } // static -SHA1HashValue X509Certificate::CalculateFingerprint( +SHA1Fingerprint X509Certificate::CalculateFingerprint( OSCertHandle cert) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); DCHECK(NULL != cert->derCert.data); @@ -400,9 +400,9 @@ SHA1HashValue X509Certificate::CalculateFingerprint( } // static -SHA1HashValue X509Certificate::CalculateCAFingerprint( +SHA1Fingerprint X509Certificate::CalculateCAFingerprint( const OSCertHandles& intermediates) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); HASHContext* sha1_ctx = HASH_Create(HASH_AlgSHA1); diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc index aef938d..43198dc 100644 --- a/net/base/x509_certificate_openssl.cc +++ b/net/base/x509_certificate_openssl.cc @@ -288,8 +288,8 @@ void X509Certificate::ResetCertStore() { } // static -SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { - SHA1HashValue sha1; +SHA1Fingerprint X509Certificate::CalculateFingerprint(OSCertHandle cert) { + SHA1Fingerprint sha1; unsigned int sha1_size = static_cast<unsigned int>(sizeof(sha1.data)); int ret = X509_digest(cert, EVP_sha1(), sha1.data, &sha1_size); CHECK(ret); @@ -298,9 +298,9 @@ SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { } // static -SHA1HashValue X509Certificate::CalculateCAFingerprint( +SHA1Fingerprint X509Certificate::CalculateCAFingerprint( const OSCertHandles& intermediates) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); SHA_CTX sha1_ctx; diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc index f8f43fc..76a50c1b 100644 --- a/net/base/x509_certificate_unittest.cc +++ b/net/base/x509_certificate_unittest.cc @@ -186,7 +186,7 @@ void CheckGoogleCert(const scoped_refptr<X509Certificate>& google_cert, const Time& valid_expiry = google_cert->valid_expiry(); EXPECT_EQ(valid_to, valid_expiry.ToDoubleT()); - const SHA1HashValue& fingerprint = google_cert->fingerprint(); + const SHA1Fingerprint& fingerprint = google_cert->fingerprint(); for (size_t i = 0; i < 20; ++i) EXPECT_EQ(expected_fingerprint[i], fingerprint.data[i]); @@ -243,7 +243,7 @@ TEST(X509CertificateTest, WebkitCertParsing) { const Time& valid_expiry = webkit_cert->valid_expiry(); EXPECT_EQ(1300491319, valid_expiry.ToDoubleT()); // Mar 18 23:35:19 2011 GMT - const SHA1HashValue& fingerprint = webkit_cert->fingerprint(); + const SHA1Fingerprint& fingerprint = webkit_cert->fingerprint(); for (size_t i = 0; i < 20; ++i) EXPECT_EQ(webkit_fingerprint[i], fingerprint.data[i]); @@ -298,7 +298,7 @@ TEST(X509CertificateTest, ThawteCertParsing) { const Time& valid_expiry = thawte_cert->valid_expiry(); EXPECT_EQ(1263772799, valid_expiry.ToDoubleT()); // Jan 17 23:59:59 2010 GMT - const SHA1HashValue& fingerprint = thawte_cert->fingerprint(); + const SHA1Fingerprint& fingerprint = thawte_cert->fingerprint(); for (size_t i = 0; i < 20; ++i) EXPECT_EQ(thawte_fingerprint[i], fingerprint.data[i]); @@ -888,7 +888,7 @@ TEST_P(X509CertificateParseTest, CanParseFormat) { // Compare the parsed certificate with the expected certificate, by // comparing fingerprints. const X509Certificate* cert = certs[i]; - const SHA1HashValue& actual_fingerprint = cert->fingerprint(); + const SHA1Fingerprint& actual_fingerprint = cert->fingerprint(); uint8* expected_fingerprint = test_data_.chain_fingerprints[i]; for (size_t j = 0; j < 20; ++j) diff --git a/net/base/x509_certificate_win.cc b/net/base/x509_certificate_win.cc index 26c1587..5079622 100644 --- a/net/base/x509_certificate_win.cc +++ b/net/base/x509_certificate_win.cc @@ -338,13 +338,13 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { } // static -SHA1HashValue X509Certificate::CalculateFingerprint( +SHA1Fingerprint X509Certificate::CalculateFingerprint( OSCertHandle cert) { DCHECK(NULL != cert->pbCertEncoded); DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); BOOL rv; - SHA1HashValue sha1; + SHA1Fingerprint sha1; DWORD sha1_size = sizeof(sha1.data); rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, cert->cbCertEncoded, sha1.data, &sha1_size); @@ -358,9 +358,9 @@ SHA1HashValue X509Certificate::CalculateFingerprint( // functions to ensure it is fast. Reimplement this function with // CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. // static -SHA1HashValue X509Certificate::CalculateCAFingerprint( +SHA1Fingerprint X509Certificate::CalculateCAFingerprint( const OSCertHandles& intermediates) { - SHA1HashValue sha1; + SHA1Fingerprint sha1; memset(sha1.data, 0, sizeof(sha1.data)); SHA1Context* sha1_ctx = SHA1_NewContext(); |