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