| 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/ownership/owner_settings_service_chromeos.h" | 5 #include "chrome/browser/chromeos/ownership/owner_settings_service_chromeos.h" |
| 6 | 6 |
| 7 #include <keyhi.h> | 7 #include <keyhi.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 #include <memory> |
| 11 #include <string> | 12 #include <string> |
| 12 #include <utility> | 13 #include <utility> |
| 13 | 14 |
| 14 #include "base/bind.h" | 15 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 16 #include "base/bind_helpers.h" |
| 16 #include "base/callback.h" | 17 #include "base/callback.h" |
| 17 #include "base/command_line.h" | 18 #include "base/command_line.h" |
| 18 #include "base/memory/ptr_util.h" | 19 #include "base/memory/ptr_util.h" |
| 19 #include "base/threading/sequenced_worker_pool.h" | 20 #include "base/threading/sequenced_worker_pool.h" |
| 20 #include "base/threading/thread_checker.h" | 21 #include "base/threading/thread_checker.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 ::switches::kTestType) || | 59 ::switches::kTestType) || |
| 59 !CrosSettings::IsInitialized()) { | 60 !CrosSettings::IsInitialized()) { |
| 60 return false; | 61 return false; |
| 61 } | 62 } |
| 62 const base::Value* value = CrosSettings::Get()->GetPref(kDeviceOwner); | 63 const base::Value* value = CrosSettings::Get()->GetPref(kDeviceOwner); |
| 63 if (!value || value->GetType() != base::Value::Type::STRING) | 64 if (!value || value->GetType() != base::Value::Type::STRING) |
| 64 return false; | 65 return false; |
| 65 return static_cast<const base::Value*>(value)->GetString() == user_id; | 66 return static_cast<const base::Value*>(value)->GetString() == user_id; |
| 66 } | 67 } |
| 67 | 68 |
| 68 void LoadPrivateKeyByPublicKey( | 69 void LoadPrivateKeyByPublicKeyOnWorkerThread( |
| 69 const scoped_refptr<OwnerKeyUtil>& owner_key_util, | 70 const scoped_refptr<OwnerKeyUtil>& owner_key_util, |
| 70 scoped_refptr<PublicKey> public_key, | 71 crypto::ScopedPK11Slot public_slot, |
| 71 const std::string& username_hash, | 72 crypto::ScopedPK11Slot private_slot, |
| 72 const base::Callback<void(const scoped_refptr<PublicKey>& public_key, | 73 const base::Callback<void(const scoped_refptr<PublicKey>& public_key, |
| 73 const scoped_refptr<PrivateKey>& private_key)>& | 74 const scoped_refptr<PrivateKey>& private_key)>& |
| 74 callback) { | 75 callback) { |
| 75 crypto::EnsureNSSInit(); | 76 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); |
| 76 crypto::ScopedPK11Slot public_slot = | 77 |
| 77 crypto::GetPublicSlotForChromeOSUser(username_hash); | 78 std::vector<uint8_t> public_key_data; |
| 78 crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser( | 79 scoped_refptr<PublicKey> public_key; |
| 79 username_hash, base::Callback<void(crypto::ScopedPK11Slot)>()); | 80 if (!owner_key_util->ImportPublicKey(&public_key_data)) { |
| 81 scoped_refptr<PrivateKey> private_key; |
| 82 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 83 base::Bind(callback, public_key, private_key)); |
| 84 return; |
| 85 } |
| 86 public_key = new PublicKey(); |
| 87 public_key->data().swap(public_key_data); |
| 80 | 88 |
| 81 // If private slot is already available, this will check it. If not, we'll get | 89 // If private slot is already available, this will check it. If not, we'll get |
| 82 // called again later when the TPM Token is ready, and the slot will be | 90 // called again later when the TPM Token is ready, and the slot will be |
| 83 // available then. FindPrivateKeyInSlot internally checks for a null slot if | 91 // available then. FindPrivateKeyInSlot internally checks for a null slot if |
| 84 // needbe. | 92 // needbe. |
| 85 // | 93 // |
| 86 // TODO(davidben): The null check should be in the caller rather than | 94 // TODO(davidben): The null check should be in the caller rather than |
| 87 // internally in the OwnerKeyUtil implementation. The tests currently get a | 95 // internally in the OwnerKeyUtil implementation. The tests currently get a |
| 88 // null private_slot and expect the mock OwnerKeyUtil to still be called. | 96 // null private_slot and expect the mock OwnerKeyUtil to still be called. |
| 89 scoped_refptr<PrivateKey> private_key( | 97 scoped_refptr<PrivateKey> private_key( |
| 90 new PrivateKey(owner_key_util->FindPrivateKeyInSlot(public_key->data(), | 98 new PrivateKey(owner_key_util->FindPrivateKeyInSlot(public_key->data(), |
| 91 private_slot.get()))); | 99 private_slot.get()))); |
| 92 if (!private_key->key()) { | 100 if (!private_key->key()) { |
| 93 private_key = new PrivateKey(owner_key_util->FindPrivateKeyInSlot( | 101 private_key = new PrivateKey(owner_key_util->FindPrivateKeyInSlot( |
| 94 public_key->data(), public_slot.get())); | 102 public_key->data(), public_slot.get())); |
| 95 } | 103 } |
| 96 BrowserThread::PostTask(BrowserThread::UI, | 104 BrowserThread::PostTask(BrowserThread::UI, |
| 97 FROM_HERE, | 105 FROM_HERE, |
| 98 base::Bind(callback, public_key, private_key)); | 106 base::Bind(callback, public_key, private_key)); |
| 99 } | 107 } |
| 100 | 108 |
| 101 void LoadPrivateKey( | 109 void LoadPrivateKeyOnIOThread( |
| 102 const scoped_refptr<OwnerKeyUtil>& owner_key_util, | 110 const scoped_refptr<OwnerKeyUtil>& owner_key_util, |
| 103 const std::string username_hash, | 111 const std::string username_hash, |
| 104 const base::Callback<void(const scoped_refptr<PublicKey>& public_key, | 112 const base::Callback<void(const scoped_refptr<PublicKey>& public_key, |
| 105 const scoped_refptr<PrivateKey>& private_key)>& | 113 const scoped_refptr<PrivateKey>& private_key)>& |
| 106 callback) { | 114 callback) { |
| 107 std::vector<uint8_t> public_key_data; | 115 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 108 scoped_refptr<PublicKey> public_key; | 116 |
| 109 if (!owner_key_util->ImportPublicKey(&public_key_data)) { | 117 crypto::EnsureNSSInit(); |
| 110 scoped_refptr<PrivateKey> private_key; | 118 crypto::ScopedPK11Slot public_slot = |
| 111 BrowserThread::PostTask(BrowserThread::UI, | 119 crypto::GetPublicSlotForChromeOSUser(username_hash); |
| 112 FROM_HERE, | 120 crypto::ScopedPK11Slot private_slot = crypto::GetPrivateSlotForChromeOSUser( |
| 113 base::Bind(callback, public_key, private_key)); | 121 username_hash, base::Callback<void(crypto::ScopedPK11Slot)>()); |
| 114 return; | 122 |
| 115 } | 123 scoped_refptr<base::TaskRunner> task_runner = |
| 116 public_key = new PublicKey(); | 124 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( |
| 117 public_key->data().swap(public_key_data); | 125 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); |
| 118 bool rv = BrowserThread::PostTask(BrowserThread::IO, | 126 task_runner->PostTask( |
| 119 FROM_HERE, | 127 FROM_HERE, |
| 120 base::Bind(&LoadPrivateKeyByPublicKey, | 128 base::Bind(&LoadPrivateKeyByPublicKeyOnWorkerThread, owner_key_util, |
| 121 owner_key_util, | 129 base::Passed(std::move(public_slot)), |
| 122 public_key, | 130 base::Passed(std::move(private_slot)), callback)); |
| 123 username_hash, | |
| 124 callback)); | |
| 125 if (!rv) { | |
| 126 // IO thread doesn't exists in unit tests, but it's safe to use NSS from | |
| 127 // BlockingPool in unit tests. | |
| 128 LoadPrivateKeyByPublicKey( | |
| 129 owner_key_util, public_key, username_hash, callback); | |
| 130 } | |
| 131 } | 131 } |
| 132 | 132 |
| 133 bool DoesPrivateKeyExistAsyncHelper( | 133 bool DoesPrivateKeyExistAsyncHelper( |
| 134 const scoped_refptr<OwnerKeyUtil>& owner_key_util) { | 134 const scoped_refptr<OwnerKeyUtil>& owner_key_util) { |
| 135 std::vector<uint8_t> public_key; | 135 std::vector<uint8_t> public_key; |
| 136 if (!owner_key_util->ImportPublicKey(&public_key)) | 136 if (!owner_key_util->ImportPublicKey(&public_key)) |
| 137 return false; | 137 return false; |
| 138 crypto::ScopedSECKEYPrivateKey key = | 138 crypto::ScopedSECKEYPrivateKey key = |
| 139 crypto::FindNSSKeyFromPublicKeyInfo(public_key); | 139 crypto::FindNSSKeyFromPublicKeyInfo(public_key); |
| 140 return key && SECKEY_GetPrivateKeyType(key.get()) == rsaKey; | 140 return key && SECKEY_GetPrivateKeyType(key.get()) == rsaKey; |
| (...skipping 514 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 has_pending_fixups_ = true; | 655 has_pending_fixups_ = true; |
| 656 } | 656 } |
| 657 | 657 |
| 658 void OwnerSettingsServiceChromeOS::ReloadKeypairImpl(const base::Callback< | 658 void OwnerSettingsServiceChromeOS::ReloadKeypairImpl(const base::Callback< |
| 659 void(const scoped_refptr<PublicKey>& public_key, | 659 void(const scoped_refptr<PublicKey>& public_key, |
| 660 const scoped_refptr<PrivateKey>& private_key)>& callback) { | 660 const scoped_refptr<PrivateKey>& private_key)>& callback) { |
| 661 DCHECK(thread_checker_.CalledOnValidThread()); | 661 DCHECK(thread_checker_.CalledOnValidThread()); |
| 662 | 662 |
| 663 if (waiting_for_profile_creation_ || waiting_for_tpm_token_) | 663 if (waiting_for_profile_creation_ || waiting_for_tpm_token_) |
| 664 return; | 664 return; |
| 665 scoped_refptr<base::TaskRunner> task_runner = | 665 |
| 666 BrowserThread::GetBlockingPool()->GetTaskRunnerWithShutdownBehavior( | 666 bool rv = BrowserThread::PostTask( |
| 667 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN); | 667 BrowserThread::IO, FROM_HERE, |
| 668 task_runner->PostTask( | 668 base::Bind(&LoadPrivateKeyOnIOThread, owner_key_util_, |
| 669 FROM_HERE, | 669 ProfileHelper::GetUserIdHashFromProfile(profile_), callback)); |
| 670 base::Bind(&LoadPrivateKey, | 670 if (!rv) { |
| 671 owner_key_util_, | 671 // IO thread doesn't exists in unit tests, but it's safe to use NSS from |
| 672 ProfileHelper::GetUserIdHashFromProfile(profile_), | 672 // BlockingPool in unit tests. |
| 673 callback)); | 673 LoadPrivateKeyOnIOThread(owner_key_util_, |
| 674 ProfileHelper::GetUserIdHashFromProfile(profile_), |
| 675 callback); |
| 676 } |
| 674 } | 677 } |
| 675 | 678 |
| 676 void OwnerSettingsServiceChromeOS::StorePendingChanges() { | 679 void OwnerSettingsServiceChromeOS::StorePendingChanges() { |
| 677 if (!HasPendingChanges() || store_settings_factory_.HasWeakPtrs() || | 680 if (!HasPendingChanges() || store_settings_factory_.HasWeakPtrs() || |
| 678 !device_settings_service_ || user_id_.empty()) { | 681 !device_settings_service_ || user_id_.empty()) { |
| 679 return; | 682 return; |
| 680 } | 683 } |
| 681 | 684 |
| 682 em::ChromeDeviceSettingsProto settings; | 685 em::ChromeDeviceSettingsProto settings; |
| 683 if (tentative_settings_.get()) { | 686 if (tentative_settings_.get()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 729 | 732 |
| 730 void OwnerSettingsServiceChromeOS::ReportStatusAndContinueStoring( | 733 void OwnerSettingsServiceChromeOS::ReportStatusAndContinueStoring( |
| 731 bool success) { | 734 bool success) { |
| 732 store_settings_factory_.InvalidateWeakPtrs(); | 735 store_settings_factory_.InvalidateWeakPtrs(); |
| 733 for (auto& observer : observers_) | 736 for (auto& observer : observers_) |
| 734 observer.OnSignedPolicyStored(success); | 737 observer.OnSignedPolicyStored(success); |
| 735 StorePendingChanges(); | 738 StorePendingChanges(); |
| 736 } | 739 } |
| 737 | 740 |
| 738 } // namespace chromeos | 741 } // namespace chromeos |
| OLD | NEW |