1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#ifndef CHROMEOS_CERT_LOADER_H_
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define CHROMEOS_CERT_LOADER_H_
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string>
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include <vector>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
11c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch#include "base/basictypes.h"
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/compiler_specific.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/ref_counted.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/memory/weak_ptr.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/observer_list.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/threading/thread_checker.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chromeos/chromeos_export.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_database.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace net {
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class NSSCertDatabase;
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class X509Certificate;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)typedef std::vector<scoped_refptr<X509Certificate> > CertificateList;
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace chromeos {
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// This class is responsible for loading certificates once the TPM is
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// initialized. It is expected to be constructed on the UI thread and public
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// methods should all be called from the UI thread.
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// When certificates have been loaded (after login completes and tpm token is
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// initialized), or the cert database changes, observers are called with
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// OnCertificatesLoaded().
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class CHROMEOS_EXPORT CertLoader : public net::CertDatabase::Observer {
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) public:
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  class Observer {
37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   public:
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Called when the certificates, passed for convenience as |cert_list|,
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // have completed loading. |initial_load| is true the first time this
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // is called.
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                      bool initial_load) = 0;
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)   protected:
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    virtual ~Observer() {}
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  };
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
48558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Sets the global instance. Must be called before any calls to Get().
49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  static void Initialize();
50558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
51558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Destroys the global instance.
52558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  static void Shutdown();
53558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
54558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Gets the global instance. Initialize() must be called first.
55558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  static CertLoader* Get();
56558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  // Returns true if the global instance has been initialized.
58558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  static bool IsInitialized();
59558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
60c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // Returns the PKCS#11 attribute CKA_ID for a certificate as an upper-case
61c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // hex string, or the empty string if none is found. Note that the returned ID
62c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // should be used only to identify the cert in its slot.
63c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // This should be used only for user certificates, assuming that only one
64c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // private slot is loaded for a user.
65c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // TODO(tbarzic): Make this check cert slot id if we start loading
66c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  // certificates for secondary users.
67c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  static std::string GetPkcs11IdForCert(const net::X509Certificate& cert);
68c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Starts the CertLoader with the NSS cert database.
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The CertLoader will _not_ take the ownership of the database, but it
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // expects it to stay alive at least until the shutdown starts on the main
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // thread. This assumes that |StartWithNSSDB| and other methods directly
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // using |database_| are not called during shutdown.
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void StartWithNSSDB(net::NSSCertDatabase* database);
753240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void AddObserver(CertLoader::Observer* observer);
77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void RemoveObserver(CertLoader::Observer* observer);
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int TPMTokenSlotID() const;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool IsHardwareBacked() const;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Whether the certificate is hardware backed. Returns false if the CertLoader
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // was not yet started (both |CertificatesLoading()| and
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |certificates_loaded()| are false).
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool IsCertificateHardwareBacked(const net::X509Certificate* cert) const;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Returns true when the certificate list has been requested but not loaded.
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool CertificatesLoading() const;
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool certificates_loaded() const { return certificates_loaded_; }
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This will be empty until certificates_loaded() is true.
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const net::CertificateList& cert_list() const { return *cert_list_; }
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void force_hardware_backed_for_test() {
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    force_hardware_backed_for_test_ = true;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) private:
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CertLoader();
101558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  virtual ~CertLoader();
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Trigger a certificate load. If a certificate loading task is already in
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // progress, will start a reload once the current task is finished.
1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  void LoadCertificates();
1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Called if a certificate load task is finished.
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void UpdateCertificates(scoped_ptr<net::CertificateList> cert_list);
109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  void NotifyCertificatesLoaded(bool initial_load);
111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // net::CertDatabase::Observer
1131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  virtual void OnCACertChanged(const net::X509Certificate* cert) OVERRIDE;
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnCertAdded(const net::X509Certificate* cert) OVERRIDE;
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnCertRemoved(const net::X509Certificate* cert) OVERRIDE;
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ObserverList<Observer> observers_;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Flags describing current CertLoader state.
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool certificates_loaded_;
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool certificates_update_required_;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool certificates_update_running_;
12390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The user-specific NSS certificate database from which the certificates
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // should be loaded.
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  net::NSSCertDatabase* database_;
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Set during tests if |IsHardwareBacked()| should always return true.
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool force_hardware_backed_for_test_;
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Cached Certificates loaded from the database.
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<net::CertificateList> cert_list_;
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::ThreadChecker thread_checker_;
135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::WeakPtrFactory<CertLoader> weak_factory_;
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(CertLoader);
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace chromeos
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
143558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif  // CHROMEOS_CERT_LOADER_H_
144