Home | History | Annotate | Download | only in chromeos
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      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 CHROMEOS_CERT_LOADER_H_
      6 #define CHROMEOS_CERT_LOADER_H_
      7 
      8 #include <string>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_ptr.h"
     13 #include "base/memory/weak_ptr.h"
     14 #include "base/observer_list_threadsafe.h"
     15 #include "base/threading/thread_checker.h"
     16 #include "chromeos/chromeos_export.h"
     17 #include "chromeos/dbus/dbus_method_call_status.h"
     18 #include "chromeos/login/login_state.h"
     19 #include "net/cert/cert_database.h"
     20 #include "net/cert/x509_certificate.h"
     21 
     22 namespace base {
     23 class SequencedTaskRunner;
     24 class TaskRunner;
     25 }
     26 
     27 namespace crypto {
     28 class SymmetricKey;
     29 }
     30 
     31 namespace chromeos {
     32 
     33 // This class is responsible for initializing the TPM token and loading
     34 // certificates once the TPM is initialized. It is expected to be constructed
     35 // on the UI thread and public methods should all be called from the UI thread.
     36 // When certificates have been loaded (after login completes), or the cert
     37 // database changes, observers are called with OnCertificatesLoaded().
     38 class CHROMEOS_EXPORT CertLoader : public net::CertDatabase::Observer,
     39                                    public LoginState::Observer {
     40  public:
     41   class Observer {
     42    public:
     43     virtual ~Observer() {}
     44 
     45     // Called when the certificates, passed for convenience as |cert_list|,
     46     // have completed loading. |initial_load| is true the first time this
     47     // is called.
     48     virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
     49                                       bool initial_load) = 0;
     50 
     51    protected:
     52     Observer() {}
     53 
     54    private:
     55     DISALLOW_COPY_AND_ASSIGN(Observer);
     56   };
     57 
     58   // Sets the global instance. Must be called before any calls to Get().
     59   static void Initialize();
     60 
     61   // Destroys the global instance.
     62   static void Shutdown();
     63 
     64   // Gets the global instance. Initialize() must be called first.
     65   static CertLoader* Get();
     66 
     67   // Returns true if the global instance has been initialized.
     68   static bool IsInitialized();
     69 
     70   static std::string GetPkcs11IdForCert(const net::X509Certificate& cert);
     71 
     72   // By default, CertLoader tries to load the TPMToken only if running in a
     73   // ChromeOS environment. Tests can call this function after Initialize() and
     74   // before SetCryptoTaskRunner() to enable the TPM initialization.
     75   void InitializeTPMForTest();
     76 
     77   // |crypto_task_runner| is the task runner that any synchronous crypto calls
     78   // should be made from, e.g. in Chrome this is the IO thread. Must be called
     79   // after the thread is started. Starts TPM initialization and Certificate
     80   // loading.
     81   void SetCryptoTaskRunner(
     82       const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner);
     83 
     84   // Sets the task runner that any slow calls will be made from, e.g. calls
     85   // to the NSS database. If not set, uses base::WorkerPool.
     86   void SetSlowTaskRunnerForTest(
     87       const scoped_refptr<base::TaskRunner>& task_runner);
     88 
     89   void AddObserver(CertLoader::Observer* observer);
     90   void RemoveObserver(CertLoader::Observer* observer);
     91 
     92   // Returns true when the certificate list has been requested but not loaded.
     93   bool CertificatesLoading() const;
     94 
     95   // Returns true if the TPM is available for hardware-backed certificates.
     96   bool IsHardwareBacked() const;
     97 
     98   bool certificates_loaded() const { return certificates_loaded_; }
     99 
    100   // TPM info is only valid once the TPM is available (IsHardwareBacked is
    101   // true). Otherwise empty strings will be returned.
    102   const std::string& tpm_token_name() const { return tpm_token_name_; }
    103   int tpm_token_slot_id() const { return tpm_token_slot_id_; }
    104   const std::string& tpm_user_pin() const { return tpm_user_pin_; }
    105 
    106   // This will be empty until certificates_loaded() is true.
    107   const net::CertificateList& cert_list() const { return cert_list_; }
    108 
    109  private:
    110   CertLoader();
    111   virtual ~CertLoader();
    112 
    113   void MaybeRequestCertificates();
    114 
    115   // This is the cyclic chain of callbacks to initialize the TPM token and to
    116   // kick off the update of the certificate list.
    117   void InitializeTokenAndLoadCertificates();
    118   void RetryTokenInitializationLater();
    119   void OnPersistentNSSDBOpened();
    120   void OnTpmIsEnabled(DBusMethodCallStatus call_status,
    121                       bool tpm_is_enabled);
    122   void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status,
    123                                bool is_tpm_token_ready);
    124   void OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status,
    125                                const std::string& token_name,
    126                                const std::string& user_pin,
    127                                int token_slot_id);
    128   void OnTPMTokenInitialized(bool success);
    129 
    130   // These calls handle the updating of the certificate list after the TPM token
    131   // was initialized.
    132 
    133   // Start certificate loading. Must be called at most once.
    134   void StartLoadCertificates();
    135 
    136   // Trigger a certificate load. If a certificate loading task is already in
    137   // progress, will start a reload once the current task finised.
    138   void LoadCertificates();
    139 
    140   // Called if a certificate load task is finished.
    141   void UpdateCertificates(net::CertificateList* cert_list);
    142 
    143   void NotifyCertificatesLoaded(bool initial_load);
    144 
    145   // net::CertDatabase::Observer
    146   virtual void OnCACertChanged(const net::X509Certificate* cert) OVERRIDE;
    147   virtual void OnCertAdded(const net::X509Certificate* cert) OVERRIDE;
    148   virtual void OnCertRemoved(const net::X509Certificate* cert) OVERRIDE;
    149 
    150   // LoginState::Observer
    151   virtual void LoggedInStateChanged() OVERRIDE;
    152 
    153   bool initialize_tpm_for_test_;
    154 
    155   ObserverList<Observer> observers_;
    156 
    157   bool certificates_requested_;
    158   bool certificates_loaded_;
    159   bool certificates_update_required_;
    160   bool certificates_update_running_;
    161 
    162   // The states are traversed in this order but some might get omitted or never
    163   // be left.
    164   enum TPMTokenState {
    165     TPM_STATE_UNKNOWN,
    166     TPM_DB_OPENED,
    167     TPM_DISABLED,
    168     TPM_ENABLED,
    169     TPM_TOKEN_READY,
    170     TPM_TOKEN_INFO_RECEIVED,
    171     TPM_TOKEN_INITIALIZED,
    172   };
    173   TPMTokenState tpm_token_state_;
    174 
    175   // The current request delay before the next attempt to initialize the
    176   // TPM. Will be adapted after each attempt.
    177   base::TimeDelta tpm_request_delay_;
    178 
    179   // Cached TPM token info.
    180   std::string tpm_token_name_;
    181   int tpm_token_slot_id_;
    182   std::string tpm_user_pin_;
    183 
    184   // Cached Certificates.
    185   net::CertificateList cert_list_;
    186 
    187   base::ThreadChecker thread_checker_;
    188 
    189   // TaskRunner for crypto calls.
    190   scoped_refptr<base::SequencedTaskRunner> crypto_task_runner_;
    191 
    192   // TaskRunner for other slow tasks. May be set in tests.
    193   scoped_refptr<base::TaskRunner> slow_task_runner_for_test_;
    194 
    195   // This factory should be used only for callbacks during TPMToken
    196   // initialization.
    197   base::WeakPtrFactory<CertLoader> initialize_token_factory_;
    198 
    199   // This factory should be used only for callbacks during updating the
    200   // certificate list.
    201   base::WeakPtrFactory<CertLoader> update_certificates_factory_;
    202 
    203   DISALLOW_COPY_AND_ASSIGN(CertLoader);
    204 };
    205 
    206 }  // namespace chromeos
    207 
    208 #endif  // CHROMEOS_CERT_LOADER_H_
    209