1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_CERT_CACHING_CERT_VERIFIER_H_ 6 #define NET_CERT_CACHING_CERT_VERIFIER_H_ 7 8 #include <memory> 9 10 #include "base/gtest_prod_util.h" 11 #include "base/time/time.h" 12 #include "net/base/completion_once_callback.h" 13 #include "net/base/expiring_cache.h" 14 #include "net/base/net_export.h" 15 #include "net/cert/cert_database.h" 16 #include "net/cert/cert_verifier.h" 17 #include "net/cert/cert_verify_result.h" 18 19 namespace net { 20 21 // CertVerifier that caches the results of certificate verifications. 22 // 23 // In general, certificate verification results will vary on only three 24 // parameters: 25 // - The time of validation (as certificates are only valid for a period of 26 // time) 27 // - The revocation status (a certificate may be revoked at any time, but 28 // revocation statuses themselves have validity period, so a 'good' result 29 // may be reused for a period of time) 30 // - The trust settings (a user may change trust settings at any time) 31 // 32 // This class tries to optimize by allowing certificate verification results 33 // to be cached for a limited amount of time (presently, 30 minutes), which 34 // tries to balance the implementation complexity of needing to monitor the 35 // above for meaningful changes and the practical utility of being able to 36 // cache results when they're not expected to change. 37 class NET_EXPORT CachingCertVerifier : public CertVerifier, 38 public CertVerifier::Observer, 39 public CertDatabase::Observer { 40 public: 41 // Creates a CachingCertVerifier that will use |verifier| to perform the 42 // actual verifications if they're not already cached or if the cached 43 // item has expired. 44 explicit CachingCertVerifier(std::unique_ptr<CertVerifier> verifier); 45 46 CachingCertVerifier(const CachingCertVerifier&) = delete; 47 CachingCertVerifier& operator=(const CachingCertVerifier&) = delete; 48 49 ~CachingCertVerifier() override; 50 51 // CertVerifier implementation: 52 int Verify(const RequestParams& params, 53 CertVerifyResult* verify_result, 54 CompletionOnceCallback callback, 55 std::unique_ptr<Request>* out_req, 56 const NetLogWithSource& net_log) override; 57 void SetConfig(const Config& config) override; 58 void AddObserver(CertVerifier::Observer* observer) override; 59 void RemoveObserver(CertVerifier::Observer* observer) override; 60 61 private: 62 FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, CacheHit); 63 FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, CacheHitCTResultsCached); 64 FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierTest, DifferentCACerts); 65 FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierCacheClearingTest, 66 CacheClearedSyncVerification); 67 FRIEND_TEST_ALL_PREFIXES(CachingCertVerifierCacheClearingTest, 68 CacheClearedAsyncVerification); 69 70 // CachedResult contains the result of a certificate verification. 71 struct NET_EXPORT_PRIVATE CachedResult { 72 CachedResult(); 73 ~CachedResult(); 74 75 int error = ERR_FAILED; // The return value of CertVerifier::Verify. 76 CertVerifyResult result; // The output of CertVerifier::Verify. 77 }; 78 79 // Rather than having a single validity point along a monotonically increasing 80 // timeline, certificate verification is based on falling within a range of 81 // the certificate's NotBefore and NotAfter and based on what the current 82 // system clock says (which may advance forwards or backwards as users correct 83 // clock skew). CacheValidityPeriod and CacheExpirationFunctor are helpers to 84 // ensure that expiration is measured both by the 'general' case (now + cache 85 // TTL) and by whether or not significant enough clock skew was introduced 86 // since the last verification. 87 struct CacheValidityPeriod { 88 explicit CacheValidityPeriod(base::Time now); 89 CacheValidityPeriod(base::Time now, base::Time expiration); 90 91 base::Time verification_time; 92 base::Time expiration_time; 93 }; 94 95 struct CacheExpirationFunctor { 96 // Returns true iff |now| is within the validity period of |expiration|. 97 bool operator()(const CacheValidityPeriod& now, 98 const CacheValidityPeriod& expiration) const; 99 }; 100 101 using CertVerificationCache = ExpiringCache<RequestParams, 102 CachedResult, 103 CacheValidityPeriod, 104 CacheExpirationFunctor>; 105 106 // Handles completion of the request matching |params|, which started at 107 // |start_time| and with config |config_id|, completing. |verify_result| and 108 // |result| are added to the cache, and then |callback| (the original caller's 109 // callback) is invoked. 110 void OnRequestFinished(uint32_t config_id, 111 const RequestParams& params, 112 base::Time start_time, 113 CompletionOnceCallback callback, 114 CertVerifyResult* verify_result, 115 int error); 116 117 // Adds |verify_result| and |error| to the cache for |params|, whose 118 // verification attempt began at |start_time| with config |config_id|. See the 119 // implementation for more details about the necessity of |start_time|. 120 void AddResultToCache(uint32_t config_id, 121 const RequestParams& params, 122 base::Time start_time, 123 const CertVerifyResult& verify_result, 124 int error); 125 126 // CertVerifier::Observer methods: 127 void OnCertVerifierChanged() override; 128 129 // CertDatabase::Observer methods: 130 void OnTrustStoreChanged() override; 131 132 // For unit testing. 133 void ClearCache(); 134 size_t GetCacheSize() const; cache_hits()135 uint64_t cache_hits() const { return cache_hits_; } requests()136 uint64_t requests() const { return requests_; } 137 138 std::unique_ptr<CertVerifier> verifier_; 139 140 uint32_t config_id_ = 0u; 141 CertVerificationCache cache_; 142 143 uint64_t requests_ = 0u; 144 uint64_t cache_hits_ = 0u; 145 }; 146 147 } // namespace net 148 149 #endif // NET_CERT_CACHING_CERT_VERIFIER_H_ 150