• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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