diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-08 10:28:10 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-20 13:40:30 +0000 |
commit | e733310db58160074f574c429d48f8308c0afe17 (patch) | |
tree | f8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/net/cert | |
parent | 2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff) | |
download | qtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz |
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/cert')
57 files changed, 1545 insertions, 1284 deletions
diff --git a/chromium/net/cert/asn1_util.cc b/chromium/net/cert/asn1_util.cc index 6b0b71d9024..97e12dfc45a 100644 --- a/chromium/net/cert/asn1_util.cc +++ b/chromium/net/cert/asn1_util.cc @@ -70,6 +70,75 @@ bool SeekToSPKI(der::Input in, der::Parser* tbs_certificate) { return true; } +// Parses input |in| which should point to the beginning of a +// Certificate. If parsing fails, this function returns false, with +// |*extensions_present| and |*extensions_parser| left in an undefined +// state. If parsing succeeds and extensions are present, this function +// sets |*extensions_present| to true and sets |*extensions_parser| +// ready to parse the Extensions. If extensions are not present, it sets +// |*extensions_present| to false and |*extensions_parser| is left in an +// undefined state. +bool SeekToExtensions(der::Input in, + bool* extensions_present, + der::Parser* extensions_parser) { + bool present; + der::Parser tbs_cert_parser; + if (!SeekToSPKI(in, &tbs_cert_parser)) + return false; + + // From RFC 5280, section 4.1 + // TBSCertificate ::= SEQUENCE { + // ... + // subjectPublicKeyInfo SubjectPublicKeyInfo, + // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + // extensions [3] EXPLICIT Extensions OPTIONAL } + + // subjectPublicKeyInfo + if (!tbs_cert_parser.SkipTag(der::kSequence)) + return false; + // issuerUniqueID + if (!tbs_cert_parser.SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 1, &present)) { + return false; + } + // subjectUniqueID + if (!tbs_cert_parser.SkipOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 2, &present)) { + return false; + } + + der::Input extensions; + if (!tbs_cert_parser.ReadOptionalTag( + der::kTagConstructed | der::kTagContextSpecific | 3, &extensions, + &present)) { + return false; + } + + if (!present) { + *extensions_present = false; + return true; + } + + // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + // Extension ::= SEQUENCE { + // extnID OBJECT IDENTIFIER, + // critical BOOLEAN DEFAULT FALSE, + // extnValue OCTET STRING } + + // |extensions| was EXPLICITly tagged, so we still need to remove the + // ASN.1 SEQUENCE header. + der::Parser explicit_extensions_parser(extensions); + if (!explicit_extensions_parser.ReadSequence(extensions_parser)) + return false; + + if (explicit_extensions_parser.HasMore()) + return false; + + *extensions_present = true; + return true; +} + } // namespace bool ExtractSPKIFromDERCert(base::StringPiece cert, @@ -118,60 +187,14 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, std::vector<base::StringPiece>* urls_out) { urls_out->clear(); std::vector<base::StringPiece> tmp_urls_out; - bool present; - der::Parser tbs_cert_parser; - if (!SeekToSPKI(der::Input(cert), &tbs_cert_parser)) - return false; - - // From RFC 5280, section 4.1 - // TBSCertificate ::= SEQUENCE { - // ... - // subjectPublicKeyInfo SubjectPublicKeyInfo, - // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, - // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, - // extensions [3] EXPLICIT Extensions OPTIONAL } - - // subjectPublicKeyInfo - if (!tbs_cert_parser.SkipTag(der::kSequence)) - return false; - // issuerUniqueID - if (!tbs_cert_parser.SkipOptionalTag( - der::kTagConstructed | der::kTagContextSpecific | 1, &present)) { - return false; - } - // subjectUniqueID - if (!tbs_cert_parser.SkipOptionalTag( - der::kTagConstructed | der::kTagContextSpecific | 2, &present)) { - return false; - } - - der::Input extensions; - if (!tbs_cert_parser.ReadOptionalTag( - der::kTagConstructed | der::kTagContextSpecific | 3, &extensions, - &present)) { + der::Parser extensions_parser; + if (!SeekToExtensions(der::Input(cert), &present, &extensions_parser)) return false; - } if (!present) return true; - // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension - // Extension ::= SEQUENCE { - // extnID OBJECT IDENTIFIER, - // critical BOOLEAN DEFAULT FALSE, - // extnValue OCTET STRING } - - // |extensions| was EXPLICITly tagged, so we still need to remove the - // ASN.1 SEQUENCE header. - der::Parser explicit_extensions_parser(extensions); - der::Parser extensions_parser; - if (!explicit_extensions_parser.ReadSequence(&extensions_parser)) - return false; - - if (explicit_extensions_parser.HasMore()) - return false; - while (extensions_parser.HasMore()) { der::Parser extension_parser; if (!extensions_parser.ReadSequence(&extension_parser)) @@ -289,6 +312,34 @@ bool ExtractCRLURLsFromDERCert(base::StringPiece cert, return true; } +bool HasTLSFeatureExtension(base::StringPiece cert) { + bool present; + der::Parser extensions_parser; + if (!SeekToExtensions(der::Input(cert), &present, &extensions_parser)) + return false; + if (!present) + return false; + + while (extensions_parser.HasMore()) { + der::Parser extension_parser; + if (!extensions_parser.ReadSequence(&extension_parser)) + return false; + + der::Input oid; + if (!extension_parser.ReadTag(der::kOid, &oid)) + return false; + + // kTLSFeatureExtensionOID is the DER encoding of the OID for the + // X.509 TLS Feature Extension. + static const uint8_t kTLSFeatureExtensionOID[] = {0x2B, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x18}; + if (oid == der::Input(kTLSFeatureExtensionOID)) + return true; + } + + return false; +} + } // namespace asn1 } // namespace net diff --git a/chromium/net/cert/asn1_util.h b/chromium/net/cert/asn1_util.h index 23bc2d2cf90..fb64bfbb58b 100644 --- a/chromium/net/cert/asn1_util.h +++ b/chromium/net/cert/asn1_util.h @@ -43,6 +43,13 @@ NET_EXPORT_PRIVATE bool ExtractCRLURLsFromDERCert( base::StringPiece cert, std::vector<base::StringPiece>* urls_out); +// HasTLSFeatureExtension parses the DER encoded certificate in |cert| +// and extracts the TLS feature extension +// (https://tools.ietf.org/html/rfc7633) if present. Returns true if the +// TLS feature extension was present, and false if the extension was not +// present or if there was a parsing failure. +NET_EXPORT_PRIVATE bool HasTLSFeatureExtension(base::StringPiece cert); + } // namespace asn1 } // namespace net diff --git a/chromium/net/cert/caching_cert_verifier.cc b/chromium/net/cert/caching_cert_verifier.cc index 43515f8d4b5..342adf80ea2 100644 --- a/chromium/net/cert/caching_cert_verifier.cc +++ b/chromium/net/cert/caching_cert_verifier.cc @@ -198,7 +198,7 @@ void CachingCertVerifier::VisitEntries(CacheVisitor* visitor) const { } } -void CachingCertVerifier::OnCACertChanged(const X509Certificate* cert) { +void CachingCertVerifier::OnCertDBChanged(const X509Certificate* cert) { ClearCache(); } diff --git a/chromium/net/cert/caching_cert_verifier.h b/chromium/net/cert/caching_cert_verifier.h index e10d6db0ed2..57a61428d47 100644 --- a/chromium/net/cert/caching_cert_verifier.h +++ b/chromium/net/cert/caching_cert_verifier.h @@ -144,7 +144,7 @@ class NET_EXPORT CachingCertVerifier : public CertVerifier, int error); // CertDatabase::Observer methods: - void OnCACertChanged(const X509Certificate* cert) override; + void OnCertDBChanged(const X509Certificate* cert) override; // For unit testing. void ClearCache(); diff --git a/chromium/net/cert/cert_database.cc b/chromium/net/cert/cert_database.cc index 3d423b0c4f4..d2ef9ffdf4a 100644 --- a/chromium/net/cert/cert_database.cc +++ b/chromium/net/cert/cert_database.cc @@ -25,19 +25,8 @@ void CertDatabase::RemoveObserver(Observer* observer) { observer_list_->RemoveObserver(observer); } -void CertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded, - base::RetainedRef(cert)); -} - -void CertDatabase::NotifyObserversOfCertRemoved(const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved, - base::RetainedRef(cert)); -} - -void CertDatabase::NotifyObserversOfCACertChanged( - const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged, +void CertDatabase::NotifyObserversCertDBChanged(const X509Certificate* cert) { + observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged, base::RetainedRef(cert)); } diff --git a/chromium/net/cert/cert_database.h b/chromium/net/cert/cert_database.h index 873a7c7c9cb..819716a9596 100644 --- a/chromium/net/cert/cert_database.h +++ b/chromium/net/cert/cert_database.h @@ -39,17 +39,11 @@ class NET_EXPORT CertDatabase { public: virtual ~Observer() {} - // Will be called when a new certificate is added. If the imported cert can - // be determined, |cert| will be non-NULL, but if not, or if multiple - // certificates were imported, |cert| may be NULL. - virtual void OnCertAdded(const X509Certificate* cert) {} - - // Will be called when a certificate is removed. - virtual void OnCertRemoved(const X509Certificate* cert) {} - - // Will be called when a CA certificate was added, removed, or its trust - // changed. This can also mean that a client certificate's trust changed. - virtual void OnCACertChanged(const X509Certificate* cert) {} + // Called whenever the Cert Database is known to have changed. + // Typically, this will be in response to a CA certificate being added, + // removed, or its trust changed, but may also signal on client + // certificate events when they can be reliably detected. + virtual void OnCertDBChanged(const X509Certificate* cert) {} protected: Observer() {} @@ -61,15 +55,6 @@ class NET_EXPORT CertDatabase { // Returns the CertDatabase singleton. static CertDatabase* GetInstance(); - // Check whether this is a valid user cert that we have the private key for. - // Returns OK or a network error code such as ERR_CERT_CONTAINS_ERRORS. - int CheckUserCert(X509Certificate* cert); - - // Store user (client) certificate. Assumes CheckUserCert has already passed. - // Returns OK, or ERR_ADD_USER_CERT_FAILED if there was a problem saving to - // the platform cert database, or possibly other network error codes. - int AddUserCert(X509Certificate* cert); - // Registers |observer| to receive notifications of certificate changes. The // thread on which this is called is the thread on which |observer| will be // called back with notifications. @@ -101,9 +86,7 @@ class NET_EXPORT CertDatabase { // Synthetically injects notifications to all observers. In general, this // should only be called by the creator of the CertDatabase. Used to inject // notifcations from other DB interfaces. - void NotifyObserversOfCertAdded(const X509Certificate* cert); - void NotifyObserversOfCertRemoved(const X509Certificate* cert); - void NotifyObserversOfCACertChanged(const X509Certificate* cert); + void NotifyObserversCertDBChanged(const X509Certificate* cert); private: friend struct base::DefaultSingletonTraits<CertDatabase>; diff --git a/chromium/net/cert/cert_database_android.cc b/chromium/net/cert/cert_database_android.cc index 89a1a44a54b..b3a75b09ac3 100644 --- a/chromium/net/cert/cert_database_android.cc +++ b/chromium/net/cert/cert_database_android.cc @@ -17,38 +17,18 @@ CertDatabase::CertDatabase() CertDatabase::~CertDatabase() {} -int CertDatabase::CheckUserCert(X509Certificate* cert) { - // NOTE: This method shall never be called on Android. - // - // On other platforms, it is only used by the SSLAddCertHandler class - // to handle veritication and installation of downloaded certificates. - // - // On Android, the certificate data is passed directly to the system's - // CertInstaller activity, which handles verification, naming, - // installation and UI (for success/failure). - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; -} - -int CertDatabase::AddUserCert(X509Certificate* cert) { - // This method is only used by the content SSLAddCertHandler which is - // never used on Android. - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; -} - void CertDatabase::OnAndroidKeyStoreChanged() { - NotifyObserversOfCertAdded(NULL); + NotifyObserversCertDBChanged(NULL); // Dump the OpenSSLClientKeyStore to drop references to now disconnected // PrivateKeys stored in the in-memory key store. Note: this assumes that // every SSLClientAuthCache is dumped as part of notifying - // OnCertAdded. Otherwise client auth decisions will be silently converted to - // no-certificate decisions. See https://crbug.com/382696 + // OnCertDBChanged. Otherwise client auth decisions will be silently converted + // to no-certificate decisions. See https://crbug.com/382696 OpenSSLClientKeyStore::GetInstance()->Flush(); } void CertDatabase::OnAndroidKeyChainChanged() { - observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged, nullptr); + observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged, nullptr); } } // namespace net diff --git a/chromium/net/cert/cert_database_ios.cc b/chromium/net/cert/cert_database_ios.cc index 87dfd39843e..c426ee9f21c 100644 --- a/chromium/net/cert/cert_database_ios.cc +++ b/chromium/net/cert/cert_database_ios.cc @@ -16,16 +16,4 @@ CertDatabase::CertDatabase() CertDatabase::~CertDatabase() {} -int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { - // iOS doesn't handle user certificates. - NOTREACHED(); - return OK; -} - -int CertDatabase::AddUserCert(X509Certificate* cert_obj) { - // iOS doesn't handle user certificates. - NOTREACHED(); - return OK; -} - } // namespace net diff --git a/chromium/net/cert/cert_database_mac.cc b/chromium/net/cert/cert_database_mac.cc index 42e54c1c973..34088e2f6aa 100644 --- a/chromium/net/cert/cert_database_mac.cc +++ b/chromium/net/cert/cert_database_mac.cc @@ -104,7 +104,7 @@ OSStatus CertDatabase::Notifier::KeychainCallback( switch (keychain_event) { case kSecKeychainListChangedEvent: case kSecTrustSettingsChangedEvent: - that->cert_db_->NotifyObserversOfCACertChanged(NULL); + that->cert_db_->NotifyObserversCertDBChanged(NULL); break; default: @@ -132,45 +132,4 @@ CertDatabase::~CertDatabase() { notifier_.release()->Shutdown(); } -int CertDatabase::CheckUserCert(X509Certificate* cert) { - if (!cert) - return ERR_CERT_INVALID; - if (cert->HasExpired()) - return ERR_CERT_DATE_INVALID; - - // Verify the Keychain already has the corresponding private key: - SecIdentityRef identity = NULL; - OSStatus err = SecIdentityCreateWithCertificate(NULL, cert->os_cert_handle(), - &identity); - if (err == errSecItemNotFound) - return ERR_NO_PRIVATE_KEY_FOR_CERT; - - if (err != noErr || !identity) { - // TODO(snej): Map the error code more intelligently. - return ERR_CERT_INVALID; - } - - CFRelease(identity); - return OK; -} - -int CertDatabase::AddUserCert(X509Certificate* cert) { - OSStatus err; - { - base::AutoLock locked(crypto::GetMacSecurityServicesLock()); - err = SecCertificateAddToKeychain(cert->os_cert_handle(), NULL); - } - switch (err) { - case noErr: - CertDatabase::NotifyObserversOfCertAdded(cert); - // Fall through. - case errSecDuplicateItem: - return OK; - default: - OSSTATUS_LOG(ERROR, err) << "CertDatabase failed to add cert to keychain"; - // TODO(snej): Map the error code more intelligently. - return ERR_ADD_USER_CERT_FAILED; - } -} - } // namespace net diff --git a/chromium/net/cert/cert_database_nss.cc b/chromium/net/cert/cert_database_nss.cc index 2073de1890b..cd71820d1de 100644 --- a/chromium/net/cert/cert_database_nss.cc +++ b/chromium/net/cert/cert_database_nss.cc @@ -4,23 +4,8 @@ #include "net/cert/cert_database.h" -#include <cert.h> -#include <pk11pub.h> -#include <secmod.h> - -#include <vector> - -#include "base/logging.h" #include "base/observer_list_threadsafe.h" #include "crypto/nss_util.h" -#include "crypto/scoped_nss_types.h" -#include "net/base/net_errors.h" -#include "net/cert/x509_certificate.h" -#include "net/cert/x509_util_nss.h" -#include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" - -// PSM = Mozilla's Personal Security Manager. -namespace psm = mozilla_security_manager; namespace net { @@ -31,38 +16,4 @@ CertDatabase::CertDatabase() CertDatabase::~CertDatabase() {} -int CertDatabase::CheckUserCert(X509Certificate* cert_obj) { - if (!cert_obj) - return ERR_CERT_INVALID; - if (cert_obj->HasExpired()) - return ERR_CERT_DATE_INVALID; - - // Check if the private key corresponding to the certificate exist - // We shouldn't accept any random client certificate sent by a CA. - - // Note: The NSS source documentation wrongly suggests that this - // also imports the certificate if the private key exists. This - // doesn't seem to be the case. - - CERTCertificate* cert = cert_obj->os_cert_handle(); - PK11SlotInfo* slot = PK11_KeyForCertExists(cert, NULL, NULL); - if (!slot) - return ERR_NO_PRIVATE_KEY_FOR_CERT; - - PK11_FreeSlot(slot); - - return OK; -} - -int CertDatabase::AddUserCert(X509Certificate* cert_obj) { - CertificateList cert_list; - cert_list.push_back(cert_obj); - int result = psm::ImportUserCert(cert_list); - - if (result == OK) - NotifyObserversOfCertAdded(NULL); - - return result; -} - } // namespace net diff --git a/chromium/net/cert/cert_database_openssl.cc b/chromium/net/cert/cert_database_openssl.cc index a59c2eb0c43..35048d04ff6 100644 --- a/chromium/net/cert/cert_database_openssl.cc +++ b/chromium/net/cert/cert_database_openssl.cc @@ -4,15 +4,7 @@ #include "net/cert/cert_database.h" -#include <openssl/x509.h> - -#include "base/logging.h" #include "base/observer_list_threadsafe.h" -#include "crypto/scoped_openssl_types.h" -#include "net/base/crypto_module.h" -#include "net/base/net_errors.h" -#include "net/base/openssl_private_key_store.h" -#include "net/cert/x509_certificate.h" namespace net { @@ -22,37 +14,4 @@ CertDatabase::CertDatabase() CertDatabase::~CertDatabase() {} -// This method is used to check a client certificate before trying to -// install it on the system, which will happen later by calling -// AddUserCert() below. -// -// On the Linux/OpenSSL build, there is simply no system keystore, but -// OpenSSLPrivateKeyStore() implements a small in-memory store for -// (public/private) key pairs generated through keygen. -// -// Try to check for a private key in the in-memory store to check -// for the case when the browser is trying to install a server-generated -// certificate from a <keygen> exchange. -int CertDatabase::CheckUserCert(X509Certificate* cert) { - if (!cert) - return ERR_CERT_INVALID; - if (cert->HasExpired()) - return ERR_CERT_DATE_INVALID; - - // X509_PUBKEY_get() transfers ownership, not X509_get_X509_PUBKEY() - crypto::ScopedEVP_PKEY public_key( - X509_PUBKEY_get(X509_get_X509_PUBKEY(cert->os_cert_handle()))); - - if (!OpenSSLPrivateKeyStore::HasPrivateKey(public_key.get())) - return ERR_NO_PRIVATE_KEY_FOR_CERT; - - return OK; -} - -int CertDatabase::AddUserCert(X509Certificate* cert) { - // There is no certificate store on the Linux/OpenSSL build. - NOTIMPLEMENTED(); - return ERR_NOT_IMPLEMENTED; -} - } // namespace net diff --git a/chromium/net/cert/cert_database_win.cc b/chromium/net/cert/cert_database_win.cc index bda2ef02a49..32c9168ab98 100644 --- a/chromium/net/cert/cert_database_win.cc +++ b/chromium/net/cert/cert_database_win.cc @@ -4,12 +4,7 @@ #include "net/cert/cert_database.h" -#include <windows.h> - #include "base/observer_list_threadsafe.h" -#include "crypto/wincrypt_shim.h" -#include "net/base/net_errors.h" -#include "net/cert/x509_certificate.h" namespace net { @@ -19,42 +14,4 @@ CertDatabase::CertDatabase() CertDatabase::~CertDatabase() {} -int CertDatabase::CheckUserCert(X509Certificate* cert) { - if (!cert) - return ERR_CERT_INVALID; - if (cert->HasExpired()) - return ERR_CERT_DATE_INVALID; - - // TODO(rsleevi): Should CRYPT_FIND_SILENT_KEYSET_FLAG be specified? A UI - // may be shown here / this call may block. - if (!CryptFindCertificateKeyProvInfo(cert->os_cert_handle(), 0, NULL)) - return ERR_NO_PRIVATE_KEY_FOR_CERT; - - return OK; -} - -int CertDatabase::AddUserCert(X509Certificate* cert) { - // TODO(rsleevi): Would it be more appropriate to have the CertDatabase take - // construction parameters (Keychain filepath on Mac OS X, PKCS #11 slot on - // NSS, and Store Type / Path) here? For now, certs will be stashed into the - // user's personal store, which will not automatically mark them as trusted, - // but will allow them to be used for client auth. - HCERTSTORE cert_db = CertOpenSystemStore(NULL, L"MY"); - if (!cert_db) - return ERR_ADD_USER_CERT_FAILED; - - BOOL added = CertAddCertificateContextToStore(cert_db, - cert->os_cert_handle(), - CERT_STORE_ADD_USE_EXISTING, - NULL); - - CertCloseStore(cert_db, 0); - - if (!added) - return ERR_ADD_USER_CERT_FAILED; - - NotifyObserversOfCertAdded(cert); - return OK; -} - } // namespace net diff --git a/chromium/net/cert/cert_verifier.cc b/chromium/net/cert/cert_verifier.cc index 3aea1be694a..c471fa92161 100644 --- a/chromium/net/cert/cert_verifier.cc +++ b/chromium/net/cert/cert_verifier.cc @@ -4,8 +4,6 @@ #include "net/cert/cert_verifier.h" -#include <openssl/sha.h> - #include <algorithm> #include <memory> @@ -13,6 +11,7 @@ #include "base/strings/string_util.h" #include "build/build_config.h" #include "net/cert/cert_verify_proc.h" +#include "third_party/boringssl/src/include/openssl/sha.h" #if defined(OS_NACL) #include "base/logging.h" diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc index 8fdd93cbb1b..413abb4b2fb 100644 --- a/chromium/net/cert/cert_verify_proc.cc +++ b/chromium/net/cert/cert_verify_proc.cc @@ -18,6 +18,7 @@ #include "net/base/net_errors.h" #include "net/base/registry_controlled_domains/registry_controlled_domain.h" #include "net/base/url_util.h" +#include "net/cert/asn1_util.h" #include "net/cert/cert_status_flags.h" #include "net/cert/cert_verifier.h" #include "net/cert/cert_verify_proc_whitelist.h" @@ -40,6 +41,7 @@ #elif defined(OS_MACOSX) #include "net/cert/cert_verify_proc_mac.h" #elif defined(OS_WIN) +#include "base/win/windows_version.h" #include "net/cert/cert_verify_proc_win.h" #else #error Implement certificate verification. @@ -309,6 +311,34 @@ void CheckOCSP(const std::string& raw_response, } } +// Records histograms indicating whether the certificate |cert|, which +// is assumed to have been validated chaining to a private root, +// contains the TLS Feature Extension (https://tools.ietf.org/html/rfc7633) and +// has valid OCSP information stapled. +void RecordTLSFeatureExtensionWithPrivateRoot( + X509Certificate* cert, + const OCSPVerifyResult& ocsp_result) { + std::string cert_der; + if (!X509Certificate::GetDEREncoded(cert->os_cert_handle(), &cert_der)) + return; + + // This checks only for the presence of the TLS Feature Extension, but + // does not check the feature list, and in particular does not verify that + // its value is 'status_request' or 'status_request2'. In practice the + // only use of the TLS feature extension is for OCSP stapling, so + // don't bother to check the value. + bool has_extension = asn1::HasTLSFeatureExtension(cert_der); + + UMA_HISTOGRAM_BOOLEAN("Net.Certificate.TLSFeatureExtensionWithPrivateRoot", + has_extension); + if (!has_extension) + return; + + UMA_HISTOGRAM_BOOLEAN( + "Net.Certificate.TLSFeatureExtensionWithPrivateRootHasOCSP", + (ocsp_result.response_status != OCSPVerifyResult::MISSING)); +} + // Comparison functor used for binary searching whether a given HashValue, // which MUST be a SHA-256 hash, is contained with an array of SHA-256 // hashes. @@ -328,6 +358,17 @@ struct HashToArrayComparator { } }; +bool AreSHA1IntermediatesAllowed() { +#if defined(OS_WIN) + // TODO(rsleevi): Remove this once https://crbug.com/588789 is resolved + // for Windows 7/2008 users. + // Note: This must be kept in sync with cert_verify_proc_unittest.cc + return base::win::GetVersion() < base::win::VERSION_WIN8; +#else + return false; +#endif +}; + } // namespace // static @@ -349,7 +390,8 @@ CertVerifyProc* CertVerifyProc::CreateDefault() { #endif } -CertVerifyProc::CertVerifyProc() {} +CertVerifyProc::CertVerifyProc() + : sha1_legacy_mode_enabled(base::FeatureList::IsEnabled(kSHA1LegacyMode)) {} CertVerifyProc::~CertVerifyProc() {} @@ -444,8 +486,20 @@ int CertVerifyProc::Verify(X509Certificate* cert, // TODO(mattm): apply the SHA-1 deprecation check to all certs unless // CertVerifier::VERIFY_ENABLE_SHA1_LOCAL_ANCHORS flag is present. if (verify_result->has_md5 || - (verify_result->has_sha1_leaf && verify_result->is_issued_by_known_root && - IsPastSHA1DeprecationDate(*cert))) { + // Current SHA-1 behaviour: + // - Reject all publicly trusted SHA-1 + // - ... unless it's in the intermediate and SHA-1 intermediates are + // allowed for that platform. See https://crbug.com/588789 + (!sha1_legacy_mode_enabled && + (verify_result->is_issued_by_known_root && + (verify_result->has_sha1_leaf || + (verify_result->has_sha1 && !AreSHA1IntermediatesAllowed())))) || + // Legacy SHA-1 behaviour: + // - Reject all publicly trusted SHA-1 leaf certs issued after + // 2016-01-01. + (sha1_legacy_mode_enabled && (verify_result->has_sha1_leaf && + verify_result->is_issued_by_known_root && + IsPastSHA1DeprecationDate(*cert)))) { verify_result->cert_status |= CERT_STATUS_WEAK_SIGNATURE_ALGORITHM; // Avoid replacing a more serious error, such as an OS/library failure, // by ensuring that if verification failed, it failed with a certificate @@ -472,6 +526,11 @@ int CertVerifyProc::Verify(X509Certificate* cert, rv = MapCertStatusToNetError(verify_result->cert_status); } + // Record a histogram for the presence of the TLS feature extension in + // a certificate chaining to a private root. + if (rv == OK && !verify_result->is_issued_by_known_root) + RecordTLSFeatureExtensionWithPrivateRoot(cert, verify_result->ocsp_result); + return rv; } @@ -531,13 +590,11 @@ static bool CheckNameConstraints(const std::vector<std::string>& dns_names, if (host_info.IsIPAddress()) continue; - const size_t registry_len = registry_controlled_domains::GetRegistryLength( - dns_name, - registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, - registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); // If the name is not in a known TLD, ignore it. This permits internal // names. - if (registry_len == 0) + if (!registry_controlled_domains::HostHasRegistryControlledDomain( + dns_name, registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, + registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) continue; for (size_t j = 0; domains[j][0]; ++j) { @@ -693,12 +750,12 @@ bool CertVerifyProc::HasTooLongValidity(const X509Certificate& cert) { if (exploded_expiry.day_of_month > exploded_start.day_of_month) ++month_diff; - static const base::Time time_2012_07_01 = - base::Time::FromUTCExploded({2012, 7, 0, 1, 0, 0, 0, 0}); - static const base::Time time_2015_04_01 = - base::Time::FromUTCExploded({2015, 4, 0, 1, 0, 0, 0, 0}); - static const base::Time time_2019_07_01 = - base::Time::FromUTCExploded({2019, 7, 0, 1, 0, 0, 0, 0}); + const base::Time time_2012_07_01 = + base::Time::FromInternalValue(12985574400000000); + const base::Time time_2015_04_01 = + base::Time::FromInternalValue(13072320000000000); + const base::Time time_2019_07_01 = + base::Time::FromInternalValue(13206412800000000); // For certificates issued before the BRs took effect. if (start < time_2012_07_01 && (month_diff > 120 || expiry > time_2019_07_01)) @@ -715,4 +772,8 @@ bool CertVerifyProc::HasTooLongValidity(const X509Certificate& cert) { return false; } +// static +const base::Feature CertVerifyProc::kSHA1LegacyMode{ + "SHA1LegacyMode", base::FEATURE_DISABLED_BY_DEFAULT}; + } // namespace net diff --git a/chromium/net/cert/cert_verify_proc.h b/chromium/net/cert/cert_verify_proc.h index 629fde8bf38..352610f22e5 100644 --- a/chromium/net/cert/cert_verify_proc.h +++ b/chromium/net/cert/cert_verify_proc.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/feature_list.h" #include "base/gtest_prod_util.h" #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -83,6 +84,8 @@ class NET_EXPORT CertVerifyProc friend class base::RefCountedThreadSafe<CertVerifyProc>; FRIEND_TEST_ALL_PREFIXES(CertVerifyProcTest, DigiNotarCerts); FRIEND_TEST_ALL_PREFIXES(CertVerifyProcTest, TestHasTooLongValidity); + FRIEND_TEST_ALL_PREFIXES(CertVerifyProcTest, + VerifyRejectsSHA1AfterDeprecationLegacyMode); // Performs the actual verification using the desired underlying // cryptographic library. On entry, |verify_result->verified_cert| @@ -124,6 +127,10 @@ class NET_EXPORT CertVerifyProc // (i.e. by 1 July 2019). static bool HasTooLongValidity(const X509Certificate& cert); + // Emergency kill-switch for SHA-1 deprecation. Disabled by default. + static const base::Feature kSHA1LegacyMode; + const bool sha1_legacy_mode_enabled; + DISALLOW_COPY_AND_ASSIGN(CertVerifyProc); }; diff --git a/chromium/net/cert/cert_verify_proc_android.cc b/chromium/net/cert/cert_verify_proc_android.cc index 3825b20a475..2cb12f75c23 100644 --- a/chromium/net/cert/cert_verify_proc_android.cc +++ b/chromium/net/cert/cert_verify_proc_android.cc @@ -4,8 +4,6 @@ #include "net/cert/cert_verify_proc_android.h" -#include <openssl/x509v3.h> - #include <string> #include <vector> @@ -20,6 +18,7 @@ #include "net/cert/cert_status_flags.h" #include "net/cert/cert_verify_result.h" #include "net/cert/x509_certificate.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" namespace net { diff --git a/chromium/net/cert/cert_verify_proc_ios.cc b/chromium/net/cert/cert_verify_proc_ios.cc index 73f8a150481..2ab30ed07e4 100644 --- a/chromium/net/cert/cert_verify_proc_ios.cc +++ b/chromium/net/cert/cert_verify_proc_ios.cc @@ -125,7 +125,7 @@ void GetCertChainInfo(CFArrayRef cert_chain, CertVerifyResult* verify_result) { if (!X509Certificate::GetDEREncoded(chain_cert, &der_bytes)) return; const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_bytes.data()); - ScopedX509 x509_cert(d2i_X509(NULL, &bytes, der_bytes.size())); + bssl::UniquePtr<X509> x509_cert(d2i_X509(NULL, &bytes, der_bytes.size())); base::StringPiece spki_bytes; if (!asn1::ExtractSPKIFromDERCert(der_bytes, &spki_bytes)) diff --git a/chromium/net/cert/cert_verify_proc_openssl.cc b/chromium/net/cert/cert_verify_proc_openssl.cc index 824a95cdc45..988bdec1e2e 100644 --- a/chromium/net/cert/cert_verify_proc_openssl.cc +++ b/chromium/net/cert/cert_verify_proc_openssl.cc @@ -4,15 +4,12 @@ #include "net/cert/cert_verify_proc_openssl.h" -#include <openssl/x509v3.h> - #include <string> #include <vector> #include "base/logging.h" #include "base/sha1.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" #include "crypto/sha2.h" #include "net/base/net_errors.h" #include "net/cert/asn1_util.h" @@ -21,6 +18,7 @@ #include "net/cert/cert_verify_result.h" #include "net/cert/test_root_certs.h" #include "net/cert/x509_certificate.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" namespace net { @@ -90,11 +88,9 @@ CertStatus MapCertErrorToCertStatus(int err) { } } -// sk_X509_free is a function-style macro, so can't be used as a template -// param directly. -void sk_X509_free_fn(STACK_OF(X509)* st) { - sk_X509_free(st); -} +struct ShallowX509StackDeleter { + void operator()(STACK_OF(X509) * st) const { sk_X509_free(st); } +}; void GetCertChainInfo(X509_STORE_CTX* store_ctx, CertVerifyResult* verify_result) { @@ -211,10 +207,9 @@ int CertVerifyProcOpenSSL::VerifyInternal( verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; } - crypto::ScopedOpenSSL<X509_STORE_CTX, X509_STORE_CTX_free> ctx( - X509_STORE_CTX_new()); + bssl::UniquePtr<X509_STORE_CTX> ctx(X509_STORE_CTX_new()); - crypto::ScopedOpenSSL<STACK_OF(X509), sk_X509_free_fn> intermediates( + std::unique_ptr<STACK_OF(X509), ShallowX509StackDeleter> intermediates( sk_X509_new_null()); if (!intermediates.get()) return ERR_OUT_OF_MEMORY; diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc index ee6a9b14f55..862f7c8690c 100644 --- a/chromium/net/cert/cert_verify_proc_unittest.cc +++ b/chromium/net/cert/cert_verify_proc_unittest.cc @@ -13,6 +13,8 @@ #include "base/macros.h" #include "base/sha1.h" #include "base/strings/string_number_conversions.h" +#include "base/test/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "crypto/sha2.h" #include "net/base/net_errors.h" @@ -39,6 +41,10 @@ #include "net/cert/test_keychain_search_list_mac.h" #endif +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif + using net::test::IsError; using net::test::IsOk; @@ -48,6 +54,11 @@ namespace net { namespace { +const char kTLSFeatureExtensionHistogram[] = + "Net.Certificate.TLSFeatureExtensionWithPrivateRoot"; +const char kTLSFeatureExtensionOCSPHistogram[] = + "Net.Certificate.TLSFeatureExtensionWithPrivateRootHasOCSP"; + // Mock CertVerifyProc that sets the CertVerifyResult to a given value for // all certificates that are Verify()'d class MockCertVerifyProc : public CertVerifyProc { @@ -164,6 +175,17 @@ class CertVerifyProcTest : public testing::Test { additional_trust_anchors, verify_result); } + int VerifyWithOCSPResponse(X509Certificate* cert, + const std::string& hostname, + const std::string& ocsp_response, + int flags, + CRLSet* crl_set, + const CertificateList& additional_trust_anchors, + CertVerifyResult* verify_result) { + return verify_proc_->Verify(cert, hostname, ocsp_response, flags, crl_set, + additional_trust_anchors, verify_result); + } + const CertificateList empty_cert_list_; scoped_refptr<CertVerifyProc> verify_proc_; }; @@ -854,10 +876,18 @@ TEST_F(CertVerifyProcTest, IntranetHostsRejected) { EXPECT_FALSE(verify_result.cert_status & CERT_STATUS_NON_UNIQUE_NAME); } -// Test that a SHA-1 certificate from a publicly trusted CA issued after -// 1 January 2016 is rejected, but those issued before that date, or with -// SHA-1 in the intermediate, is not rejected. -TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecation) { +// While all SHA-1 certificates should be rejected, in the event that there +// emerges some unexpected bug, test that the 'legacy' behaviour works +// correctly - rejecting all SHA-1 certificates from publicly trusted CAs +// that were issued after 1 January 2016, while still allowing those from +// before that date, with SHA-1 in the intermediate, or from an enterprise +// CA. +// +// TODO(rsleevi): This code should be removed in M57. +TEST_F(CertVerifyProcTest, VerifyRejectsSHA1AfterDeprecationLegacyMode) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(CertVerifyProc::kSHA1LegacyMode); + CertVerifyResult dummy_result; CertVerifyResult verify_result; int error = 0; @@ -1495,6 +1525,131 @@ TEST_F(CertVerifyProcTest, MacSystemRootCertificateKeychainLocation) { } #endif +bool AreSHA1IntermediatesAllowed() { +#if defined(OS_WIN) + // TODO(rsleevi): Remove this once https://crbug.com/588789 is resolved + // for Windows 7/2008 users. + // Note: This must be kept in sync with cert_verify_proc.cc + return base::win::GetVersion() < base::win::VERSION_WIN8; +#else + return false; +#endif +} + +TEST_F(CertVerifyProcTest, RejectsMD2) { + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_md2 = true; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); +} + +TEST_F(CertVerifyProcTest, RejectsMD4) { + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_md4 = true; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + EXPECT_THAT(error, IsError(ERR_CERT_INVALID)); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_INVALID); +} + +TEST_F(CertVerifyProcTest, RejectsMD5) { + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_md5 = true; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); +} + +TEST_F(CertVerifyProcTest, RejectsPublicSHA1Leaves) { + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_sha1 = true; + result.has_sha1_leaf = true; + result.is_issued_by_known_root = true; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); +} + +TEST_F(CertVerifyProcTest, RejectsPublicSHA1IntermediatesUnlessAllowed) { + scoped_refptr<X509Certificate> cert(ImportCertFromFile( + GetTestCertsDirectory(), "39_months_after_2015_04.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_sha1 = true; + result.has_sha1_leaf = false; + result.is_issued_by_known_root = true; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + if (AreSHA1IntermediatesAllowed()) { + EXPECT_THAT(error, IsOk()); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); + } else { + EXPECT_THAT(error, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); + EXPECT_TRUE(verify_result.cert_status & + CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); + } +} + +TEST_F(CertVerifyProcTest, AcceptsPrivateSHA1) { + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + + CertVerifyResult result; + result.has_sha1 = true; + result.has_sha1_leaf = true; + result.is_issued_by_known_root = false; + verify_proc_ = new MockCertVerifyProc(result); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, nullptr /* crl_set */, + empty_cert_list_, &verify_result); + EXPECT_THAT(error, IsOk()); + EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_SHA1_SIGNATURE_PRESENT); +} + enum ExpectedAlgorithms { EXPECT_MD2 = 1 << 0, EXPECT_MD4 = 1 << 1, @@ -1529,7 +1684,10 @@ class CertVerifyProcWeakDigestTest virtual ~CertVerifyProcWeakDigestTest() {} }; -TEST_P(CertVerifyProcWeakDigestTest, Verify) { +// Test that the underlying cryptographic library properly surfaces the +// algorithms used in the chain. Some libraries, like NSS, don't return +// the failing chain on error, and thus not all tests can be run. +TEST_P(CertVerifyProcWeakDigestTest, VerifyDetectsAlgorithm) { WeakDigestTestData data = GetParam(); base::FilePath certs_dir = GetTestCertsDirectory(); @@ -1537,16 +1695,16 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) { if (data.root_cert_filename) { scoped_refptr<X509Certificate> root_cert = ImportCertFromFile(certs_dir, data.root_cert_filename); - ASSERT_NE(static_cast<X509Certificate*>(NULL), root_cert.get()); + ASSERT_TRUE(root_cert); test_root.Reset(root_cert.get()); } scoped_refptr<X509Certificate> intermediate_cert = ImportCertFromFile(certs_dir, data.intermediate_cert_filename); - ASSERT_NE(static_cast<X509Certificate*>(NULL), intermediate_cert.get()); + ASSERT_TRUE(intermediate_cert); scoped_refptr<X509Certificate> ee_cert = ImportCertFromFile(certs_dir, data.ee_cert_filename); - ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_cert.get()); + ASSERT_TRUE(ee_cert); X509Certificate::OSCertHandles intermediates; intermediates.push_back(intermediate_cert->os_cert_handle()); @@ -1554,53 +1712,18 @@ TEST_P(CertVerifyProcWeakDigestTest, Verify) { scoped_refptr<X509Certificate> ee_chain = X509Certificate::CreateFromHandle(ee_cert->os_cert_handle(), intermediates); - ASSERT_NE(static_cast<X509Certificate*>(NULL), ee_chain.get()); + ASSERT_TRUE(ee_chain); int flags = 0; CertVerifyResult verify_result; - int rv = Verify(ee_chain.get(), - "127.0.0.1", - flags, - NULL, - empty_cert_list_, - &verify_result); + Verify(ee_chain.get(), "127.0.0.1", flags, NULL, empty_cert_list_, + &verify_result); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD2), verify_result.has_md2); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD4), verify_result.has_md4); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_MD5), verify_result.has_md5); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1), verify_result.has_sha1); EXPECT_EQ(!!(data.expected_algorithms & EXPECT_SHA1_LEAF), verify_result.has_sha1_leaf); - - EXPECT_FALSE(verify_result.is_issued_by_additional_trust_anchor); - - // Ensure that MD4 and MD2 are tagged as invalid. - if (data.expected_algorithms & (EXPECT_MD2 | EXPECT_MD4)) { - EXPECT_EQ(CERT_STATUS_INVALID, - verify_result.cert_status & CERT_STATUS_INVALID); - } - - // Ensure that MD5 is flagged as weak. - if (data.expected_algorithms & EXPECT_MD5) { - EXPECT_EQ( - CERT_STATUS_WEAK_SIGNATURE_ALGORITHM, - verify_result.cert_status & CERT_STATUS_WEAK_SIGNATURE_ALGORITHM); - } - - // If a root cert is present, then check that the chain was rejected if any - // weak algorithms are present. This is only checked when a root cert is - // present because the error reported for incomplete chains with weak - // algorithms depends on which implementation was used to validate (NSS, - // OpenSSL, CryptoAPI, Security.framework) and upon which weak algorithm - // present (MD2, MD4, MD5). - if (data.root_cert_filename) { - if (data.expected_algorithms & (EXPECT_MD2 | EXPECT_MD4)) { - EXPECT_THAT(rv, IsError(ERR_CERT_INVALID)); - } else if (data.expected_algorithms & EXPECT_MD5) { - EXPECT_THAT(rv, IsError(ERR_CERT_WEAK_SIGNATURE_ALGORITHM)); - } else { - EXPECT_THAT(rv, IsOk()); - } - } } // Unlike TEST/TEST_F, which are macros that expand to further macros, @@ -1844,4 +1967,105 @@ TEST_F(CertVerifyProcTest, LargeKey) { } #endif // defined(OS_MACOSX) && !defined(OS_IOS) +// Tests that CertVerifyProc records a histogram correctly when a +// certificate chaining to a private root contains the TLS feature +// extension and does not have a stapled OCSP response. +TEST_F(CertVerifyProcTest, HasTLSFeatureExtensionUMA) { + base::HistogramTester histograms; + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); + ASSERT_TRUE(cert); + CertVerifyResult result; + result.is_issued_by_known_root = false; + verify_proc_ = new MockCertVerifyProc(result); + + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); + histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1); + histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, false, 1); +} + +// Tests that CertVerifyProc records a histogram correctly when a +// certificate chaining to a private root contains the TLS feature +// extension and does have a stapled OCSP response. +TEST_F(CertVerifyProcTest, HasTLSFeatureExtensionWithStapleUMA) { + base::HistogramTester histograms; + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); + ASSERT_TRUE(cert); + CertVerifyResult result; + result.is_issued_by_known_root = false; + verify_proc_ = new MockCertVerifyProc(result); + + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); + + int flags = 0; + CertVerifyResult verify_result; + int error = + VerifyWithOCSPResponse(cert.get(), "127.0.0.1", "dummy response", flags, + NULL, empty_cert_list_, &verify_result); + EXPECT_EQ(OK, error); + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); + histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1); + histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, true, 1); +} + +// Tests that CertVerifyProc records a histogram correctly when a +// certificate chaining to a private root does not contain the TLS feature +// extension. +TEST_F(CertVerifyProcTest, DoesNotHaveTLSFeatureExtensionUMA) { + base::HistogramTester histograms; + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem")); + ASSERT_TRUE(cert); + CertVerifyResult result; + result.is_issued_by_known_root = false; + verify_proc_ = new MockCertVerifyProc(result); + + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1); + histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, false, 1); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); +} + +// Tests that CertVerifyProc does not record a histogram when a +// certificate contains the TLS feature extension but chains to a public +// root. +TEST_F(CertVerifyProcTest, HasTLSFeatureExtensionWithPublicRootUMA) { + base::HistogramTester histograms; + scoped_refptr<X509Certificate> cert( + ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem")); + ASSERT_TRUE(cert); + CertVerifyResult result; + result.is_issued_by_known_root = true; + verify_proc_ = new MockCertVerifyProc(result); + + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); + + int flags = 0; + CertVerifyResult verify_result; + int error = Verify(cert.get(), "127.0.0.1", flags, NULL, empty_cert_list_, + &verify_result); + EXPECT_EQ(OK, error); + histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0); + histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0); +} + } // namespace net diff --git a/chromium/net/cert/cert_verify_proc_whitelist.cc b/chromium/net/cert/cert_verify_proc_whitelist.cc index 8b412e447fa..5c53a77a36c 100644 --- a/chromium/net/cert/cert_verify_proc_whitelist.cc +++ b/chromium/net/cert/cert_verify_proc_whitelist.cc @@ -13,11 +13,43 @@ namespace net { namespace { // clang-format off +// SHA-256 hashes of the subjectPublicKeyInfos of root certificates owned +// or operated by WoSign, including that of StartCom. For the certificates, +// see //net/data/ssl/wosign. +const uint8_t kWosignKeys[][crypto::kSHA256Length] = { + { 0x15, 0x28, 0x39, 0x7d, 0xa2, 0x12, 0x89, 0x0a, + 0x83, 0x0b, 0x0b, 0x95, 0xa5, 0x99, 0x68, 0xce, + 0xf2, 0x34, 0x77, 0x37, 0x79, 0xdf, 0x51, 0x81, + 0xcf, 0x10, 0xfa, 0x64, 0x75, 0x34, 0xbb, 0x65 }, + { 0x38, 0x1a, 0x3f, 0xc7, 0xa8, 0xb0, 0x82, 0xfa, + 0x28, 0x61, 0x3a, 0x4d, 0x07, 0xf2, 0xc7, 0x55, + 0x3f, 0x4e, 0x19, 0x18, 0xee, 0x07, 0xca, 0xa9, + 0xe8, 0xb7, 0xce, 0xde, 0x5a, 0x9c, 0xa0, 0x6a }, + { 0x7a, 0xed, 0xdd, 0xf3, 0x6b, 0x18, 0xf8, 0xac, + 0xb7, 0x37, 0x9f, 0xe1, 0xce, 0x18, 0x32, 0x12, + 0xb2, 0x35, 0x0d, 0x07, 0x88, 0xab, 0xe0, 0xe8, + 0x24, 0x57, 0xbe, 0x9b, 0xad, 0xad, 0x6d, 0x54 }, + { 0x9d, 0x98, 0xa1, 0xfb, 0x60, 0x53, 0x8c, 0x4c, + 0xc4, 0x85, 0x7f, 0xf1, 0xa8, 0xc8, 0x03, 0x4f, + 0xaf, 0x6f, 0xc5, 0x92, 0x09, 0x3f, 0x61, 0x99, + 0x94, 0xb2, 0xc8, 0x13, 0xd2, 0x50, 0xb8, 0x64 }, + { 0xd6, 0xa1, 0x84, 0x43, 0xd3, 0x48, 0xdb, 0x99, + 0x4f, 0x93, 0x4c, 0xcd, 0x8e, 0x63, 0x5d, 0x83, + 0x3a, 0x27, 0xac, 0x1e, 0x56, 0xf8, 0xaf, 0xaf, + 0x7c, 0x97, 0xcb, 0x4f, 0x43, 0xea, 0xb6, 0x8b }, + { 0xdb, 0x15, 0xc0, 0x06, 0x2b, 0x52, 0x0f, 0x31, + 0x8a, 0x19, 0xda, 0xcf, 0xec, 0xd6, 0x4f, 0x9e, + 0x7a, 0x3f, 0xbe, 0x60, 0x9f, 0xd5, 0x86, 0x79, + 0x6f, 0x20, 0xae, 0x02, 0x8e, 0x8e, 0x30, 0x58 }, + { 0xe4, 0x2f, 0x24, 0xbd, 0x4d, 0x37, 0xf4, 0xaa, + 0x2e, 0x56, 0xb9, 0x79, 0xd8, 0x3d, 0x1e, 0x65, + 0x21, 0x9f, 0xe0, 0xe9, 0xe3, 0xa3, 0x82, 0xa1, + 0xb3, 0xcb, 0x66, 0xc9, 0x39, 0x55, 0xde, 0x75 }, +}; + +// SHA-256 hashes of the leaf certificates whitelisted as issued by CNNIC's +// DV root. const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { - { 0x00, 0x87, 0x75, 0xb8, 0xea, 0xd0, 0xfe, 0x16, - 0x26, 0x9c, 0x9a, 0x9a, 0xb2, 0x83, 0x39, 0x55, - 0x49, 0xca, 0x67, 0xc2, 0xa3, 0xaa, 0xe8, 0x2f, - 0x1a, 0x6b, 0x4d, 0x3a, 0xbc, 0xca, 0xdc, 0x27 }, { 0x00, 0xc5, 0x9f, 0x5e, 0xf3, 0xb4, 0x6d, 0xbc, 0xa0, 0xa8, 0xbb, 0xa5, 0x0a, 0x72, 0xd4, 0xe1, 0x83, 0x9a, 0x94, 0xfb, 0x1a, 0x58, 0x5a, 0xd7, @@ -42,14 +74,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xff, 0xde, 0x35, 0xe0, 0xd1, 0x28, 0xb7, 0x99, 0x92, 0x2b, 0xa9, 0x37, 0xa2, 0xe8, 0x65, 0x84, 0x36, 0x62, 0xf1, 0xf4, 0x50, 0x02, 0xb8, 0x2d }, - { 0x04, 0x18, 0xd5, 0x3e, 0xbc, 0x8e, 0x71, 0x41, - 0x25, 0x1b, 0x4d, 0xc8, 0xfa, 0x7b, 0x2b, 0xd8, - 0xfd, 0x3a, 0x1c, 0x65, 0x2a, 0xa1, 0x16, 0xe7, - 0xfc, 0x70, 0x0b, 0x2a, 0xb5, 0x1a, 0x2a, 0x1a }, - { 0x06, 0xd4, 0x08, 0xff, 0xa9, 0x93, 0xaf, 0x04, - 0x45, 0x9c, 0x45, 0x67, 0x1a, 0xab, 0xd8, 0x7e, - 0xf9, 0x2b, 0x85, 0x6b, 0x1b, 0x42, 0xc6, 0x7e, - 0x00, 0x5e, 0xb4, 0xd2, 0x71, 0x58, 0xa8, 0x42 }, { 0x07, 0x19, 0x4f, 0x47, 0xf4, 0xce, 0xd0, 0x96, 0xd1, 0x06, 0x8d, 0x34, 0x49, 0x3b, 0x67, 0x37, 0x14, 0x45, 0x16, 0x93, 0xa6, 0xa2, 0x71, 0x2f, @@ -58,14 +82,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe2, 0xc1, 0x78, 0x71, 0xaa, 0xb6, 0xe4, 0x00, 0xb3, 0xfd, 0xbc, 0xdc, 0xf3, 0x91, 0x46, 0xa0, 0x89, 0x37, 0xf9, 0xac, 0x06, 0xa1, 0xb8, 0xbd }, - { 0x07, 0xa9, 0x5c, 0x81, 0xed, 0x15, 0x9e, 0x44, - 0xa0, 0x41, 0x2b, 0xde, 0xb1, 0x31, 0xa1, 0x1f, - 0x26, 0xe3, 0x4e, 0x51, 0x67, 0xec, 0xf2, 0x11, - 0x78, 0xf3, 0xef, 0xbf, 0xb3, 0xa2, 0xbb, 0x72 }, - { 0x07, 0xe9, 0x60, 0x9e, 0x05, 0xdc, 0x0a, 0x1e, - 0x52, 0x15, 0x06, 0x49, 0xeb, 0xf4, 0x1f, 0x6d, - 0xe3, 0x86, 0x7c, 0x9c, 0x25, 0xfe, 0x17, 0x7b, - 0xab, 0xcf, 0xd9, 0xb3, 0x70, 0x46, 0x13, 0x8b }, { 0x08, 0x21, 0x0a, 0xc3, 0xa2, 0x95, 0x56, 0xf6, 0x8d, 0x33, 0xb4, 0x40, 0x87, 0x9c, 0x54, 0x63, 0x64, 0x04, 0xe9, 0x7c, 0x4d, 0x9f, 0x97, 0x82, @@ -78,10 +94,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x03, 0x7b, 0x93, 0xaa, 0x5f, 0xb4, 0x16, 0x19, 0x0a, 0xd1, 0xdf, 0x86, 0x73, 0xab, 0x31, 0xa8, 0xf6, 0xd9, 0x7f, 0x59, 0x5e, 0x8e, 0x16, 0xe9 }, - { 0x09, 0xa2, 0xc1, 0x4e, 0x5d, 0x62, 0xc3, 0x4a, - 0xa7, 0x06, 0xff, 0xab, 0xd2, 0x1e, 0x7a, 0xd2, - 0x25, 0xf6, 0x25, 0xf7, 0x1f, 0xf8, 0x9d, 0xb3, - 0x9b, 0x32, 0x2a, 0xcb, 0x0c, 0x84, 0x57, 0x4f }, { 0x09, 0xeb, 0xdd, 0x1b, 0x7f, 0xfa, 0x4e, 0xd7, 0x4b, 0xeb, 0xae, 0x96, 0xba, 0x10, 0x65, 0xdc, 0x7d, 0xa1, 0xc5, 0xd3, 0x18, 0x3c, 0xc5, 0x94, @@ -118,10 +130,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x67, 0x35, 0x89, 0x67, 0x22, 0x78, 0xb0, 0xa3, 0xc5, 0xe2, 0x69, 0x30, 0xa4, 0xdc, 0x3a, 0x82, 0x16, 0x85, 0x43, 0x24, 0x27, 0xc7, 0x31, 0x5a }, - { 0x0d, 0x66, 0x45, 0x6b, 0x0b, 0xf4, 0xaa, 0x54, - 0x16, 0xe4, 0x4d, 0x9f, 0xdb, 0x40, 0x38, 0x3d, - 0x34, 0x3d, 0x7b, 0x3f, 0x6a, 0xfe, 0x69, 0xaa, - 0x08, 0x95, 0xbb, 0x1a, 0xb5, 0xe0, 0x61, 0xa0 }, { 0x0d, 0x71, 0xc8, 0xca, 0x16, 0x56, 0x59, 0xef, 0xaf, 0x69, 0x65, 0x29, 0x28, 0x9a, 0xae, 0x25, 0xd9, 0xc4, 0x2a, 0x1b, 0xbb, 0x03, 0x5a, 0x2b, @@ -186,10 +194,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x48, 0xf7, 0x53, 0x89, 0x80, 0xc5, 0x63, 0xc8, 0xf7, 0x48, 0x95, 0x4c, 0xf2, 0x64, 0x41, 0x9a, 0x72, 0xfc, 0xc6, 0x34, 0x0a, 0x10, 0x23, 0x80 }, - { 0x19, 0x77, 0x3e, 0xe9, 0xe9, 0x35, 0x6b, 0x88, - 0x11, 0xd6, 0x56, 0x79, 0x9c, 0x53, 0x16, 0x0b, - 0x61, 0x73, 0xfa, 0x8a, 0x81, 0x47, 0x97, 0xdb, - 0xcd, 0x55, 0xb2, 0x27, 0x38, 0x70, 0x60, 0x3e }, { 0x19, 0xff, 0xe6, 0xc6, 0x7a, 0x35, 0x86, 0xfc, 0x48, 0x6c, 0xe2, 0x07, 0xfa, 0x2a, 0xf6, 0x62, 0xf5, 0x50, 0xfc, 0x51, 0x2f, 0xdd, 0x78, 0x17, @@ -242,10 +246,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xcc, 0xd4, 0xe6, 0xad, 0xe1, 0xcb, 0x75, 0x13, 0x8d, 0xd6, 0xd9, 0x06, 0xfe, 0xf3, 0x49, 0xc0, 0xc9, 0x86, 0xa5, 0x1b, 0x29, 0xb9, 0xe5, 0x2d }, - { 0x21, 0x09, 0xf3, 0x10, 0x7d, 0x97, 0xf8, 0x70, - 0x48, 0x70, 0x8e, 0xc8, 0x7c, 0xa2, 0xdc, 0x31, - 0x8b, 0x2f, 0x2b, 0x57, 0x47, 0xc3, 0x38, 0xbd, - 0x9c, 0x6d, 0xbc, 0xd6, 0x0f, 0xd6, 0xbe, 0xa2 }, { 0x21, 0x78, 0xe8, 0x28, 0x3a, 0x73, 0x39, 0x6e, 0x08, 0xc0, 0xa1, 0x1a, 0x88, 0x72, 0xfa, 0x4a, 0x9f, 0xcc, 0x05, 0x67, 0x0c, 0xee, 0xff, 0xb8, @@ -310,10 +310,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xca, 0x55, 0xb2, 0xe1, 0x63, 0xfd, 0xbb, 0xbc, 0x9d, 0x74, 0xb4, 0xe5, 0xf3, 0x7b, 0x7d, 0xbd, 0x13, 0xc9, 0x4e, 0x85, 0x8d, 0x40, 0xda, 0xd0 }, - { 0x2b, 0xf1, 0xe3, 0xf0, 0x37, 0x5a, 0x9a, 0x21, - 0xc0, 0x7a, 0x92, 0x18, 0x04, 0x2f, 0x18, 0x77, - 0x3f, 0x43, 0xea, 0xb0, 0xf5, 0xc0, 0x00, 0x26, - 0x45, 0x40, 0x48, 0x2f, 0x04, 0xae, 0x18, 0xef }, { 0x2c, 0x82, 0x47, 0x4f, 0x0e, 0xf6, 0xcb, 0x65, 0x0a, 0x13, 0xef, 0x20, 0x99, 0x6e, 0x65, 0x7b, 0x67, 0x24, 0xf0, 0xa0, 0xd5, 0xee, 0x24, 0x6d, @@ -342,10 +338,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x08, 0xed, 0x48, 0x1a, 0x99, 0x7a, 0x8a, 0x88, 0xb7, 0xbf, 0x22, 0xdd, 0x26, 0xaa, 0x17, 0x17, 0x31, 0xb8, 0xf7, 0xe0, 0xd5, 0x97, 0xb7, 0x08 }, - { 0x30, 0xcb, 0x41, 0x11, 0xfb, 0x10, 0x08, 0x6f, - 0xc6, 0xa4, 0x1f, 0x04, 0xb7, 0xe9, 0xd4, 0xcf, - 0x66, 0x10, 0xbb, 0x06, 0x59, 0xd8, 0xe2, 0xac, - 0x80, 0x4f, 0xc8, 0x96, 0xb0, 0x25, 0x42, 0xbb }, { 0x30, 0xe0, 0x69, 0x80, 0x9c, 0x79, 0x90, 0xf0, 0xb5, 0xf2, 0x66, 0xe8, 0x94, 0x59, 0x96, 0x42, 0xe8, 0x53, 0x50, 0xab, 0x82, 0x81, 0x05, 0x34, @@ -378,14 +370,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xc8, 0x68, 0x5e, 0xea, 0xac, 0x57, 0x87, 0x2d, 0x3b, 0x47, 0xe6, 0x02, 0xf4, 0x97, 0xe9, 0xf0, 0x28, 0x54, 0x12, 0x32, 0x59, 0xfb, 0xe1, 0x69 }, - { 0x35, 0x98, 0x10, 0xff, 0xfe, 0xd1, 0x3a, 0x2c, - 0x25, 0xcd, 0x91, 0xfc, 0xf0, 0x85, 0x59, 0x33, - 0xc9, 0x94, 0xa9, 0xdf, 0xc9, 0x39, 0x2d, 0x97, - 0x07, 0xc3, 0xc0, 0xe7, 0x30, 0x0f, 0x90, 0x8d }, - { 0x35, 0xdf, 0x79, 0x2b, 0x10, 0x0a, 0x79, 0xa6, - 0x5c, 0x44, 0x87, 0x04, 0x30, 0x9d, 0xd6, 0x4b, - 0x54, 0x39, 0x4e, 0xba, 0xe8, 0xc4, 0x8c, 0x3b, - 0xd5, 0xde, 0xe9, 0xcc, 0x68, 0x7d, 0x60, 0x34 }, { 0x36, 0x45, 0xef, 0x7f, 0x5d, 0x15, 0xa5, 0x46, 0x7e, 0x85, 0x30, 0x7d, 0xda, 0x15, 0xcb, 0xbb, 0x55, 0xb7, 0x30, 0xae, 0xf8, 0xef, 0x9c, 0x71, @@ -410,18 +394,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x6a, 0xb9, 0x3b, 0x18, 0xc2, 0xf3, 0x75, 0x5e, 0xe2, 0x6f, 0x8c, 0x3a, 0xdb, 0x75, 0x9b, 0x6f, 0x34, 0x78, 0x9f, 0xb8, 0xec, 0xf0, 0x54, 0x28 }, - { 0x39, 0x7b, 0xa8, 0x8a, 0x05, 0xda, 0xfd, 0x7d, - 0x58, 0xfa, 0xcf, 0x45, 0x60, 0xa6, 0x88, 0xab, - 0xee, 0xd2, 0x13, 0xe0, 0xf8, 0x8c, 0x76, 0xb6, - 0x2a, 0xb2, 0xfd, 0xe3, 0x67, 0xc3, 0x2d, 0x32 }, { 0x39, 0x7d, 0x00, 0x6e, 0xf8, 0xaf, 0xb2, 0x0f, 0x43, 0x61, 0xa6, 0xc9, 0x72, 0xf0, 0xc5, 0x7c, 0xc0, 0x87, 0x74, 0x01, 0x06, 0x12, 0x78, 0x3f, 0xba, 0xbc, 0xb8, 0xd6, 0xf6, 0x03, 0x9e, 0x2c }, - { 0x39, 0xff, 0x6e, 0x31, 0x69, 0x9f, 0x5d, 0x68, - 0x92, 0x97, 0x6d, 0x11, 0xdd, 0xbb, 0x14, 0x24, - 0xed, 0x0c, 0xec, 0x48, 0x36, 0x3e, 0x94, 0xea, - 0xe3, 0xcd, 0x5f, 0x4c, 0xaf, 0x1c, 0xbd, 0x2f }, { 0x3a, 0xcf, 0x85, 0x3c, 0x4e, 0x45, 0x02, 0xbd, 0x82, 0xd5, 0x85, 0xd5, 0xe0, 0x82, 0xc4, 0xb3, 0xad, 0x03, 0xcd, 0xb6, 0xb5, 0x05, 0xca, 0x80, @@ -434,10 +410,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xca, 0x6c, 0x31, 0xb3, 0x78, 0x39, 0xc9, 0x50, 0x76, 0x63, 0x70, 0xd7, 0xf4, 0xb6, 0x4a, 0xd0, 0x18, 0x55, 0xca, 0xcf, 0xe3, 0x51, 0x2f, 0xc3 }, - { 0x3b, 0x6e, 0x3b, 0xb7, 0x00, 0x04, 0xbd, 0x78, - 0xc9, 0x69, 0xa7, 0xfb, 0xd5, 0x11, 0x33, 0xa2, - 0xb3, 0xc4, 0xdf, 0xb6, 0xba, 0x38, 0x5d, 0xce, - 0x3f, 0xb8, 0x4d, 0x73, 0x6b, 0xea, 0xb1, 0xd9 }, { 0x3b, 0xaa, 0x31, 0x31, 0x70, 0x68, 0xac, 0xe0, 0x89, 0xae, 0xb4, 0xa8, 0x8d, 0x7e, 0xde, 0xbe, 0x94, 0xab, 0x4a, 0xce, 0x46, 0xbb, 0xd2, 0x68, @@ -474,10 +446,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x29, 0x96, 0x5a, 0x27, 0xc1, 0x6c, 0x2f, 0xed, 0x28, 0xd9, 0xb9, 0x14, 0x0e, 0x4f, 0xb5, 0x5b, 0x37, 0x22, 0x4c, 0x67, 0xb2, 0xa0, 0x55, 0x1f }, - { 0x3f, 0xb6, 0xc4, 0x03, 0x19, 0x63, 0xb9, 0x67, - 0x28, 0xbf, 0x93, 0x8d, 0x9b, 0x59, 0xc9, 0x05, - 0x43, 0xa9, 0xa6, 0x3e, 0xa3, 0x9c, 0xd2, 0x76, - 0x14, 0xf2, 0x41, 0x28, 0xa9, 0x64, 0xef, 0x84 }, { 0x40, 0x58, 0xec, 0x4a, 0x7a, 0x7b, 0xa0, 0xb8, 0x65, 0xa7, 0x39, 0xa0, 0x0c, 0x85, 0xf3, 0x44, 0x58, 0x79, 0xd6, 0x5e, 0x1d, 0x42, 0x2e, 0xed, @@ -502,10 +470,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xd1, 0xdb, 0xd3, 0x3d, 0x8d, 0x16, 0x34, 0xc4, 0xfa, 0xfe, 0xb6, 0xf8, 0x05, 0xf1, 0xcc, 0xb5, 0x34, 0xac, 0xb7, 0x2a, 0xed, 0xa2, 0xcd, 0x0a }, - { 0x43, 0x13, 0x91, 0xe1, 0x14, 0x14, 0xec, 0x0c, - 0x5c, 0xf5, 0xe7, 0xb3, 0x9c, 0x65, 0xfe, 0xdb, - 0x2e, 0xc8, 0x8c, 0x54, 0x48, 0xbf, 0x35, 0xee, - 0x17, 0x0d, 0xc3, 0xb5, 0xe1, 0x7e, 0xd0, 0x88 }, { 0x44, 0x12, 0x63, 0x80, 0xa0, 0x73, 0xfe, 0xa1, 0xa2, 0x00, 0x4f, 0x71, 0x1d, 0xf2, 0xca, 0x47, 0xc2, 0xc4, 0xb4, 0xff, 0x64, 0x4e, 0x76, 0xaf, @@ -546,26 +510,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x21, 0xfe, 0xf9, 0x3d, 0x26, 0x0c, 0x24, 0x8c, 0xe3, 0xbe, 0x98, 0x62, 0x68, 0x68, 0xe7, 0x5a, 0x3f, 0x63, 0x34, 0xbb, 0x7d, 0xc1, 0x81, 0xec }, - { 0x4a, 0xcf, 0x9d, 0xa9, 0x05, 0x2f, 0x0b, 0x8c, - 0xff, 0xf7, 0x37, 0xcd, 0xa3, 0x39, 0x11, 0xc2, - 0x9e, 0xfc, 0xbf, 0xfd, 0x4b, 0xf4, 0xb7, 0x24, - 0x83, 0xfa, 0xa7, 0xc7, 0x45, 0x1d, 0xfd, 0x42 }, { 0x4b, 0x1f, 0xc8, 0x2d, 0x24, 0x72, 0x92, 0x7a, 0xc1, 0x7c, 0x58, 0x43, 0x07, 0xcb, 0x96, 0xd6, 0xfd, 0xdb, 0x8d, 0x50, 0xa5, 0x29, 0x53, 0x07, 0xd3, 0x0c, 0x75, 0x88, 0x59, 0x6a, 0xd4, 0x0b }, - { 0x4b, 0x35, 0x02, 0xff, 0xad, 0x64, 0x16, 0x39, - 0x4f, 0x2f, 0x78, 0x47, 0x76, 0x13, 0x39, 0x69, - 0xa5, 0x5c, 0xa8, 0xf3, 0x9f, 0x78, 0x3c, 0x26, - 0x0f, 0xfe, 0xdb, 0xa8, 0xfc, 0xe4, 0x19, 0x70 }, { 0x4b, 0x51, 0xfc, 0x11, 0x4b, 0xac, 0x8e, 0x2d, 0x2a, 0xf2, 0xae, 0x56, 0x84, 0x42, 0x9c, 0xca, 0xab, 0x21, 0x39, 0xc9, 0xb3, 0x51, 0xbf, 0x7e, 0x1b, 0x03, 0x0a, 0xe8, 0x62, 0x4a, 0xc1, 0x72 }, - { 0x4b, 0x92, 0xdc, 0xfd, 0x0e, 0xda, 0x00, 0x5d, - 0x9a, 0x37, 0x3d, 0x91, 0xa6, 0x1f, 0x23, 0x12, - 0x9d, 0x7b, 0x85, 0x3d, 0x79, 0x52, 0x87, 0xc9, - 0x5c, 0x7e, 0x17, 0x24, 0xa9, 0x1c, 0x53, 0xb3 }, { 0x4c, 0xd0, 0xd6, 0x7e, 0xcc, 0x3b, 0x01, 0xc8, 0xc2, 0x63, 0x4e, 0x7a, 0x73, 0x76, 0x12, 0xf6, 0x3a, 0x17, 0xff, 0x51, 0x0a, 0x77, 0xa8, 0x04, @@ -582,10 +534,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x58, 0xe4, 0x62, 0xbf, 0x13, 0x22, 0x10, 0xd8, 0xb7, 0x86, 0x12, 0xd0, 0xc2, 0x2a, 0x6b, 0x6a, 0x68, 0x2e, 0x0b, 0x9e, 0x9c, 0x9f, 0x9a, 0x44 }, - { 0x50, 0x15, 0xb9, 0xc9, 0x92, 0xc8, 0x87, 0xc2, - 0x4c, 0x99, 0x15, 0x38, 0xdd, 0xd5, 0x1d, 0x01, - 0x49, 0xcd, 0x9f, 0xf3, 0x60, 0x49, 0xf3, 0xd8, - 0xa0, 0xb2, 0xd2, 0x92, 0x23, 0xf7, 0x91, 0x38 }, { 0x50, 0xf4, 0x78, 0x1e, 0xb1, 0xc1, 0x46, 0x70, 0xd9, 0xa5, 0x52, 0xc3, 0x49, 0x5f, 0xb9, 0xf6, 0xae, 0x86, 0x8a, 0xb1, 0xc9, 0xd9, 0x83, 0xe0, @@ -622,10 +570,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x58, 0x4d, 0x9e, 0x7b, 0x57, 0x92, 0xa4, 0x03, 0xc2, 0x1d, 0x39, 0xd6, 0xe1, 0xf5, 0xe8, 0xed, 0x37, 0xb9, 0x3f, 0xa6, 0x1d, 0x88, 0x35, 0x16 }, - { 0x58, 0x0c, 0x45, 0xd6, 0xe2, 0x55, 0x8e, 0x7c, - 0x7d, 0xa8, 0x19, 0xa5, 0x99, 0xd5, 0xb1, 0x6f, - 0x0e, 0x18, 0x79, 0xf0, 0xcb, 0x58, 0x31, 0xdf, - 0xdb, 0x9a, 0xb2, 0xff, 0x6e, 0x8e, 0x4b, 0xa0 }, { 0x58, 0x1a, 0xde, 0x64, 0x84, 0x95, 0xb4, 0xb1, 0x62, 0x9c, 0x3c, 0x7c, 0x78, 0xef, 0xbe, 0xf2, 0x75, 0x06, 0x56, 0x65, 0xb2, 0x41, 0x1c, 0x0e, @@ -654,10 +598,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa9, 0x38, 0x1a, 0x5c, 0xd8, 0x7b, 0x80, 0xd1, 0x10, 0xf2, 0x6e, 0xe8, 0x39, 0x27, 0x1b, 0xc2, 0x70, 0x60, 0x8f, 0xd1, 0x43, 0x7f, 0x55, 0xb0 }, - { 0x5b, 0x29, 0x3d, 0x30, 0x9f, 0x64, 0x24, 0xbc, - 0x26, 0x4f, 0x4b, 0xb0, 0x18, 0xae, 0xf5, 0x0e, - 0x63, 0xe3, 0x37, 0xd1, 0x4d, 0xf0, 0x64, 0xc5, - 0x7a, 0x23, 0x52, 0x83, 0x42, 0x16, 0x1c, 0x68 }, { 0x5c, 0x7f, 0xf0, 0x55, 0xc2, 0xfd, 0x03, 0x3f, 0x34, 0xc4, 0xc4, 0xf7, 0xc4, 0xfb, 0x7d, 0xda, 0xaa, 0xfb, 0x43, 0x56, 0xc5, 0x60, 0xc9, 0x9e, @@ -670,10 +610,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xac, 0xb5, 0x4f, 0x66, 0xa9, 0xb7, 0x78, 0x55, 0x69, 0x6e, 0xce, 0x16, 0x7f, 0xe6, 0xc6, 0x0a, 0x05, 0x16, 0x8b, 0xe4, 0x39, 0x19, 0xc8, 0x0f }, - { 0x5e, 0x23, 0xdb, 0xd4, 0xd0, 0xc9, 0xbf, 0xb1, - 0x5f, 0x61, 0x6a, 0x95, 0x17, 0xa1, 0x30, 0xd8, - 0x66, 0xa8, 0xcb, 0x0b, 0x18, 0x96, 0x3d, 0x54, - 0xe7, 0xed, 0xae, 0xe2, 0x61, 0xcb, 0x1c, 0x19 }, { 0x5f, 0x8b, 0x88, 0x8e, 0xe9, 0x6c, 0x0c, 0x0f, 0x5a, 0x91, 0x72, 0x90, 0xac, 0xa6, 0x5a, 0xfd, 0x6e, 0xbd, 0xae, 0x05, 0xa0, 0x2a, 0xaf, 0x04, @@ -706,10 +642,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xde, 0x0b, 0x41, 0x28, 0x5d, 0x9a, 0x13, 0x3f, 0xa7, 0xf5, 0x70, 0xa3, 0xc8, 0x13, 0x55, 0x79, 0xb8, 0x60, 0x19, 0x9d, 0x0a, 0x51, 0x45, 0x7c }, - { 0x67, 0xcf, 0x34, 0x6c, 0xf2, 0x46, 0x77, 0x1b, - 0x3f, 0x5f, 0x3e, 0x51, 0xcd, 0x75, 0x4e, 0x10, - 0x93, 0x27, 0x3d, 0x35, 0x69, 0x88, 0x80, 0x84, - 0x26, 0xf5, 0xdd, 0x2e, 0xd4, 0x8b, 0xbf, 0x49 }, { 0x69, 0x01, 0x4b, 0xbc, 0x84, 0x29, 0xd8, 0x5f, 0x41, 0xc2, 0x22, 0xd9, 0x7f, 0x7e, 0xd5, 0x35, 0xcf, 0x81, 0x23, 0x9a, 0xf2, 0x7a, 0xcc, 0x88, @@ -730,10 +662,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x0d, 0xe7, 0x20, 0xf4, 0xbb, 0xde, 0xdf, 0x49, 0x10, 0x15, 0x13, 0xdf, 0xd1, 0xdb, 0x0b, 0x0a, 0x97, 0xcc, 0x3f, 0xdd, 0x9a, 0x39, 0xc6, 0xe7 }, - { 0x6c, 0x72, 0x94, 0x87, 0xc9, 0x02, 0x5d, 0x18, - 0x10, 0x51, 0x29, 0xfa, 0x0b, 0xa2, 0x94, 0x4d, - 0xa8, 0x6a, 0xf1, 0xdb, 0x2d, 0x03, 0x4b, 0xe2, - 0xbb, 0x73, 0x64, 0x50, 0x0c, 0x05, 0xa6, 0xde }, { 0x6c, 0x8f, 0xd1, 0xe6, 0xe1, 0x1b, 0xaf, 0xa6, 0x17, 0x78, 0x13, 0xa0, 0x44, 0x40, 0xb1, 0xb9, 0x6a, 0x1c, 0xdb, 0x7c, 0x2d, 0x70, 0x3f, 0x55, @@ -746,14 +674,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x14, 0xca, 0x72, 0x70, 0x3f, 0x64, 0x46, 0x9b, 0x98, 0x58, 0xfc, 0x39, 0x96, 0x4b, 0x4c, 0x03, 0x93, 0xb3, 0x7d, 0xde, 0xab, 0x8b, 0x19, 0x75 }, - { 0x6d, 0x4e, 0xd4, 0x29, 0x38, 0x15, 0x90, 0xbd, - 0x3c, 0x6b, 0x7c, 0xb7, 0xe4, 0xe4, 0x25, 0xc8, - 0xe2, 0x1f, 0x79, 0xff, 0x4d, 0x40, 0x00, 0xb9, - 0x65, 0x3f, 0xa1, 0x27, 0xe1, 0x41, 0xd3, 0x50 }, - { 0x6d, 0xc9, 0x87, 0x5c, 0xd3, 0x46, 0xa2, 0x2b, - 0x47, 0xb2, 0x80, 0xb1, 0xb1, 0x45, 0x0d, 0x87, - 0x8e, 0x09, 0x8b, 0xb2, 0xe2, 0xa9, 0xe3, 0xc2, - 0x5c, 0xc7, 0x6a, 0xff, 0x93, 0xc0, 0xbe, 0xab }, { 0x6e, 0x1a, 0x88, 0x63, 0xf2, 0x93, 0x4b, 0x39, 0x01, 0x23, 0x7e, 0x84, 0xd0, 0x76, 0x27, 0x04, 0x23, 0x06, 0x78, 0x7f, 0x2d, 0xe0, 0x66, 0x30, @@ -770,22 +690,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x73, 0xab, 0x5e, 0xea, 0x4e, 0xc2, 0xf4, 0x84, 0xce, 0x91, 0xd1, 0x0e, 0x31, 0x34, 0x5f, 0x15, 0xa7, 0x6a, 0x84, 0x85, 0xb8, 0xff, 0xfb, 0x7e }, - { 0x6f, 0xdc, 0x18, 0xd6, 0x55, 0x14, 0xdd, 0xce, - 0xf0, 0x2f, 0xea, 0x81, 0x7a, 0x1b, 0x70, 0x84, - 0x71, 0x95, 0xff, 0x5c, 0x07, 0xb1, 0x3d, 0x6a, - 0x97, 0x1e, 0x0e, 0x77, 0x4b, 0x44, 0x10, 0xa0 }, { 0x70, 0xb8, 0xec, 0xd5, 0x62, 0xec, 0x3d, 0x9f, 0x48, 0x64, 0x75, 0x2a, 0x3a, 0x8c, 0x54, 0x39, 0x93, 0xb4, 0x38, 0x72, 0x8f, 0xe2, 0x71, 0x81, 0xf4, 0xc0, 0x8d, 0xe6, 0xa0, 0xd8, 0xb7, 0x9a }, - { 0x70, 0xe0, 0xb7, 0xf5, 0xc7, 0xa3, 0xd1, 0xf3, - 0x96, 0x85, 0x84, 0x5d, 0x94, 0xfc, 0x9e, 0x77, - 0x7c, 0x12, 0x69, 0xcf, 0x15, 0x31, 0x68, 0x51, - 0x98, 0x3d, 0x60, 0x58, 0x76, 0x1c, 0xf0, 0x63 }, - { 0x71, 0x1e, 0xf0, 0x96, 0x33, 0x43, 0x8a, 0xc5, - 0xbe, 0x9d, 0xa8, 0x12, 0x2e, 0x7a, 0xcf, 0x0e, - 0xa2, 0x68, 0xb8, 0x72, 0xad, 0xdc, 0x3e, 0xe8, - 0x37, 0x2b, 0x91, 0x6d, 0x60, 0x65, 0xcf, 0xa8 }, { 0x72, 0x1b, 0x1f, 0x92, 0x9d, 0xa7, 0xea, 0xf8, 0x96, 0x24, 0x64, 0x7b, 0xa3, 0xcc, 0x4e, 0x1e, 0xd1, 0x57, 0x54, 0xab, 0x83, 0x6e, 0x33, 0x58, @@ -802,10 +710,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x0e, 0xdf, 0xa3, 0x41, 0x1f, 0xbc, 0x9b, 0xad, 0x31, 0x65, 0xbe, 0x66, 0x0f, 0x34, 0x0a, 0xa2, 0x30, 0x8a, 0x5a, 0x33, 0x23, 0xfa, 0xbf, 0xa7 }, - { 0x74, 0x54, 0x0f, 0xa5, 0x0a, 0x36, 0x2e, 0x68, - 0x6d, 0x99, 0x17, 0x98, 0x18, 0x35, 0x09, 0x83, - 0x6c, 0x95, 0xa3, 0xfb, 0x04, 0x58, 0x00, 0x22, - 0xf9, 0x68, 0x58, 0x4f, 0x8a, 0xcf, 0x60, 0x1f }, { 0x74, 0x8e, 0xbb, 0x72, 0xd1, 0x02, 0x04, 0xf4, 0x04, 0x10, 0xbe, 0x70, 0x80, 0xbf, 0xe7, 0xee, 0x63, 0x1f, 0xc0, 0x4d, 0x1f, 0xdb, 0x50, 0x72, @@ -818,10 +722,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xa2, 0xa2, 0xab, 0x2a, 0x4e, 0x85, 0x49, 0x83, 0xc5, 0xfd, 0xe6, 0x73, 0xce, 0x8e, 0xb1, 0x71, 0x23, 0x49, 0x48, 0x64, 0x86, 0x7a, 0x98, 0xb1 }, - { 0x77, 0xdd, 0xc8, 0x1b, 0xd2, 0x8b, 0x9d, 0x46, - 0x1e, 0x7d, 0x3c, 0xd4, 0xa8, 0x12, 0x2a, 0xa9, - 0x8a, 0x24, 0x60, 0xfb, 0xa0, 0x8f, 0x1b, 0x7b, - 0xac, 0xb6, 0x6c, 0x92, 0xd7, 0x99, 0x1c, 0xcc }, { 0x78, 0x0c, 0x33, 0xfe, 0x95, 0x4c, 0xc4, 0xdb, 0x39, 0x04, 0xd7, 0x6a, 0x68, 0x58, 0xbc, 0xd1, 0x01, 0x7f, 0x52, 0xda, 0x59, 0x9d, 0x36, 0xda, @@ -830,18 +730,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x00, 0x66, 0xdd, 0x88, 0xa2, 0xa8, 0xda, 0xfb, 0xbe, 0x6c, 0xd6, 0x5d, 0x54, 0xb7, 0x76, 0x06, 0x42, 0x1b, 0x45, 0x43, 0x8c, 0x65, 0x8a, 0xd4 }, - { 0x79, 0x44, 0x5a, 0x43, 0x7b, 0xbe, 0xb4, 0xa5, - 0x59, 0xc8, 0x1c, 0x8e, 0x57, 0xbb, 0xfb, 0x18, - 0x66, 0xe2, 0xe2, 0xbf, 0x6e, 0x70, 0xa5, 0x63, - 0x22, 0x1b, 0x62, 0x7b, 0x71, 0x7d, 0xe6, 0xb1 }, { 0x79, 0x8f, 0x83, 0xb1, 0xc4, 0xc6, 0x5c, 0x4d, 0x5d, 0xea, 0x13, 0x03, 0x53, 0x53, 0xd8, 0xed, 0xe5, 0xd7, 0x1d, 0x99, 0x47, 0xf4, 0x34, 0xfd, 0xea, 0x0d, 0xbc, 0x1e, 0xc8, 0x2f, 0x45, 0x35 }, - { 0x79, 0xa8, 0xfc, 0x72, 0x70, 0xb2, 0xe5, 0xf3, - 0x35, 0x6b, 0x09, 0xc6, 0xb8, 0x64, 0xfc, 0x92, - 0xe5, 0xfb, 0xc9, 0xe6, 0x9b, 0xec, 0x93, 0xa4, - 0xe3, 0x3b, 0x8d, 0xf5, 0x75, 0x60, 0x17, 0xbe }, { 0x7b, 0xfe, 0x47, 0xae, 0xba, 0x8b, 0x0a, 0x3a, 0x94, 0x5a, 0x88, 0xd8, 0xef, 0x18, 0x91, 0xc9, 0x89, 0x97, 0x8a, 0xbf, 0x12, 0x2e, 0xc5, 0xe0, @@ -954,10 +846,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe8, 0x1c, 0x27, 0xd1, 0xca, 0xf2, 0x74, 0xb1, 0x7d, 0x72, 0x0d, 0xf8, 0x07, 0x8b, 0x6f, 0x2a, 0x5c, 0x3b, 0xb8, 0xd8, 0xdf, 0xf0, 0x55, 0x00 }, - { 0x88, 0x76, 0x88, 0xdc, 0x6e, 0x9f, 0xe3, 0xdb, - 0x05, 0x05, 0x7f, 0xc6, 0x38, 0xeb, 0x8b, 0x29, - 0x4c, 0x3d, 0x8e, 0x0a, 0xae, 0x17, 0x51, 0xf7, - 0x58, 0xf6, 0x36, 0x70, 0x37, 0x2e, 0x66, 0x6d }, { 0x88, 0x8d, 0x6d, 0x77, 0xd8, 0x1c, 0x62, 0x91, 0xcb, 0x84, 0xd9, 0xd6, 0x56, 0x27, 0x82, 0xfd, 0x2e, 0xb3, 0x42, 0x5d, 0x49, 0x1e, 0x68, 0x74, @@ -1026,10 +914,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x41, 0x8a, 0x30, 0x7c, 0x76, 0x36, 0xe4, 0x9b, 0x14, 0x4f, 0xa5, 0x3e, 0x52, 0xe1, 0x04, 0x15, 0x5f, 0x58, 0x03, 0x5e, 0x45, 0x41, 0xcd, 0x6e }, - { 0x90, 0xb3, 0xa1, 0x85, 0x36, 0x86, 0xaf, 0xeb, - 0x15, 0x4a, 0xef, 0x7e, 0x84, 0x0d, 0x38, 0x04, - 0x4e, 0x7d, 0x7f, 0x6d, 0xc4, 0xce, 0x82, 0x8c, - 0xe3, 0x97, 0x55, 0xac, 0x88, 0xe4, 0x2e, 0x07 }, { 0x90, 0xe2, 0x51, 0x86, 0x7f, 0x6b, 0x0c, 0x14, 0xbd, 0x9b, 0x51, 0x0c, 0xfd, 0xa8, 0x48, 0x49, 0x72, 0xfd, 0xf0, 0xe0, 0x6d, 0xc1, 0x1f, 0x5d, @@ -1038,10 +922,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe1, 0x9d, 0x17, 0xdb, 0xbe, 0x6e, 0x7c, 0x82, 0x31, 0x86, 0x9c, 0xa7, 0xf6, 0xe3, 0x07, 0xa2, 0xc2, 0xcc, 0x54, 0x77, 0x8d, 0x4a, 0x89, 0xb3 }, - { 0x91, 0xc7, 0x6e, 0xf8, 0xc7, 0x05, 0x3b, 0x2a, - 0x27, 0x0b, 0x97, 0x19, 0x78, 0x3c, 0x85, 0x10, - 0xa2, 0x89, 0x0a, 0x48, 0x40, 0x18, 0x63, 0x72, - 0x6e, 0x23, 0x3a, 0x82, 0xbf, 0x9a, 0x0b, 0xcf }, { 0x92, 0x3f, 0x0f, 0x8c, 0x40, 0x5a, 0x02, 0xe6, 0x82, 0xc4, 0xb4, 0x66, 0x5a, 0x7e, 0xe7, 0x16, 0xaa, 0x57, 0xe0, 0xa5, 0x86, 0xc2, 0x4a, 0x16, @@ -1050,10 +930,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x07, 0xe9, 0x40, 0x7f, 0x7f, 0xff, 0x6a, 0x64, 0x63, 0x5d, 0x7c, 0xe9, 0x06, 0x66, 0xd4, 0x29, 0x94, 0x09, 0x7a, 0xf4, 0x0c, 0x31, 0x36, 0xfb }, - { 0x93, 0x8a, 0xe3, 0xe7, 0x15, 0x48, 0xa9, 0xc3, - 0x14, 0x27, 0xcb, 0xa7, 0x40, 0xbe, 0x2e, 0xb9, - 0x26, 0x88, 0x68, 0xbd, 0xac, 0xc1, 0xda, 0xa8, - 0x67, 0x02, 0xfa, 0xb7, 0x93, 0x70, 0xb8, 0xf9 }, { 0x94, 0xdc, 0x80, 0x07, 0x49, 0x1d, 0xa8, 0xbf, 0xb7, 0x39, 0x14, 0xad, 0xce, 0xf7, 0x1a, 0x12, 0x41, 0x58, 0xba, 0xd1, 0x7b, 0xa8, 0x8f, 0xa9, @@ -1082,30 +958,14 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb1, 0xad, 0xa6, 0x09, 0xe2, 0x00, 0x95, 0xfb, 0xc3, 0x3a, 0x6b, 0xbc, 0x6a, 0x21, 0xd8, 0x0a, 0x4e, 0xcb, 0x27, 0x3c, 0x60, 0xac, 0x2a, 0xc7 }, - { 0x97, 0xe2, 0x11, 0x70, 0x95, 0x44, 0x9c, 0xdf, - 0xc0, 0xa8, 0x3e, 0xd4, 0x9e, 0x65, 0x0a, 0xdf, - 0xd9, 0xbc, 0x0b, 0x3c, 0x50, 0x04, 0x9d, 0x7b, - 0x93, 0x24, 0x5a, 0xcc, 0x3a, 0x0c, 0x16, 0xaf }, - { 0x98, 0xb5, 0x92, 0x4e, 0x06, 0xcd, 0xea, 0x1b, - 0xa1, 0x7f, 0xdb, 0x1b, 0x13, 0x97, 0x90, 0x24, - 0xb1, 0xc2, 0x5b, 0x0a, 0x69, 0x0c, 0xfe, 0x87, - 0x8d, 0x4c, 0xb4, 0x07, 0x76, 0xb9, 0x6f, 0xb0 }, { 0x99, 0xa5, 0x5f, 0x76, 0xcb, 0xea, 0x0f, 0x3e, 0x60, 0x71, 0xd3, 0x82, 0x18, 0x1a, 0xf6, 0xcb, 0x25, 0xbd, 0xc5, 0x87, 0x5e, 0x29, 0xf0, 0xf4, 0xd7, 0x19, 0xa9, 0xd3, 0x5b, 0x5b, 0xd6, 0xbf }, - { 0x99, 0xb4, 0x6c, 0x68, 0x90, 0x62, 0x37, 0x40, - 0x23, 0xdb, 0x68, 0x19, 0xf8, 0x89, 0xd3, 0xc1, - 0xbb, 0x8a, 0x83, 0x8c, 0x6b, 0x51, 0x7e, 0x32, - 0x7e, 0xd9, 0x1c, 0x6c, 0x96, 0x2d, 0x06, 0x49 }, { 0x9a, 0x4b, 0x49, 0x93, 0xb4, 0xed, 0x8c, 0x27, 0xe7, 0x7f, 0x3c, 0x8a, 0xaf, 0xdb, 0xdc, 0x11, 0x1a, 0x36, 0xb7, 0x3c, 0xca, 0xdb, 0x87, 0x04, 0x98, 0x25, 0x00, 0xd1, 0xb0, 0xf1, 0x09, 0xf2 }, - { 0x9a, 0x5f, 0xab, 0xe5, 0x8a, 0x1e, 0xae, 0x4b, - 0x20, 0xba, 0xb3, 0xa7, 0xeb, 0x5e, 0x42, 0xa2, - 0xda, 0x83, 0x11, 0x59, 0x25, 0x7d, 0xd4, 0xe3, - 0x55, 0x2e, 0xc6, 0xf7, 0xd2, 0x67, 0xfa, 0xba }, { 0x9a, 0xae, 0x9d, 0x45, 0xaa, 0x04, 0x03, 0x06, 0x4b, 0xc5, 0xa7, 0x4d, 0xd0, 0x32, 0x5d, 0xa4, 0x1e, 0x12, 0xcf, 0x58, 0x6c, 0x46, 0x2e, 0xe0, @@ -1118,14 +978,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xbc, 0x8a, 0x77, 0x53, 0x12, 0x57, 0x2a, 0xb2, 0x79, 0x21, 0x6d, 0x55, 0x6d, 0xa7, 0x4a, 0xc2, 0xa7, 0xc0, 0x41, 0xe8, 0xce, 0xb0, 0xbe, 0x0a }, - { 0x9c, 0xca, 0x23, 0x7c, 0xdf, 0xca, 0x2c, 0x72, - 0xc6, 0x09, 0x25, 0x4a, 0x72, 0x57, 0xfe, 0xd5, - 0x3a, 0xf1, 0x44, 0xab, 0xc2, 0x5e, 0xcd, 0x8e, - 0xf7, 0x01, 0x30, 0x8c, 0xb1, 0x3c, 0xf7, 0x69 }, - { 0x9d, 0x32, 0x0d, 0x7b, 0x3d, 0x46, 0x34, 0x5f, - 0x0f, 0x2d, 0xec, 0xb7, 0x62, 0xa4, 0x81, 0x7b, - 0x26, 0xa9, 0xa7, 0xcf, 0xe8, 0x71, 0xb1, 0x3e, - 0x84, 0xe7, 0xec, 0x81, 0x0a, 0xae, 0xb6, 0x2c }, { 0x9d, 0x6b, 0xdf, 0xcf, 0x0c, 0xbf, 0xfe, 0xea, 0x3b, 0x1a, 0xc7, 0xe9, 0x63, 0xcb, 0xb5, 0xf2, 0x7f, 0xbd, 0xa8, 0x9d, 0x27, 0x77, 0xf6, 0x0e, @@ -1166,10 +1018,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x02, 0x57, 0x46, 0x34, 0xde, 0x70, 0x7d, 0x2f, 0x92, 0xf4, 0xd0, 0xcb, 0x90, 0xcd, 0xb6, 0x1d, 0xd1, 0x95, 0x8b, 0xcf, 0x0c, 0x55, 0x20, 0x86 }, - { 0xa5, 0x67, 0x98, 0x6c, 0xe0, 0xe3, 0x36, 0xf8, - 0x4f, 0xdc, 0x08, 0x15, 0xb8, 0x6e, 0xa3, 0x03, - 0x34, 0x3c, 0xf8, 0xc1, 0x0f, 0x37, 0x27, 0x83, - 0x27, 0x14, 0x86, 0xb9, 0xc9, 0x3b, 0x63, 0x67 }, { 0xa6, 0x62, 0xfc, 0x81, 0xc9, 0x09, 0x34, 0xb9, 0xb4, 0xd6, 0x30, 0xb5, 0xd8, 0x2e, 0x86, 0xf2, 0x36, 0x3e, 0xc1, 0x5c, 0xcf, 0xcd, 0xaf, 0xa7, @@ -1198,10 +1046,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x56, 0x21, 0x2d, 0xb3, 0xab, 0x34, 0x89, 0x6e, 0x91, 0x70, 0x93, 0x11, 0x3e, 0x47, 0xca, 0x35, 0x96, 0x2e, 0xac, 0xca, 0x9c, 0xb3, 0x86, 0xf0 }, - { 0xa9, 0x71, 0x2f, 0x85, 0xed, 0x2e, 0x25, 0xad, - 0xa5, 0x7d, 0xc1, 0xf0, 0xf8, 0x6d, 0xe1, 0x07, - 0xb5, 0xe2, 0xf0, 0x36, 0x09, 0x53, 0xf1, 0xed, - 0x12, 0x5e, 0x37, 0x07, 0x59, 0x47, 0x1d, 0x09 }, { 0xaa, 0x4b, 0xb3, 0x6f, 0x51, 0xd3, 0xc5, 0x33, 0xb5, 0x27, 0x23, 0xcf, 0x66, 0xa5, 0xa9, 0x9f, 0xc1, 0x2f, 0x11, 0xd4, 0xcc, 0x12, 0x87, 0x56, @@ -1226,10 +1070,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x8a, 0x54, 0xca, 0xb5, 0x4a, 0x96, 0xe9, 0x66, 0x6e, 0x72, 0xa8, 0x20, 0x22, 0x44, 0xef, 0x3d, 0x7c, 0xa9, 0x34, 0xdf, 0xcc, 0x24, 0xfc, 0xa7 }, - { 0xac, 0x7c, 0x14, 0xb9, 0x56, 0x8f, 0x92, 0x07, - 0x5a, 0xd4, 0xa3, 0xba, 0x3d, 0x4b, 0x01, 0x84, - 0x91, 0xf3, 0x66, 0x1a, 0x37, 0x9b, 0x3d, 0xfe, - 0xdd, 0x6f, 0xd3, 0xc3, 0x2e, 0xfa, 0x84, 0x7d }, { 0xad, 0x69, 0x54, 0x5f, 0x9f, 0x85, 0x25, 0x5f, 0xe4, 0x16, 0x51, 0x3d, 0x94, 0xdb, 0x31, 0x50, 0x5f, 0x38, 0x4b, 0x52, 0x3c, 0x2c, 0xa2, 0x6e, @@ -1238,18 +1078,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe8, 0x54, 0xb5, 0x15, 0x50, 0xea, 0x44, 0x4f, 0xa3, 0xb8, 0xbb, 0x50, 0xae, 0x93, 0x74, 0x01, 0x3c, 0xfe, 0xf3, 0x88, 0x73, 0x5d, 0x0b, 0xd3 }, - { 0xae, 0x4d, 0xf3, 0x97, 0x9b, 0x74, 0x27, 0x34, - 0xa3, 0x39, 0xc4, 0x70, 0x1d, 0x5e, 0x13, 0x21, - 0x26, 0x3f, 0xf4, 0x4e, 0x67, 0x56, 0x49, 0x05, - 0xf4, 0x9e, 0x25, 0x34, 0x62, 0xb8, 0x02, 0x25 }, { 0xaf, 0x1f, 0x37, 0x1f, 0x34, 0x84, 0x57, 0x51, 0x65, 0x2d, 0xc7, 0x48, 0x23, 0xf3, 0x01, 0x5c, 0x5a, 0x11, 0xca, 0x65, 0x3f, 0x28, 0x70, 0x1e, 0xdd, 0x4a, 0x7e, 0x0d, 0x23, 0x17, 0x1b, 0xbb }, - { 0xaf, 0x6a, 0x9d, 0x88, 0xad, 0xe1, 0x24, 0xdb, - 0xf9, 0x50, 0xb2, 0xc4, 0x27, 0xbc, 0x40, 0x19, - 0x63, 0xb9, 0x61, 0x25, 0xc0, 0xa2, 0xae, 0xbb, - 0x7f, 0xb3, 0xf9, 0x8e, 0x48, 0x7a, 0x7f, 0xa6 }, { 0xaf, 0x6b, 0x80, 0x51, 0x47, 0x14, 0x0a, 0x0e, 0x41, 0x81, 0xd8, 0x6a, 0x7e, 0x8f, 0x07, 0x69, 0xb6, 0x1d, 0x46, 0xd7, 0xb6, 0xfa, 0xc6, 0xe6, @@ -1274,22 +1106,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x91, 0x04, 0xf9, 0x4f, 0xaa, 0x66, 0xe0, 0xcc, 0xc0, 0x41, 0x34, 0xd5, 0x80, 0x9a, 0x2a, 0x26, 0x70, 0xa3, 0xb7, 0xbc, 0x7d, 0xd9, 0x64, 0xf8 }, - { 0xb3, 0xe6, 0x42, 0x06, 0x6e, 0x41, 0x78, 0x67, - 0xd9, 0x0f, 0xb9, 0xb2, 0xba, 0x15, 0x41, 0x98, - 0xa5, 0xc5, 0xf6, 0xcc, 0x82, 0x9b, 0x51, 0x39, - 0xdf, 0xd6, 0x91, 0xe5, 0x1a, 0xd3, 0x74, 0xad }, { 0xb3, 0xf4, 0xb1, 0x6f, 0x8e, 0xce, 0xbb, 0x41, 0x47, 0x4f, 0x92, 0x4f, 0xee, 0xf9, 0xb0, 0xbd, 0x97, 0x9b, 0x36, 0x36, 0xc3, 0x4f, 0xf2, 0x72, 0x3f, 0x67, 0x3c, 0x8e, 0xee, 0x2a, 0xf1, 0x52 }, - { 0xb4, 0xd4, 0x67, 0xfc, 0x5e, 0x97, 0xdb, 0x25, - 0xa1, 0xfd, 0xb0, 0x06, 0xd2, 0x77, 0x66, 0xb9, - 0x99, 0x5b, 0xb9, 0xc7, 0x7b, 0x66, 0x43, 0x97, - 0x08, 0xa4, 0x59, 0xb0, 0x43, 0xd0, 0x33, 0x24 }, - { 0xb4, 0xed, 0xcd, 0x6f, 0x8a, 0x01, 0x82, 0xb7, - 0x17, 0xf0, 0x6f, 0xe1, 0xd7, 0xac, 0x9c, 0x62, - 0x33, 0xd4, 0x38, 0x22, 0xe9, 0xfd, 0x14, 0xdb, - 0x98, 0xf7, 0xf8, 0x4e, 0x32, 0x79, 0x6d, 0x08 }, { 0xb5, 0xe5, 0xdc, 0xde, 0xcb, 0x8d, 0xeb, 0x27, 0x13, 0x4f, 0x02, 0xa5, 0x18, 0x79, 0x43, 0x16, 0xf0, 0x8f, 0xaf, 0x9c, 0x2b, 0x1f, 0xda, 0xd6, @@ -1298,10 +1118,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xec, 0x6c, 0xe0, 0x92, 0x02, 0x2b, 0x49, 0x32, 0x81, 0xe2, 0x9a, 0x21, 0x73, 0x50, 0x8c, 0x9b, 0xd0, 0xfb, 0xc2, 0xc3, 0xd9, 0x68, 0xe3, 0xe7 }, - { 0xb7, 0x1f, 0x29, 0x1e, 0x6e, 0xc6, 0xbd, 0x6c, - 0x4f, 0x2b, 0x81, 0xf7, 0xf7, 0x21, 0x06, 0x73, - 0xe9, 0x73, 0x08, 0xaf, 0xf1, 0x24, 0x3f, 0x26, - 0x99, 0x5a, 0x25, 0xfa, 0x23, 0x0c, 0xfe, 0x4c }, { 0xb7, 0xa2, 0xae, 0x06, 0x06, 0xaa, 0x2c, 0xfb, 0x27, 0x01, 0xb3, 0xb2, 0x77, 0xf4, 0xd7, 0x12, 0x54, 0x70, 0x48, 0x7e, 0xfd, 0x94, 0x05, 0x85, @@ -1310,10 +1126,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xef, 0x73, 0xde, 0x4b, 0x74, 0xf2, 0x83, 0xc4, 0x2b, 0x2c, 0xcb, 0x1c, 0xa3, 0x7c, 0x5b, 0x30, 0xaa, 0xd6, 0x55, 0xa7, 0x40, 0x1a, 0x3d, 0x2f }, - { 0xb8, 0x8c, 0xe8, 0x1a, 0x7b, 0x4b, 0x62, 0x65, - 0x71, 0x0f, 0x38, 0xd0, 0xca, 0x3e, 0x01, 0xff, - 0xab, 0xde, 0x0f, 0xc2, 0x48, 0x3e, 0x21, 0xb8, - 0xf1, 0xa5, 0xff, 0x48, 0x3b, 0x2d, 0x60, 0xce }, { 0xb9, 0x8d, 0x83, 0x38, 0x55, 0xc3, 0x67, 0x88, 0x62, 0xb6, 0x2f, 0x36, 0x50, 0xdb, 0x00, 0xa3, 0x45, 0xf4, 0x6a, 0x0e, 0x8e, 0x01, 0x1a, 0x20, @@ -1442,10 +1254,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x42, 0xed, 0x3c, 0x79, 0xbe, 0xd9, 0x44, 0x1e, 0x92, 0x50, 0xbd, 0x05, 0x20, 0x25, 0xad, 0x8a, 0xf4, 0x40, 0x41, 0xac, 0x19, 0xef, 0xbb, 0x4c }, - { 0xc9, 0x43, 0x10, 0x03, 0xbb, 0xea, 0xb5, 0x8e, - 0x35, 0x2f, 0xde, 0xb4, 0x5b, 0x7f, 0xcf, 0x15, - 0xc7, 0x3f, 0x07, 0x34, 0xa0, 0x7d, 0x6c, 0xbd, - 0xf6, 0x32, 0x92, 0x92, 0xeb, 0x81, 0x2c, 0x93 }, { 0xc9, 0x72, 0xf4, 0xf9, 0x6e, 0x71, 0x33, 0xe1, 0x6e, 0x55, 0x57, 0xa0, 0x57, 0xb1, 0xd4, 0x2b, 0xa9, 0x2d, 0x98, 0x5c, 0xae, 0xe7, 0x3c, 0xaf, @@ -1470,10 +1278,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xc5, 0x6f, 0xdf, 0x19, 0x1e, 0x1d, 0xaf, 0x9f, 0x32, 0x5c, 0x65, 0x0b, 0xd6, 0x2f, 0x07, 0xc4, 0x67, 0x71, 0x72, 0x07, 0x35, 0x1a, 0xe3, 0x29 }, - { 0xcc, 0x2a, 0x70, 0x6f, 0xe6, 0x8f, 0x5d, 0x17, - 0xf4, 0xab, 0xaf, 0x60, 0x86, 0xe5, 0xbd, 0x97, - 0xae, 0x35, 0xeb, 0x35, 0x9f, 0x75, 0xc0, 0x92, - 0xbb, 0xa4, 0x93, 0xfe, 0x11, 0xf2, 0x69, 0xfd }, { 0xcc, 0x30, 0xd8, 0x19, 0xde, 0x54, 0x05, 0xf6, 0x49, 0xc8, 0xb7, 0xa8, 0x14, 0x8f, 0x26, 0xd7, 0x71, 0x08, 0x3e, 0xc5, 0x18, 0xf9, 0xb6, 0x6f, @@ -1554,14 +1358,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x1a, 0xf6, 0x6b, 0xfa, 0x8f, 0x90, 0xd1, 0x41, 0xe9, 0x93, 0xf0, 0x00, 0x21, 0x33, 0xf2, 0x8d, 0xe9, 0x7f, 0x56, 0x4a, 0x1d, 0x60, 0x4e, 0xcc }, - { 0xd9, 0x7f, 0x55, 0xb9, 0x57, 0x9b, 0x05, 0xae, - 0x4a, 0x3e, 0xd7, 0xfc, 0x55, 0x8c, 0x58, 0x45, - 0x64, 0x51, 0x60, 0xda, 0xb3, 0x53, 0x85, 0xc1, - 0x38, 0xbc, 0x89, 0x9c, 0x4d, 0xad, 0x8b, 0x36 }, - { 0xd9, 0xe8, 0xcc, 0xda, 0x78, 0xfb, 0x8d, 0x5d, - 0xbc, 0xe6, 0x94, 0x15, 0x57, 0x61, 0xf4, 0xd0, - 0x2c, 0x30, 0xcc, 0x8d, 0x7a, 0xea, 0x0e, 0x11, - 0x88, 0x2d, 0x79, 0x37, 0x6c, 0x72, 0x90, 0xff }, { 0xda, 0xdf, 0x97, 0x13, 0x34, 0x14, 0xad, 0x51, 0x3f, 0xc7, 0x50, 0x14, 0xe9, 0x56, 0x65, 0xda, 0xd7, 0x76, 0xb1, 0x50, 0x4b, 0x15, 0x67, 0x43, @@ -1570,10 +1366,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x64, 0x8d, 0x0e, 0xd8, 0x9b, 0x5d, 0xe0, 0xee, 0x93, 0x1f, 0x1b, 0x33, 0x84, 0x78, 0xab, 0xf5, 0x69, 0x29, 0xa9, 0x4d, 0x3b, 0xd6, 0x1d, 0x46 }, - { 0xdc, 0xb2, 0x1d, 0xef, 0x3c, 0x26, 0x0b, 0x20, - 0x50, 0xf3, 0x4c, 0x5f, 0x51, 0xbe, 0x30, 0x9c, - 0x3c, 0x76, 0x36, 0x30, 0x6d, 0x51, 0xb9, 0xbe, - 0x43, 0xd8, 0x9d, 0xe0, 0x8f, 0x60, 0xd9, 0x4a }, { 0xde, 0xcd, 0xb9, 0xfc, 0x1d, 0xde, 0xc9, 0x7e, 0x09, 0xc3, 0x02, 0x6a, 0xce, 0xb7, 0x6b, 0xda, 0xe9, 0xde, 0xb6, 0x62, 0x75, 0x1d, 0xda, 0x34, @@ -1638,18 +1430,10 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x89, 0x0b, 0xc1, 0xf9, 0xfa, 0x00, 0xd8, 0x09, 0x0b, 0x5a, 0xc9, 0x82, 0x5e, 0xa9, 0xd2, 0xfd, 0xf7, 0x7c, 0xa4, 0xda, 0xe9, 0x44, 0x51, 0xb2 }, - { 0xe7, 0x5d, 0x32, 0x90, 0xa6, 0x9a, 0xb5, 0x96, - 0xee, 0x17, 0x9d, 0xc1, 0x34, 0xaa, 0x07, 0x1e, - 0x69, 0xfd, 0x98, 0x25, 0xfc, 0x06, 0x2e, 0x33, - 0x8b, 0xa2, 0x23, 0x5e, 0xe3, 0x25, 0x56, 0xd2 }, { 0xe8, 0x16, 0xf9, 0x92, 0x94, 0xa1, 0x3a, 0xc2, 0xfa, 0x2b, 0xfb, 0x76, 0xc2, 0x2d, 0xfa, 0x71, 0xbc, 0x3d, 0xa4, 0x8f, 0x67, 0x1e, 0xf7, 0x7c, 0x00, 0xaa, 0x8e, 0x45, 0x9b, 0x7c, 0xc8, 0x2a }, - { 0xe8, 0x21, 0x3c, 0x45, 0x51, 0x81, 0x61, 0xbc, - 0x36, 0x37, 0x3d, 0xcd, 0x2d, 0x4b, 0x21, 0xb7, - 0x6a, 0x7c, 0x06, 0x6d, 0xf5, 0x52, 0x6e, 0x88, - 0x8b, 0x6e, 0xed, 0x09, 0xa9, 0xee, 0xd0, 0x62 }, { 0xe9, 0xd4, 0x98, 0x51, 0xbf, 0x78, 0x37, 0x6d, 0x54, 0x08, 0x2d, 0x1e, 0xb8, 0x2b, 0xd2, 0xdc, 0x96, 0x82, 0x07, 0x09, 0xb7, 0x77, 0x2d, 0x3f, @@ -1686,10 +1470,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x0b, 0xab, 0x5d, 0x66, 0x42, 0xf6, 0x60, 0xb8, 0x42, 0xd6, 0xc9, 0x73, 0x07, 0x44, 0x93, 0xe4, 0xef, 0x1b, 0xbf, 0x31, 0x1a, 0x92, 0x79, 0x95 }, - { 0xee, 0x1a, 0x2f, 0xa9, 0x58, 0x37, 0x5e, 0x11, - 0x06, 0xe2, 0xc9, 0x05, 0xed, 0x8a, 0x26, 0x4f, - 0x28, 0x19, 0xcb, 0xb5, 0x26, 0x11, 0x8d, 0x30, - 0x68, 0x9d, 0x17, 0x90, 0x42, 0x9a, 0x46, 0xa1 }, { 0xee, 0x34, 0xe1, 0xa1, 0x9b, 0xc8, 0x89, 0xf8, 0x5f, 0x7f, 0x0f, 0x5b, 0xf8, 0x72, 0xb1, 0xac, 0x56, 0x5e, 0xc6, 0xf1, 0x9d, 0xb5, 0x17, 0xba, @@ -1706,14 +1486,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xb7, 0x6a, 0x93, 0x23, 0x49, 0xc4, 0x5d, 0x09, 0xb2, 0x8b, 0x2d, 0x8a, 0x00, 0x17, 0x19, 0xa5, 0x8d, 0xfa, 0xcc, 0x74, 0x84, 0xc7, 0xcf, 0x42 }, - { 0xf0, 0x11, 0xad, 0x9e, 0xdd, 0x4f, 0xe7, 0x18, - 0x8d, 0x77, 0x2e, 0xba, 0xfa, 0x5b, 0xf5, 0x32, - 0x92, 0x47, 0x77, 0x88, 0xdc, 0x12, 0x80, 0x32, - 0x76, 0xb0, 0x00, 0xc4, 0x41, 0x91, 0x03, 0xf0 }, - { 0xf0, 0x2f, 0x9d, 0xa4, 0x5d, 0x9e, 0xb9, 0x86, - 0x19, 0x4e, 0x06, 0xf5, 0xe6, 0x18, 0x95, 0x45, - 0x12, 0xc9, 0x02, 0x6e, 0x7c, 0xa7, 0xb5, 0x1e, - 0x66, 0x5d, 0xb6, 0xad, 0xba, 0xc1, 0xf6, 0x00 }, { 0xf0, 0x6b, 0x35, 0x95, 0x36, 0xd1, 0x34, 0x32, 0x8b, 0x36, 0x00, 0x4d, 0xa9, 0xa9, 0x19, 0x0c, 0x3a, 0x76, 0x69, 0xe8, 0x27, 0x8d, 0xb9, 0xf7, @@ -1742,14 +1514,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x35, 0xe8, 0x25, 0x67, 0xa6, 0xe2, 0x36, 0x75, 0x03, 0x94, 0xc1, 0x19, 0x14, 0x09, 0x87, 0x0c, 0x6f, 0xbe, 0x95, 0x2d, 0x08, 0xa3, 0x3a, 0xba }, - { 0xf6, 0x6e, 0xdf, 0xf6, 0xa3, 0x94, 0xc6, 0x6d, - 0xf5, 0xbf, 0x9f, 0xe7, 0x84, 0xe6, 0x31, 0xf7, - 0x9a, 0xf3, 0x9c, 0xb1, 0x4f, 0x3a, 0xc5, 0x16, - 0x11, 0xf6, 0xfe, 0x1d, 0x9d, 0x1e, 0x1c, 0xe9 }, - { 0xf6, 0xaa, 0xef, 0x12, 0xfc, 0x25, 0x2d, 0xd9, - 0xe7, 0xf7, 0x75, 0x2c, 0x2f, 0x74, 0x5d, 0x59, - 0xd6, 0x37, 0x57, 0xc6, 0xcc, 0x14, 0xd2, 0x25, - 0x3a, 0x64, 0x7c, 0xd1, 0x81, 0x49, 0x39, 0x93 }, { 0xf8, 0x64, 0x44, 0x3e, 0x2f, 0x63, 0x9e, 0x7c, 0xff, 0xd2, 0x42, 0x21, 0xf6, 0x1b, 0xbf, 0xf0, 0x7c, 0xce, 0x5c, 0x61, 0xdd, 0xb1, 0x68, 0xb3, @@ -1770,10 +1534,6 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0x13, 0x18, 0x26, 0x6b, 0x72, 0x58, 0x56, 0x00, 0x35, 0xbc, 0x64, 0x60, 0x8e, 0x34, 0xb9, 0x90, 0xca, 0x92, 0xa5, 0x52, 0xf3, 0x14, 0x21, 0x61 }, - { 0xfb, 0xdd, 0x65, 0xd5, 0x6e, 0x48, 0x0c, 0xd2, - 0x53, 0x1b, 0xab, 0xfb, 0x98, 0xad, 0x6e, 0x35, - 0x22, 0x1e, 0xb9, 0x8a, 0xe4, 0x63, 0x2c, 0x43, - 0x12, 0xdb, 0x75, 0x17, 0xb1, 0x36, 0x54, 0x72 }, { 0xfb, 0xed, 0xd3, 0x88, 0x89, 0xf0, 0xb4, 0x1f, 0x73, 0x4d, 0xe2, 0xf4, 0xc9, 0xd6, 0xf2, 0x7c, 0x8d, 0x4a, 0xa9, 0xab, 0x73, 0x64, 0x91, 0xe1, @@ -1831,11 +1591,9 @@ const uint8_t kCNNICDVWhitelist[][crypto::kSHA256Length] = { 0xe4, 0xdf, 0x42, 0x99, 0xfb, 0xe3, 0xf6, 0x81, 0xaf, 0x3f, 0x5c, 0xf4, 0x22, 0x5a, 0x8e, 0xaf }, }; + +// SHA-256 hashes of leaf certificates issued by CNNIC's EV root. const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { - { 0x9f, 0xfa, 0x4e, 0xf4, 0xfc, 0xf2, 0xcf, 0xd1, - 0xb2, 0x7c, 0x6a, 0x62, 0xe3, 0xc4, 0x23, 0x5b, - 0xd8, 0x3c, 0xc5, 0xe0, 0x06, 0xe9, 0x2a, 0x55, - 0xe4, 0xa9, 0x86, 0xe6, 0x30, 0x53, 0x57, 0xe3 }, { 0xb5, 0xef, 0x42, 0xc4, 0xbc, 0xed, 0xf1, 0x7b, 0xec, 0xc7, 0x5b, 0xf4, 0x63, 0x66, 0x49, 0xce, 0xbf, 0xf8, 0x71, 0x1b, 0xce, 0xff, 0xfa, 0x69, @@ -1844,10 +1602,6 @@ const uint8_t kCNNICEVWhitelist[][crypto::kSHA256Length] = { 0x4b, 0xcf, 0x60, 0xf2, 0x38, 0x21, 0xac, 0x6c, 0x58, 0x19, 0x73, 0x51, 0xea, 0xcf, 0xa5, 0x57, 0x4c, 0xf0, 0x41, 0xb4, 0xce, 0x6b, 0x84, 0x04 }, - { 0xba, 0xcf, 0x5e, 0x99, 0xf5, 0x7f, 0x78, 0xcc, - 0x32, 0xf2, 0xaf, 0x8d, 0x4e, 0x80, 0x6a, 0x0a, - 0x36, 0xce, 0x9b, 0x42, 0xe9, 0xc7, 0x5c, 0x54, - 0x8d, 0xed, 0x55, 0xd2, 0x48, 0x62, 0xca, 0x17 }, { 0xdf, 0x69, 0xf9, 0x6a, 0x85, 0x67, 0x8f, 0x6c, 0xaf, 0x3f, 0xde, 0x25, 0xec, 0xfb, 0x5d, 0xf4, 0x74, 0x70, 0x87, 0xc2, 0xaf, 0x3b, 0x00, 0x65, @@ -1884,36 +1638,54 @@ const PublicKeyWhitelist* g_whitelist = kBuiltinWhitelist; size_t g_whitelist_size = kBuiltinWhitelistSize; // Comparator to compare a SHA256HashValue with a uint8_t array containing a -// raw SHA-256 hash. -// Return value follows memcmp semantics. -int CompareHashValueToRawHash(const void* key, const void* element) { +// raw SHA-256 hash. Return value follows memcmp semantics. +int CompareSHA256HashValueToRawHash(const void* key, const void* element) { const SHA256HashValue* search_key = reinterpret_cast<const SHA256HashValue*>(key); return memcmp(search_key->data, element, sizeof(search_key->data)); } +// Comparator to compare a (SHA-256) HashValue with a uint8_t array containing +// a raw SHA-256 hash. Return value follows memcmp semantics. +int CompareHashValueToRawHash(const void* key, const void* element) { + const HashValue* search_key = reinterpret_cast<const HashValue*>(key); + return memcmp(search_key->data(), element, search_key->size()); +} + } // namespace bool IsNonWhitelistedCertificate(const X509Certificate& cert, const HashValueVector& public_key_hashes) { - if (g_whitelist_size == 0) - return false; - for (size_t i = 0; i < g_whitelist_size; ++i) { - for (const auto& hash : public_key_hashes) { - if (hash.tag != HASH_VALUE_SHA256) - continue; + // 2016-10-21 00:00:00 UTC + const base::Time last_wosign_cert = + base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(1477008000); + + for (const auto& hash : public_key_hashes) { + if (hash.tag != HASH_VALUE_SHA256) + continue; + + // Check for WoSign/StartCom certificates. + if (bsearch(&hash, kWosignKeys, arraysize(kWosignKeys), + crypto::kSHA256Length, CompareHashValueToRawHash) != nullptr && + (cert.valid_start().is_null() || cert.valid_start().is_max() || + cert.valid_start() > last_wosign_cert)) { + return true; + } + + // Check the public key whitelist. + for (size_t i = 0; i < g_whitelist_size; ++i) { if (memcmp(hash.data(), g_whitelist[i].public_key, crypto::kSHA256Length) != 0) { continue; } const SHA256HashValue leaf_hash = X509Certificate::CalculateFingerprint256(cert.os_cert_handle()); - void* result = bsearch(&leaf_hash, g_whitelist[i].whitelist, - g_whitelist[i].whitelist_size, - crypto::kSHA256Length, CompareHashValueToRawHash); + void* result = bsearch( + &leaf_hash, g_whitelist[i].whitelist, g_whitelist[i].whitelist_size, + crypto::kSHA256Length, CompareSHA256HashValueToRawHash); if (result == nullptr) - return true; - return false; + return true; // Hash was not found on the public key whitelist. + break; } } return false; diff --git a/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc b/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc index dea54129ba8..791957315a6 100644 --- a/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc +++ b/chromium/net/cert/cert_verify_proc_whitelist_unittest.cc @@ -184,6 +184,25 @@ TEST(CertVerifyProcWhitelistTest, AcceptsUnconstrainedLeaf) { SetCertificateWhitelistForTesting(nullptr, 0); } +TEST(CertVerifyProcWhitelistTest, HandlesWosignCerts) { + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(GetTestCertsDirectory(), "wosign_before_oct_21.pem"); + ASSERT_TRUE(cert); + + HashValueVector public_key_hashes; + public_key_hashes.emplace_back(SHA256HashValue{ + {0x15, 0x28, 0x39, 0x7d, 0xa2, 0x12, 0x89, 0x0a, 0x83, 0x0b, 0x0b, + 0x95, 0xa5, 0x99, 0x68, 0xce, 0xf2, 0x34, 0x77, 0x37, 0x79, 0xdf, + 0x51, 0x81, 0xcf, 0x10, 0xfa, 0x64, 0x75, 0x34, 0xbb, 0x65}}); + + EXPECT_FALSE(IsNonWhitelistedCertificate(*cert, public_key_hashes)); + + cert = ImportCertFromFile(GetTestCertsDirectory(), "wosign_after_oct_21.pem"); + ASSERT_TRUE(cert); + + EXPECT_TRUE(IsNonWhitelistedCertificate(*cert, public_key_hashes)); +} + } // namespace } // namespace net diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc index a2647969d80..a13117a7a8e 100644 --- a/chromium/net/cert/cert_verify_proc_win.cc +++ b/chromium/net/cert/cert_verify_proc_win.cc @@ -9,6 +9,7 @@ #include <vector> #include "base/memory/free_deleter.h" +#include "base/metrics/histogram_macros.h" #include "base/sha1.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -78,6 +79,8 @@ int MapSecurityError(SECURITY_STATUS err) { return ERR_CERT_COMMON_NAME_INVALID; case SEC_E_UNTRUSTED_ROOT: // Schannel case CERT_E_UNTRUSTEDROOT: // CryptoAPI + case TRUST_E_CERT_SIGNATURE: // CryptoAPI. Caused by weak crypto or bad + // signatures, but not differentiable. return ERR_CERT_AUTHORITY_INVALID; case SEC_E_CERT_EXPIRED: // Schannel case CERT_E_EXPIRED: // CryptoAPI @@ -283,8 +286,44 @@ bool IsIssuedByKnownRoot(PCCERT_CHAIN_CONTEXT chain_context) { PCCERT_CONTEXT cert = element[num_elements - 1]->pCertContext; SHA256HashValue hash = X509Certificate::CalculateFingerprint256(cert); - return IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0], - sizeof(kKnownRootCertSHA256Hashes)); + bool is_builtin = + IsSHA256HashInSortedArray(hash, &kKnownRootCertSHA256Hashes[0][0], + sizeof(kKnownRootCertSHA256Hashes)); + + // Test to see if the use of a built-in set of known roots on Windows can be + // replaced with using AuthRoot's SHA-256 property. On any system other than + // a fresh RTM with no AuthRoot updates, this property should always exist for + // roots delivered via AuthRoot.stl, but should not exist on any manually or + // administratively deployed roots. + BYTE hash_prop[32] = {0}; + DWORD size = sizeof(hash_prop); + bool found_property = + CertGetCertificateContextProperty( + cert, CERT_AUTH_ROOT_SHA256_HASH_PROP_ID, &hash_prop, &size) && + size == sizeof(hash_prop); + + enum BuiltinStatus { + BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_NOT_SET = 0, + BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_SET = 1, + BUILT_IN_PROPERTY_FOUND_BUILTIN_NOT_SET = 2, + BUILT_IN_PROPERTY_FOUND_BUILTIN_SET = 3, + BUILT_IN_MAX_VALUE, + } status; + if (!found_property && !is_builtin) { + status = BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_NOT_SET; + } else if (!found_property && is_builtin) { + status = BUILT_IN_PROPERTY_NOT_FOUND_BUILTIN_SET; + } else if (found_property && !is_builtin) { + status = BUILT_IN_PROPERTY_FOUND_BUILTIN_NOT_SET; + } else if (found_property && is_builtin) { + status = BUILT_IN_PROPERTY_FOUND_BUILTIN_SET; + } else { + status = BUILT_IN_MAX_VALUE; + } + UMA_HISTOGRAM_ENUMERATION("Net.SSL_AuthRootConsistency", status, + BUILT_IN_MAX_VALUE); + + return is_builtin; } // Saves some information about the certificate chain |chain_context| in @@ -974,16 +1013,68 @@ int CertVerifyProcWin::VerifyInternal( CERT_SET_PROPERTY_IGNORE_PERSIST_ERROR_FLAG, &ocsp_response_blob); } + CERT_STRONG_SIGN_SERIALIZED_INFO strong_signed_info; + memset(&strong_signed_info, 0, sizeof(strong_signed_info)); + strong_signed_info.dwFlags = 0; // Don't check OCSP or CRL signatures. + + // Note that the following two configurations result in disabling support for + // any CNG-added algorithms, which may result in some disruption for internal + // PKI operations that use national forms of crypto (e.g. GOST). However, the + // fallback mechanism for this (to support SHA-1 chains) will re-enable them, + // so they should continue to work - just with added latency. + wchar_t hash_algs[] = + L"RSA/SHA256;RSA/SHA384;RSA/SHA512;" + L"ECDSA/SHA256;ECDSA/SHA384;ECDSA/SHA512"; + strong_signed_info.pwszCNGSignHashAlgids = hash_algs; + + // RSA-1024 bit support is intentionally enabled here. More investigation is + // needed to determine if setting CERT_STRONG_SIGN_DISABLE_END_CHECK_FLAG in + // the dwStrongSignFlags of |chain_para| would allow the ability to disable + // support for intermediates/roots < 2048-bits, while still ensuring that + // end-entity certs signed with SHA-1 are flagged/rejected. + wchar_t key_sizes[] = L"RSA/1024;ECDSA/256"; + strong_signed_info.pwszCNGPubKeyMinBitLengths = key_sizes; + + CERT_STRONG_SIGN_PARA strong_sign_params; + memset(&strong_sign_params, 0, sizeof(strong_sign_params)); + strong_sign_params.cbSize = sizeof(strong_sign_params); + strong_sign_params.dwInfoChoice = CERT_STRONG_SIGN_SERIALIZED_INFO_CHOICE; + strong_sign_params.pSerializedInfo = &strong_signed_info; + + chain_para.dwStrongSignFlags = 0; + chain_para.pStrongSignPara = &strong_sign_params; + PCCERT_CHAIN_CONTEXT chain_context = nullptr; - if (!CertGetCertificateChain( - chain_engine, - cert_list.get(), - NULL, // current system time - cert_list->hCertStore, - &chain_para, - chain_flags, - NULL, // reserved - &chain_context)) { + + // First, try to verify with strong signing enabled. If this fails, or if the + // chain is rejected, then clear it from |chain_para| so that all subsequent + // calls will use the fallback path. + BOOL chain_result = + CertGetCertificateChain(chain_engine, cert_list.get(), + NULL, // current system time + cert_list->hCertStore, &chain_para, chain_flags, + NULL, // reserved + &chain_context); + if (chain_result && chain_context && + (chain_context->TrustStatus.dwErrorStatus & + (CERT_TRUST_HAS_WEAK_SIGNATURE | CERT_TRUST_IS_NOT_SIGNATURE_VALID))) { + // The attempt to verify with strong-sign (only SHA-2) failed, so fall back + // to disabling it. This will allow SHA-1 chains to be returned, which will + // then be subsequently signalled as weak if necessary. + CertFreeCertificateChain(chain_context); + chain_context = nullptr; + + chain_para.pStrongSignPara = nullptr; + chain_para.dwStrongSignFlags = 0; + chain_result = + CertGetCertificateChain(chain_engine, cert_list.get(), + NULL, // current system time + cert_list->hCertStore, &chain_para, chain_flags, + NULL, // reserved + &chain_context); + } + + if (!chain_result) { verify_result->cert_status |= CERT_STATUS_INVALID; return MapSecurityError(GetLastError()); } diff --git a/chromium/net/cert/ct_log_verifier.cc b/chromium/net/cert/ct_log_verifier.cc index 04eb2f15a12..2af57306d2c 100644 --- a/chromium/net/cert/ct_log_verifier.cc +++ b/chromium/net/cert/ct_log_verifier.cc @@ -5,17 +5,19 @@ #include "net/cert/ct_log_verifier.h" #include <string.h> -#include <openssl/bytestring.h> -#include <openssl/evp.h> + +#include <vector> #include "base/logging.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" #include "crypto/sha2.h" #include "net/cert/ct_log_verifier_util.h" #include "net/cert/ct_serialization.h" +#include "net/cert/merkle_audit_proof.h" #include "net/cert/merkle_consistency_proof.h" #include "net/cert/signed_tree_head.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/evp.h" namespace net { @@ -243,6 +245,61 @@ bool CTLogVerifier::VerifyConsistencyProof( return fr == old_tree_hash && sr == new_tree_hash && sn == 0; } +bool CTLogVerifier::VerifyAuditProof(const ct::MerkleAuditProof& proof, + const std::string& root_hash, + const std::string& leaf_hash) const { + // Implements the algorithm described in + // https://tools.ietf.org/html/draft-ietf-trans-rfc6962-bis-19#section-10.4.1 + // + // It maintains a hash |r|, initialized to |leaf_hash|, and hashes nodes from + // |proof| into it. The proof is then valid if |r| is |root_hash|, proving + // that |root_hash| includes |leaf_hash|. + + // 1. Compare "leaf_index" against "tree_size". If "leaf_index" is + // greater than or equal to "tree_size" fail the proof verification. + if (proof.leaf_index >= proof.tree_size) + return false; + + // 2. Set "fn" to "leaf_index" and "sn" to "tree_size - 1". + uint64_t fn = proof.leaf_index; + uint64_t sn = proof.tree_size - 1; + // 3. Set "r" to "hash". + std::string r = leaf_hash; + + // 4. For each value "p" in the "inclusion_path" array: + for (const std::string& p : proof.nodes) { + // If "sn" is 0, stop the iteration and fail the proof verification. + if (sn == 0) + return false; + + // If "LSB(fn)" is set, or if "fn" is equal to "sn", then: + if ((fn & 1) || fn == sn) { + // 1. Set "r" to "HASH(0x01 || p || r)" + r = ct::internal::HashNodes(p, r); + + // 2. If "LSB(fn)" is not set, then right-shift both "fn" and "sn" + // equally until either "LSB(fn)" is set or "fn" is "0". + while (!(fn & 1) && fn != 0) { + fn >>= 1; + sn >>= 1; + } + } else { // Otherwise: + // Set "r" to "HASH(0x01 || r || p)" + r = ct::internal::HashNodes(r, p); + } + + // Finally, right-shift both "fn" and "sn" one time. + fn >>= 1; + sn >>= 1; + } + + // 5. Compare "sn" to 0. Compare "r" against the "root_hash". If "sn" + // is equal to 0, and "r" and the "root_hash" are equal, then the + // log has proven the inclusion of "hash". Otherwise, fail the + // proof verification. + return sn == 0 && r == root_hash; +} + CTLogVerifier::~CTLogVerifier() { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); diff --git a/chromium/net/cert/ct_log_verifier.h b/chromium/net/cert/ct_log_verifier.h index e9ba307c3e9..6e3b938eb0b 100644 --- a/chromium/net/cert/ct_log_verifier.h +++ b/chromium/net/cert/ct_log_verifier.h @@ -21,10 +21,9 @@ typedef struct evp_pkey_st EVP_PKEY; namespace net { namespace ct { - -struct SignedTreeHead; +struct MerkleAuditProof; struct MerkleConsistencyProof; - +struct SignedTreeHead; } // namespace ct // Class for verifying signatures of a single Certificate Transparency @@ -76,6 +75,14 @@ class NET_EXPORT CTLogVerifier const std::string& old_tree_hash, const std::string& new_tree_hash) const; + // Verifies that |proof| is a valid audit proof (RFC 6962, Section 2.1.1) for + // this log, and which proves that the certificate represented by |leaf_hash| + // has been incorporated into the Merkle tree represented by |root_hash|. + // Returns true if verification succeeds, false otherwise. + bool VerifyAuditProof(const ct::MerkleAuditProof& proof, + const std::string& root_hash, + const std::string& leaf_hash) const; + private: FRIEND_TEST_ALL_PREFIXES(CTLogVerifierTest, VerifySignature); friend class base::RefCountedThreadSafe<CTLogVerifier>; diff --git a/chromium/net/cert/ct_log_verifier_unittest.cc b/chromium/net/cert/ct_log_verifier_unittest.cc index 91ddbc737e3..9067cb6e394 100644 --- a/chromium/net/cert/ct_log_verifier_unittest.cc +++ b/chromium/net/cert/ct_log_verifier_unittest.cc @@ -10,11 +10,13 @@ #include <string> #include <vector> +#include "base/macros.h" #include "base/strings/string_number_conversions.h" #include "base/time/time.h" #include "crypto/secure_hash.h" #include "net/base/hash_value.h" #include "net/cert/ct_log_verifier_util.h" +#include "net/cert/merkle_audit_proof.h" #include "net/cert/merkle_consistency_proof.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/cert/signed_tree_head.h" @@ -27,37 +29,45 @@ namespace { // Calculate the power of two nearest to, but less than, |n|. // |n| must be at least 2. -uint64_t CalculateNearestPowerOfTwo(uint64_t n) { +size_t CalculateNearestPowerOfTwo(size_t n) { DCHECK_GT(n, 1u); - uint64_t ret = UINT64_C(1) << 63; + size_t ret = size_t(1) << (sizeof(size_t) * 8 - 1); while (ret >= n) ret >>= 1; return ret; } -// A single consistency proof. Contains the old and new tree sizes -// (snapshot1 and snapshot2), the length of the proof (proof_length) and -// at most 3 proof nodes (all test proofs will be for a tree of size 8). -struct ProofTestVector { - uint64_t snapshot1; - uint64_t snapshot2; - size_t proof_length; - const char* const proof[3]; -}; - // All test data replicated from // https://github.com/google/certificate-transparency/blob/c41b090ecc14ddd6b3531dc7e5ce36b21e253fdd/cpp/merkletree/merkle_tree_test.cc -// A hash of the empty string. -const uint8_t kSHA256EmptyTreeHash[32] = { + +// The SHA-256 hash of an empty Merkle tree. +const uint8_t kEmptyTreeHash[32] = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; -// Root hashes from building the sample tree of size 8 leaf-by-leaf. -// The first entry is the root at size 0, the last is the root at size 8. -const char* const kSHA256Roots[8] = { +std::string GetEmptyTreeHash() { + return std::string(std::begin(kEmptyTreeHash), std::end(kEmptyTreeHash)); +} + +// SHA-256 Merkle leaf hashes for the sample tree that all of the other test +// data relates to (8 leaves). +const char* const kLeafHashes[8] = { + "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", + "96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", + "0298d122906dcfc10892cb53a73992fc5b9f493ea4c9badb27b791b4127a7fe7", + "07506a85fd9dd2f120eb694f86011e5bb4662e5c415a62917033d4a9624487e7", + "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", + "4271a26be0d8a84f0bd54c8c302e7cb3a3b5d1fa6780a40bcce2873477dab658", + "b08693ec2e721597130641e8211e7eedccb4c26413963eee6c1e2ed16ffb1a5f", + "46f6ffadd3d06a09ff3c5860d2755c8b9819db7df44251788c7d8e3180de8eb1"}; + +// SHA-256 Merkle root hashes from building the sample tree leaf-by-leaf. +// The first entry is the root when the tree contains 1 leaf, and the last is +// the root when the tree contains all 8 leaves. +const char* const kRootHashes[8] = { "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", "fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", "aeb6bcfe274b70a14fb067a5e5578264db0fa9b51af5e0ba159158f329e06e77", @@ -67,9 +77,18 @@ const char* const kSHA256Roots[8] = { "ddb89be403809e325750d3d263cd78929c2942b7942a34b77e122c9594a74c8c", "5dc9da79a70659a9ad559cb701ded9a2ab9d823aad2f4960cfe370eff4604328"}; -// A collection of consistency proofs between various sub-trees of the tree -// defined by |kSHA256Roots|. -const ProofTestVector kSHA256Proofs[4] = { +// A single consistency proof. Contains at most 3 proof nodes (all test proofs +// will be for a tree of size 8). +struct ConsistencyProofTestVector { + size_t old_tree_size; + size_t new_tree_size; + size_t proof_length; + const char* const proof[3]; +}; + +// A collection of consistency proofs between various sub-trees of the sample +// tree. +const ConsistencyProofTestVector kConsistencyProofs[] = { // Empty consistency proof between trees of the same size (1). {1, 1, 0, {"", "", ""}}, // Consistency proof between tree of size 1 and tree of size 8, with 3 @@ -96,6 +115,43 @@ const ProofTestVector kSHA256Proofs[4] = { {"5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", ""}}}; +// A single audit proof. Contains at most 3 proof nodes (all test proofs will be +// for a tree of size 8). +struct AuditProofTestVector { + size_t leaf; + size_t tree_size; + size_t proof_length; + const char* const proof[3]; +}; + +// A collection of audit proofs for various leaves and sub-trees of the tree +// defined by |kRootHashes|. +const AuditProofTestVector kAuditProofs[] = { + {0, 1, 0, {"", "", ""}}, + {0, + 8, + 3, + {"96a296d224f285c67bee93c30f8a309157f0daa35dc5b87e410b78630a09cfc7", + "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", + "6b47aaf29ee3c2af9af889bc1fb9254dabd31177f16232dd6aab035ca39bf6e4"}}, + {5, + 8, + 3, + {"bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b", + "ca854ea128ed050b41b35ffc1b87b8eb2bde461e9e3b5596ece6b9d5975a0ae0", + "d37ee418976dd95753c1c73862b9398fa2a2cf9b4ff0fdfe8b30cd95209614b7"}}, + {2, + 3, + 1, + {"fac54203e7cc696cf0dfcb42c92a1d9dbaf70ad9e621f4bd8d98662f00e3c125", "", + ""}}, + {1, + 5, + 3, + {"6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d", + "5f083f0a1a33ca076a95279832580db3e0ef4584bdff1f54c8a360f50de3031e", + "bc1a0643b12e4d2d7c77918f44e0f4f79a838b6cf9ec5b5c283e1f4d88599e6b"}}}; + // Decodes a hexadecimal string into the binary data it represents. std::string HexToBytes(const std::string& hex_data) { std::vector<uint8_t> output; @@ -105,131 +161,232 @@ std::string HexToBytes(const std::string& hex_data) { return result; } -std::string GetEmptyTreeHash() { - return std::string(std::begin(kSHA256EmptyTreeHash), - std::end(kSHA256EmptyTreeHash)); +// Constructs a consistency/audit proof from a test vector. +// This is templated so that it can be used with both ConsistencyProofTestVector +// and AuditProofTestVector. +template <typename TestVectorType> +std::vector<std::string> GetProof(const TestVectorType& test_vector) { + std::vector<std::string> proof(test_vector.proof_length); + std::transform(test_vector.proof, + test_vector.proof + test_vector.proof_length, proof.begin(), + &HexToBytes); + + return proof; } -// Creates a ct::MerkleConsistencyProof and returns the result of -// calling log->VerifyConsistencyProof with that proof and snapshots. -bool VerifyConsistencyProof(scoped_refptr<const CTLogVerifier> log, - uint64_t old_tree_size, +// Creates a ct::MerkleConsistencyProof from its arguments and returns the +// result of passing this to log.VerifyConsistencyProof(). +bool VerifyConsistencyProof(const CTLogVerifier& log, + size_t old_tree_size, const std::string& old_tree_root, - uint64_t new_tree_size, + size_t new_tree_size, const std::string& new_tree_root, const std::vector<std::string>& proof) { - return log->VerifyConsistencyProof( - ct::MerkleConsistencyProof(log->key_id(), proof, old_tree_size, + return log.VerifyConsistencyProof( + ct::MerkleConsistencyProof(log.key_id(), proof, old_tree_size, new_tree_size), old_tree_root, new_tree_root); } +// Creates a ct::MerkleAuditProof from its arguments and returns the result of +// passing this to log.VerifyAuditProof(). +bool VerifyAuditProof(const CTLogVerifier& log, + size_t leaf, + size_t tree_size, + const std::vector<std::string>& proof, + const std::string& tree_root, + const std::string& leaf_hash) { + return log.VerifyAuditProof(ct::MerkleAuditProof(leaf, tree_size, proof), + tree_root, leaf_hash); +} + class CTLogVerifierTest : public ::testing::Test { public: - CTLogVerifierTest() {} - void SetUp() override { log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog", "https://ct.example.com", "ct.example.com"); ASSERT_TRUE(log_); - ASSERT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); - ASSERT_EQ("ct.example.com", log_->dns_domain()); + EXPECT_EQ(ct::GetTestPublicKeyId(), log_->key_id()); + EXPECT_EQ("ct.example.com", log_->dns_domain()); } - // Given a consistency proof between two snapshots of the tree, asserts that - // it verifies and no other combination of snapshots and proof nodes verifies. - void VerifierConsistencyCheck(int snapshot1, - int snapshot2, - const std::string& root1, - const std::string& root2, - const std::vector<std::string>& proof) { - // Verify the original consistency proof. - EXPECT_TRUE( - VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, root2, proof)) - << " " << snapshot1 << " " << snapshot2; - - if (proof.empty()) { - // For simplicity test only non-trivial proofs that have root1 != root2 - // snapshot1 != 0 and snapshot1 != snapshot2. - return; - } + protected: + scoped_refptr<const CTLogVerifier> log_; +}; - // Wrong snapshot index: The proof checking code should not accept - // as a valid proof a proof for a tree size different than the original - // size it was produced for. - // Test that this is not the case for off-by-one changes. - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 - 1, root1, snapshot2, - root2, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 + 1, root1, snapshot2, - root2, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1 ^ 2, root1, snapshot2, - root2, proof)); - - // Test that the proof is not accepted for trees with wrong tree height. - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2 * 2, - root2, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2 / 2, - root2, proof)); - - // Test that providing the wrong input root fails checking an - // otherwise-valid proof. - const std::string wrong_root("WrongRoot"); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - wrong_root, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, wrong_root, snapshot2, - root2, proof)); - // Test that swapping roots fails checking an otherwise-valid proof (that - // the right root is used for each calculation). - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root2, snapshot2, - root1, proof)); - - // Variations of wrong proofs, all of which should be rejected. - std::vector<std::string> wrong_proof; - // Empty proof. - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - - // Modify a single element in the proof. - for (size_t j = 0; j < proof.size(); ++j) { - wrong_proof = proof; - wrong_proof[j] = GetEmptyTreeHash(); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - } +// Given an audit proof for a leaf in a Merkle tree, asserts that it verifies +// and no other combination of leaves, tree sizes and proof nodes verifies. +void CheckVerifyAuditProof(const CTLogVerifier& log, + size_t leaf, + size_t tree_size, + const std::vector<std::string>& proof, + const std::string& root_hash, + const std::string& leaf_hash) { + EXPECT_TRUE( + VerifyAuditProof(log, leaf, tree_size, proof, root_hash, leaf_hash)) + << "proof for leaf " << leaf << " did not pass verification"; + EXPECT_FALSE( + VerifyAuditProof(log, leaf - 1, tree_size, proof, root_hash, leaf_hash)) + << "proof passed verification with wrong leaf index"; + EXPECT_FALSE( + VerifyAuditProof(log, leaf + 1, tree_size, proof, root_hash, leaf_hash)) + << "proof passed verification with wrong leaf index"; + EXPECT_FALSE( + VerifyAuditProof(log, leaf ^ 2, tree_size, proof, root_hash, leaf_hash)) + << "proof passed verification with wrong leaf index"; + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size * 2, proof, root_hash, leaf_hash)) + << "proof passed verification with wrong tree height"; + EXPECT_FALSE(VerifyAuditProof(log, leaf / 2, tree_size / 2, proof, root_hash, + leaf_hash)) + << "proof passed verification with wrong leaf index and tree height"; + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size / 2, proof, root_hash, leaf_hash)) + << "proof passed verification with wrong tree height"; + EXPECT_FALSE(VerifyAuditProof(log, leaf, tree_size, proof, GetEmptyTreeHash(), + leaf_hash)) + << "proof passed verification with wrong root hash"; - // Add garbage at the end of the proof. + std::vector<std::string> wrong_proof; + + // Modify a single element on the proof. + for (size_t j = 0; j < proof.size(); ++j) { wrong_proof = proof; - wrong_proof.push_back(std::string()); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - wrong_proof.pop_back(); + wrong_proof[j] = GetEmptyTreeHash(); + EXPECT_FALSE(VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, + leaf_hash)) + << "proof passed verification with one wrong node (node " << j << ")"; + } - wrong_proof.push_back(proof.back()); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - wrong_proof.pop_back(); + wrong_proof = proof; + wrong_proof.push_back(std::string()); + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, leaf_hash)) + << "proof passed verification with an empty node appended"; + + wrong_proof.back() = root_hash; + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, leaf_hash)) + << "proof passed verification with an incorrect node appended"; + wrong_proof.pop_back(); - // Remove a node from the end. + if (!wrong_proof.empty()) { wrong_proof.pop_back(); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - - // Add garbage in the beginning of the proof. - wrong_proof.clear(); - wrong_proof.push_back(std::string()); - wrong_proof.insert(wrong_proof.end(), proof.begin(), proof.end()); - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); - - wrong_proof[0] = proof[0]; - EXPECT_FALSE(VerifyConsistencyProof(log_, snapshot1, root1, snapshot2, - root2, wrong_proof)); + EXPECT_FALSE(VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, + leaf_hash)) + << "proof passed verification with the last node missing"; } - protected: - scoped_refptr<const CTLogVerifier> log_; -}; + wrong_proof.clear(); + wrong_proof.push_back(std::string()); + wrong_proof.insert(wrong_proof.end(), proof.begin(), proof.end()); + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, leaf_hash)) + << "proof passed verification with an empty node prepended"; + + wrong_proof[0] = root_hash; + EXPECT_FALSE( + VerifyAuditProof(log, leaf, tree_size, wrong_proof, root_hash, leaf_hash)) + << "proof passed verification with an incorrect node prepended"; +} + +// Given a consistency proof between two snapshots of the tree, asserts that it +// verifies and no other combination of tree sizes and proof nodes verifies. +void CheckVerifyConsistencyProof(const CTLogVerifier& log, + int old_tree_size, + int new_tree_size, + const std::string& old_root, + const std::string& new_root, + const std::vector<std::string>& proof) { + // Verify the original consistency proof. + EXPECT_TRUE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, proof)) + << "proof between trees of size " << old_tree_size << " and " + << new_tree_size << " did not pass verification"; + + if (proof.empty()) { + // For simplicity test only non-trivial proofs that have old_root != + // new_root + // old_tree_size != 0 and old_tree_size != new_tree_size. + return; + } + + // Wrong tree size: The proof checking code should not accept as a valid proof + // a proof for a tree size different than the original size it was produced + // for. Test that this is not the case for off-by-one changes. + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size - 1, old_root, + new_tree_size, new_root, proof)) + << "proof passed verification with old tree size - 1"; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size + 1, old_root, + new_tree_size, new_root, proof)) + << "proof passed verification with old tree size + 1"; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size ^ 2, old_root, + new_tree_size, new_root, proof)) + << "proof passed verification with old tree size ^ 2"; + + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size * 2, new_root, proof)) + << "proof passed verification with new tree height + 1"; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size / 2, new_root, proof)) + << "proof passed verification with new tree height - 1"; + + const std::string wrong_root("WrongRoot"); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, wrong_root, proof)) + << "proof passed verification with wrong old root"; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, wrong_root, + new_tree_size, new_root, proof)) + << "proof passed verification with wrong new root"; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, new_root, + new_tree_size, old_root, proof)) + << "proof passed verification with old and new root swapped"; + + // Variations of wrong proofs, all of which should be rejected. + std::vector<std::string> wrong_proof; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "empty proof passed verification"; + + // Modify a single element in the proof. + for (size_t j = 0; j < proof.size(); ++j) { + wrong_proof = proof; + wrong_proof[j] = GetEmptyTreeHash(); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with incorrect node (node " << j << ")"; + } + + wrong_proof = proof; + wrong_proof.push_back(std::string()); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with empty node appended"; + + wrong_proof.back() = proof.back(); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with last node duplicated"; + wrong_proof.pop_back(); + + wrong_proof.pop_back(); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with last node missing"; + + wrong_proof.clear(); + wrong_proof.push_back(std::string()); + wrong_proof.insert(wrong_proof.end(), proof.begin(), proof.end()); + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with empty node prepended"; + + wrong_proof[0] = proof[0]; + EXPECT_FALSE(VerifyConsistencyProof(log, old_tree_size, old_root, + new_tree_size, new_root, wrong_proof)) + << "proof passed verification with first node duplicated"; +} TEST_F(CTLogVerifierTest, VerifiesCertSCT) { ct::LogEntry cert_entry; @@ -315,33 +472,38 @@ TEST_F(CTLogVerifierTest, ExcessDataInPublicKey) { TEST_F(CTLogVerifierTest, VerifiesConsistencyProofEdgeCases_EmptyProof) { std::vector<std::string> empty_proof; - std::string root1(GetEmptyTreeHash()), root2(GetEmptyTreeHash()); + std::string old_root(GetEmptyTreeHash()), new_root(GetEmptyTreeHash()); - // Snapshots that are always consistent, because they are either - // from an empty tree to a non-empty one or for trees of the same - // size. - EXPECT_TRUE(VerifyConsistencyProof(log_, 0, root1, 0, root2, empty_proof)); - EXPECT_TRUE(VerifyConsistencyProof(log_, 0, root1, 1, root2, empty_proof)); - EXPECT_TRUE(VerifyConsistencyProof(log_, 1, root1, 1, root2, empty_proof)); + // Tree snapshots that are always consistent, because the proofs are either + // from an empty tree to a non-empty one or for trees of the same size. + EXPECT_TRUE( + VerifyConsistencyProof(*log_, 0, old_root, 0, new_root, empty_proof)); + EXPECT_TRUE( + VerifyConsistencyProof(*log_, 0, old_root, 1, new_root, empty_proof)); + EXPECT_TRUE( + VerifyConsistencyProof(*log_, 1, old_root, 1, new_root, empty_proof)); // Invalid consistency proofs. // Time travel to the past. - EXPECT_FALSE(VerifyConsistencyProof(log_, 1, root1, 0, root2, empty_proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, 2, root1, 1, root2, empty_proof)); + EXPECT_FALSE( + VerifyConsistencyProof(*log_, 1, old_root, 0, new_root, empty_proof)); + EXPECT_FALSE( + VerifyConsistencyProof(*log_, 2, old_root, 1, new_root, empty_proof)); // Proof between two trees of different size can never be empty. - EXPECT_FALSE(VerifyConsistencyProof(log_, 1, root1, 2, root2, empty_proof)); + EXPECT_FALSE( + VerifyConsistencyProof(*log_, 1, old_root, 2, new_root, empty_proof)); } TEST_F(CTLogVerifierTest, VerifiesConsistencyProofEdgeCases_MismatchingRoots) { + const std::string old_root(GetEmptyTreeHash()); + std::string new_root; std::vector<std::string> empty_proof; - std::string root2; - const std::string empty_tree_hash(GetEmptyTreeHash()); // Roots don't match. EXPECT_FALSE( - VerifyConsistencyProof(log_, 0, empty_tree_hash, 0, root2, empty_proof)); + VerifyConsistencyProof(*log_, 0, old_root, 0, new_root, empty_proof)); EXPECT_FALSE( - VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, root2, empty_proof)); + VerifyConsistencyProof(*log_, 1, old_root, 1, new_root, empty_proof)); } TEST_F(CTLogVerifierTest, @@ -355,155 +517,244 @@ TEST_F(CTLogVerifierTest, // but the proof is not empty (the verification code should not accept // proofs with redundant nodes in this case). proof.push_back(empty_tree_hash); - EXPECT_FALSE(VerifyConsistencyProof(log_, 0, empty_tree_hash, 0, + EXPECT_FALSE(VerifyConsistencyProof(*log_, 0, empty_tree_hash, 0, empty_tree_hash, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, 0, empty_tree_hash, 1, + EXPECT_FALSE(VerifyConsistencyProof(*log_, 0, empty_tree_hash, 1, empty_tree_hash, proof)); - EXPECT_FALSE(VerifyConsistencyProof(log_, 1, empty_tree_hash, 1, + EXPECT_FALSE(VerifyConsistencyProof(*log_, 1, empty_tree_hash, 1, empty_tree_hash, proof)); } -TEST_F(CTLogVerifierTest, VerifiesValidConsistencyProofs) { +class CTLogVerifierConsistencyProofTest + : public CTLogVerifierTest, + public ::testing::WithParamInterface<size_t /* proof index */> {}; + +// Checks that a sample set of valid consistency proofs verify successfully. +TEST_P(CTLogVerifierConsistencyProofTest, VerifiesValidConsistencyProof) { + const ConsistencyProofTestVector& test_vector = + kConsistencyProofs[GetParam()]; + const std::vector<std::string> proof = GetProof(test_vector); + + const char* const old_root = kRootHashes[test_vector.old_tree_size - 1]; + const char* const new_root = kRootHashes[test_vector.new_tree_size - 1]; + CheckVerifyConsistencyProof(*log_, test_vector.old_tree_size, + test_vector.new_tree_size, HexToBytes(old_root), + HexToBytes(new_root), proof); +} + +INSTANTIATE_TEST_CASE_P(KnownGoodProofs, + CTLogVerifierConsistencyProofTest, + ::testing::Range(size_t(0), + arraysize(kConsistencyProofs))); + +class CTLogVerifierAuditProofTest + : public CTLogVerifierTest, + public ::testing::WithParamInterface<size_t /* proof index */> {}; + +// Checks that a sample set of valid audit proofs verify successfully. +TEST_P(CTLogVerifierAuditProofTest, VerifiesValidAuditProofs) { + const AuditProofTestVector& test_vector = kAuditProofs[GetParam()]; + const std::vector<std::string> proof = GetProof(test_vector); + + const char* const root_hash = kRootHashes[test_vector.tree_size - 1]; + CheckVerifyAuditProof(*log_, test_vector.leaf, test_vector.tree_size, proof, + HexToBytes(root_hash), + HexToBytes(kLeafHashes[test_vector.leaf])); +} + +INSTANTIATE_TEST_CASE_P(KnownGoodProofs, + CTLogVerifierAuditProofTest, + ::testing::Range(size_t(0), arraysize(kAuditProofs))); + +TEST_F(CTLogVerifierTest, VerifiesAuditProofEdgeCases_InvalidLeafIndex) { std::vector<std::string> proof; - std::string root1, root2; - - // Known good proofs. - for (size_t i = 0; i < arraysize(kSHA256Proofs); ++i) { - SCOPED_TRACE(i); - proof.clear(); - for (size_t j = 0; j < kSHA256Proofs[i].proof_length; ++j) { - const char* const v = kSHA256Proofs[i].proof[j]; - proof.push_back(HexToBytes(v)); - } - const uint64_t snapshot1 = kSHA256Proofs[i].snapshot1; - const uint64_t snapshot2 = kSHA256Proofs[i].snapshot2; - const char* const old_root = kSHA256Roots[snapshot1 - 1]; - const char* const new_root = kSHA256Roots[snapshot2 - 1]; - VerifierConsistencyCheck(snapshot1, snapshot2, HexToBytes(old_root), - HexToBytes(new_root), proof); - } + EXPECT_FALSE( + VerifyAuditProof(*log_, 1, 0, proof, std::string(), std::string())); + EXPECT_FALSE( + VerifyAuditProof(*log_, 2, 1, proof, std::string(), std::string())); + + const std::string empty_hash = GetEmptyTreeHash(); + EXPECT_FALSE(VerifyAuditProof(*log_, 1, 0, proof, empty_hash, std::string())); + EXPECT_FALSE(VerifyAuditProof(*log_, 2, 1, proof, empty_hash, std::string())); } -const char kLeafPrefix[] = {'\x00'}; +// Functions that implement algorithms from RFC6962 necessary for constructing +// Merkle trees and proofs. This allows tests to generate a variety of trees +// for exhaustive testing. +namespace rfc6962 { -// Reference implementation of RFC6962. -// This allows generation of arbitrary-sized Merkle trees and consistency -// proofs between them for testing the consistency proof validation -// code. -class TreeHasher { - public: - static std::string HashLeaf(const std::string& leaf) { - SHA256HashValue sha256; - memset(sha256.data, 0, sizeof(sha256.data)); - - std::unique_ptr<crypto::SecureHash> hash( - crypto::SecureHash::Create(crypto::SecureHash::SHA256)); - hash->Update(kLeafPrefix, 1); - hash->Update(leaf.data(), leaf.size()); - hash->Finish(sha256.data, sizeof(sha256.data)); - - return std::string(reinterpret_cast<const char*>(sha256.data), - sizeof(sha256.data)); - } -}; +// Calculates the hash of a leaf in a Merkle tree, given its content. +// See RFC6962, section 2.1. +std::string HashLeaf(const std::string& leaf) { + const char kLeafPrefix[] = {'\x00'}; + + SHA256HashValue sha256; + memset(sha256.data, 0, sizeof(sha256.data)); -// Reference implementation of Merkle hash, for cross-checking. -// Recursively calculates the hash of the root given the leaf data -// specified in |inputs|. -std::string ReferenceMerkleTreeHash(std::string* inputs, uint64_t input_size) { - if (!input_size) + std::unique_ptr<crypto::SecureHash> hash( + crypto::SecureHash::Create(crypto::SecureHash::SHA256)); + hash->Update(kLeafPrefix, 1); + hash->Update(leaf.data(), leaf.size()); + hash->Finish(sha256.data, sizeof(sha256.data)); + + return std::string(reinterpret_cast<const char*>(sha256.data), + sizeof(sha256.data)); +} + +// Calculates the root hash of a Merkle tree, given its leaf data and size. +// See RFC6962, section 2.1. +std::string HashTree(std::string leaves[], size_t tree_size) { + if (tree_size == 0) return GetEmptyTreeHash(); - if (input_size == 1) - return TreeHasher::HashLeaf(inputs[0]); + if (tree_size == 1) + return HashLeaf(leaves[0]); - const uint64_t split = CalculateNearestPowerOfTwo(input_size); + // Find the index of the last leaf in the left sub-tree. + const size_t split = CalculateNearestPowerOfTwo(tree_size); - return ct::internal::HashNodes( - ReferenceMerkleTreeHash(&inputs[0], split), - ReferenceMerkleTreeHash(&inputs[split], input_size - split)); + // Hash the left and right sub-trees, then hash the results. + return ct::internal::HashNodes(HashTree(leaves, split), + HashTree(&leaves[split], tree_size - split)); } -// Reference implementation of snapshot consistency. Returns a -// consistency proof between two snapshots of the tree designated -// by |inputs|. -// Call with have_root1 = true. -std::vector<std::string> ReferenceSnapshotConsistency(std::string* inputs, - uint64_t snapshot2, - uint64_t snapshot1, - bool have_root1) { +// Returns a Merkle audit proof for the leaf with index |leaf_index|. +// The tree consists of |leaves[0]| to |leaves[tree_size-1]|. +// If |leaf_index| is >= |tree_size|, an empty proof will be returned. +// See RFC6962, section 2.1.1, for more details. +std::vector<std::string> CreateAuditProof(std::string leaves[], + size_t tree_size, + size_t leaf_index) { std::vector<std::string> proof; - if (snapshot1 == 0 || snapshot1 > snapshot2) + if (leaf_index >= tree_size) + return proof; + if (tree_size == 1) return proof; - if (snapshot1 == snapshot2) { + + // Find the index of the first leaf in the right sub-tree. + const size_t split = CalculateNearestPowerOfTwo(tree_size); + + // Recurse down the correct branch of the tree (left or right) to reach the + // leaf with |leaf_index|. Add the hash of the branch not taken at each step + // on the way up to build the proof. + if (leaf_index < split) { + proof = CreateAuditProof(leaves, split, leaf_index); + proof.push_back(HashTree(&leaves[split], tree_size - split)); + } else { + proof = + CreateAuditProof(&leaves[split], tree_size - split, leaf_index - split); + proof.push_back(HashTree(leaves, split)); + } + + return proof; +} + +// Returns a Merkle consistency proof between two Merkle trees. +// The old tree contains |leaves[0]| to |leaves[old_tree_size-1]|. +// The new tree contains |leaves[0]| to |leaves[new_tree_size-1]|. +// Call with |contains_old_tree| = true. +// See RFC6962, section 2.1.2, for more details. +std::vector<std::string> CreateConsistencyProof(std::string leaves[], + size_t new_tree_size, + size_t old_tree_size, + bool contains_old_tree = true) { + std::vector<std::string> proof; + if (old_tree_size == 0 || old_tree_size > new_tree_size) + return proof; + if (old_tree_size == new_tree_size) { // Consistency proof for two equal subtrees is empty. - if (!have_root1) { + if (!contains_old_tree) { // Record the hash of this subtree unless it's the root for which - // the proof was originally requested. (This happens when the snapshot1 - // tree is balanced.) - proof.push_back(ReferenceMerkleTreeHash(inputs, snapshot1)); + // the proof was originally requested. (This happens when the old tree is + // balanced). + proof.push_back(HashTree(leaves, old_tree_size)); } return proof; } - // 0 < snapshot1 < snapshot2 - const uint64_t split = CalculateNearestPowerOfTwo(snapshot2); + // Find the index of the last leaf in the left sub-tree. + const size_t split = CalculateNearestPowerOfTwo(new_tree_size); - std::vector<std::string> subproof; - if (snapshot1 <= split) { - // Root of snapshot1 is in the left subtree of snapshot2. + if (old_tree_size <= split) { + // Root of the old tree is in the left subtree of the new tree. // Prove that the left subtrees are consistent. - subproof = - ReferenceSnapshotConsistency(inputs, split, snapshot1, have_root1); - proof.insert(proof.end(), subproof.begin(), subproof.end()); - // Record the hash of the right subtree (only present in snapshot2). - proof.push_back(ReferenceMerkleTreeHash(&inputs[split], snapshot2 - split)); + proof = + CreateConsistencyProof(leaves, split, old_tree_size, contains_old_tree); + // Record the hash of the right subtree (only present in the new tree). + proof.push_back(HashTree(&leaves[split], new_tree_size - split)); } else { - // Snapshot1 root is at the same level as snapshot2 root. + // The old tree root is at the same level as the new tree root. // Prove that the right subtrees are consistent. The right subtree - // doesn't contain the root of snapshot1, so set have_root1 = false. - subproof = ReferenceSnapshotConsistency(&inputs[split], snapshot2 - split, - snapshot1 - split, false); - proof.insert(proof.end(), subproof.begin(), subproof.end()); + // doesn't contain the root of the old tree, so set contains_old_tree = + // false. + proof = CreateConsistencyProof(&leaves[split], new_tree_size - split, + old_tree_size - split, + /* contains_old_tree = */ false); // Record the hash of the left subtree (equal in both trees). - proof.push_back(ReferenceMerkleTreeHash(&inputs[0], split)); + proof.push_back(HashTree(leaves, split)); } return proof; } -class CTLogVerifierTestUsingReferenceGenerator +} // namespace rfc6962 + +class CTLogVerifierTestUsingGenerator : public CTLogVerifierTest, - public ::testing::WithParamInterface<uint64_t> {}; - -const uint64_t kReferenceTreeSize = 256; - -// Tests that every possible valid consistency proof for a tree of a given size -// verifies correctly. Also checks that invalid variations of each proof fail to -// verify (see VerifierConsistencyCheck). -TEST_P(CTLogVerifierTestUsingReferenceGenerator, - VerifiesValidConsistencyProof) { - std::vector<std::string> data; - for (uint64_t i = 0; i < kReferenceTreeSize; ++i) - data.push_back(std::string(1, static_cast<char>(i))); - - const uint64_t tree_size = GetParam(); - const std::string tree_root = ReferenceMerkleTreeHash(data.data(), tree_size); - - for (uint64_t snapshot = 1; snapshot <= tree_size; ++snapshot) { - SCOPED_TRACE(snapshot); - const std::string snapshot_root = - ReferenceMerkleTreeHash(data.data(), snapshot); - const std::vector<std::string> proof = - ReferenceSnapshotConsistency(data.data(), tree_size, snapshot, true); - VerifierConsistencyCheck(snapshot, tree_size, snapshot_root, tree_root, - proof); + public ::testing::WithParamInterface<size_t /* tree_size */> {}; + +// Checks that valid consistency proofs for a range of generated Merkle trees +// verify successfully. +TEST_P(CTLogVerifierTestUsingGenerator, VerifiesValidConsistencyProof) { + const size_t tree_size = GetParam(); + + std::vector<std::string> tree_leaves(tree_size); + for (size_t i = 0; i < tree_size; ++i) + tree_leaves[i].push_back(static_cast<char>(i)); + + const std::string tree_root = + rfc6962::HashTree(tree_leaves.data(), tree_size); + + // Check consistency proofs for every sub-tree. + for (size_t old_tree_size = 0; old_tree_size <= tree_size; ++old_tree_size) { + SCOPED_TRACE(old_tree_size); + const std::string old_tree_root = + rfc6962::HashTree(tree_leaves.data(), old_tree_size); + const std::vector<std::string> proof = rfc6962::CreateConsistencyProof( + tree_leaves.data(), tree_size, old_tree_size); + // Checks that the consistency proof verifies only with the correct tree + // sizes and root hashes. + CheckVerifyConsistencyProof(*log_, old_tree_size, tree_size, old_tree_root, + tree_root, proof); + } +} + +// Checks that valid audit proofs for a range of generated Merkle trees verify +// successfully. +TEST_P(CTLogVerifierTestUsingGenerator, VerifiesValidAuditProofs) { + const size_t tree_size = GetParam(); + + std::vector<std::string> tree_leaves(tree_size); + for (size_t i = 0; i < tree_size; ++i) + tree_leaves[i].push_back(static_cast<char>(i)); + + const std::string root = rfc6962::HashTree(tree_leaves.data(), tree_size); + + // Check audit proofs for every leaf in the tree. + for (size_t leaf = 0; leaf < tree_size; ++leaf) { + SCOPED_TRACE(leaf); + std::vector<std::string> proof = + rfc6962::CreateAuditProof(tree_leaves.data(), tree_size, leaf); + // Checks that the audit proof verifies only for this leaf data, index, + // hash, tree size and root hash. + CheckVerifyAuditProof(*log_, leaf, tree_size, proof, root, + rfc6962::HashLeaf(tree_leaves[leaf])); } } -// Test verification of consistency proofs between all tree sizes from 1 to 128. -INSTANTIATE_TEST_CASE_P(RangeOfTreeSizesAndSnapshots, - CTLogVerifierTestUsingReferenceGenerator, - testing::Range(UINT64_C(1), - (kReferenceTreeSize / 2) + 1)); +// Test verification of consistency proofs and audit proofs for all tree sizes +// from 0 to 128. +INSTANTIATE_TEST_CASE_P(RangeOfTreeSizes, + CTLogVerifierTestUsingGenerator, + testing::Range(size_t(0), size_t(129))); } // namespace diff --git a/chromium/net/cert/ct_objects_extractor.cc b/chromium/net/cert/ct_objects_extractor.cc index 3453e445d2b..4f451fdd1f2 100644 --- a/chromium/net/cert/ct_objects_extractor.cc +++ b/chromium/net/cert/ct_objects_extractor.cc @@ -6,18 +6,15 @@ #include <string.h> -#include <openssl/bytestring.h> -#include <openssl/obj.h> -#include <openssl/x509.h> - #include "base/logging.h" #include "base/sha1.h" #include "base/strings/string_util.h" -#include "crypto/scoped_openssl_types.h" #include "crypto/sha2.h" #include "net/cert/asn1_util.h" #include "net/cert/signed_certificate_timestamp.h" -#include "net/ssl/scoped_openssl_types.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/obj.h" +#include "third_party/boringssl/src/include/openssl/x509.h" namespace net { @@ -25,13 +22,6 @@ namespace ct { namespace { -void FreeX509_EXTENSIONS(X509_EXTENSIONS* ptr) { - sk_X509_EXTENSION_pop_free(ptr, X509_EXTENSION_free); -} - -using ScopedX509_EXTENSIONS = - crypto::ScopedOpenSSL<X509_EXTENSIONS, FreeX509_EXTENSIONS>; - // The wire form of the OID 1.3.6.1.4.1.11129.2.4.2. See Section 3.3 of // RFC6962. const uint8_t kEmbeddedSCTOid[] = {0x2B, 0x06, 0x01, 0x04, 0x01, @@ -49,15 +39,16 @@ bool StringEqualToCBS(const std::string& value1, const CBS* value2) { return memcmp(value1.data(), CBS_data(value2), CBS_len(value2)) == 0; } -ScopedX509 OSCertHandleToOpenSSL(X509Certificate::OSCertHandle os_handle) { +bssl::UniquePtr<X509> OSCertHandleToOpenSSL( + X509Certificate::OSCertHandle os_handle) { #if defined(USE_OPENSSL_CERTS) - return ScopedX509(X509Certificate::DupOSCertHandle(os_handle)); + return bssl::UniquePtr<X509>(X509Certificate::DupOSCertHandle(os_handle)); #else std::string der_encoded; if (!X509Certificate::GetDEREncoded(os_handle, &der_encoded)) - return ScopedX509(); + return bssl::UniquePtr<X509>(); const uint8_t* bytes = reinterpret_cast<const uint8_t*>(der_encoded.data()); - return ScopedX509(d2i_X509(NULL, &bytes, der_encoded.size())); + return bssl::UniquePtr<X509>(d2i_X509(NULL, &bytes, der_encoded.size())); #endif } @@ -171,7 +162,7 @@ bool FindMatchingSingleResponse(CBS* responses, bool ExtractEmbeddedSCTList(X509Certificate::OSCertHandle cert, std::string* sct_list) { - ScopedX509 x509(OSCertHandleToOpenSSL(cert)); + bssl::UniquePtr<X509> x509(OSCertHandleToOpenSSL(cert)); if (!x509) return false; X509_EXTENSIONS* x509_exts = x509->cert_info->extensions; @@ -187,7 +178,7 @@ bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, LogEntry* result) { result->Reset(); - ScopedX509 leaf_x509(OSCertHandleToOpenSSL(leaf)); + bssl::UniquePtr<X509> leaf_x509(OSCertHandleToOpenSSL(leaf)); if (!leaf_x509) return false; @@ -203,7 +194,7 @@ bool GetPrecertLogEntry(X509Certificate::OSCertHandle leaf, // The Precertificate log entry is the final certificate's TBSCertificate // without the SCT extension (RFC6962, section 3.2). - ScopedX509 leaf_copy(X509_dup(leaf_x509.get())); + bssl::UniquePtr<X509> leaf_copy(X509_dup(leaf_x509.get())); if (!leaf_copy || !leaf_copy->cert_info->extensions) { NOTREACHED(); return false; @@ -346,7 +337,7 @@ bool ExtractSCTListFromOCSPResponse(X509Certificate::OSCertHandle issuer, if (!CBS_get_asn1(&single_response, &extensions, kSingleExtensionsTag)) return false; const uint8_t* ptr = CBS_data(&extensions); - ScopedX509_EXTENSIONS x509_exts( + bssl::UniquePtr<X509_EXTENSIONS> x509_exts( d2i_X509_EXTENSIONS(NULL, &ptr, CBS_len(&extensions))); if (!x509_exts || ptr != CBS_data(&extensions) + CBS_len(&extensions)) return false; diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc index 6afd32224e5..1930ba892ce 100644 --- a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc +++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.cc @@ -13,7 +13,6 @@ #include "base/strings/stringprintf.h" #include "base/values.h" #include "net/cert/ct_sct_to_string.h" -#include "net/cert/ct_verify_result.h" #include "net/cert/signed_certificate_timestamp.h" #include "net/log/net_log_capture_mode.h" @@ -76,11 +75,11 @@ std::unique_ptr<base::ListValue> SCTListToPrintableValues( } // namespace std::unique_ptr<base::Value> NetLogSignedCertificateTimestampCallback( - const ct::CTVerifyResult* ct_result, + const SignedCertificateTimestampAndStatusList* scts, NetLogCaptureMode capture_mode) { std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); - dict->Set("scts", SCTListToPrintableValues(ct_result->scts)); + dict->Set("scts", SCTListToPrintableValues(*scts)); return std::move(dict); } diff --git a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h index 1c1a7d8ad2e..373a7525337 100644 --- a/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h +++ b/chromium/net/cert/ct_signed_certificate_timestamp_log_param.h @@ -8,6 +8,8 @@ #include <memory> #include <string> +#include "net/cert/signed_certificate_timestamp_and_status.h" + namespace base { class Value; } @@ -16,16 +18,12 @@ namespace net { class NetLogCaptureMode; -namespace ct { -struct CTVerifyResult; -} - // Creates a dictionary of processed Signed Certificate Timestamps to be // logged in the NetLog. // See the documentation for SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED // in net/log/net_log_event_type_list.h std::unique_ptr<base::Value> NetLogSignedCertificateTimestampCallback( - const ct::CTVerifyResult* ct_result, + const SignedCertificateTimestampAndStatusList* scts, NetLogCaptureMode capture_mode); // Creates a dictionary of raw Signed Certificate Timestamps to be logged diff --git a/chromium/net/cert/ct_verifier.h b/chromium/net/cert/ct_verifier.h index 38ce2efa471..b65a1334b48 100644 --- a/chromium/net/cert/ct_verifier.h +++ b/chromium/net/cert/ct_verifier.h @@ -8,14 +8,10 @@ #include <string> #include "net/base/net_export.h" +#include "net/cert/signed_certificate_timestamp_and_status.h" namespace net { -namespace ct { -struct CTVerifyResult; -struct SignedCertificateTimestamp; -} // namespace ct - class CTLogVerifier; class NetLogWithSource; class X509Certificate; @@ -54,7 +50,7 @@ class NET_EXPORT CTVerifier { virtual int Verify(X509Certificate* cert, const std::string& stapled_ocsp_response, const std::string& sct_list_from_tls_extension, - ct::CTVerifyResult* result, + SignedCertificateTimestampAndStatusList* output_scts, const NetLogWithSource& net_log) = 0; // Registers |observer| to receive notifications of validated SCTs. Does not diff --git a/chromium/net/cert/internal/signature_policy.cc b/chromium/net/cert/internal/signature_policy.cc index 20a4cd3588e..0785cbf6532 100644 --- a/chromium/net/cert/internal/signature_policy.cc +++ b/chromium/net/cert/internal/signature_policy.cc @@ -7,8 +7,7 @@ #include "base/logging.h" #include "net/cert/internal/cert_error_params.h" #include "net/cert/internal/cert_errors.h" - -#include <openssl/obj.h> +#include "third_party/boringssl/src/include/openssl/obj.h" namespace net { diff --git a/chromium/net/cert/internal/verify_name_match.cc b/chromium/net/cert/internal/verify_name_match.cc index 3cfa4a17586..b999355b457 100644 --- a/chromium/net/cert/internal/verify_name_match.cc +++ b/chromium/net/cert/internal/verify_name_match.cc @@ -9,12 +9,12 @@ #include "base/strings/string_util.h" #include "base/tuple.h" -#include "crypto/auto_cbb.h" -#include "crypto/scoped_openssl_types.h" #include "net/cert/internal/parse_name.h" #include "net/der/input.h" #include "net/der/parser.h" #include "net/der/tag.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/mem.h" namespace net { @@ -294,7 +294,7 @@ bool NormalizeName(const der::Input& name_rdn_sequence, // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName der::Parser rdn_sequence_parser(name_rdn_sequence); - crypto::AutoCBB cbb; + bssl::ScopedCBB cbb; if (!CBB_init(cbb.get(), 0)) return false; @@ -316,13 +316,13 @@ bool NormalizeName(const der::Input& name_rdn_sequence, CBB rdn_cbb; if (!CBB_add_asn1(cbb.get(), &rdn_cbb, CBS_ASN1_SET)) return false; - std::vector<crypto::ScopedOpenSSLBytes> + std::vector<bssl::UniquePtr<uint8_t>> scoped_encoded_attribute_type_and_values; std::vector<der::Input> encoded_attribute_type_and_values; for (const auto& type_and_value : type_and_values) { // A top-level CBB for encoding each individual AttributeTypeAndValue. - crypto::AutoCBB type_and_value_encoder_cbb; + bssl::ScopedCBB type_and_value_encoder_cbb; if (!CBB_init(type_and_value_encoder_cbb.get(), 0)) return false; @@ -367,7 +367,7 @@ bool NormalizeName(const der::Input& name_rdn_sequence, if (!CBB_finish(type_and_value_encoder_cbb.get(), &bytes, &len)) return false; scoped_encoded_attribute_type_and_values.push_back( - crypto::ScopedOpenSSLBytes(bytes)); + bssl::UniquePtr<uint8_t>(bytes)); encoded_attribute_type_and_values.push_back(der::Input(bytes, len)); } diff --git a/chromium/net/cert/internal/verify_name_match_fuzzer.cc b/chromium/net/cert/internal/verify_name_match_fuzzer.cc index 464108e51d2..3b5f74cf261 100644 --- a/chromium/net/cert/internal/verify_name_match_fuzzer.cc +++ b/chromium/net/cert/internal/verify_name_match_fuzzer.cc @@ -11,11 +11,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::FuzzedDataProvider fuzzed_data(data, size); size_t first_part_size = fuzzed_data.ConsumeUint16(); - base::StringPiece first_part = fuzzed_data.ConsumeBytes(first_part_size); - base::StringPiece second_part = fuzzed_data.ConsumeRemainingBytes(); + std::string first_part = fuzzed_data.ConsumeBytes(first_part_size); + std::string second_part = fuzzed_data.ConsumeRemainingBytes(); - net::der::Input in1(first_part); - net::der::Input in2(second_part); + net::der::Input in1(&first_part); + net::der::Input in2(&second_part); bool match = net::VerifyNameMatch(in1, in2); bool reverse_order_match = net::VerifyNameMatch(in2, in1); // Result should be the same regardless of argument order. diff --git a/chromium/net/cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc b/chromium/net/cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc index 1d4ea048513..971797eca3a 100644 --- a/chromium/net/cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc +++ b/chromium/net/cert/internal/verify_name_match_verifynameinsubtree_fuzzer.cc @@ -11,11 +11,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { base::FuzzedDataProvider fuzzed_data(data, size); size_t first_part_size = fuzzed_data.ConsumeUint16(); - base::StringPiece first_part = fuzzed_data.ConsumeBytes(first_part_size); - base::StringPiece second_part = fuzzed_data.ConsumeRemainingBytes(); + std::string first_part = fuzzed_data.ConsumeBytes(first_part_size); + std::string second_part = fuzzed_data.ConsumeRemainingBytes(); - net::der::Input in1(first_part); - net::der::Input in2(second_part); + net::der::Input in1(&first_part); + net::der::Input in2(&second_part); bool match = net::VerifyNameInSubtree(in1, in2); bool reverse_order_match = net::VerifyNameInSubtree(in2, in1); // If both InSubtree matches are true, then in1 == in2 (modulo normalization). diff --git a/chromium/net/cert/internal/verify_signed_data.cc b/chromium/net/cert/internal/verify_signed_data.cc index bd0ee60f5ea..37fc0eb0a9e 100644 --- a/chromium/net/cert/internal/verify_signed_data.cc +++ b/chromium/net/cert/internal/verify_signed_data.cc @@ -4,23 +4,22 @@ #include "net/cert/internal/verify_signed_data.h" -#include <openssl/bytestring.h> -#include <openssl/digest.h> -#include <openssl/ec.h> -#include <openssl/ec_key.h> -#include <openssl/evp.h> -#include <openssl/rsa.h> - #include "base/compiler_specific.h" #include "base/logging.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" #include "net/cert/internal/cert_errors.h" #include "net/cert/internal/signature_algorithm.h" #include "net/cert/internal/signature_policy.h" #include "net/der/input.h" #include "net/der/parse_values.h" #include "net/der/parser.h" +#include "third_party/boringssl/src/include/openssl/bn.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/digest.h" +#include "third_party/boringssl/src/include/openssl/ec.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/evp.h" +#include "third_party/boringssl/src/include/openssl/rsa.h" namespace net { @@ -81,7 +80,7 @@ WARN_UNUSED_RESULT bool ApplyRsaPssOptions(const RsaPssParameters* params, // See https://crbug.com/522228 and https://crbug.com/522232 WARN_UNUSED_RESULT bool ImportPkeyFromSpki(const der::Input& spki, int expected_pkey_id, - crypto::ScopedEVP_PKEY* pkey) { + bssl::UniquePtr<EVP_PKEY>* pkey) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); CBS cbs; @@ -153,7 +152,7 @@ WARN_UNUSED_RESULT bool ImportPkeyFromSpki(const der::Input& spki, // // Following RFC 3279 in this case. WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki, - crypto::ScopedEVP_PKEY* pkey, + bssl::UniquePtr<EVP_PKEY>* pkey, const SignaturePolicy* policy, CertErrors* errors) { // TODO(crbug.com/634443): Add more specific errors. @@ -161,7 +160,7 @@ WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki, return false; // Extract the modulus length from the key. - crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey->get())); + RSA* rsa = EVP_PKEY_get0_RSA(pkey->get()); if (!rsa) return false; unsigned int modulus_length_bits = BN_num_bits(rsa->n); @@ -191,7 +190,7 @@ WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm, crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); + bssl::ScopedEVP_MD_CTX ctx; EVP_PKEY_CTX* pctx = nullptr; // Owned by |ctx|. const EVP_MD* digest; @@ -262,7 +261,7 @@ WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm, // ... -- Extensible // } WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki, - crypto::ScopedEVP_PKEY* pkey, + bssl::UniquePtr<EVP_PKEY>* pkey, const SignaturePolicy* policy, CertErrors* errors) { // TODO(crbug.com/634443): Add more specific errors. @@ -270,10 +269,10 @@ WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki, return false; // Extract the curve name. - crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey->get())); - if (!ec.get()) + EC_KEY* ec = EVP_PKEY_get0_EC_KEY(pkey->get()); + if (!ec) return false; // Unexpected. - int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get())); + int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); if (!policy->IsAcceptableCurveForEcdsa(curve_nid, errors)) { errors->AddError(kUnacceptableEcdsaCurve); @@ -296,7 +295,7 @@ bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, return false; } - crypto::ScopedEVP_PKEY public_key; + bssl::UniquePtr<EVP_PKEY> public_key; // Parse the SPKI to an EVP_PKEY appropriate for the signature algorithm. switch (signature_algorithm.algorithm()) { diff --git a/chromium/net/cert/internal/verify_signed_data_unittest.cc b/chromium/net/cert/internal/verify_signed_data_unittest.cc index 7710abc47f2..1f729038ab5 100644 --- a/chromium/net/cert/internal/verify_signed_data_unittest.cc +++ b/chromium/net/cert/internal/verify_signed_data_unittest.cc @@ -15,8 +15,7 @@ #include "net/der/parse_values.h" #include "net/der/parser.h" #include "testing/gtest/include/gtest/gtest.h" - -#include <openssl/obj.h> +#include "third_party/boringssl/src/include/openssl/obj.h" namespace net { diff --git a/chromium/net/cert/jwk_serializer.cc b/chromium/net/cert/jwk_serializer.cc index 3a6a86d3e7c..0faab404164 100644 --- a/chromium/net/cert/jwk_serializer.cc +++ b/chromium/net/cert/jwk_serializer.cc @@ -4,18 +4,16 @@ #include "net/cert/jwk_serializer.h" -#include <openssl/bn.h> -#include <openssl/bytestring.h> -#include <openssl/ec.h> -#include <openssl/ec_key.h> -#include <openssl/evp.h> - #include "base/base64url.h" #include "base/logging.h" #include "base/strings/string_util.h" #include "base/values.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" +#include "third_party/boringssl/src/include/openssl/bn.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/ec.h" +#include "third_party/boringssl/src/include/openssl/ec_key.h" +#include "third_party/boringssl/src/include/openssl/evp.h" namespace net { @@ -26,10 +24,10 @@ namespace { bool ConvertEcKeyToJwk(EVP_PKEY* pkey, base::DictionaryValue* public_key_jwk, const crypto::OpenSSLErrStackTracer& err_tracer) { - crypto::ScopedEC_KEY ec_key(EVP_PKEY_get1_EC_KEY(pkey)); + EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey); if (!ec_key) return false; - const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key.get()); + const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key); if (!ec_group) return false; @@ -47,12 +45,12 @@ bool ConvertEcKeyToJwk(EVP_PKEY* pkey, int degree_bytes = (EC_GROUP_get_degree(ec_group) + 7) / 8; - const EC_POINT* ec_point = EC_KEY_get0_public_key(ec_key.get()); + const EC_POINT* ec_point = EC_KEY_get0_public_key(ec_key); if (!ec_point) return false; - crypto::ScopedBIGNUM x(BN_new()); - crypto::ScopedBIGNUM y(BN_new()); + bssl::UniquePtr<BIGNUM> x(BN_new()); + bssl::UniquePtr<BIGNUM> y(BN_new()); if (!EC_POINT_get_affine_coordinates_GFp(ec_group, ec_point, x.get(), y.get(), NULL)) { return false; @@ -98,7 +96,7 @@ bool ConvertSpkiFromDerToJwk(const base::StringPiece& spki_der, CBS cbs; CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki_der.data()), spki_der.size()); - crypto::ScopedEVP_PKEY pubkey(EVP_parse_public_key(&cbs)); + bssl::UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&cbs)); if (!pubkey || CBS_len(&cbs) != 0) return false; diff --git a/chromium/net/cert/merkle_audit_proof.cc b/chromium/net/cert/merkle_audit_proof.cc index 675485b2589..f1829af1f3e 100644 --- a/chromium/net/cert/merkle_audit_proof.cc +++ b/chromium/net/cert/merkle_audit_proof.cc @@ -31,8 +31,9 @@ uint64_t CalculateAuditPathLength(uint64_t leaf_index, uint64_t tree_size) { MerkleAuditProof::MerkleAuditProof() {} MerkleAuditProof::MerkleAuditProof(uint64_t leaf_index, + uint64_t tree_size, const std::vector<std::string>& audit_path) - : leaf_index(leaf_index), nodes(audit_path) {} + : leaf_index(leaf_index), tree_size(tree_size), nodes(audit_path) {} MerkleAuditProof::~MerkleAuditProof() {} diff --git a/chromium/net/cert/merkle_audit_proof.h b/chromium/net/cert/merkle_audit_proof.h index b214891ee14..d7c6e3c52f0 100644 --- a/chromium/net/cert/merkle_audit_proof.h +++ b/chromium/net/cert/merkle_audit_proof.h @@ -26,13 +26,21 @@ NET_EXPORT uint64_t CalculateAuditPathLength(uint64_t leaf_index, struct NET_EXPORT MerkleAuditProof { MerkleAuditProof(); MerkleAuditProof(uint64_t leaf_index, + uint64_t tree_size, const std::vector<std::string>& audit_path); ~MerkleAuditProof(); // Index of the tree leaf in the log. + // Must be provided when fetching the proof from the log. uint64_t leaf_index = 0; + // The proof works only in conjunction with an STH for this tree size. + // Must be provided when fetching the proof from the log. + uint64_t tree_size = 0; + // Audit path nodes. + // Using the leaf hash and these nodes, the STH hash can be reconstructed to + // prove that leaf was included in the log's tree. std::vector<std::string> nodes; }; diff --git a/chromium/net/cert/multi_log_ct_verifier.cc b/chromium/net/cert/multi_log_ct_verifier.cc index 8dc172677a5..61c07b6d4e5 100644 --- a/chromium/net/cert/multi_log_ct_verifier.cc +++ b/chromium/net/cert/multi_log_ct_verifier.cc @@ -15,8 +15,8 @@ #include "net/cert/ct_objects_extractor.h" #include "net/cert/ct_serialization.h" #include "net/cert/ct_signed_certificate_timestamp_log_param.h" -#include "net/cert/ct_verify_result.h" #include "net/cert/sct_status_flags.h" +#include "net/cert/signed_certificate_timestamp_and_status.h" #include "net/cert/x509_certificate.h" #include "net/log/net_log_event_type.h" #include "net/log/net_log_parameters_callback.h" @@ -50,9 +50,9 @@ void LogSCTOriginToUMA(ct::SignedCertificateTimestamp::Origin origin) { // This metric would allow measuring: // * Of all SSL connections, how many had SCTs available for validation. // * When SCTs are available, how many are available per connection. -void LogNumSCTsToUMA(const ct::CTVerifyResult& result) { +void LogNumSCTsToUMA(const SignedCertificateTimestampAndStatusList& scts) { UMA_HISTOGRAM_CUSTOM_COUNTS("Net.CertificateTransparency.SCTsPerConnection", - result.scts.size(), 1, 10, 11); + scts.size(), 1, 10, 11); } void AddSCTAndLogStatus(scoped_refptr<ct::SignedCertificateTimestamp> sct, @@ -81,15 +81,16 @@ void MultiLogCTVerifier::SetObserver(Observer* observer) { observer_ = observer; } -int MultiLogCTVerifier::Verify(X509Certificate* cert, - const std::string& stapled_ocsp_response, - const std::string& sct_list_from_tls_extension, - ct::CTVerifyResult* result, - const NetLogWithSource& net_log) { +int MultiLogCTVerifier::Verify( + X509Certificate* cert, + const std::string& stapled_ocsp_response, + const std::string& sct_list_from_tls_extension, + SignedCertificateTimestampAndStatusList* output_scts, + const NetLogWithSource& net_log) { DCHECK(cert); - DCHECK(result); + DCHECK(output_scts); - result->scts.clear(); + output_scts->clear(); bool has_verified_scts = false; @@ -105,7 +106,8 @@ int MultiLogCTVerifier::Verify(X509Certificate* cert, cert->GetIntermediateCertificates().front(), &precert_entry) && VerifySCTs(embedded_scts, precert_entry, - ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert, result); + ct::SignedCertificateTimestamp::SCT_EMBEDDED, cert, + output_scts); } std::string sct_list_from_ocsp; @@ -127,22 +129,24 @@ int MultiLogCTVerifier::Verify(X509Certificate* cert, ct::LogEntry x509_entry; if (ct::GetX509LogEntry(cert->os_cert_handle(), &x509_entry)) { - has_verified_scts |= VerifySCTs( - sct_list_from_ocsp, x509_entry, - ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert, result); - - has_verified_scts |= VerifySCTs( - sct_list_from_tls_extension, x509_entry, - ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert, result); + has_verified_scts |= + VerifySCTs(sct_list_from_ocsp, x509_entry, + ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE, cert, + output_scts); + + has_verified_scts |= + VerifySCTs(sct_list_from_tls_extension, x509_entry, + ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION, cert, + output_scts); } NetLogParametersCallback net_log_checked_callback = - base::Bind(&NetLogSignedCertificateTimestampCallback, result); + base::Bind(&NetLogSignedCertificateTimestampCallback, output_scts); net_log.AddEvent(NetLogEventType::SIGNED_CERTIFICATE_TIMESTAMPS_CHECKED, net_log_checked_callback); - LogNumSCTsToUMA(*result); + LogNumSCTsToUMA(*output_scts); if (has_verified_scts) return OK; @@ -155,7 +159,7 @@ bool MultiLogCTVerifier::VerifySCTs( const ct::LogEntry& expected_entry, ct::SignedCertificateTimestamp::Origin origin, X509Certificate* cert, - ct::CTVerifyResult* result) { + SignedCertificateTimestampAndStatusList* output_scts) { if (logs_.empty()) return false; @@ -179,7 +183,7 @@ bool MultiLogCTVerifier::VerifySCTs( } decoded_sct->origin = origin; - verified |= VerifySingleSCT(decoded_sct, expected_entry, cert, result); + verified |= VerifySingleSCT(decoded_sct, expected_entry, cert, output_scts); } return verified; @@ -189,12 +193,12 @@ bool MultiLogCTVerifier::VerifySingleSCT( scoped_refptr<ct::SignedCertificateTimestamp> sct, const ct::LogEntry& expected_entry, X509Certificate* cert, - ct::CTVerifyResult* result) { + SignedCertificateTimestampAndStatusList* output_scts) { // Assume this SCT is untrusted until proven otherwise. const auto& it = logs_.find(sct->log_id); if (it == logs_.end()) { DVLOG(1) << "SCT does not match any known log."; - AddSCTAndLogStatus(sct, ct::SCT_STATUS_LOG_UNKNOWN, &(result->scts)); + AddSCTAndLogStatus(sct, ct::SCT_STATUS_LOG_UNKNOWN, output_scts); return false; } @@ -202,18 +206,18 @@ bool MultiLogCTVerifier::VerifySingleSCT( if (!it->second->Verify(expected_entry, *sct.get())) { DVLOG(1) << "Unable to verify SCT signature."; - AddSCTAndLogStatus(sct, ct::SCT_STATUS_INVALID_SIGNATURE, &(result->scts)); + AddSCTAndLogStatus(sct, ct::SCT_STATUS_INVALID_SIGNATURE, output_scts); return false; } // SCT verified ok, just make sure the timestamp is legitimate. if (sct->timestamp > base::Time::Now()) { DVLOG(1) << "SCT is from the future!"; - AddSCTAndLogStatus(sct, ct::SCT_STATUS_INVALID_TIMESTAMP, &(result->scts)); + AddSCTAndLogStatus(sct, ct::SCT_STATUS_INVALID_TIMESTAMP, output_scts); return false; } - AddSCTAndLogStatus(sct, ct::SCT_STATUS_OK, &(result->scts)); + AddSCTAndLogStatus(sct, ct::SCT_STATUS_OK, output_scts); if (observer_) observer_->OnSCTVerified(cert, sct.get()); return true; diff --git a/chromium/net/cert/multi_log_ct_verifier.h b/chromium/net/cert/multi_log_ct_verifier.h index 38ea659dfb8..05c2c069264 100644 --- a/chromium/net/cert/multi_log_ct_verifier.h +++ b/chromium/net/cert/multi_log_ct_verifier.h @@ -37,7 +37,7 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier { int Verify(X509Certificate* cert, const std::string& stapled_ocsp_response, const std::string& sct_list_from_tls_extension, - ct::CTVerifyResult* result, + SignedCertificateTimestampAndStatusList* output_scts, const NetLogWithSource& net_log) override; void SetObserver(Observer* observer) override; @@ -50,13 +50,13 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier { const ct::LogEntry& expected_entry, ct::SignedCertificateTimestamp::Origin origin, X509Certificate* cert, - ct::CTVerifyResult* result); + SignedCertificateTimestampAndStatusList* output_scts); // Verifies a single, parsed SCT against all logs. bool VerifySingleSCT(scoped_refptr<ct::SignedCertificateTimestamp> sct, const ct::LogEntry& expected_entry, X509Certificate* cert, - ct::CTVerifyResult* result); + SignedCertificateTimestampAndStatusList* output_scts); // Mapping from a log's ID to the verifier for this log. // A log's ID is the SHA-256 of the log's key, as defined in section 3.2. diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc index 7186a3a22e6..2efd7012a46 100644 --- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc +++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc @@ -16,10 +16,10 @@ #include "net/base/net_errors.h" #include "net/cert/ct_log_verifier.h" #include "net/cert/ct_serialization.h" -#include "net/cert/ct_verify_result.h" #include "net/cert/pem_tokenizer.h" #include "net/cert/sct_status_flags.h" #include "net/cert/signed_certificate_timestamp.h" +#include "net/cert/signed_certificate_timestamp_and_status.h" #include "net/cert/x509_certificate.h" #include "net/log/net_log_source_type.h" #include "net/log/net_log_with_source.h" @@ -111,32 +111,33 @@ class MultiLogCTVerifierTest : public ::testing::Test { return true; } - bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain, - const NetLogWithSource& net_log, - ct::CTVerifyResult* result) { - return verifier_->Verify(chain.get(), std::string(), std::string(), result, - net_log) == OK; + bool VerifySinglePrecertificateChain( + scoped_refptr<X509Certificate> chain, + const NetLogWithSource& net_log, + SignedCertificateTimestampAndStatusList* output_scts) { + return verifier_->Verify(chain.get(), std::string(), std::string(), + output_scts, net_log) == OK; } bool VerifySinglePrecertificateChain(scoped_refptr<X509Certificate> chain) { - ct::CTVerifyResult result; + SignedCertificateTimestampAndStatusList scts; TestNetLog test_net_log; NetLogWithSource net_log = NetLogWithSource::Make(&test_net_log, NetLogSourceType::CONNECT_JOB); - return verifier_->Verify(chain.get(), std::string(), std::string(), &result, + return verifier_->Verify(chain.get(), std::string(), std::string(), &scts, net_log) == OK; } bool CheckPrecertificateVerification(scoped_refptr<X509Certificate> chain) { - ct::CTVerifyResult result; + SignedCertificateTimestampAndStatusList scts; TestNetLog test_net_log; NetLogWithSource net_log = NetLogWithSource::Make(&test_net_log, NetLogSourceType::CONNECT_JOB); - return (VerifySinglePrecertificateChain(chain, net_log, &result) && - ct::CheckForSingleVerifiedSCTInResult(result, kLogDescription) && + return (VerifySinglePrecertificateChain(chain, net_log, &scts) && + ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription) && ct::CheckForSCTOrigin( - result, ct::SignedCertificateTimestamp::SCT_EMBEDDED) && + scts, ct::SignedCertificateTimestamp::SCT_EMBEDDED) && CheckForEmbeddedSCTInNetLog(test_net_log)); } @@ -210,23 +211,23 @@ TEST_F(MultiLogCTVerifierTest, TEST_F(MultiLogCTVerifierTest, VerifiesSCTOverX509Cert) { std::string sct_list = ct::GetSCTListForTesting(); - ct::CTVerifyResult result; - EXPECT_EQ(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, - &result, NetLogWithSource())); - ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(result, kLogDescription)); + SignedCertificateTimestampAndStatusList scts; + EXPECT_EQ(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts, + NetLogWithSource())); + ASSERT_TRUE(ct::CheckForSingleVerifiedSCTInResult(scts, kLogDescription)); ASSERT_TRUE(ct::CheckForSCTOrigin( - result, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION)); + scts, ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION)); } TEST_F(MultiLogCTVerifierTest, IdentifiesSCTFromUnknownLog) { std::string sct_list = ct::GetSCTListWithInvalidSCT(); - ct::CTVerifyResult result; + SignedCertificateTimestampAndStatusList scts; - EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, - &result, NetLogWithSource())); - EXPECT_EQ(1U, result.scts.size()); - EXPECT_EQ("", result.scts[0].sct->log_description); - EXPECT_EQ(ct::SCT_STATUS_LOG_UNKNOWN, result.scts[0].status); + EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts, + NetLogWithSource())); + EXPECT_EQ(1U, scts.size()); + EXPECT_EQ("", scts[0].sct->log_description); + EXPECT_EQ(ct::SCT_STATUS_LOG_UNKNOWN, scts[0].status); } TEST_F(MultiLogCTVerifierTest, CountsValidSCTsInStatusHistogram) { @@ -239,13 +240,14 @@ TEST_F(MultiLogCTVerifierTest, CountsValidSCTsInStatusHistogram) { TEST_F(MultiLogCTVerifierTest, CountsInvalidSCTsInStatusHistogram) { std::string sct_list = ct::GetSCTListWithInvalidSCT(); - ct::CTVerifyResult result; + SignedCertificateTimestampAndStatusList scts; + int num_valid_scts = NumValidSCTsInStatusHistogram(); int num_invalid_scts = GetValueFromHistogram( "Net.CertificateTransparency.SCTStatus", ct::SCT_STATUS_LOG_UNKNOWN); - EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, - &result, NetLogWithSource())); + EXPECT_NE(OK, verifier_->Verify(chain_.get(), std::string(), sct_list, &scts, + NetLogWithSource())); ASSERT_EQ(num_valid_scts, NumValidSCTsInStatusHistogram()); ASSERT_EQ(num_invalid_scts + 1, diff --git a/chromium/net/cert/multi_threaded_cert_verifier.cc b/chromium/net/cert/multi_threaded_cert_verifier.cc index b2e8e28203c..061ecd973f9 100644 --- a/chromium/net/cert/multi_threaded_cert_verifier.cc +++ b/chromium/net/cert/multi_threaded_cert_verifier.cc @@ -18,7 +18,6 @@ #include "base/metrics/histogram_macros.h" #include "base/profiler/scoped_tracker.h" #include "base/sha1.h" -#include "base/stl_util.h" #include "base/threading/worker_pool.h" #include "base/time/time.h" #include "base/trace_event/trace_event.h" @@ -345,7 +344,6 @@ MultiThreadedCertVerifier::MultiThreadedCertVerifier( : requests_(0), inflight_joins_(0), verify_proc_(verify_proc) {} MultiThreadedCertVerifier::~MultiThreadedCertVerifier() { - base::STLDeleteElements(&inflight_); } int MultiThreadedCertVerifier::Verify(const RequestParams& params, @@ -371,8 +369,8 @@ int MultiThreadedCertVerifier::Verify(const RequestParams& params, inflight_joins_++; } else { // Need to make a new job. - std::unique_ptr<CertVerifierJob> new_job( - new CertVerifierJob(params, net_log.net_log(), this)); + std::unique_ptr<CertVerifierJob> new_job = + base::MakeUnique<CertVerifierJob>(params, net_log.net_log(), this); if (!new_job->Start(verify_proc_, crl_set)) { // TODO(wtc): log to the NetLog. @@ -380,8 +378,8 @@ int MultiThreadedCertVerifier::Verify(const RequestParams& params, return ERR_INSUFFICIENT_RESOURCES; // Just a guess. } - job = new_job.release(); - inflight_.insert(job); + job = new_job.get(); + inflight_[job] = std::move(new_job); if (requests_ == 1) job->set_is_first_job(true); @@ -406,15 +404,18 @@ bool MultiThreadedCertVerifier::JobComparator::operator()( std::unique_ptr<CertVerifierJob> MultiThreadedCertVerifier::RemoveJob( CertVerifierJob* job) { DCHECK(CalledOnValidThread()); - bool erased_job = inflight_.erase(job) == 1; - DCHECK(erased_job); - return base::WrapUnique(job); + auto it = inflight_.find(job); + DCHECK(it != inflight_.end()); + std::unique_ptr<CertVerifierJob> job_ptr = std::move(it->second); + inflight_.erase(it); + return job_ptr; } struct MultiThreadedCertVerifier::JobToRequestParamsComparator { - bool operator()(const CertVerifierJob* job, + bool operator()(const std::pair<CertVerifierJob* const, + std::unique_ptr<CertVerifierJob>>& item, const CertVerifier::RequestParams& value) const { - return job->key() < value; + return item.first->key() < value; } }; @@ -425,8 +426,8 @@ CertVerifierJob* MultiThreadedCertVerifier::FindJob(const RequestParams& key) { // search. auto it = std::lower_bound(inflight_.begin(), inflight_.end(), key, JobToRequestParamsComparator()); - if (it != inflight_.end() && !(key < (*it)->key())) - return *it; + if (it != inflight_.end() && !(key < it->first->key())) + return it->first; return nullptr; } diff --git a/chromium/net/cert/multi_threaded_cert_verifier.h b/chromium/net/cert/multi_threaded_cert_verifier.h index d30d1fbd5d0..6022984dac6 100644 --- a/chromium/net/cert/multi_threaded_cert_verifier.h +++ b/chromium/net/cert/multi_threaded_cert_verifier.h @@ -8,8 +8,8 @@ #include <stddef.h> #include <stdint.h> +#include <map> #include <memory> -#include <set> #include <string> #include <vector> @@ -64,8 +64,6 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier const CertVerifierJob* job2) const; }; - using JobSet = std::set<CertVerifierJob*, JobComparator>; - // Returns an inflight job for |key|. If there is no such job then returns // null. CertVerifierJob* FindJob(const RequestParams& key); @@ -78,8 +76,12 @@ class NET_EXPORT_PRIVATE MultiThreadedCertVerifier uint64_t requests() const { return requests_; } uint64_t inflight_joins() const { return inflight_joins_; } - // inflight_ holds the jobs for which an active verification is taking place. - JobSet inflight_; + // inflight_ holds the jobs for which an active verification is taking place, + // mapping the job's raw pointer to an owned pointer. Would be a + // set<unique_ptr> but extraction of owned objects from a set of owned types + // doesn't come until C++17. + std::map<CertVerifierJob*, std::unique_ptr<CertVerifierJob>, JobComparator> + inflight_; uint64_t requests_; uint64_t inflight_joins_; diff --git a/chromium/net/cert/nss_cert_database.cc b/chromium/net/cert/nss_cert_database.cc index 8d143a71298..6842643d5f6 100644 --- a/chromium/net/cert/nss_cert_database.cc +++ b/chromium/net/cert/nss_cert_database.cc @@ -53,17 +53,8 @@ class CertNotificationForwarder : public NSSCertDatabase::Observer { ~CertNotificationForwarder() override {} - // NSSCertDatabase::Observer implementation: - void OnCertAdded(const X509Certificate* cert) override { - cert_db_->NotifyObserversOfCertAdded(cert); - } - - void OnCertRemoved(const X509Certificate* cert) override { - cert_db_->NotifyObserversOfCertRemoved(cert); - } - - void OnCACertChanged(const X509Certificate* cert) override { - cert_db_->NotifyObserversOfCACertChanged(cert); + void OnCertDBChanged(const X509Certificate* cert) override { + cert_db_->NotifyObserversCertDBChanged(cert); } private: @@ -199,7 +190,7 @@ int NSSCertDatabase::ImportFromPKCS12(CryptoModule* module, is_extractable, imported_certs); if (result == OK) - NotifyObserversOfCertAdded(NULL); + NotifyObserversCertDBChanged(NULL); return result; } @@ -241,7 +232,18 @@ int NSSCertDatabase::ImportUserCert(const std::string& data) { int result = psm::ImportUserCert(certificates); if (result == OK) - NotifyObserversOfCertAdded(NULL); + NotifyObserversCertDBChanged(NULL); + + return result; +} + +int NSSCertDatabase::ImportUserCert(X509Certificate* certificate) { + CertificateList certificates; + certificates.emplace_back(certificate); + int result = psm::ImportUserCert(certificates); + + if (result == OK) + NotifyObserversCertDBChanged(NULL); return result; } @@ -254,7 +256,7 @@ bool NSSCertDatabase::ImportCACerts(const CertificateList& certificates, bool success = psm::ImportCACerts( slot.get(), certificates, root, trust_bits, not_imported); if (success) - NotifyObserversOfCACertChanged(NULL); + NotifyObserversCertDBChanged(NULL); return success; } @@ -372,7 +374,7 @@ bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, TrustBits trust_bits) { bool success = psm::SetCertTrust(cert, type, trust_bits); if (success) - NotifyObserversOfCACertChanged(cert); + NotifyObserversCertDBChanged(cert); return success; } @@ -380,7 +382,7 @@ bool NSSCertDatabase::SetCertTrust(const X509Certificate* cert, bool NSSCertDatabase::DeleteCertAndKey(X509Certificate* cert) { if (!DeleteCertAndKeyImpl(cert)) return false; - NotifyObserversOfCertRemoved(cert); + NotifyObserversCertDBChanged(cert); return true; } @@ -451,24 +453,13 @@ void NSSCertDatabase::NotifyCertRemovalAndCallBack( const DeleteCertCallback& callback, bool success) { if (success) - NotifyObserversOfCertRemoved(cert.get()); + NotifyObserversCertDBChanged(cert.get()); callback.Run(success); } -void NSSCertDatabase::NotifyObserversOfCertAdded(const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCertAdded, - base::RetainedRef(cert)); -} - -void NSSCertDatabase::NotifyObserversOfCertRemoved( - const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCertRemoved, - base::RetainedRef(cert)); -} - -void NSSCertDatabase::NotifyObserversOfCACertChanged( +void NSSCertDatabase::NotifyObserversCertDBChanged( const X509Certificate* cert) { - observer_list_->Notify(FROM_HERE, &Observer::OnCACertChanged, + observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged, base::RetainedRef(cert)); } diff --git a/chromium/net/cert/nss_cert_database.h b/chromium/net/cert/nss_cert_database.h index 00e72f3f19b..2ee859dbb71 100644 --- a/chromium/net/cert/nss_cert_database.h +++ b/chromium/net/cert/nss_cert_database.h @@ -42,18 +42,10 @@ class NET_EXPORT NSSCertDatabase { public: virtual ~Observer() {} - // Will be called when a new certificate is added. - // Called with |cert| == NULL after importing a list of certificates - // in ImportFromPKCS12(). - virtual void OnCertAdded(const X509Certificate* cert) {} - - // Will be called when a certificate is removed. - virtual void OnCertRemoved(const X509Certificate* cert) {} - // Will be called when a CA certificate is changed. // Called with |cert| == NULL after importing a list of certificates // in ImportCACerts(). - virtual void OnCACertChanged(const X509Certificate* cert) {} + virtual void OnCertDBChanged(const X509Certificate* cert) {} protected: Observer() {} @@ -199,6 +191,7 @@ class NET_EXPORT NSSCertDatabase { // already be installed, otherwise we return ERR_NO_PRIVATE_KEY_FOR_CERT. // Returns OK or a network error code. int ImportUserCert(const std::string& data); + int ImportUserCert(X509Certificate* cert); // Import CA certificates. // Tries to import all the certificates given. The root will be trusted @@ -275,9 +268,7 @@ class NET_EXPORT NSSCertDatabase { protected: // Broadcasts notifications to all registered observers. - void NotifyObserversOfCertAdded(const X509Certificate* cert); - void NotifyObserversOfCertRemoved(const X509Certificate* cert); - void NotifyObserversOfCACertChanged(const X509Certificate* cert); + void NotifyObserversCertDBChanged(const X509Certificate* cert); private: // Registers |observer| to receive notifications of certificate changes. The diff --git a/chromium/net/cert/nss_cert_database_chromeos_unittest.cc b/chromium/net/cert/nss_cert_database_chromeos_unittest.cc index 05678df5ae7..9cd226411e2 100644 --- a/chromium/net/cert/nss_cert_database_chromeos_unittest.cc +++ b/chromium/net/cert/nss_cert_database_chromeos_unittest.cc @@ -85,13 +85,7 @@ class NSSCertDatabaseChromeOSTest : public testing::Test, } // CertDatabase::Observer: - void OnCertAdded(const X509Certificate* cert) override { - added_.push_back(cert ? cert->os_cert_handle() : NULL); - } - - void OnCertRemoved(const X509Certificate* cert) override {} - - void OnCACertChanged(const X509Certificate* cert) override { + void OnCertDBChanged(const X509Certificate* cert) override { added_ca_.push_back(cert ? cert->os_cert_handle() : NULL); } @@ -99,7 +93,6 @@ class NSSCertDatabaseChromeOSTest : public testing::Test, bool observer_added_; // Certificates that were passed to the CertDatabase observers. std::vector<CERTCertificate*> added_ca_; - std::vector<CERTCertificate*> added_; crypto::ScopedTestNSSChromeOSUser user_1_; crypto::ScopedTestNSSChromeOSUser user_2_; @@ -180,13 +173,12 @@ TEST_F(NSSCertDatabaseChromeOSTest, ImportCACerts) { // Run the message loop so the observer notifications get processed. base::RunLoop().RunUntilIdle(); - // Should have gotten two OnCACertChanged notifications. + // Should have gotten two OnCertDBChanged notifications. ASSERT_EQ(2U, added_ca_.size()); // TODO(mattm): make NSSCertDatabase actually pass the cert to the callback, // and enable these checks: // EXPECT_EQ(certs_1[0]->os_cert_handle(), added_ca_[0]); // EXPECT_EQ(certs_2[0]->os_cert_handle(), added_ca_[1]); - EXPECT_EQ(0U, added_.size()); // Tests that the new certs are loaded by async ListCerts method. CertificateList user_1_certlist_async; @@ -251,7 +243,6 @@ TEST_F(NSSCertDatabaseChromeOSTest, ImportServerCert) { // TODO(mattm): ImportServerCert doesn't actually cause any observers to // fire. Is that correct? EXPECT_EQ(0U, added_ca_.size()); - EXPECT_EQ(0U, added_.size()); // Tests that the new certs are loaded by async ListCerts method. CertificateList user_1_certlist_async; diff --git a/chromium/net/cert/sth_distributor.cc b/chromium/net/cert/sth_distributor.cc index c511e27a163..61b2ce83370 100644 --- a/chromium/net/cert/sth_distributor.cc +++ b/chromium/net/cert/sth_distributor.cc @@ -35,7 +35,8 @@ void STHDistributor::NewSTHObserved(const SignedTreeHead& sth) { else *it = sth; - FOR_EACH_OBSERVER(STHObserver, observer_list_, NewSTHObserved(sth)); + for (auto& observer : observer_list_) + observer.NewSTHObserved(sth); if (sth.log_id.compare(0, sth.log_id.size(), reinterpret_cast<const char*>(kPilotLogID), diff --git a/chromium/net/cert/test_root_certs.h b/chromium/net/cert/test_root_certs.h index 1775e39379c..a77f0bf5f1d 100644 --- a/chromium/net/cert/test_root_certs.h +++ b/chromium/net/cert/test_root_certs.h @@ -12,7 +12,8 @@ #include "net/base/net_export.h" #if defined(USE_NSS_CERTS) -#include <list> +#include <cert.h> +#include <vector> #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) #include <vector> #elif defined(OS_WIN) @@ -24,9 +25,7 @@ #include "base/mac/scoped_cftyperef.h" #endif -#if defined(USE_NSS_CERTS) -typedef struct CERTCertificateStr CERTCertificate; -#elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) +#if defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) typedef struct x509_st X509; #endif @@ -103,12 +102,35 @@ class NET_EXPORT TestRootCerts { void Init(); #if defined(USE_NSS_CERTS) + // TrustEntry is used to store the original CERTCertificate and CERTCertTrust + // for a certificate whose trust status has been changed by the + // TestRootCerts. + class TrustEntry { + public: + // Creates a new TrustEntry by incrementing the reference to |certificate| + // and copying |trust|. + TrustEntry(CERTCertificate* certificate, const CERTCertTrust& trust); + ~TrustEntry(); + + CERTCertificate* certificate() const { return certificate_; } + const CERTCertTrust& trust() const { return trust_; } + + private: + // The temporary root certificate. + CERTCertificate* certificate_; + + // The original trust settings, before |certificate_| was manipulated to + // be a temporarily trusted root. + CERTCertTrust trust_; + + DISALLOW_COPY_AND_ASSIGN(TrustEntry); + }; + // It is necessary to maintain a cache of the original certificate trust // settings, in order to restore them when Clear() is called. - class TrustEntry; - std::list<TrustEntry*> trust_cache_; + std::vector<std::unique_ptr<TrustEntry>> trust_cache_; #elif defined(USE_OPENSSL_CERTS) && !defined(OS_ANDROID) - std::vector<scoped_refptr<X509Certificate> > temporary_roots_; + std::vector<scoped_refptr<X509Certificate>> temporary_roots_; #elif defined(OS_WIN) HCERTSTORE temporary_roots_; #elif defined(OS_MACOSX) diff --git a/chromium/net/cert/test_root_certs_nss.cc b/chromium/net/cert/test_root_certs_nss.cc index 99ca63491c9..afa37f13ea2 100644 --- a/chromium/net/cert/test_root_certs_nss.cc +++ b/chromium/net/cert/test_root_certs_nss.cc @@ -8,7 +8,7 @@ #include "base/logging.h" #include "base/macros.h" -#include "base/stl_util.h" +#include "base/memory/ptr_util.h" #include "crypto/nss_util.h" #include "net/cert/x509_certificate.h" @@ -18,29 +18,6 @@ namespace net { -// TrustEntry is used to store the original CERTCertificate and CERTCertTrust -// for a certificate whose trust status has been changed by the -// TestRootCerts. -class TestRootCerts::TrustEntry { - public: - // Creates a new TrustEntry by incrementing the reference to |certificate| - // and copying |trust|. - TrustEntry(CERTCertificate* certificate, const CERTCertTrust& trust); - ~TrustEntry(); - - CERTCertificate* certificate() const { return certificate_; } - const CERTCertTrust& trust() const { return trust_; } - - private: - // The temporary root certificate. - CERTCertificate* certificate_; - - // The original trust settings, before |certificate_| was manipulated to - // be a temporarily trusted root. - CERTCertTrust trust_; - - DISALLOW_COPY_AND_ASSIGN(TrustEntry); -}; TestRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate, const CERTCertTrust& trust) @@ -87,7 +64,8 @@ bool TestRootCerts::Add(X509Certificate* certificate) { return false; } - trust_cache_.push_back(new TrustEntry(cert_handle, original_trust)); + trust_cache_.push_back( + base::MakeUnique<TrustEntry>(cert_handle, original_trust)); return true; } @@ -97,8 +75,7 @@ void TestRootCerts::Clear() { // added twice, the second entry's original trust status will be that of // the first entry, while the first entry contains the desired resultant // status. - for (std::list<TrustEntry*>::reverse_iterator it = trust_cache_.rbegin(); - it != trust_cache_.rend(); ++it) { + for (auto it = trust_cache_.rbegin(); it != trust_cache_.rend(); ++it) { CERTCertTrust original_trust = (*it)->trust(); SECStatus rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), (*it)->certificate(), @@ -108,7 +85,7 @@ void TestRootCerts::Clear() { // occur after Clear() has been called. DCHECK_EQ(SECSuccess, rv) << "Cannot restore certificate trust."; } - base::STLDeleteElements(&trust_cache_); + trust_cache_.clear(); } bool TestRootCerts::IsEmpty() const { @@ -117,11 +94,10 @@ bool TestRootCerts::IsEmpty() const { #if defined(USE_NSS_CERTS) bool TestRootCerts::Contains(CERTCertificate* cert) const { - for (std::list<TrustEntry*>::const_iterator it = trust_cache_.begin(); - it != trust_cache_.end(); ++it) { - if (X509Certificate::IsSameOSCert(cert, (*it)->certificate())) + for (const auto& item : trust_cache_) + if (X509Certificate::IsSameOSCert(cert, item->certificate())) return true; - } + return false; } #endif diff --git a/chromium/net/cert/test_root_certs_openssl.cc b/chromium/net/cert/test_root_certs_openssl.cc index 76906d86f00..0cac6ab3660 100644 --- a/chromium/net/cert/test_root_certs_openssl.cc +++ b/chromium/net/cert/test_root_certs_openssl.cc @@ -4,13 +4,12 @@ #include "net/cert/test_root_certs.h" -#include <openssl/err.h> -#include <openssl/x509v3.h> - #include "base/location.h" #include "base/logging.h" #include "crypto/openssl_util.h" #include "net/cert/x509_certificate.h" +#include "third_party/boringssl/src/include/openssl/err.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" namespace net { diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc index 48cc5b5c8c5..7f23e7bf1d4 100644 --- a/chromium/net/cert/x509_certificate.cc +++ b/chromium/net/cert/x509_certificate.cc @@ -551,7 +551,7 @@ bool X509Certificate::VerifyHostname( // is not registry controlled, this ensures that all reference domains // contain at least three domain components when using wildcards. size_t registry_length = - registry_controlled_domains::GetRegistryLength( + registry_controlled_domains::GetCanonicalHostRegistryLength( reference_name, registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES, registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); diff --git a/chromium/net/cert/x509_certificate_ios.cc b/chromium/net/cert/x509_certificate_ios.cc index f50652ce8b6..737970768fb 100644 --- a/chromium/net/cert/x509_certificate_ios.cc +++ b/chromium/net/cert/x509_certificate_ios.cc @@ -7,18 +7,16 @@ #include <CommonCrypto/CommonDigest.h> #include <Security/Security.h> -#include <openssl/x509.h> -#include <openssl/x509v3.h> - #include "base/mac/scoped_cftyperef.h" #include "base/pickle.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" #include "net/base/ip_address.h" #include "net/cert/x509_util_openssl.h" #include "net/ssl/openssl_ssl_util.h" +#include "third_party/boringssl/src/include/openssl/x509.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" using base::ScopedCFTypeRef; @@ -26,9 +24,6 @@ namespace net { namespace { -using ScopedGENERAL_NAMES = - crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; - // Returns true if a given |cert_handle| is actually a valid X.509 certificate // handle. // @@ -109,7 +104,7 @@ void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, std::vector<std::string>* dns_names, std::vector<std::string>* ip_addresses) { DCHECK(dns_names || ip_addresses); - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); + bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); if (!cert.get()) return; int index = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1); @@ -117,7 +112,7 @@ void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, if (!alt_name_ext) return; - ScopedGENERAL_NAMES alt_names( + bssl::UniquePtr<GENERAL_NAMES> alt_names( reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); if (!alt_names.get()) return; @@ -150,11 +145,6 @@ void ParseSubjectAltName(X509Certificate::OSCertHandle os_cert, } } -// Used to free a list of X509_NAMEs and the objects it points to. -void sk_X509_NAME_free_all(STACK_OF(X509_NAME) * sk) { - sk_X509_NAME_pop_free(sk, X509_NAME_free); -} - } // namespace // static @@ -173,7 +163,7 @@ void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { void X509Certificate::Initialize() { crypto::EnsureOpenSSLInit(); - ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); + bssl::UniquePtr<X509> x509_cert = OSCertHandleToOpenSSL(cert_handle_); if (!x509_cert) return; ASN1_INTEGER* serial_num = X509_get_serialNumber(x509_cert.get()); @@ -342,10 +332,10 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle os_cert, PublicKeyType* type) { *type = kPublicKeyTypeUnknown; *size_bits = 0; - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); + bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); if (!cert) return; - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); + bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); if (!scoped_key) return; @@ -392,8 +382,7 @@ bool X509Certificate::IsIssuedByEncoded( // Convert to a temporary list of X509_NAME objects. // It will own the objects it points to. - crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> - issuer_names(sk_X509_NAME_new_null()); + bssl::UniquePtr<STACK_OF(X509_NAME)> issuer_names(sk_X509_NAME_new_null()); if (!issuer_names) return false; @@ -407,7 +396,7 @@ bool X509Certificate::IsIssuedByEncoded( sk_X509_NAME_push(issuer_names.get(), ca_name); } - ScopedX509 x509_cert = OSCertHandleToOpenSSL(cert_handle_); + bssl::UniquePtr<X509> x509_cert = OSCertHandleToOpenSSL(cert_handle_); if (!x509_cert) return false; X509_NAME* cert_issuer = X509_get_issuer_name(x509_cert.get()); @@ -423,7 +412,7 @@ bool X509Certificate::IsIssuedByEncoded( for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); it != intermediate_ca_certs_.end(); ++it) { - ScopedX509 intermediate_cert = OSCertHandleToOpenSSL(*it); + bssl::UniquePtr<X509> intermediate_cert = OSCertHandleToOpenSSL(*it); if (!intermediate_cert) return false; cert_issuer = X509_get_issuer_name(intermediate_cert.get()); @@ -443,10 +432,10 @@ bool X509Certificate::IsIssuedByEncoded( // static bool X509Certificate::IsSelfSigned(OSCertHandle os_cert) { - ScopedX509 cert = OSCertHandleToOpenSSL(os_cert); + bssl::UniquePtr<X509> cert = OSCertHandleToOpenSSL(os_cert); if (!cert) return false; - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert.get())); + bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert.get())); if (!scoped_key) return false; if (!X509_verify(cert.get(), scoped_key.get())) diff --git a/chromium/net/cert/x509_certificate_openssl.cc b/chromium/net/cert/x509_certificate_openssl.cc index e22ea9f099d..30d9598a50a 100644 --- a/chromium/net/cert/x509_certificate_openssl.cc +++ b/chromium/net/cert/x509_certificate_openssl.cc @@ -4,15 +4,6 @@ #include "net/cert/x509_certificate.h" -#include <openssl/asn1.h> -#include <openssl/bytestring.h> -#include <openssl/crypto.h> -#include <openssl/obj_mac.h> -#include <openssl/pem.h> -#include <openssl/sha.h> -#include <openssl/ssl.h> -#include <openssl/x509v3.h> - #include "base/macros.h" #include "base/memory/singleton.h" #include "base/numerics/safe_conversions.h" @@ -22,10 +13,17 @@ #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "crypto/openssl_util.h" -#include "crypto/scoped_openssl_types.h" #include "net/base/ip_address.h" #include "net/base/net_errors.h" #include "net/cert/x509_util_openssl.h" +#include "third_party/boringssl/src/include/openssl/asn1.h" +#include "third_party/boringssl/src/include/openssl/bytestring.h" +#include "third_party/boringssl/src/include/openssl/crypto.h" +#include "third_party/boringssl/src/include/openssl/obj_mac.h" +#include "third_party/boringssl/src/include/openssl/pem.h" +#include "third_party/boringssl/src/include/openssl/sha.h" +#include "third_party/boringssl/src/include/openssl/ssl.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" #if defined(OS_ANDROID) #include "base/logging.h" @@ -36,9 +34,6 @@ namespace net { namespace { -using ScopedGENERAL_NAMES = - crypto::ScopedOpenSSL<GENERAL_NAMES, GENERAL_NAMES_free>; - void CreateOSCertHandlesFromPKCS7Bytes( const char* data, size_t length, @@ -106,7 +101,7 @@ void ParseSubjectAltName(X509Certificate::OSCertHandle cert, if (!alt_name_ext) return; - ScopedGENERAL_NAMES alt_names( + bssl::UniquePtr<GENERAL_NAMES> alt_names( reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(alt_name_ext))); if (!alt_names.get()) return; @@ -164,16 +159,11 @@ class X509InitSingleton { ResetCertStore(); } - crypto::ScopedOpenSSL<X509_STORE, X509_STORE_free> store_; + bssl::UniquePtr<X509_STORE> store_; DISALLOW_COPY_AND_ASSIGN(X509InitSingleton); }; -// Used to free a list of X509_NAMEs and the objects it points to. -void sk_X509_NAME_free_all(STACK_OF(X509_NAME)* sk) { - sk_X509_NAME_pop_free(sk, X509_NAME_free); -} - } // namespace // static @@ -361,11 +351,10 @@ void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, *type = kPublicKeyTypeUnknown; *size_bits = 0; - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert_handle)); + bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); if (!scoped_key.get()) return; - CHECK(scoped_key.get()); EVP_PKEY* key = scoped_key.get(); switch (key->type) { @@ -395,8 +384,7 @@ bool X509Certificate::IsIssuedByEncoded( // Convert to a temporary list of X509_NAME objects. // It will own the objects it points to. - crypto::ScopedOpenSSL<STACK_OF(X509_NAME), sk_X509_NAME_free_all> - issuer_names(sk_X509_NAME_new_null()); + bssl::UniquePtr<STACK_OF(X509_NAME)> issuer_names(sk_X509_NAME_new_null()); if (!issuer_names.get()) return false; @@ -442,7 +430,7 @@ bool X509Certificate::IsIssuedByEncoded( // static bool X509Certificate::IsSelfSigned(OSCertHandle cert_handle) { - crypto::ScopedEVP_PKEY scoped_key(X509_get_pubkey(cert_handle)); + bssl::UniquePtr<EVP_PKEY> scoped_key(X509_get_pubkey(cert_handle)); if (!scoped_key) return false; if (!X509_verify(cert_handle, scoped_key.get())) diff --git a/chromium/net/cert/x509_certificate_unittest.cc b/chromium/net/cert/x509_certificate_unittest.cc index 771dda12122..9cadb266849 100644 --- a/chromium/net/cert/x509_certificate_unittest.cc +++ b/chromium/net/cert/x509_certificate_unittest.cc @@ -492,6 +492,32 @@ TEST(X509CertificateTest, ExtractCRLURLsFromDERCert) { } } +TEST(X509CertificateTest, HasTLSFeatureExtension) { + base::FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(certs_dir, "tls_feature_extension.pem"); + ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); + + std::string derBytes; + EXPECT_TRUE( + X509Certificate::GetDEREncoded(cert->os_cert_handle(), &derBytes)); + + EXPECT_TRUE(asn1::HasTLSFeatureExtension(derBytes)); +} + +TEST(X509CertificateTest, DoesNotHaveTLSFeatureExtension) { + base::FilePath certs_dir = GetTestCertsDirectory(); + scoped_refptr<X509Certificate> cert = + ImportCertFromFile(certs_dir, "ok_cert.pem"); + ASSERT_NE(static_cast<X509Certificate*>(NULL), cert.get()); + + std::string derBytes; + EXPECT_TRUE( + X509Certificate::GetDEREncoded(cert->os_cert_handle(), &derBytes)); + + EXPECT_FALSE(asn1::HasTLSFeatureExtension(derBytes)); +} + // Tests X509CertificateCache via X509Certificate::CreateFromHandle. We // call X509Certificate::CreateFromHandle several times and observe whether // it returns a cached or new OSCertHandle. diff --git a/chromium/net/cert/x509_certificate_win.cc b/chromium/net/cert/x509_certificate_win.cc index 4c6e389177b..c67011e06b9 100644 --- a/chromium/net/cert/x509_certificate_win.cc +++ b/chromium/net/cert/x509_certificate_win.cc @@ -6,8 +6,6 @@ #include <memory> -#include <openssl/sha.h> - #include "base/logging.h" #include "base/memory/free_deleter.h" #include "base/numerics/safe_conversions.h" @@ -19,6 +17,7 @@ #include "crypto/scoped_capi_types.h" #include "crypto/sha2.h" #include "net/base/net_errors.h" +#include "third_party/boringssl/src/include/openssl/sha.h" using base::Time; diff --git a/chromium/net/cert/x509_util_openssl.cc b/chromium/net/cert/x509_util_openssl.cc index 4c6ee78547e..4a2aba01dc6 100644 --- a/chromium/net/cert/x509_util_openssl.cc +++ b/chromium/net/cert/x509_util_openssl.cc @@ -5,9 +5,6 @@ #include "net/cert/x509_util_openssl.h" #include <limits.h> -#include <openssl/asn1.h> -#include <openssl/digest.h> -#include <openssl/mem.h> #include <algorithm> #include <memory> @@ -20,27 +17,19 @@ #include "crypto/ec_private_key.h" #include "crypto/openssl_util.h" #include "crypto/rsa_private_key.h" -#include "crypto/scoped_openssl_types.h" #include "net/cert/internal/parse_certificate.h" #include "net/cert/internal/signature_algorithm.h" #include "net/cert/x509_cert_types.h" #include "net/cert/x509_certificate.h" #include "net/cert/x509_util.h" -#include "net/ssl/scoped_openssl_types.h" +#include "third_party/boringssl/src/include/openssl/asn1.h" +#include "third_party/boringssl/src/include/openssl/digest.h" +#include "third_party/boringssl/src/include/openssl/mem.h" namespace net { namespace { -using ScopedASN1_INTEGER = - crypto::ScopedOpenSSL<ASN1_INTEGER, ASN1_INTEGER_free>; -using ScopedASN1_OCTET_STRING = - crypto::ScopedOpenSSL<ASN1_OCTET_STRING, ASN1_OCTET_STRING_free>; -using ScopedASN1_STRING = crypto::ScopedOpenSSL<ASN1_STRING, ASN1_STRING_free>; -using ScopedASN1_TIME = crypto::ScopedOpenSSL<ASN1_TIME, ASN1_TIME_free>; -using ScopedX509_EXTENSION = - crypto::ScopedOpenSSL<X509_EXTENSION, X509_EXTENSION_free>; - const EVP_MD* ToEVP(x509_util::DigestAlgorithm alg) { switch (alg) { case x509_util::DIGEST_SHA1: @@ -57,34 +46,34 @@ namespace x509_util { namespace { -X509* CreateCertificate(EVP_PKEY* key, - DigestAlgorithm alg, - const std::string& common_name, - uint32_t serial_number, - base::Time not_valid_before, - base::Time not_valid_after) { +bssl::UniquePtr<X509> CreateCertificate(EVP_PKEY* key, + DigestAlgorithm alg, + const std::string& common_name, + uint32_t serial_number, + base::Time not_valid_before, + base::Time not_valid_after) { // Put the serial number into an OpenSSL-friendly object. - ScopedASN1_INTEGER asn1_serial(ASN1_INTEGER_new()); + bssl::UniquePtr<ASN1_INTEGER> asn1_serial(ASN1_INTEGER_new()); if (!asn1_serial.get() || !ASN1_INTEGER_set(asn1_serial.get(), static_cast<long>(serial_number))) { LOG(ERROR) << "Invalid serial number " << serial_number; - return NULL; + return nullptr; } // Do the same for the time stamps. - ScopedASN1_TIME asn1_not_before_time( - ASN1_TIME_set(NULL, not_valid_before.ToTimeT())); + bssl::UniquePtr<ASN1_TIME> asn1_not_before_time( + ASN1_TIME_set(nullptr, not_valid_before.ToTimeT())); if (!asn1_not_before_time.get()) { LOG(ERROR) << "Invalid not_valid_before time: " << not_valid_before.ToTimeT(); - return NULL; + return nullptr; } - ScopedASN1_TIME asn1_not_after_time( - ASN1_TIME_set(NULL, not_valid_after.ToTimeT())); + bssl::UniquePtr<ASN1_TIME> asn1_not_after_time( + ASN1_TIME_set(nullptr, not_valid_after.ToTimeT())); if (!asn1_not_after_time.get()) { LOG(ERROR) << "Invalid not_valid_after time: " << not_valid_after.ToTimeT(); - return NULL; + return nullptr; } // Because |common_name| only contains a common name and starts with 'CN=', @@ -95,11 +84,11 @@ X509* CreateCertificate(EVP_PKEY* key, if (common_name.size() < kCommonNamePrefixLen || strncmp(common_name.c_str(), kCommonNamePrefix, kCommonNamePrefixLen)) { LOG(ERROR) << "Common name must begin with " << kCommonNamePrefix; - return NULL; + return nullptr; } if (common_name.size() > INT_MAX) { LOG(ERROR) << "Common name too long"; - return NULL; + return nullptr; } unsigned char* common_name_str = reinterpret_cast<unsigned char*>(const_cast<char*>(common_name.data())) + @@ -107,7 +96,7 @@ X509* CreateCertificate(EVP_PKEY* key, int common_name_len = static_cast<int>(common_name.size() - kCommonNamePrefixLen); - ScopedX509_NAME name(X509_NAME_new()); + bssl::UniquePtr<X509_NAME> name(X509_NAME_new()); if (!name.get() || !X509_NAME_add_entry_by_NID(name.get(), NID_commonName, MBSTRING_ASC, @@ -116,11 +105,11 @@ X509* CreateCertificate(EVP_PKEY* key, -1, 0)) { LOG(ERROR) << "Can't parse common name: " << common_name.c_str(); - return NULL; + return nullptr; } // Now create certificate and populate it. - ScopedX509 cert(X509_new()); + bssl::UniquePtr<X509> cert(X509_new()); if (!cert.get() || !X509_set_version(cert.get(), 2L) /* i.e. version 3 */ || !X509_set_pubkey(cert.get(), key) || !X509_set_serialNumber(cert.get(), asn1_serial.get()) || @@ -129,10 +118,10 @@ X509* CreateCertificate(EVP_PKEY* key, !X509_set_subject_name(cert.get(), name.get()) || !X509_set_issuer_name(cert.get(), name.get())) { LOG(ERROR) << "Could not create certificate"; - return NULL; + return nullptr; } - return cert.release(); + return cert; } // DER-encodes |x509|. On success, returns true and writes the @@ -211,13 +200,10 @@ bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, base::Time not_valid_after, std::string* der_encoded) { crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - ScopedX509 cert(CreateCertificate(key->key(), - alg, - common_name, - serial_number, - not_valid_before, - not_valid_after)); - if (!cert.get()) + bssl::UniquePtr<X509> cert = + CreateCertificate(key->key(), alg, common_name, serial_number, + not_valid_before, not_valid_after); + if (!cert) return false; return SignAndDerEncodeCert(cert.get(), key->key(), alg, der_encoded); diff --git a/chromium/net/cert/x509_util_openssl.h b/chromium/net/cert/x509_util_openssl.h index c77aed07a7a..b735c1ac21a 100644 --- a/chromium/net/cert/x509_util_openssl.h +++ b/chromium/net/cert/x509_util_openssl.h @@ -5,14 +5,13 @@ #ifndef NET_CERT_X509_UTIL_OPENSSL_H_ #define NET_CERT_X509_UTIL_OPENSSL_H_ -#include <openssl/asn1.h> -#include <openssl/x509v3.h> - #include <string> #include <vector> #include "base/strings/string_piece.h" #include "net/base/net_export.h" +#include "third_party/boringssl/src/include/openssl/asn1.h" +#include "third_party/boringssl/src/include/openssl/x509v3.h" namespace base { class Time; |