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

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: Fix tests 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.h » ('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(
76 const scoped_refptr<base::SequencedTaskRunner>& crypto_task_runner) {
77 crypto_task_runner_ = crypto_task_runner;
61 net::CertDatabase::GetInstance()->AddObserver(this); 78 net::CertDatabase::GetInstance()->AddObserver(this);
62 if (LoginState::IsInitialized()) 79 if (LoginState::IsInitialized())
63 LoginState::Get()->AddObserver(this); 80 LoginState::Get()->AddObserver(this);
64 RequestCertificates(); 81 RequestCertificates();
65 } 82 }
66 83
67 CertLoader::~CertLoader() { 84 CertLoader::~CertLoader() {
68 net::CertDatabase::GetInstance()->RemoveObserver(this); 85 net::CertDatabase::GetInstance()->RemoveObserver(this);
69 if (LoginState::IsInitialized()) 86 if (LoginState::IsInitialized())
70 LoginState::Get()->RemoveObserver(this); 87 LoginState::Get()->RemoveObserver(this);
(...skipping 18 matching lines...) Expand all
89 void CertLoader::RequestCertificates() { 106 void CertLoader::RequestCertificates() {
90 CHECK(thread_checker_.CalledOnValidThread()); 107 CHECK(thread_checker_.CalledOnValidThread());
91 const bool logged_in = LoginState::IsInitialized() ? 108 const bool logged_in = LoginState::IsInitialized() ?
92 LoginState::Get()->IsUserLoggedIn() : false; 109 LoginState::Get()->IsUserLoggedIn() : false;
93 VLOG(1) << "RequestCertificates: " << logged_in; 110 VLOG(1) << "RequestCertificates: " << logged_in;
94 if (certificates_requested_ || !logged_in) 111 if (certificates_requested_ || !logged_in)
95 return; 112 return;
96 113
97 certificates_requested_ = true; 114 certificates_requested_ = true;
98 115
99 // Ensure we've opened the user's key/certificate database. 116 // This is the entry point to the TPM token initialization process,
100 crypto::OpenPersistentNSSDB(); 117 // which we should do at most once.
101 if (base::chromeos::IsRunningOnChromeOS()) 118 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(); 119 InitializeTokenAndLoadCertificates();
108 } 120 }
109 121
110 void CertLoader::InitializeTokenAndLoadCertificates() { 122 void CertLoader::InitializeTokenAndLoadCertificates() {
111 CHECK(thread_checker_.CalledOnValidThread()); 123 CHECK(thread_checker_.CalledOnValidThread());
112 VLOG(1) << "InitializeTokenAndLoadCertificates"; 124 VLOG(1) << "InitializeTokenAndLoadCertificates: " << tpm_token_state_;
113 125
114 switch (tpm_token_state_) { 126 switch (tpm_token_state_) {
115 case TPM_STATE_UNKNOWN: { 127 case TPM_STATE_UNKNOWN: {
128 if (crypto_task_runner_->PostTaskAndReply(
129 FROM_HERE,
130 base::Bind(&CallOpenPersistentNSSDB),
131 base::Bind(&CertLoader::OnPersistentNSSDBOpened,
132 initialize_token_factory_.GetWeakPtr()))) {
133 return;
134 }
135 // The task was not posted, e.g. because a test has not started the
136 // thread supplied to Init(). Call the crypto methonds on the current
Ryan Sleevi 2013/06/07 23:12:43 typo: s/methonds/methods
137 // thread which should be safe, just not asynchronous.
Ryan Sleevi 2013/06/07 23:12:43 I don't think this should be necessary. Your synch
stevenjb 2013/06/08 02:06:51 I did some investigating and discovered that we we
138 CallOpenPersistentNSSDB();
139 tpm_token_state_ = TPM_DB_OPENED;
140 // FALL_THROUGH_INTENDED
141 }
142 case TPM_DB_OPENED: {
116 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled( 143 DBusThreadManager::Get()->GetCryptohomeClient()->TpmIsEnabled(
117 base::Bind(&CertLoader::OnTpmIsEnabled, 144 base::Bind(&CertLoader::OnTpmIsEnabled,
118 initialize_token_factory_.GetWeakPtr())); 145 initialize_token_factory_.GetWeakPtr()));
119 return; 146 return;
120 } 147 }
121 case TPM_DISABLED: { 148 case TPM_DISABLED: {
122 // TPM is disabled, so proceed with empty tpm token name. 149 // TPM is disabled, so proceed with empty tpm token name.
123 StartLoadCertificates(); 150 StartLoadCertificates();
124 return; 151 return;
125 } 152 }
126 case TPM_ENABLED: { 153 case TPM_ENABLED: {
127 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady( 154 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11IsTpmTokenReady(
128 base::Bind(&CertLoader::OnPkcs11IsTpmTokenReady, 155 base::Bind(&CertLoader::OnPkcs11IsTpmTokenReady,
129 initialize_token_factory_.GetWeakPtr())); 156 initialize_token_factory_.GetWeakPtr()));
130 return; 157 return;
131 } 158 }
132 case TPM_TOKEN_READY: { 159 case TPM_TOKEN_READY: {
133 // Retrieve token_name_ and user_pin_ here since they will never change 160 // Retrieve token_name_ and user_pin_ here since they will never change
134 // and CryptohomeClient calls are not thread safe. 161 // and CryptohomeClient calls are not thread safe.
135 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo( 162 DBusThreadManager::Get()->GetCryptohomeClient()->Pkcs11GetTpmTokenInfo(
136 base::Bind(&CertLoader::OnPkcs11GetTpmTokenInfo, 163 base::Bind(&CertLoader::OnPkcs11GetTpmTokenInfo,
137 initialize_token_factory_.GetWeakPtr())); 164 initialize_token_factory_.GetWeakPtr()));
138 return; 165 return;
139 } 166 }
140 case TPM_TOKEN_INFO_RECEIVED: { 167 case TPM_TOKEN_INFO_RECEIVED: {
141 InitializeNSSForTPMToken(); 168 if (base::chromeos::IsRunningOnChromeOS()) {
142 return; 169 if (base::PostTaskAndReplyWithResult(
170 crypto_task_runner_.get(),
171 FROM_HERE,
172 base::Bind(&crypto::InitializeTPMToken,
173 tpm_token_name_, tpm_user_pin_),
174 base::Bind(&CertLoader::OnTPMTokenInitialized,
175 initialize_token_factory_.GetWeakPtr()))) {
176 return;
177 }
178 // No task posted, call InitializeTPMToken directly.
179 crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_);
Ryan Sleevi 2013/06/07 23:12:43 Same here
180 }
181 tpm_token_state_ = TPM_TOKEN_INITIALIZED;
182 // FALL_THROUGH_INTENDED
143 } 183 }
144 case TPM_TOKEN_NSS_INITIALIZED: { 184 case TPM_TOKEN_INITIALIZED: {
145 StartLoadCertificates(); 185 StartLoadCertificates();
146 return; 186 return;
147 } 187 }
148 } 188 }
149 } 189 }
150 190
151 void CertLoader::RetryTokenInitializationLater() { 191 void CertLoader::RetryTokenInitializationLater() {
192 CHECK(thread_checker_.CalledOnValidThread());
152 LOG(WARNING) << "Re-Requesting Certificates later."; 193 LOG(WARNING) << "Re-Requesting Certificates later.";
153 base::MessageLoop::current()->PostDelayedTask( 194 base::MessageLoop::current()->PostDelayedTask(
154 FROM_HERE, 195 FROM_HERE,
155 base::Bind(&CertLoader::InitializeTokenAndLoadCertificates, 196 base::Bind(&CertLoader::InitializeTokenAndLoadCertificates,
156 initialize_token_factory_.GetWeakPtr()), 197 initialize_token_factory_.GetWeakPtr()),
157 tpm_request_delay_); 198 tpm_request_delay_);
158 tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_); 199 tpm_request_delay_ = GetNextRequestDelayMs(tpm_request_delay_);
159 } 200 }
160 201
202 void CertLoader::OnPersistentNSSDBOpened() {
203 VLOG(1) << "PersistentNSSDBOpened";
204 tpm_token_state_ = TPM_DB_OPENED;
205 InitializeTokenAndLoadCertificates();
206 }
207
161 // For background see this discussion on dev-tech-crypto.lists.mozilla.org: 208 // For background see this discussion on dev-tech-crypto.lists.mozilla.org:
162 // http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX 209 // http://web.archiveorange.com/archive/v/6JJW7E40sypfZGtbkzxX
163 // 210 //
164 // NOTE: This function relies on the convention that the same PKCS#11 ID 211 // 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 212 // is shared between a certificate and its associated private and public
166 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(), 213 // keys. I tried to implement this with PK11_GetLowLevelKeyIDForCert(),
167 // but that always returns NULL on Chrome OS for me. 214 // but that always returns NULL on Chrome OS for me.
168 std::string CertLoader::GetPkcs11IdForCert( 215 std::string CertLoader::GetPkcs11IdForCert(
169 const net::X509Certificate& cert) const { 216 const net::X509Certificate& cert) const {
170 if (!IsHardwareBacked()) 217 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 274 // 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. 275 // crbug.com/201101. For now, use a hard coded, well known slot instead.
229 const char kHardcodedTpmSlot[] = "0"; 276 const char kHardcodedTpmSlot[] = "0";
230 tpm_token_slot_ = kHardcodedTpmSlot; 277 tpm_token_slot_ = kHardcodedTpmSlot;
231 tpm_user_pin_ = user_pin; 278 tpm_user_pin_ = user_pin;
232 tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED; 279 tpm_token_state_ = TPM_TOKEN_INFO_RECEIVED;
233 280
234 InitializeTokenAndLoadCertificates(); 281 InitializeTokenAndLoadCertificates();
235 } 282 }
236 283
237 void CertLoader::InitializeNSSForTPMToken() { 284 void CertLoader::OnTPMTokenInitialized(bool success) {
238 VLOG(1) << "InitializeNSSForTPMToken"; 285 VLOG(1) << "OnTPMTokenInitialized: " << success;
239 286 if (!success) {
240 if (base::chromeos::IsRunningOnChromeOS() &&
241 !crypto::InitializeTPMToken(tpm_token_name_, tpm_user_pin_)) {
242 RetryTokenInitializationLater(); 287 RetryTokenInitializationLater();
243 return; 288 return;
244 } 289 }
245 290 tpm_token_state_ = TPM_TOKEN_INITIALIZED;
246 tpm_token_state_ = TPM_TOKEN_NSS_INITIALIZED;
247 InitializeTokenAndLoadCertificates(); 291 InitializeTokenAndLoadCertificates();
248 } 292 }
249 293
250 void CertLoader::StartLoadCertificates() { 294 void CertLoader::StartLoadCertificates() {
251 VLOG(1) << "StartLoadCertificates"; 295 CHECK(thread_checker_.CalledOnValidThread());
296 VLOG(1) << "StartLoadCertificates: " << certificates_update_running_;
252 297
253 if (certificates_update_running_) { 298 if (certificates_update_running_) {
254 certificates_update_required_ = true; 299 certificates_update_required_ = true;
255 return; 300 return;
256 } 301 }
257 302
258 net::CertificateList* cert_list = new net::CertificateList; 303 net::CertificateList* cert_list = new net::CertificateList;
259 certificates_update_running_ = true; 304 certificates_update_running_ = true;
260 certificates_update_required_ = false; 305 certificates_update_required_ = false;
261 base::WorkerPool::GetTaskRunner(true /* task_is_slow */)-> 306 base::WorkerPool::GetTaskRunner(true /* task_is_slow */)->
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 StartLoadCertificates(); 341 StartLoadCertificates();
297 } 342 }
298 343
299 void CertLoader::OnCertRemoved(const net::X509Certificate* cert) { 344 void CertLoader::OnCertRemoved(const net::X509Certificate* cert) {
300 VLOG(1) << "OnCertRemoved"; 345 VLOG(1) << "OnCertRemoved";
301 StartLoadCertificates(); 346 StartLoadCertificates();
302 } 347 }
303 348
304 void CertLoader::LoggedInStateChanged(LoginState::LoggedInState state) { 349 void CertLoader::LoggedInStateChanged(LoginState::LoggedInState state) {
305 VLOG(1) << "LoggedInStateChanged: " << state; 350 VLOG(1) << "LoggedInStateChanged: " << state;
306 RequestCertificates(); 351 if (state == LoginState::LOGGED_IN_ACTIVE)
352 RequestCertificates();
307 } 353 }
308 354
309 } // namespace chromeos 355 } // namespace chromeos
OLDNEW
« no previous file with comments | « chromeos/network/cert_loader.h ('k') | chromeos/network/network_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698