summaryrefslogtreecommitdiff
path: root/chromeos/tpm_token_loader.h
blob: 9ac7a61e61df4adfc9b5636c31771a2c35fcd190 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
// Copyright 2014 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_TPM_TOKEN_LOADER_H_
#define CHROMEOS_TPM_TOKEN_LOADER_H_

#include <string>

#include "base/basictypes.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 "base/time/time.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/login/login_state.h"

namespace base {
class SequencedTaskRunner;
}

namespace chromeos {

// This class is responsible for loading the TPM token when the user logs
// in. It is expected to be constructed on the UI thread and public methods
// should all be called from the UI thread. When the TPM token is loaded,
// or if the TPM should stay disabled for the session, the observers are
// notified using |OnTPMTokenReady|.
class CHROMEOS_EXPORT TPMTokenLoader : public LoginState::Observer {
 public:
  class Observer {
   public:
    // Called when the TPM token initialization is done or the case where TPM
    // should stay disabled is detected (e.g. on guest login).
    virtual void OnTPMTokenReady() = 0;

   protected:
    virtual ~Observer() {}
  };

  // Sets the global instance. Must be called before any calls to Get().
  // The global instance will immediately start observing |LoginState|.
  static void Initialize();

  // Sets the global. stubbed out, instance. To be used in tests.
  static void InitializeForTest();

  // Destroys the global instance.
  static void Shutdown();

  // Gets the global instance. Initialize() must be called before this.
  static TPMTokenLoader* Get();

  // Returns true if the global instance has been initialized.
  static bool IsInitialized();

  // |crypto_task_runner| is the task runner that any synchronous crypto calls
  // should be made from, e.g. in Chrome this is the IO thread. Must be called
  // after the thread is started. When called, this will attempt to start TPM
  // token loading.
  void SetCryptoTaskRunner(
      const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner);

  void AddObserver(TPMTokenLoader::Observer* observer);
  void RemoveObserver(TPMTokenLoader::Observer* observer);

  // Checks if the TPM token in ready to be used.
  bool IsTPMTokenReady() const;

  std::string tpm_user_pin() const { return tpm_user_pin_; }

 private:
  explicit TPMTokenLoader(bool for_test);
  virtual ~TPMTokenLoader();

  // Starts tpm token initialization if the user is logged in and the crypto
  // task runner is set.
  void MaybeStartTokenInitialization();

  // This is the cyclic chain of callbacks to initialize the TPM token.
  void ContinueTokenInitialization();
  void OnPersistentNSSDBOpened();
  void OnTpmIsEnabled(DBusMethodCallStatus call_status,
                      bool tpm_is_enabled);
  void OnPkcs11IsTpmTokenReady(DBusMethodCallStatus call_status,
                               bool is_tpm_token_ready);
  void OnPkcs11GetTpmTokenInfo(DBusMethodCallStatus call_status,
                               const std::string& token_name,
                               const std::string& user_pin,
                               int token_slot_id);
  void OnTPMTokenInitialized(bool success);

  // If token initialization step fails (e.g. if tpm token is not yet ready)
  // schedules the initialization step retry attempt after a timeout.
  void RetryTokenInitializationLater();

  // Notifies observers that the TPM token is ready.
  void NotifyTPMTokenReady();

  // LoginState::Observer
  virtual void LoggedInStateChanged() OVERRIDE;

  bool initialized_for_test_;

  ObserverList<Observer> observers_;

  // The states are traversed in this order but some might get omitted or never
  // be left.
  enum TPMTokenState {
    TPM_STATE_UNKNOWN,
    TPM_INITIALIZATION_STARTED,
    TPM_DB_OPENED,
    TPM_DISABLED,
    TPM_ENABLED,
    TPM_TOKEN_READY,
    TPM_TOKEN_INFO_RECEIVED,
    TPM_TOKEN_INITIALIZED,
  };
  TPMTokenState tpm_token_state_;

  // The current request delay before the next attempt to initialize the
  // TPM. Will be adapted after each attempt.
  base::TimeDelta tpm_request_delay_;

  // Cached TPM token info.
  std::string tpm_token_name_;
  int tpm_token_slot_id_;
  std::string tpm_user_pin_;

  base::ThreadChecker thread_checker_;

  // TaskRunner for crypto calls.
  scoped_refptr<base::SequencedTaskRunner> crypto_task_runner_;

  base::WeakPtrFactory<TPMTokenLoader> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(TPMTokenLoader);
};

}  // namespace chromeos

#endif  // CHROMEOS_TPM_TOKEN_LOADER_H_