| // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMEOS_CERT_LOADER_H_ |
| #define CHROMEOS_CERT_LOADER_H_ |
| |
| #include <string> |
| #include <vector> |
| |
| #include "base/compiler_specific.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.h" |
| #include "base/threading/thread_checker.h" |
| #include "chromeos/chromeos_export.h" |
| #include "net/cert/x509_certificate.h" |
| |
| namespace net { |
| class NSSCertDatabase; |
| typedef std::vector<scoped_refptr<X509Certificate> > CertificateList; |
| } |
| |
| namespace chromeos { |
| |
| // This class is responsible for loading certificates once the TPM is |
| // initialized. It is expected to be constructed on the UI thread and public |
| // methods should all be called from the UI thread. |
| // When certificates have been loaded (after login completes and tpm token is |
| // initialized), or the cert database changes, observers are called with |
| // OnCertificatesLoaded(). |
| // This class supports using one or two cert databases. The expected usage is |
| // that CertLoader is used with a NSSCertDatabase backed by the system token |
| // before user sign-in, and additionally with a user-specific NSSCertDatabase |
| // after user sign-in. When both NSSCertDatabase are used, CertLoader combines |
| // certificates from both into |all_certs()|. |
| class CHROMEOS_EXPORT CertLoader { |
| public: |
| class Observer { |
| public: |
| // Called when the certificates, passed for convenience as |all_certs|, |
| // have completed loading. |initial_load| is true the first time this |
| // is called. It will be false if this is called because another slot has |
| // been added to CertLoader's data sources. |
| virtual void OnCertificatesLoaded(const net::CertificateList& all_certs, |
| bool initial_load) = 0; |
| |
| protected: |
| virtual ~Observer() {} |
| }; |
| |
| // Sets the global instance. Must be called before any calls to Get(). |
| static void Initialize(); |
| |
| // Destroys the global instance. |
| static void Shutdown(); |
| |
| // Gets the global instance. Initialize() must be called first. |
| static CertLoader* Get(); |
| |
| // Returns true if the global instance has been initialized. |
| static bool IsInitialized(); |
| |
| // Returns the PKCS#11 attribute CKA_ID for a certificate as an upper-case |
| // hex string and sets |slot_id| to the id of the containing slot, or returns |
| // an empty string and doesn't modify |slot_id| if the PKCS#11 id could not be |
| // determined. |
| static std::string GetPkcs11IdAndSlotForCert(const net::X509Certificate& cert, |
| int* slot_id); |
| |
| // Sets the NSS cert database which CertLoader should use to access system |
| // slot certificates. The CertLoader will _not_ take ownership of the database |
| // - see comment on SetUserNSSDB. CertLoader supports working with only one |
| // database or with both (system and user) databases. |
| void SetSystemNSSDB(net::NSSCertDatabase* system_slot_database); |
| |
| // Sets the NSS cert database which CertLoader should use to access user slot |
| // certificates. CertLoader understands the edge case that this database could |
| // also give access to system slot certificates (e.g. for affiliated users). |
| // The CertLoader will _not_ take the ownership of the database, but it |
| // expects it to stay alive at least until the shutdown starts on the main |
| // thread. This assumes that SetUserNSSDB and other methods directly using |
| // |database_| are not called during shutdown. CertLoader supports working |
| // with only one database or with both (system and user) databases. |
| void SetUserNSSDB(net::NSSCertDatabase* user_database); |
| |
| void AddObserver(CertLoader::Observer* observer); |
| void RemoveObserver(CertLoader::Observer* observer); |
| |
| // Returns true if |cert| is hardware backed. See also |
| // ForceHardwareBackedForTesting(). |
| static bool IsCertificateHardwareBacked(const net::X509Certificate* cert); |
| |
| // Returns true when the certificate list has been requested but not loaded. |
| // When two databases are in use (SetSystemNSSDB and SetUserNSSDB have both |
| // been called), this returns true when at least one of them is currently |
| // loading certificates. |
| // Note that this method poses an exception in the CertLoader interface: |
| // While most of CertLoader's interface treats the initial load of a second |
| // database the same way as an update in the first database, this method does |
| // not. The reason is that it's targeted at displaying a message in the GUI, |
| // so the user knows that (more) certificates will be available soon. |
| bool initial_load_of_any_database_running() const; |
| |
| // Returns true if any certificates have been loaded. If CertLoader uses a |
| // system and a user NSS database, this returns true after the certificates |
| // from the first (usually system) database have been loaded. |
| bool initial_load_finished() const; |
| |
| // Returns all certificates. This will be empty until certificates_loaded() is |
| // true. |
| const net::CertificateList& all_certs() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return all_certs_; |
| } |
| |
| // Returns certificates from the system token. This will be empty until |
| // certificates_loaded() is true. |
| const net::CertificateList& system_certs() const { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| return system_certs_; |
| } |
| |
| // Called in tests if |IsCertificateHardwareBacked()| should always return |
| // true. |
| static void ForceHardwareBackedForTesting(); |
| |
| private: |
| class CertCache; |
| |
| CertLoader(); |
| ~CertLoader(); |
| |
| // Called by |system_cert_cache_| or |user_cert_cache| when these had an |
| // update. |
| void CacheUpdated(); |
| |
| // Called if a certificate load task is finished. |
| void UpdateCertificates(net::CertificateList all_certs, |
| net::CertificateList system_certs); |
| |
| void NotifyCertificatesLoaded(bool initial_load); |
| |
| // True if the initial load of CertLoader is still pending. This is used to |
| // set the |initial_load| parameter when calling Observers. |
| bool pending_initial_load_; |
| |
| base::ObserverList<Observer> observers_; |
| |
| // Cache for certificates from the system-token NSSCertDatabase. |
| std::unique_ptr<CertCache> system_cert_cache_; |
| // Cache for certificates from the user-specific NSSCertDatabase. |
| std::unique_ptr<CertCache> user_cert_cache_; |
| |
| // Cached certificates loaded from the database(s). |
| net::CertificateList all_certs_; |
| |
| // Cached certificates from system token. |
| net::CertificateList system_certs_; |
| |
| base::ThreadChecker thread_checker_; |
| |
| base::WeakPtrFactory<CertLoader> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(CertLoader); |
| }; |
| |
| } // namespace chromeos |
| |
| #endif // CHROMEOS_CERT_LOADER_H_ |