Home | History | Annotate | Download | only in ownership
      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 
     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 
     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 
     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 
    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 
    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 
    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 
    151 bool OwnerSettingsService::IsOwner() {
    152   DCHECK(thread_checker_.CalledOnValidThread());
    153   return private_key_ && private_key_->key();
    154 }
    155 
    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 
    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 
    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 
    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 
    210 void OwnerSettingsService::OwnerKeySet(bool success) {
    211   DCHECK(thread_checker_.CalledOnValidThread());
    212   if (success)
    213     ReloadPrivateKey();
    214 }
    215 
    216 // static
    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
    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
    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 
    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 
    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 
    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 
    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