15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef NET_CERT_MULTI_THREADED_CERT_VERIFIER_H_ 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define NET_CERT_MULTI_THREADED_CERT_VERIFIER_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <vector> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/non_thread_safe.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/expiring_cache.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/hash_value.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_export.h" 20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_database.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_result.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_cert_types.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CertTrustAnchorProvider; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CertVerifierJob; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CertVerifierRequest; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CertVerifierWorker; 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CertVerifyProc; 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MultiThreadedCertVerifier is a CertVerifier implementation that runs 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// synchronous CertVerifier implementations on worker threads. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NET_EXPORT_PRIVATE MultiThreadedCertVerifier 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public CertVerifier, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NON_EXPORTED_BASE(public base::NonThreadSafe), 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public CertDatabase::Observer { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit MultiThreadedCertVerifier(CertVerifyProc* verify_proc); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the verifier is destroyed, all certificate verifications requests are 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // canceled, and their completion callbacks will not be called. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~MultiThreadedCertVerifier(); 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Configures a source of additional certificates that should be treated as 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // trust anchors during verification, provided that the underlying 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // CertVerifyProc supports additional trust beyond the default implementation. 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The CertTrustAnchorProvider will only be accessed on the same 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // thread that Verify() is called on; that is, it will not be 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // accessed from worker threads. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It must outlive the MultiThreadedCertVerifier. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void SetCertTrustAnchorProvider( 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertTrustAnchorProvider* trust_anchor_provider); 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CertVerifier implementation 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual int Verify(X509Certificate* cert, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet* crl_set, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifyResult* verify_result, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback, 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifier::RequestHandle* out_req, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const BoundNetLog& net_log) OVERRIDE; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void CancelRequest(CertVerifier::RequestHandle req) OVERRIDE; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class CertVerifierWorker; // Calls HandleResult. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class CertVerifierRequest; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class CertVerifierJob; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MultiThreadedCertVerifierTest; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CacheHit); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, DifferentCACerts); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, InflightJoin); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CancelRequest); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestParamsComparators); 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertTrustAnchorProvider); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Input parameters of a certificate verification request. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct NET_EXPORT_PRIVATE RequestParams { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RequestParams(const SHA1HashValue& cert_fingerprint_arg, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SHA1HashValue& ca_fingerprint_arg, 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname_arg, 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags_arg, 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CertificateList& additional_trust_anchors); 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ~RequestParams(); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool operator<(const RequestParams& other) const; 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string hostname; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags; 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<SHA1HashValue> hash_values; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CachedResult contains the result of a certificate verification. 996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) struct NET_EXPORT_PRIVATE CachedResult { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedResult(); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~CachedResult(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error; // The return value of CertVerifier::Verify. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifyResult result; // The output of CertVerifier::Verify. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Rather than having a single validity point along a monotonically increasing 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // timeline, certificate verification is based on falling within a range of 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the certificate's NotBefore and NotAfter and based on what the current 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // system clock says (which may advance forwards or backwards as users correct 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // clock skew). CacheValidityPeriod and CacheExpirationFunctor are helpers to 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ensure that expiration is measured both by the 'general' case (now + cache 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TTL) and by whether or not significant enough clock skew was introduced 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since the last verification. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct CacheValidityPeriod { 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit CacheValidityPeriod(const base::Time& now); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheValidityPeriod(const base::Time& now, const base::Time& expiration); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time verification_time; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time expiration_time; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct CacheExpirationFunctor { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true iff |now| is within the validity period of |expiration|. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator()(const CacheValidityPeriod& now, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CacheValidityPeriod& expiration) const; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef ExpiringCache<RequestParams, CachedResult, CacheValidityPeriod, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CacheExpirationFunctor> CertVerifierCache; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void HandleResult(X509Certificate* cert, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& hostname, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CertificateList& additional_trust_anchors, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CertVerifyResult& verify_result); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CertDatabase::Observer methods: 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void OnCACertChanged(const X509Certificate* cert) OVERRIDE; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For unit testing. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ClearCache() { cache_.Clear(); } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t GetCacheSize() const { return cache_.size(); } 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 cache_hits() const { return cache_hits_; } 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 requests() const { return requests_; } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 inflight_joins() const { return inflight_joins_; } 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cache_ maps from a request to a cached result. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifierCache cache_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inflight_ maps from a request to an active verification which is taking 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // place. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<RequestParams, CertVerifierJob*> inflight_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 156c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // A non-owning pointer to the first job for histogramming. 157c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch CertVerifierJob* first_job_; 158c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 requests_; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 cache_hits_; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 inflight_joins_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CertVerifyProc> verify_proc_; 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertTrustAnchorProvider* trust_anchor_provider_; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MultiThreadedCertVerifier); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif // NET_CERT_MULTI_THREADED_CERT_VERIFIER_H_ 173