OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.
h" | 5 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.
h" |
6 | 6 |
7 #include <cryptohi.h> | 7 #include <cryptohi.h> |
8 | 8 |
9 #include "base/base64.h" | 9 #include "base/base64.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include "crypto/nss_util_internal.h" | 25 #include "crypto/nss_util_internal.h" |
26 #include "crypto/rsa_private_key.h" | 26 #include "crypto/rsa_private_key.h" |
27 #include "crypto/scoped_nss_types.h" | 27 #include "crypto/scoped_nss_types.h" |
28 | 28 |
29 namespace { | 29 namespace { |
30 | 30 |
31 // The modulus length for RSA keys used by easy sign-in. | 31 // The modulus length for RSA keys used by easy sign-in. |
32 const int kKeyModulusLength = 2048; | 32 const int kKeyModulusLength = 2048; |
33 | 33 |
34 // Relays |GetSystemSlotOnIOThread| callback to |response_task_runner|. | 34 // Relays |GetSystemSlotOnIOThread| callback to |response_task_runner|. |
35 void RunCallbackOnThreadRunner( | 35 void RunCallbackOnTaskRunner( |
36 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, | 36 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, |
37 const base::Callback<void(crypto::ScopedPK11Slot)>& callback, | 37 const base::Callback<void(crypto::ScopedPK11Slot)>& callback, |
38 crypto::ScopedPK11Slot slot) { | 38 crypto::ScopedPK11Slot slot) { |
39 response_task_runner->PostTask(FROM_HERE, | 39 response_task_runner->PostTask(FROM_HERE, |
40 base::Bind(callback, base::Passed(&slot))); | 40 base::Bind(callback, base::Passed(&slot))); |
41 } | 41 } |
42 | 42 |
43 // Gets TPM system slot. Must be called on IO thread. | 43 // Gets TPM system slot. Must be called on IO thread. |
44 // The callback wil be relayed to |response_task_runner|. | 44 // The callback wil be relayed to |response_task_runner|. |
45 void GetSystemSlotOnIOThread( | 45 void GetSystemSlotOnIOThread( |
46 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, | 46 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, |
47 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) { | 47 const base::Callback<void(crypto::ScopedPK11Slot)>& callback) { |
48 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread = | 48 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread = |
49 base::Bind(&RunCallbackOnThreadRunner, response_task_runner, callback); | 49 base::Bind(&RunCallbackOnTaskRunner, response_task_runner, callback); |
50 | 50 |
51 crypto::ScopedPK11Slot system_slot = | 51 crypto::ScopedPK11Slot system_slot = |
52 crypto::GetSystemNSSKeySlot(callback_on_origin_thread); | 52 crypto::GetSystemNSSKeySlot(callback_on_origin_thread); |
53 if (system_slot) | 53 if (system_slot) |
54 callback_on_origin_thread.Run(system_slot.Pass()); | 54 callback_on_origin_thread.Run(system_slot.Pass()); |
55 } | 55 } |
56 | 56 |
| 57 // Relays |EnsureUserTpmInitializedOnIOThread| callback to |
| 58 // |response_task_runner|, ignoring |slot|. |
| 59 void RunCallbackWithoutSlotOnTaskRunner( |
| 60 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, |
| 61 const base::Closure& callback, |
| 62 crypto::ScopedPK11Slot slot) { |
| 63 response_task_runner->PostTask(FROM_HERE, callback); |
| 64 } |
| 65 |
| 66 void EnsureUserTPMInitializedOnIOThread( |
| 67 const std::string& username_hash, |
| 68 const scoped_refptr<base::SingleThreadTaskRunner>& response_task_runner, |
| 69 const base::Closure& callback) { |
| 70 base::Callback<void(crypto::ScopedPK11Slot)> callback_on_origin_thread = |
| 71 base::Bind(&RunCallbackWithoutSlotOnTaskRunner, response_task_runner, |
| 72 callback); |
| 73 |
| 74 crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser( |
| 75 username_hash, callback_on_origin_thread); |
| 76 if (private_slot) |
| 77 callback_on_origin_thread.Run(private_slot.Pass()); |
| 78 } |
| 79 |
57 // Checks if a private RSA key associated with |public_key| can be found in | 80 // Checks if a private RSA key associated with |public_key| can be found in |
58 // |slot|. | 81 // |slot|. |
59 // Must be called on a worker thread. | 82 // Must be called on a worker thread. |
60 scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( | 83 scoped_ptr<crypto::RSAPrivateKey> GetPrivateKeyOnWorkerThread( |
61 PK11SlotInfo* slot, | 84 PK11SlotInfo* slot, |
62 const std::string& public_key) { | 85 const std::string& public_key) { |
63 const uint8* public_key_uint8 = | 86 const uint8* public_key_uint8 = |
64 reinterpret_cast<const uint8*>(public_key.data()); | 87 reinterpret_cast<const uint8*>(public_key.data()); |
65 std::vector<uint8> public_key_vector( | 88 std::vector<uint8> public_key_vector( |
66 public_key_uint8, public_key_uint8 + public_key.size()); | 89 public_key_uint8, public_key_uint8 + public_key.size()); |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 if (!g_browser_process) | 184 if (!g_browser_process) |
162 return; | 185 return; |
163 PrefService* local_state = g_browser_process->local_state(); | 186 PrefService* local_state = g_browser_process->local_state(); |
164 if (!local_state) | 187 if (!local_state) |
165 return; | 188 return; |
166 | 189 |
167 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockLocalStateTpmKeys); | 190 DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockLocalStateTpmKeys); |
168 update->RemoveWithoutPathExpansion(user_id, NULL); | 191 update->RemoveWithoutPathExpansion(user_id, NULL); |
169 } | 192 } |
170 | 193 |
171 EasyUnlockTpmKeyManager::EasyUnlockTpmKeyManager(const std::string& user_id, | 194 EasyUnlockTpmKeyManager::EasyUnlockTpmKeyManager( |
172 PrefService* local_state) | 195 const std::string& user_id, |
| 196 const std::string& username_hash, |
| 197 PrefService* local_state) |
173 : user_id_(user_id), | 198 : user_id_(user_id), |
| 199 username_hash_(username_hash), |
174 local_state_(local_state), | 200 local_state_(local_state), |
175 create_tpm_key_state_(CREATE_TPM_KEY_NOT_STARTED), | 201 create_tpm_key_state_(CREATE_TPM_KEY_NOT_STARTED), |
176 get_tpm_slot_weak_ptr_factory_(this), | 202 get_tpm_slot_weak_ptr_factory_(this), |
177 weak_ptr_factory_(this) { | 203 weak_ptr_factory_(this) { |
178 } | 204 } |
179 | 205 |
180 EasyUnlockTpmKeyManager::~EasyUnlockTpmKeyManager() { | 206 EasyUnlockTpmKeyManager::~EasyUnlockTpmKeyManager() { |
181 } | 207 } |
182 | 208 |
183 bool EasyUnlockTpmKeyManager::PrepareTpmKey( | 209 bool EasyUnlockTpmKeyManager::PrepareTpmKey( |
184 bool check_private_key, | 210 bool check_private_key, |
185 const base::Closure& callback) { | 211 const base::Closure& callback) { |
186 CHECK(!user_id_.empty()); | 212 CHECK(!user_id_.empty()); |
| 213 CHECK(!username_hash_.empty()); |
187 | 214 |
188 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE) | 215 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE) |
189 return true; | 216 return true; |
190 | 217 |
191 std::string key = GetPublicTpmKey(user_id_); | 218 std::string key = GetPublicTpmKey(user_id_); |
192 if (!check_private_key && !key.empty() && | 219 if (!check_private_key && !key.empty() && |
193 create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { | 220 create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { |
194 return true; | 221 return true; |
195 } | 222 } |
196 | 223 |
197 prepare_tpm_key_callbacks_.push_back(callback); | 224 prepare_tpm_key_callbacks_.push_back(callback); |
198 | 225 |
199 if (create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { | 226 if (create_tpm_key_state_ == CREATE_TPM_KEY_NOT_STARTED) { |
200 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_SYSTEM_SLOT; | 227 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_USER_SLOT; |
201 | 228 |
202 base::Callback<void(crypto::ScopedPK11Slot)> create_key_with_system_slot = | 229 base::Closure on_user_tpm_ready = |
203 base::Bind(&EasyUnlockTpmKeyManager::CreateKeyInSystemSlot, | 230 base::Bind(&EasyUnlockTpmKeyManager::OnUserTPMInitialized, |
204 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), | 231 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), key); |
205 key); | |
206 | 232 |
207 content::BrowserThread::PostTask( | 233 content::BrowserThread::PostTask( |
208 content::BrowserThread::IO, | 234 content::BrowserThread::IO, FROM_HERE, |
209 FROM_HERE, | 235 base::Bind(&EnsureUserTPMInitializedOnIOThread, username_hash_, |
210 base::Bind(&GetSystemSlotOnIOThread, | 236 base::ThreadTaskRunnerHandle::Get(), on_user_tpm_ready)); |
211 base::ThreadTaskRunnerHandle::Get(), | |
212 create_key_with_system_slot)); | |
213 } | 237 } |
214 | 238 |
215 return false; | 239 return false; |
216 } | 240 } |
217 | 241 |
218 bool EasyUnlockTpmKeyManager::StartGetSystemSlotTimeoutMs(size_t timeout_ms) { | 242 bool EasyUnlockTpmKeyManager::StartGetSystemSlotTimeoutMs(size_t timeout_ms) { |
219 if (create_tpm_key_state_ == CREATE_TPM_KEY_DONE || | 243 if (StartedCreatingTpmKeys()) |
220 create_tpm_key_state_ == CREATE_TPM_KEY_GOT_SYSTEM_SLOT) { | |
221 return false; | 244 return false; |
222 } | |
223 | 245 |
224 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 246 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
225 FROM_HERE, | 247 FROM_HERE, |
226 base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, | 248 base::Bind(&EasyUnlockTpmKeyManager::OnTpmKeyCreated, |
227 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), | 249 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), |
228 std::string()), | 250 std::string()), |
229 base::TimeDelta::FromMilliseconds(timeout_ms)); | 251 base::TimeDelta::FromMilliseconds(timeout_ms)); |
230 return true; | 252 return true; |
231 } | 253 } |
232 | 254 |
(...skipping 27 matching lines...) Expand all Loading... |
260 key, data, callback); | 282 key, data, callback); |
261 | 283 |
262 content::BrowserThread::PostTask( | 284 content::BrowserThread::PostTask( |
263 content::BrowserThread::IO, | 285 content::BrowserThread::IO, |
264 FROM_HERE, | 286 FROM_HERE, |
265 base::Bind(&GetSystemSlotOnIOThread, | 287 base::Bind(&GetSystemSlotOnIOThread, |
266 base::ThreadTaskRunnerHandle::Get(), | 288 base::ThreadTaskRunnerHandle::Get(), |
267 sign_with_system_slot)); | 289 sign_with_system_slot)); |
268 } | 290 } |
269 | 291 |
| 292 bool EasyUnlockTpmKeyManager::StartedCreatingTpmKeys() const { |
| 293 return create_tpm_key_state_ == CREATE_TPM_KEY_GOT_SYSTEM_SLOT || |
| 294 create_tpm_key_state_ == CREATE_TPM_KEY_DONE; |
| 295 } |
| 296 |
270 void EasyUnlockTpmKeyManager::SetKeyInLocalState(const std::string& user_id, | 297 void EasyUnlockTpmKeyManager::SetKeyInLocalState(const std::string& user_id, |
271 const std::string& value) { | 298 const std::string& value) { |
272 if (!local_state_) | 299 if (!local_state_) |
273 return; | 300 return; |
274 | 301 |
275 std::string encoded; | 302 std::string encoded; |
276 base::Base64Encode(value, &encoded); | 303 base::Base64Encode(value, &encoded); |
277 DictionaryPrefUpdate update(local_state_, | 304 DictionaryPrefUpdate update(local_state_, |
278 prefs::kEasyUnlockLocalStateTpmKeys); | 305 prefs::kEasyUnlockLocalStateTpmKeys); |
279 update->SetStringWithoutPathExpansion(user_id, encoded); | 306 update->SetStringWithoutPathExpansion(user_id, encoded); |
280 } | 307 } |
281 | 308 |
| 309 void EasyUnlockTpmKeyManager::OnUserTPMInitialized( |
| 310 const std::string& public_key) { |
| 311 create_tpm_key_state_ = CREATE_TPM_KEY_WAITING_FOR_SYSTEM_SLOT; |
| 312 |
| 313 base::Callback<void(crypto::ScopedPK11Slot)> create_key_with_system_slot = |
| 314 base::Bind(&EasyUnlockTpmKeyManager::CreateKeyInSystemSlot, |
| 315 get_tpm_slot_weak_ptr_factory_.GetWeakPtr(), public_key); |
| 316 |
| 317 content::BrowserThread::PostTask( |
| 318 content::BrowserThread::IO, FROM_HERE, |
| 319 base::Bind(&GetSystemSlotOnIOThread, base::ThreadTaskRunnerHandle::Get(), |
| 320 create_key_with_system_slot)); |
| 321 } |
| 322 |
282 void EasyUnlockTpmKeyManager::CreateKeyInSystemSlot( | 323 void EasyUnlockTpmKeyManager::CreateKeyInSystemSlot( |
283 const std::string& public_key, | 324 const std::string& public_key, |
284 crypto::ScopedPK11Slot system_slot) { | 325 crypto::ScopedPK11Slot system_slot) { |
285 CHECK(system_slot); | 326 CHECK(system_slot); |
286 | |
287 create_tpm_key_state_ = CREATE_TPM_KEY_GOT_SYSTEM_SLOT; | 327 create_tpm_key_state_ = CREATE_TPM_KEY_GOT_SYSTEM_SLOT; |
288 | 328 |
289 // If there are any delayed tasks posted using |StartGetSystemSlotTimeoutMs|, | 329 // If there are any delayed tasks posted using |StartGetSystemSlotTimeoutMs|, |
290 // this will cancel them. | 330 // this will cancel them. |
291 // Note that this would cancel other pending |CreateKeyInSystemSlot| tasks, | 331 // Note that this would cancel other pending |CreateKeyInSystemSlot| tasks, |
292 // but there should be at most one such task at a time. | 332 // but there should be at most one such task at a time. |
293 get_tpm_slot_weak_ptr_factory_.InvalidateWeakPtrs(); | 333 get_tpm_slot_weak_ptr_factory_.InvalidateWeakPtrs(); |
294 | 334 |
295 base::WorkerPool::PostTask( | 335 base::WorkerPool::PostTask( |
296 FROM_HERE, | 336 FROM_HERE, |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 // If key creation failed, reset the state machine. | 386 // If key creation failed, reset the state machine. |
347 create_tpm_key_state_ = | 387 create_tpm_key_state_ = |
348 public_key.empty() ? CREATE_TPM_KEY_NOT_STARTED : CREATE_TPM_KEY_DONE; | 388 public_key.empty() ? CREATE_TPM_KEY_NOT_STARTED : CREATE_TPM_KEY_DONE; |
349 } | 389 } |
350 | 390 |
351 void EasyUnlockTpmKeyManager::OnDataSigned( | 391 void EasyUnlockTpmKeyManager::OnDataSigned( |
352 const base::Callback<void(const std::string&)>& callback, | 392 const base::Callback<void(const std::string&)>& callback, |
353 const std::string& signature) { | 393 const std::string& signature) { |
354 callback.Run(signature); | 394 callback.Run(signature); |
355 } | 395 } |
OLD | NEW |