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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/ownership/owner_settings_service.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/chromeos/login/users/user.h"
12 #include "chrome/browser/chromeos/login/users/user_manager.h"
13 #include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
14 #include "chrome/browser/chromeos/profiles/profile_helper.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chromeos/dbus/dbus_thread_manager.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/notification_details.h"
19 #include "content/public/browser/notification_source.h"
20 #include "crypto/nss_util.h"
21 #include "crypto/nss_util_internal.h"
22 #include "crypto/rsa_private_key.h"
23 #include "crypto/scoped_nss_types.h"
24 #include "crypto/signature_creator.h"
25
26 namespace em = enterprise_management;
27
28 using content::BrowserThread;
29
30 namespace chromeos {
31
32 namespace {
33
34 scoped_refptr<OwnerKeyUtil>* g_owner_key_util_for_testing = NULL;
35 DeviceSettingsService* g_device_settings_service_for_testing = NULL;
36
AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,crypto::RSAPrivateKey * private_key)37 std::string AssembleAndSignPolicy(scoped_ptr<em::PolicyData> policy,
38 crypto::RSAPrivateKey* private_key) {
39 // Assemble the policy.
40 em::PolicyFetchResponse policy_response;
41 if (!policy->SerializeToString(policy_response.mutable_policy_data())) {
42 LOG(ERROR) << "Failed to encode policy payload.";
43 return std::string();
44 }
45
46 // Generate the signature.
47 scoped_ptr<crypto::SignatureCreator> signature_creator(
48 crypto::SignatureCreator::Create(private_key));
49 signature_creator->Update(
50 reinterpret_cast<const uint8*>(policy_response.policy_data().c_str()),
51 policy_response.policy_data().size());
52 std::vector<uint8> signature_bytes;
53 std::string policy_blob;
54 if (!signature_creator->Final(&signature_bytes)) {
55 LOG(ERROR) << "Failed to create policy signature.";
56 return std::string();
57 }
58
59 policy_response.mutable_policy_data_signature()->assign(
60 reinterpret_cast<const char*>(vector_as_array(&signature_bytes)),
61 signature_bytes.size());
62 return policy_response.SerializeAsString();
63 }
64
LoadPrivateKeyByPublicKey(const scoped_refptr<OwnerKeyUtil> & owner_key_util,const std::vector<uint8> & public_key,const std::string & username_hash,const base::Callback<void (scoped_ptr<crypto::RSAPrivateKey>)> & callback)65 void LoadPrivateKeyByPublicKey(
66 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
67 const std::vector<uint8>& public_key,
68 const std::string& username_hash,
69 const base::Callback<void(scoped_ptr<crypto::RSAPrivateKey>)>& callback) {
70 crypto::EnsureNSSInit();
71 crypto::ScopedPK11Slot slot =
72 crypto::GetPublicSlotForChromeOSUser(username_hash);
73 scoped_ptr<crypto::RSAPrivateKey> key(
74 owner_key_util->FindPrivateKeyInSlot(public_key, slot.get()));
75 BrowserThread::PostTask(
76 BrowserThread::UI, FROM_HERE, base::Bind(callback, base::Passed(&key)));
77 }
78
LoadPrivateKey(const scoped_refptr<OwnerKeyUtil> & owner_key_util,const std::string username_hash,const base::Callback<void (scoped_ptr<crypto::RSAPrivateKey>)> & callback)79 void LoadPrivateKey(
80 const scoped_refptr<OwnerKeyUtil>& owner_key_util,
81 const std::string username_hash,
82 const base::Callback<void(scoped_ptr<crypto::RSAPrivateKey>)>& callback) {
83 std::vector<uint8> public_key;
84 if (!owner_key_util->ImportPublicKey(&public_key)) {
85 scoped_ptr<crypto::RSAPrivateKey> result;
86 BrowserThread::PostTask(BrowserThread::UI,
87 FROM_HERE,
88 base::Bind(callback, base::Passed(&result)));
89 return;
90 }
91 bool rv = BrowserThread::PostTask(BrowserThread::IO,
92 FROM_HERE,
93 base::Bind(&LoadPrivateKeyByPublicKey,
94 owner_key_util,
95 public_key,
96 username_hash,
97 callback));
98 if (!rv) {
99 // IO thread doesn't exists in unit tests, but it's safe to use NSS from
100 // BlockingPool in unit tests.
101 LoadPrivateKeyByPublicKey(
102 owner_key_util, public_key, username_hash, callback);
103 }
104 }
105
IsPrivateKeyExistAsyncHelper(const scoped_refptr<OwnerKeyUtil> & owner_key_util)106 bool IsPrivateKeyExistAsyncHelper(
107 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
108 std::vector<uint8> public_key;
109 if (!owner_key_util->ImportPublicKey(&public_key))
110 return false;
111 scoped_ptr<crypto::RSAPrivateKey> key(
112 crypto::RSAPrivateKey::FindFromPublicKeyInfo(public_key));
113 bool is_owner = key.get() != NULL;
114 return is_owner;
115 }
116
117 } // namespace
118
OwnerSettingsService(Profile * profile)119 OwnerSettingsService::OwnerSettingsService(Profile* profile)
120 : profile_(profile),
121 owner_key_util_(OwnerKeyUtil::Create()),
122 waiting_for_profile_creation_(true),
123 waiting_for_tpm_token_(true),
124 weak_factory_(this) {
125 if (TPMTokenLoader::IsInitialized()) {
126 waiting_for_tpm_token_ = !TPMTokenLoader::Get()->IsTPMTokenReady();
127 TPMTokenLoader::Get()->AddObserver(this);
128 }
129
130 if (DBusThreadManager::IsInitialized() &&
131 DBusThreadManager::Get()->GetSessionManagerClient()) {
132 DBusThreadManager::Get()->GetSessionManagerClient()->AddObserver(this);
133 }
134
135 registrar_.Add(this,
136 chrome::NOTIFICATION_PROFILE_CREATED,
137 content::Source<Profile>(profile_));
138 }
139
~OwnerSettingsService()140 OwnerSettingsService::~OwnerSettingsService() {
141 DCHECK(thread_checker_.CalledOnValidThread());
142 if (TPMTokenLoader::IsInitialized())
143 TPMTokenLoader::Get()->RemoveObserver(this);
144
145 if (DBusThreadManager::IsInitialized() &&
146 DBusThreadManager::Get()->GetSessionManagerClient()) {
147 DBusThreadManager::Get()->GetSessionManagerClient()->RemoveObserver(this);
148 }
149 }
150
IsOwner()151 bool OwnerSettingsService::IsOwner() {
152 DCHECK(thread_checker_.CalledOnValidThread());
153 return private_key_ && private_key_->key();
154 }
155
IsOwnerAsync(const IsOwnerCallback & callback)156 void OwnerSettingsService::IsOwnerAsync(const IsOwnerCallback& callback) {
157 DCHECK(thread_checker_.CalledOnValidThread());
158 if (private_key_) {
159 base::MessageLoop::current()->PostTask(FROM_HERE,
160 base::Bind(callback, IsOwner()));
161 } else {
162 pending_is_owner_callbacks_.push_back(callback);
163 }
164 }
165
AssembleAndSignPolicyAsync(scoped_ptr<enterprise_management::PolicyData> policy,const AssembleAndSignPolicyCallback & callback)166 bool OwnerSettingsService::AssembleAndSignPolicyAsync(
167 scoped_ptr<enterprise_management::PolicyData> policy,
168 const AssembleAndSignPolicyCallback& callback) {
169 DCHECK(thread_checker_.CalledOnValidThread());
170 if (!IsOwner())
171 return false;
172 base::PostTaskAndReplyWithResult(
173 BrowserThread::GetBlockingPool(),
174 FROM_HERE,
175 base::Bind(
176 &AssembleAndSignPolicy, base::Passed(&policy), private_key_->key()),
177 callback);
178 return true;
179 }
180
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)181 void OwnerSettingsService::Observe(
182 int type,
183 const content::NotificationSource& source,
184 const content::NotificationDetails& details) {
185 DCHECK(thread_checker_.CalledOnValidThread());
186 if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
187 NOTREACHED();
188 return;
189 }
190
191 Profile* profile = content::Source<Profile>(source).ptr();
192 if (profile != profile_) {
193 NOTREACHED();
194 return;
195 }
196
197 waiting_for_profile_creation_ = false;
198 ReloadPrivateKey();
199 }
200
OnTPMTokenReady()201 void OwnerSettingsService::OnTPMTokenReady() {
202 DCHECK(thread_checker_.CalledOnValidThread());
203 waiting_for_tpm_token_ = false;
204
205 // TPMTokenLoader initializes the TPM and NSS database which is necessary to
206 // determine ownership. Force a reload once we know these are initialized.
207 ReloadPrivateKey();
208 }
209
OwnerKeySet(bool success)210 void OwnerSettingsService::OwnerKeySet(bool success) {
211 DCHECK(thread_checker_.CalledOnValidThread());
212 if (success)
213 ReloadPrivateKey();
214 }
215
216 // static
IsPrivateKeyExistAsync(const IsOwnerCallback & callback)217 void OwnerSettingsService::IsPrivateKeyExistAsync(
218 const IsOwnerCallback& callback) {
219 scoped_refptr<OwnerKeyUtil> owner_key_util;
220 if (g_owner_key_util_for_testing)
221 owner_key_util = *g_owner_key_util_for_testing;
222 else
223 owner_key_util = OwnerKeyUtil::Create();
224 scoped_refptr<base::TaskRunner> task_runner =
225 content::BrowserThread::GetBlockingPool()
226 ->GetTaskRunnerWithShutdownBehavior(
227 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
228 base::PostTaskAndReplyWithResult(
229 task_runner.get(),
230 FROM_HERE,
231 base::Bind(&IsPrivateKeyExistAsyncHelper, owner_key_util),
232 callback);
233 }
234
235 // static
SetOwnerKeyUtilForTesting(const scoped_refptr<OwnerKeyUtil> & owner_key_util)236 void OwnerSettingsService::SetOwnerKeyUtilForTesting(
237 const scoped_refptr<OwnerKeyUtil>& owner_key_util) {
238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
239 if (g_owner_key_util_for_testing) {
240 delete g_owner_key_util_for_testing;
241 g_owner_key_util_for_testing = NULL;
242 }
243 if (owner_key_util.get()) {
244 g_owner_key_util_for_testing = new scoped_refptr<OwnerKeyUtil>();
245 *g_owner_key_util_for_testing = owner_key_util;
246 }
247 }
248
249 // static
SetDeviceSettingsServiceForTesting(DeviceSettingsService * device_settings_service)250 void OwnerSettingsService::SetDeviceSettingsServiceForTesting(
251 DeviceSettingsService* device_settings_service) {
252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
253 g_device_settings_service_for_testing = device_settings_service;
254 }
255
ReloadPrivateKey()256 void OwnerSettingsService::ReloadPrivateKey() {
257 DCHECK(thread_checker_.CalledOnValidThread());
258 if (waiting_for_profile_creation_ || waiting_for_tpm_token_)
259 return;
260 scoped_refptr<base::TaskRunner> task_runner =
261 content::BrowserThread::GetBlockingPool()
262 ->GetTaskRunnerWithShutdownBehavior(
263 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
264 task_runner->PostTask(
265 FROM_HERE,
266 base::Bind(&LoadPrivateKey,
267 GetOwnerKeyUtil(),
268 ProfileHelper::GetUserIdHashFromProfile(profile_),
269 base::Bind(&OwnerSettingsService::OnPrivateKeyLoaded,
270 weak_factory_.GetWeakPtr())));
271 }
272
OnPrivateKeyLoaded(scoped_ptr<crypto::RSAPrivateKey> private_key)273 void OwnerSettingsService::OnPrivateKeyLoaded(
274 scoped_ptr<crypto::RSAPrivateKey> private_key) {
275 DCHECK(thread_checker_.CalledOnValidThread());
276 private_key_ = new PrivateKey(private_key.release());
277
278 const std::string& user_id = profile_->GetProfileName();
279 if (user_id == OwnerSettingsServiceFactory::GetInstance()->GetUsername())
280 GetDeviceSettingsService()->InitOwner(user_id, weak_factory_.GetWeakPtr());
281
282 std::vector<IsOwnerCallback> is_owner_callbacks;
283 is_owner_callbacks.swap(pending_is_owner_callbacks_);
284 const bool is_owner = IsOwner();
285 for (std::vector<IsOwnerCallback>::iterator it(is_owner_callbacks.begin());
286 it != is_owner_callbacks.end();
287 ++it) {
288 it->Run(is_owner);
289 }
290 }
291
GetOwnerKeyUtil()292 scoped_refptr<OwnerKeyUtil> OwnerSettingsService::GetOwnerKeyUtil() {
293 DCHECK(thread_checker_.CalledOnValidThread());
294 if (g_owner_key_util_for_testing)
295 return *g_owner_key_util_for_testing;
296 return owner_key_util_;
297 }
298
GetDeviceSettingsService()299 DeviceSettingsService* OwnerSettingsService::GetDeviceSettingsService() {
300 DCHECK(thread_checker_.CalledOnValidThread());
301 if (g_device_settings_service_for_testing)
302 return g_device_settings_service_for_testing;
303 if (DeviceSettingsService::IsInitialized())
304 return DeviceSettingsService::Get();
305 return NULL;
306 }
307
308 } // namespace chromeos
309