Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: chromeos/network/cert_loader.cc

Issue 15649018: Call crypto::InitializeTPMToken on the IO thread (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase, move declaration Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chromeos/network/cert_loader.h ('k') | chromeos/network/network_handler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chromeos/network/cert_loader.h" 5 #include "chromeos/network/cert_loader.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/chromeos/chromeos_version.h" 9 #include "base/chromeos/chromeos_version.h"
10 #include "base/message_loop/message_loop_proxy.h"
10 #include "base/observer_list.h" 11 #include "base/observer_list.h"
12 #include "base/sequenced_task_runner.h"
11 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
12 #include "base/task_runner_util.h" 14 #include "base/task_runner_util.h"
13 #include "base/threading/worker_pool.h" 15 #include "base/threading/worker_pool.h"
14 #include "chromeos/dbus/cryptohome_client.h" 16 #include "chromeos/dbus/cryptohome_client.h"
15 #include "chromeos/dbus/dbus_thread_manager.h" 17 #include "chromeos/dbus/dbus_thread_manager.h"
16 #include "crypto/encryptor.h" 18 #include "crypto/encryptor.h"
17 #include "crypto/nss_util.h" 19 #include "crypto/nss_util.h"
18 #include "crypto/sha2.h" 20 #include "crypto/sha2.h"
19 #include "crypto/symmetric_key.h" 21 #include "crypto/symmetric_key.h"
20 #include "net/cert/nss_cert_database.h" 22 #include "net/cert/nss_cert_database.h"
(...skipping 18 matching lines...) Expand all
39 if (next_delay > max_delay) 41 if (next_delay > max_delay)
40 next_delay = max_delay; 42 next_delay = max_delay;
41 return next_delay; 43 return next_delay;
42 } 44 }
43 45
44 void LoadNSSCertificates(net::CertificateList* cert_list) { 46 void LoadNSSCertificates(net::CertificateList* cert_list) {
45 if (base::chromeos::IsRunningOnChromeOS()) 47 if (base::chromeos::IsRunningOnChromeOS())
46 net::NSSCertDatabase::GetInstance()->ListCerts(cert_list); 48 net::NSSCertDatabase::GetInstance()->ListCerts(cert_list);
47 } 49 }
48 50
51 void CallOpenPersistentNSSDB() {
52 // Called from crypto_task_runner_.
53 VLOG(1) << "CallOpenPersistentNSSDB";
54
55 // Ensure we've opened the user's key/certificate database.
56 crypto::OpenPersistentNSSDB();
57 if (base::chromeos::IsRunningOnChromeOS())
58 crypto::EnableTPMTokenForNSS();
59 }
60
49 } // namespace 61 } // namespace
50 62
51 CertLoader::CertLoader() 63 CertLoader::CertLoader()
52 : certificates_requested_(false), 64 : certificates_requested_(false),
53 certificates_loaded_(false), 65 certificates_loaded_(false),
54 certificates_update_required_(false), 66 certificates_update_required_(false),
55 certificates_update_running_(false), 67 certificates_update_running_(false),
56 tpm_token_state_(TPM_STATE_UNKNOWN), 68 tpm_token_state_(TPM_STATE_UNKNOWN),
57 tpm_request_delay_( 69 tpm_request_delay_(
58 base::TimeDelta::FromMilliseconds(kInitialRequestDelayMs)), 70 base::TimeDelta::FromMilliseconds(kInitialRequestDelayMs)),
59 initialize_token_factory_(this), 71 initialize_token_factory_(this),
60 update_certificates_factory_(this) { 72 update_certificates_factory_(this) {
73 }
74
75 void CertLoader::Init() {
61 net::CertDatabase::GetInstance()->AddObserver(this); 76 net::CertDatabase::GetInstance()->AddObserver(this);
62 if (LoginState::IsInitialized()) 77 if (LoginState::IsInitialized())
63 LoginState::Get()->AddObserver(this); 78 LoginState::Get()->AddObserver(this);
64 RequestCertificates(); 79 }
80
81 void CertLoader::SetCryptoTaskRunner(
82 const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner) {
83 crypto_task_runner_ = crypto_task_runner;
84 MaybeRequestCertificates();
65 } 85 }
66 86
67 CertLoader::~CertLoader() { 87 CertLoader::~CertLoader() {
68 net::CertDatabase::GetInstance()->RemoveObserver(this); 88 net::CertDatabase::GetInstance()->RemoveObserver(this);
69 if (LoginState::IsInitialized()) 89 if (LoginState::IsInitialized())
70 LoginState::Get()->RemoveObserver(this); 90 LoginState::Get()->RemoveObserver(this);
71 } 91 }
72 92
73 void CertLoader::AddObserver(CertLoader::Observer* observer) { 93 void CertLoader::AddObserver(CertLoader::Observer* observer) {
74 observers_.AddObserver(observer); 94 observers_.AddObserver(observer);
75 } 95 }
76 96
77 void CertLoader::RemoveObserver(CertLoader::Observer* observer) { 97 void CertLoader::RemoveObserver(CertLoader::Observer* observer) {
78 observers_.RemoveObserver(observer); 98 observers_.RemoveObserver(observer);
79 } 99 }
80 100
81 bool CertLoader::CertificatesLoading() const { 101 bool CertLoader::CertificatesLoading() const {
82 return certificates_requested_ && !certificates_loaded_; 102 return certificates_requested_ && !certificates_loaded_;
83 } 103 }
84 104
85 bool CertLoader::IsHardwareBacked() const { 105 bool CertLoader::IsHardwareBacked() const {
86 return !tpm_token_name_.empty(); 106 return !tpm_token_name_.empty();
87 } 107 }
88 108
89 void CertLoader::RequestCertificates() { 109 void CertLoader::MaybeRequestCertificates() {
90 CHECK(thread_checker_.CalledOnValidThread()); 110 CHECK(thread_checker_.CalledOnValidThread());
111 if (certificates_requested_ || !crypto_task_runner_.get())
112 return;
113
91 const bool logged_in = LoginState::IsInitialized() ? 114 const bool logged_in = LoginState::IsInitialized() ?
92 LoginState::Get()->IsUserLoggedIn() : false; 115 LoginState::Get()->IsUserLoggedIn() : false;
93 VLOG(1) << "RequestCertificates: " << logged_in; 116 VLOG(1) << "RequestCertificates: " << logged_in;
94 if (certificates_requested_ || !logged_in) 117 if (!logged_in)
95 return; 118 return;
96 119
97 certificates_requested_ = true; 120 certificates_requested_ = true;
98 121
99 // Ensure we've opened the user's key/certificate database. 122 // This is the entry point to the TPM token initialization process,
100 crypto::OpenPersistentNSSDB(); 123 // which we should do at most once.
101 if (base::chromeos::IsRunningOnChromeOS()) 124 DCHECK_EQ(tpm_token_state_, TPM_STATE_UNKNOWN);
102 crypto::EnableTPMTokenForNSS();
103
104 // This is the entry point to the TPM token initialization process, which we
105 // should do at most once.
106 DCHECK(!initialize_token_factory_.HasWeakPtrs());
107 InitializeTokenAndLoadCertificates(); 125 InitializeTokenAndLoadCertificates();
108 } 126 }
109 127
110 void CertLoader::InitializeTokenAndLoadCertificates() { 128 void CertLoader::InitializeTokenAndLoadCertificates() {
111 CHECK(thread_checker_.CalledOnValidThread()); 129 CHECK(thread_checker_.CalledOnValidThread());
112 VLOG(1) << "InitializeTokenAndLoadCertificates"; 130 VLOG(1) << "InitializeTokenAndLoadCertificates: " << tpm_token_state_;
113 131
114 switch (tpm_token_state_) { 132 switch (tpm_token_state_) {
115 case TPM_STATE_UNKNOWN: { 133 case TPM_STATE_UNKNOWN: {
134 crypto_task_runner_->PostTaskAndReply(
135 FROM_HERE,
136 base::Bind(&CallOpenPersistentNSSDB),
137 base::Bind(&CertLoader::OnPersistentNSSDBOpened,
138 initialize_token_factory_.GetWeakPtr()));
139 return;
140 }
141 case TPM_DB_OPENED: {
116 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( 142 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(
117 base::Bind(&CertLoader::OnTpmIsEnabled, 143 base::Bind(&CertLoader::OnTpmIsEnabled,
118 initialize_token_factory_.GetWeakPtr())); 144 initialize_token_factory_.GetWeakPtr()));
119 return; 145 return;
120 } 146 }
121 case TPM_DISABLED: { 147 case TPM_DISABLED: {
122 // TPM is disabled, so proceed with empty tpm token name. 148 // TPM is disabled, so proceed with empty tpm token name.
123 StartLoadCertificates(); 149 StartLoadCertificates();
124 return; 150 return;
125 } 151 }
126 case TPM_ENABLED: { 152 case TPM_ENABLED: {
127 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady( 153 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady(
128 base::Bind(&CertLoader::OnPkcs11IsTpmTokenReady, 154 base::Bind(&CertLoader::OnPkcs11IsTpmTokenReady,
129 initialize_token_factory_.GetWeakPtr())); 155 initialize_token_factory_.GetWeakPtr()));
130 return; 156 return;
131 } 157 }
132 case TPM_TOKEN_READY: { 158 case TPM_TOKEN_READY: {
133 // Retrieve token_name_ and user_pin_ here since they will never change 159 // Retrieve token_name_ and user_pin_ here since they will never change
134 // and CryptohomeClient calls are not thread safe. 160 // and CryptohomeClient calls are not thread safe.
135 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo( 161 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo(
136 base::Bind(&CertLoader::OnPkcs11GetTpmTokenInfo, 162 base::Bind(&CertLoader::OnPkcs11GetTpmTokenInfo,
137 initialize_token_factory_.GetWeakPtr())); 163 initialize_token_factory_.GetWeakPtr()));
138 return; 164 return;
139 } 165 }
140 case TPM_TOKEN_INFO_RECEIVED: { 166 case TPM_TOKEN_INFO_RECEIVED: {
141 InitializeNSSForTPMToken(); 167 if (base::chromeos::IsRunningOnChromeOS()) {
142 return; 168 base::PostTaskAndReplyWithResult(
169 crypto_task_runner_.get(),
170 FROM_HERE,
171 base::Bind(&crypto::InitializeTPMToken,
172 tpm_token_name_, tpm_user_pin_),
173 base::Bind(&CertLoader::OnTPMTokenInitialized,
174 initialize_token_factory_.GetWeakPtr()));
175 return;
176 }
177 tpm_token_state_ = TPM_TOKEN_INITIALIZED;
178 // FALL_THROUGH_INTENDED
143 } 179 }
144 case TPM_TOKEN_NSS_INITIALIZED: { 180 case TPM_TOKEN_INITIALIZED: {
145 StartLoadCertificates(); 181 StartLoadCertificates();
146 return; 182 return;
147 } 183 }
148 } 184 }
149 } 185 }
150 186
151 void CertLoader::RetryTokenInitializationLater() { 187 void CertLoader::RetryTokenInitializationLater() {
188 CHECK(thread_checker_.CalledOnValidThread());
152 LOG(WARNING) << "Re-Requesting Certificates later."; 189 LOG(WARNING) << "Re-Requesting Certificates later.";
153 base::MessageLoop::current()->PostDelayedTask( 190 base::MessageLoop::current()->PostDelayedTask(
154 FROM_HERE, 191 FROM_HERE,
155 base::Bind(&CertLoader::InitializeTokenAndLoadCertificates, 192 base::Bind(&CertLoader::InitializeTokenAndLoadCertificates,
156 initialize_token_factory_.GetWeakPtr()), 193 initialize_token_factory_.GetWeakPtr()),
157 tpm_request_delay_); 194 tpm_request_delay_);
158 tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_); 195 tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
159 } 196 }
160 197
198 void CertLoader::OnPersistentNSSDBOpened() {
199 VLOG(1) << "PersistentNSSDBOpened";
200 tpm_token_state_ = TPM_DB_OPENED;
201 InitializeTokenAndLoadCertificates();
202 }
203
161 // For background see this discussion on dev-tech-crypto.lists.mozilla.org: 204 // For background see this discussion on dev-tech-crypto.lists.mozilla.org:
162 // http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX 205 // http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX
163 // 206 //
164 // NOTE: This function relies on the convention that the same PKCS#11 ID 207 // NOTE: This function relies on the convention that the same PKCS#11 ID
165 // is shared between a certificate and its associated private and public 208 // is shared between a certificate and its associated private and public
166 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(), 209 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
167 // but that always returns NULL on Chrome OS for me. 210 // but that always returns NULL on Chrome OS for me.
168 std::string CertLoader::GetPkcs11IdForCert( 211 std::string CertLoader::GetPkcs11IdForCert(
169 const net::X509Certificate& cert) const { 212 const net::X509Certificate& cert) const {
170 if (!IsHardwareBacked()) 213 if (!IsHardwareBacked())
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 // TODO(stevenjb): The network code expects a slot ID, not a label. See 270 // TODO(stevenjb): The network code expects a slot ID, not a label. See
228 // crbug.com/201101. For now, use a hard coded, well known slot instead. 271 // crbug.com/201101. For now, use a hard coded, well known slot instead.
229 const char kHardcodedTpmSlot[] = "0"; 272 const char kHardcodedTpmSlot[] = "0";
230 tpm_token_slot_ = kHardcodedTpmSlot; 273 tpm_token_slot_ = kHardcodedTpmSlot;
231 tpm_user_pin_ = user_pin; 274 tpm_user_pin_ = user_pin;
232 tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED; 275 tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
233 276
234 InitializeTokenAndLoadCertificates(); 277 InitializeTokenAndLoadCertificates();
235 } 278 }
236 279
237 void CertLoader::InitializeNSSForTPMToken() { 280 void CertLoader::OnTPMTokenInitialized(bool success) {
238 VLOG(1) << "InitializeNSSForTPMToken"; 281 VLOG(1) << "OnTPMTokenInitialized: " << success;
239 282 if (!success) {
240 if (base::chromeos::IsRunningOnChromeOS() &&
241 !crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_)) {
242 RetryTokenInitializationLater(); 283 RetryTokenInitializationLater();
243 return; 284 return;
244 } 285 }
245 286 tpm_token_state_ = TPM_TOKEN_INITIALIZED;
246 tpm_token_state_ = TPM_TOKEN_NSS_INITIALIZED;
247 InitializeTokenAndLoadCertificates(); 287 InitializeTokenAndLoadCertificates();
248 } 288 }
249 289
250 void CertLoader::StartLoadCertificates() { 290 void CertLoader::StartLoadCertificates() {
251 VLOG(1) << "StartLoadCertificates"; 291 CHECK(thread_checker_.CalledOnValidThread());
292 VLOG(1) << "StartLoadCertificates: " << certificates_update_running_;
252 293
253 if (certificates_update_running_) { 294 if (certificates_update_running_) {
254 certificates_update_required_ = true; 295 certificates_update_required_ = true;
255 return; 296 return;
256 } 297 }
257 298
258 net::CertificateList* cert_list = new net::CertificateList; 299 net::CertificateList* cert_list = new net::CertificateList;
259 certificates_update_running_ = true; 300 certificates_update_running_ = true;
260 certificates_update_required_ = false; 301 certificates_update_required_ = false;
261 base::WorkerPool::GetTaskRunner(true /* task_is_slow */)-> 302 base::WorkerPool::GetTaskRunner(true /* task_is_slow */)->
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 StartLoadCertificates(); 337 StartLoadCertificates();
297 } 338 }
298 339
299 void CertLoader::OnCertRemoved(const net::X509Certificate* cert) { 340 void CertLoader::OnCertRemoved(const net::X509Certificate* cert) {
300 VLOG(1) << "OnCertRemoved"; 341 VLOG(1) << "OnCertRemoved";
301 StartLoadCertificates(); 342 StartLoadCertificates();
302 } 343 }
303 344
304 void CertLoader::LoggedInStateChanged(LoginState::LoggedInState state) { 345 void CertLoader::LoggedInStateChanged(LoginState::LoggedInState state) {
305 VLOG(1) << "LoggedInStateChanged: " << state; 346 VLOG(1) << "LoggedInStateChanged: " << state;
306 RequestCertificates(); 347 MaybeRequestCertificates();
307 } 348 }
308 349
309 } // namespace chromeos 350 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/cert_loader.h ('k') | chromeos/network/network_handler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698