summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-21 01:50:25 +0000
committerygorshenin@chromium.org <ygorshenin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-21 01:50:25 +0000
commit196e53e84cfd2533fe8a195fafb7a46e41440c00 (patch)
tree98a343569dc922e682a720c5f0f5b2aa8e8c2d7f
parentf571bc032bdfab736cb212b56e83dcb95ec5d7c6 (diff)
downloadchromium_src-196e53e84cfd2533fe8a195fafb7a46e41440c00.zip
chromium_src-196e53e84cfd2533fe8a195fafb7a46e41440c00.tar.gz
chromium_src-196e53e84cfd2533fe8a195fafb7a46e41440c00.tar.bz2
Implemented profile-aware owner key loading.
BUG=230018 TEST=manual Review URL: https://codereview.chromium.org/270663002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271802 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/chromeos/login/auth/parallel_authenticator.cc6
-rw-r--r--chrome/browser/chromeos/login/users/user_manager_impl.cc7
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service.cc72
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service.h51
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service_factory.cc77
-rw-r--r--chrome/browser/chromeos/ownership/owner_settings_service_factory.h60
-rw-r--r--chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc3
-rw-r--r--chrome/browser/chromeos/policy/power_policy_browsertest.cc3
-rw-r--r--chrome/browser/chromeos/settings/device_settings_provider_unittest.cc8
-rw-r--r--chrome/browser/chromeos/settings/device_settings_service.cc16
-rw-r--r--chrome/browser/chromeos/settings/device_settings_service.h4
-rw-r--r--chrome/browser/chromeos/settings/device_settings_service_unittest.cc28
-rw-r--r--chrome/browser/chromeos/settings/mock_owner_key_util.cc6
-rw-r--r--chrome/browser/chromeos/settings/mock_owner_key_util.h3
-rw-r--r--chrome/browser/chromeos/settings/owner_key_util.cc6
-rw-r--r--chrome/browser/chromeos/settings/owner_key_util.h14
-rw-r--r--chrome/browser/chromeos/settings/session_manager_operation.cc21
-rw-r--r--chrome/browser/chromeos/settings/session_manager_operation.h9
-rw-r--r--chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc2
-rw-r--r--chrome/chrome_browser_chromeos.gypi4
-rw-r--r--crypto/rsa_private_key.h18
-rw-r--r--crypto/rsa_private_key_nss.cc101
22 files changed, 462 insertions, 57 deletions
diff --git a/chrome/browser/chromeos/login/auth/parallel_authenticator.cc b/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
index 04457ff..099c9e0 100644
--- a/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
+++ b/chrome/browser/chromeos/login/auth/parallel_authenticator.cc
@@ -17,6 +17,7 @@
#include "chrome/browser/chromeos/login/auth/user_context.h"
#include "chrome/browser/chromeos/login/users/user.h"
#include "chrome/browser/chromeos/login/users/user_manager.h"
+#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/settings/cros_settings.h"
#include "chrome/common/chrome_switches.h"
#include "chromeos/cryptohome/async_method_caller.h"
@@ -488,9 +489,10 @@ bool ParallelAuthenticator::VerifyOwner() {
owner_is_verified_ = true;
return true;
}
- // Now we can continue reading the private key.
- DeviceSettingsService::Get()->SetUsername(
+
+ OwnerSettingsServiceFactory::GetInstance()->SetUsername(
current_state_->user_context.GetUserID());
+
// This should trigger certificate loading, which is needed in order to
// correctly determine if the current user is the owner.
if (LoginState::IsInitialized()) {
diff --git a/chrome/browser/chromeos/login/users/user_manager_impl.cc b/chrome/browser/chromeos/login/users/user_manager_impl.cc
index d5ba933..86bf5da 100644
--- a/chrome/browser/chromeos/login/users/user_manager_impl.cc
+++ b/chrome/browser/chromeos/login/users/user_manager_impl.cc
@@ -43,6 +43,7 @@
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/net/network_portal_detector.h"
#include "chrome/browser/chromeos/net/network_portal_detector_strategy.h"
+#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/browser/chromeos/policy/device_local_account.h"
#include "chrome/browser/chromeos/profiles/multiprofiles_session_aborted_dialog.h"
@@ -1566,10 +1567,8 @@ void UserManagerImpl::NotifyOnLogin() {
// Owner must be first user in session. DeviceSettingsService can't deal with
// multiple user and will mix up ownership, crbug.com/230018.
if (GetLoggedInUsers().size() == 1) {
- // Indicate to DeviceSettingsService that the owner key may have become
- // available.
- DeviceSettingsService::Get()->SetUsername(active_user_->email());
-
+ OwnerSettingsServiceFactory::GetInstance()->SetUsername(
+ active_user_->email());
if (NetworkPortalDetector::IsInitialized()) {
NetworkPortalDetector::Get()->SetStrategy(
PortalDetectorStrategy::STRATEGY_ID_SESSION);
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service.cc b/chrome/browser/chromeos/ownership/owner_settings_service.cc
new file mode 100644
index 0000000..fa7a21a
--- /dev/null
+++ b/chrome/browser/chromeos/ownership/owner_settings_service.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/ownership/owner_settings_service.h"
+
+#include <string>
+
+#include "base/bind.h"
+#include "chrome/browser/chrome_notification_types.h"
+#include "chrome/browser/chromeos/login/users/user.h"
+#include "chrome/browser/chromeos/login/users/user_manager.h"
+#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
+#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_details.h"
+#include "content/public/browser/notification_source.h"
+#include "crypto/nss_util_internal.h"
+#include "crypto/scoped_nss_types.h"
+
+using content::BrowserThread;
+
+namespace chromeos {
+
+OwnerSettingsService::OwnerSettingsService(Profile* profile)
+ : profile_(profile), weak_factory_(this) {
+ registrar_.Add(this,
+ chrome::NOTIFICATION_PROFILE_CREATED,
+ content::Source<Profile>(profile_));
+}
+
+OwnerSettingsService::~OwnerSettingsService() {
+}
+
+void OwnerSettingsService::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ if (type != chrome::NOTIFICATION_PROFILE_CREATED) {
+ NOTREACHED();
+ return;
+ }
+
+ Profile* profile = content::Source<Profile>(source).ptr();
+ if (profile != profile_) {
+ NOTREACHED();
+ return;
+ }
+
+ ReloadOwnerKey();
+}
+
+void OwnerSettingsService::ReloadOwnerKey() {
+ if (!UserManager::IsInitialized())
+ return;
+ const User* user = UserManager::Get()->GetUserByProfile(profile_);
+ if (!user || !user->is_profile_created())
+ return;
+ std::string user_id = user->email();
+ if (user_id != OwnerSettingsServiceFactory::GetInstance()->GetUsername())
+ return;
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(&crypto::GetPublicSlotForChromeOSUser, user->username_hash()),
+ base::Bind(&DeviceSettingsService::InitOwner,
+ base::Unretained(DeviceSettingsService::Get()),
+ user_id));
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service.h b/chrome/browser/chromeos/ownership/owner_settings_service.h
new file mode 100644
index 0000000..8324373
--- /dev/null
+++ b/chrome/browser/chromeos/ownership/owner_settings_service.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_
+#define CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class Profile;
+
+namespace chromeos {
+
+// This class reloads owner key from profile NSS slots.
+//
+// TODO (ygorshenin@): move write path for device settings here
+// (crbug.com/230018).
+class OwnerSettingsService : public KeyedService,
+ public content::NotificationObserver {
+ public:
+ virtual ~OwnerSettingsService();
+
+ // NotificationObserver implementation:
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) OVERRIDE;
+
+ private:
+ friend class OwnerSettingsServiceFactory;
+
+ explicit OwnerSettingsService(Profile* profile);
+
+ void ReloadOwnerKey();
+
+ Profile* profile_;
+
+ content::NotificationRegistrar registrar_;
+
+ base::WeakPtrFactory<OwnerSettingsService> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(OwnerSettingsService);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_H_
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_factory.cc b/chrome/browser/chromeos/ownership/owner_settings_service_factory.cc
new file mode 100644
index 0000000..606e0e3
--- /dev/null
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_factory.cc
@@ -0,0 +1,77 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
+
+#include "chrome/browser/chromeos/login/users/user.h"
+#include "chrome/browser/chromeos/login/users/user_manager.h"
+#include "chrome/browser/chromeos/ownership/owner_settings_service.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+
+namespace chromeos {
+
+OwnerSettingsServiceFactory::OwnerSettingsServiceFactory()
+ : BrowserContextKeyedServiceFactory(
+ "OwnerSettingsService",
+ BrowserContextDependencyManager::GetInstance()) {
+}
+
+OwnerSettingsServiceFactory::~OwnerSettingsServiceFactory() {
+}
+
+// static
+OwnerSettingsService* OwnerSettingsServiceFactory::GetForProfile(
+ Profile* profile) {
+ return static_cast<OwnerSettingsService*>(
+ GetInstance()->GetServiceForBrowserContext(profile, true));
+}
+
+// static
+OwnerSettingsServiceFactory* OwnerSettingsServiceFactory::GetInstance() {
+ return Singleton<OwnerSettingsServiceFactory>::get();
+}
+
+void OwnerSettingsServiceFactory::SetUsername(const std::string& username) {
+ username_ = username;
+ if (!UserManager::IsInitialized())
+ return;
+ const User* user = UserManager::Get()->FindUser(username_);
+ if (!user || !user->is_profile_created())
+ return;
+ Profile* profile = UserManager::Get()->GetProfileByUser(user);
+ if (!profile)
+ return;
+ OwnerSettingsService* service = GetForProfile(profile);
+
+ // It's safe to call ReloadOwnerKey() here, as profile is fully created
+ // at this time.
+ if (service)
+ service->ReloadOwnerKey();
+}
+
+std::string OwnerSettingsServiceFactory::GetUsername() const {
+ return username_;
+}
+
+// static
+KeyedService* OwnerSettingsServiceFactory::BuildInstanceFor(
+ content::BrowserContext* browser_context) {
+ Profile* profile = static_cast<Profile*>(browser_context);
+ if (profile->IsGuestSession() || ProfileHelper::IsSigninProfile(profile))
+ return NULL;
+ return new OwnerSettingsService(profile);
+}
+
+bool OwnerSettingsServiceFactory::ServiceIsCreatedWithBrowserContext() const {
+ return true;
+}
+
+KeyedService* OwnerSettingsServiceFactory::BuildServiceInstanceFor(
+ content::BrowserContext* context) const {
+ return BuildInstanceFor(context);
+}
+
+} // namespace chromeos
diff --git a/chrome/browser/chromeos/ownership/owner_settings_service_factory.h b/chrome/browser/chromeos/ownership/owner_settings_service_factory.h
new file mode 100644
index 0000000..055fb3e
--- /dev/null
+++ b/chrome/browser/chromeos/ownership/owner_settings_service_factory.h
@@ -0,0 +1,60 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/memory/singleton.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class KeyedService;
+class Profile;
+
+namespace chromeos {
+
+class OwnerSettingsService;
+
+class OwnerSettingsServiceFactory : public BrowserContextKeyedServiceFactory {
+ public:
+ static OwnerSettingsService* GetForProfile(Profile* profile);
+
+ static OwnerSettingsServiceFactory* GetInstance();
+
+ // Sets name of the user supposed to be an owner. If profile
+ // for |username| is ready, request to reload owner key will be
+ // sent. Otherwise, owner key will be reloaded as soon as profile will
+ // be ready.
+ void SetUsername(const std::string& username);
+
+ // Returns the name of the user supposed to be an owner.
+ std::string GetUsername() const;
+
+ private:
+ friend struct DefaultSingletonTraits<OwnerSettingsServiceFactory>;
+
+ OwnerSettingsServiceFactory();
+ virtual ~OwnerSettingsServiceFactory();
+
+ static KeyedService* BuildInstanceFor(content::BrowserContext* context);
+
+ // BrowserContextKeyedBaseFactory overrides:
+ virtual bool ServiceIsCreatedWithBrowserContext() const OVERRIDE;
+
+ // BrowserContextKeyedServiceFactory implementation:
+ virtual KeyedService* BuildServiceInstanceFor(
+ content::BrowserContext* browser_context) const OVERRIDE;
+
+ // Name of the user supposed to be an owner.
+ std::string username_;
+
+ DISALLOW_COPY_AND_ASSIGN(OwnerSettingsServiceFactory);
+};
+
+} // namespace chromeos
+
+#endif // CHROME_BROWSER_CHROMEOS_OWNERSHIP_OWNER_SETTINGS_SERVICE_FACTORY_H_
diff --git a/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc b/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc
index d37f7af..6405b4b 100644
--- a/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/login_screen_default_policy_browsertest.cc
@@ -222,7 +222,8 @@ void LoginScreenDefaultPolicyInSessionBrowsertest::SetUpOnMainThread() {
LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();
// Tell the DeviceSettingsService that there is no local owner.
- chromeos::DeviceSettingsService::Get()->SetUsername(std::string());
+ crypto::ScopedPK11Slot slot;
+ chromeos::DeviceSettingsService::Get()->InitOwner(std::string(), slot.Pass());
}
void LoginScreenDefaultPolicyInSessionBrowsertest::VerifyPrefFollowsDefault(
diff --git a/chrome/browser/chromeos/policy/power_policy_browsertest.cc b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
index 08b16f6..da8f416 100644
--- a/chrome/browser/chromeos/policy/power_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/power_policy_browsertest.cc
@@ -307,7 +307,8 @@ void PowerPolicyInSessionBrowserTest::SetUpOnMainThread() {
PowerPolicyBrowserTestBase::SetUpOnMainThread();
// Tell the DeviceSettingsService that there is no local owner.
- chromeos::DeviceSettingsService::Get()->SetUsername(std::string());
+ crypto::ScopedPK11Slot slot;
+ chromeos::DeviceSettingsService::Get()->InitOwner(std::string(), slot.Pass());
}
// Verifies that device policy is applied on the login screen.
diff --git a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
index 1da5a9b..b84ce88 100644
--- a/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_provider_unittest.cc
@@ -139,7 +139,9 @@ TEST_F(DeviceSettingsProviderTest, SetPrefFailed) {
TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
base::FundamentalValue value(true);
@@ -167,7 +169,9 @@ TEST_F(DeviceSettingsProviderTest, SetPrefSucceed) {
TEST_F(DeviceSettingsProviderTest, SetPrefTwice) {
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
EXPECT_CALL(*this, SettingChanged(_)).Times(AnyNumber());
diff --git a/chrome/browser/chromeos/settings/device_settings_service.cc b/chrome/browser/chromeos/settings/device_settings_service.cc
index 0895080..0c54895 100644
--- a/chrome/browser/chromeos/settings/device_settings_service.cc
+++ b/chrome/browser/chromeos/settings/device_settings_service.cc
@@ -232,8 +232,13 @@ void DeviceSettingsService::IsCurrentUserOwnerAsync(
}
}
-void DeviceSettingsService::SetUsername(const std::string& username) {
+void DeviceSettingsService::InitOwner(const std::string& username,
+ crypto::ScopedPK11Slot slot) {
+ if (!username_.empty())
+ return;
+
username_ = username;
+ slot_ = slot.Pass();
// The private key may have become available, so force a key reload.
owner_key_ = NULL;
@@ -292,14 +297,19 @@ void DeviceSettingsService::EnqueueLoad(bool force_key_load) {
weak_factory_.GetWeakPtr(),
base::Closure()));
operation->set_force_key_load(force_key_load);
+ operation->set_username(username_);
+ operation->set_slot(slot_.get());
Enqueue(operation);
}
void DeviceSettingsService::EnsureReload(bool force_key_load) {
- if (!pending_operations_.empty())
+ if (!pending_operations_.empty()) {
+ pending_operations_.front()->set_username(username_);
+ pending_operations_.front()->set_slot(slot_.get());
pending_operations_.front()->RestartLoad(force_key_load);
- else
+ } else {
EnqueueLoad(force_key_load);
+ }
}
void DeviceSettingsService::StartNextOperation() {
diff --git a/chrome/browser/chromeos/settings/device_settings_service.h b/chrome/browser/chromeos/settings/device_settings_service.h
index 5b05513..f22f4a9 100644
--- a/chrome/browser/chromeos/settings/device_settings_service.h
+++ b/chrome/browser/chromeos/settings/device_settings_service.h
@@ -19,6 +19,7 @@
#include "chromeos/dbus/session_manager_client.h"
#include "chromeos/tpm_token_loader.h"
#include "components/policy/core/common/cloud/cloud_policy_validator.h"
+#include "crypto/scoped_nss_types.h"
#include "policy/proto/device_management_backend.pb.h"
namespace crypto {
@@ -199,7 +200,7 @@ class DeviceSettingsService : public SessionManagerClient::Observer,
// Sets the identity of the user that's interacting with the service. This is
// relevant only for writing settings through SignAndStore().
- void SetUsername(const std::string& username);
+ void InitOwner(const std::string& username, crypto::ScopedPK11Slot slot);
const std::string& GetUsername() const;
// Adds an observer.
@@ -261,6 +262,7 @@ class DeviceSettingsService : public SessionManagerClient::Observer,
pending_is_current_user_owner_callbacks_;
std::string username_;
+ crypto::ScopedPK11Slot slot_;
scoped_refptr<OwnerKey> owner_key_;
// Whether TPM token still needs to be initialized.
bool waiting_for_tpm_token_;
diff --git a/chrome/browser/chromeos/settings/device_settings_service_unittest.cc b/chrome/browser/chromeos/settings/device_settings_service_unittest.cc
index 727a34f..88c0114 100644
--- a/chrome/browser/chromeos/settings/device_settings_service_unittest.cc
+++ b/chrome/browser/chromeos/settings/device_settings_service_unittest.cc
@@ -164,7 +164,9 @@ TEST_F(DeviceSettingsServiceTest, SignAndStoreFailure) {
device_settings_service_.status());
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
scoped_ptr<em::ChromeDeviceSettingsProto> new_device_settings(
@@ -190,7 +192,9 @@ TEST_F(DeviceSettingsServiceTest, SignAndStoreSuccess) {
device_settings_service_.status());
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
device_policy_.payload().mutable_device_policy_refresh_rate()->
@@ -229,7 +233,9 @@ TEST_F(DeviceSettingsServiceTest, SetManagementSettingsModeTransition) {
device_settings_service_.status());
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
// The initial management mode should be NOT_MANAGED.
@@ -343,7 +349,9 @@ TEST_F(DeviceSettingsServiceTest, SetManagementSettingsSuccess) {
device_settings_service_.status());
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
FlushDeviceSettings();
device_settings_service_.SetManagementSettings(
@@ -470,7 +478,9 @@ TEST_F(DeviceSettingsServiceTest, OwnershipStatus) {
EXPECT_EQ(DeviceSettingsService::OWNERSHIP_TAKEN, ownership_status_);
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
device_settings_service_.GetOwnershipStatusAsync(
base::Bind(&DeviceSettingsServiceTest::SetOwnershipStatus,
base::Unretained(this)));
@@ -554,7 +564,9 @@ TEST_F(DeviceSettingsServiceTest, OnTPMTokenReadyForOwner) {
EXPECT_FALSE(is_owner_set_);
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
device_settings_service_.OnTPMTokenReady();
FlushDeviceSettings();
@@ -580,7 +592,9 @@ TEST_F(DeviceSettingsServiceTest, IsCurrentUserOwnerAsyncWithLoadedCerts) {
owner_key_util_->SetPublicKeyFromPrivateKey(*device_policy_.GetSigningKey());
owner_key_util_->SetPrivateKey(device_policy_.GetSigningKey());
- device_settings_service_.SetUsername(device_policy_.policy_data().username());
+ crypto::ScopedPK11Slot slot;
+ device_settings_service_.InitOwner(device_policy_.policy_data().username(),
+ slot.Pass());
ReloadDeviceSettings();
device_settings_service_.OnTPMTokenReady();
diff --git a/chrome/browser/chromeos/settings/mock_owner_key_util.cc b/chrome/browser/chromeos/settings/mock_owner_key_util.cc
index 1f77545..bd62af5 100644
--- a/chrome/browser/chromeos/settings/mock_owner_key_util.cc
+++ b/chrome/browser/chromeos/settings/mock_owner_key_util.cc
@@ -22,6 +22,12 @@ crypto::RSAPrivateKey* MockOwnerKeyUtil::FindPrivateKey(
return private_key_.get() ? private_key_->Copy() : NULL;
}
+crypto::RSAPrivateKey* MockOwnerKeyUtil::FindPrivateKeyInSlot(
+ const std::vector<uint8>& key,
+ PK11SlotInfo* slot) {
+ return private_key_.get() ? private_key_->Copy() : NULL;
+}
+
bool MockOwnerKeyUtil::IsPublicKeyPresent() {
return !public_key_.empty();
}
diff --git a/chrome/browser/chromeos/settings/mock_owner_key_util.h b/chrome/browser/chromeos/settings/mock_owner_key_util.h
index c3f52bd..9c598e0 100644
--- a/chrome/browser/chromeos/settings/mock_owner_key_util.h
+++ b/chrome/browser/chromeos/settings/mock_owner_key_util.h
@@ -23,6 +23,9 @@ class MockOwnerKeyUtil : public OwnerKeyUtil {
virtual bool ImportPublicKey(std::vector<uint8>* output) OVERRIDE;
virtual crypto::RSAPrivateKey* FindPrivateKey(
const std::vector<uint8>& key) OVERRIDE;
+ virtual crypto::RSAPrivateKey* FindPrivateKeyInSlot(
+ const std::vector<uint8>& key,
+ PK11SlotInfo* slot) OVERRIDE;
virtual bool IsPublicKeyPresent() OVERRIDE;
// Clears the public and private keys.
diff --git a/chrome/browser/chromeos/settings/owner_key_util.cc b/chrome/browser/chromeos/settings/owner_key_util.cc
index d98fe07..752c372 100644
--- a/chrome/browser/chromeos/settings/owner_key_util.cc
+++ b/chrome/browser/chromeos/settings/owner_key_util.cc
@@ -70,6 +70,12 @@ crypto::RSAPrivateKey* OwnerKeyUtilImpl::FindPrivateKey(
return crypto::RSAPrivateKey::FindFromPublicKeyInfo(key);
}
+crypto::RSAPrivateKey* OwnerKeyUtilImpl::FindPrivateKeyInSlot(
+ const std::vector<uint8>& key,
+ PK11SlotInfo* slot) {
+ return crypto::RSAPrivateKey::FindFromPublicKeyInfoInSlot(key, slot);
+}
+
bool OwnerKeyUtilImpl::IsPublicKeyPresent() {
return base::PathExists(key_file_);
}
diff --git a/chrome/browser/chromeos/settings/owner_key_util.h b/chrome/browser/chromeos/settings/owner_key_util.h
index 8e42a50..8522db7 100644
--- a/chrome/browser/chromeos/settings/owner_key_util.h
+++ b/chrome/browser/chromeos/settings/owner_key_util.h
@@ -13,6 +13,7 @@
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
+#include "net/cert/x509_util_nss.h"
namespace base {
class FilePath;
@@ -38,9 +39,19 @@ class OwnerKeyUtil : public base::RefCountedThreadSafe<OwnerKeyUtil> {
// Looks for the private key associated with |key| in the default slot,
// and returns it if it can be found. Returns NULL otherwise.
// Caller takes ownership.
+ //
+ // TODO (ygorshenin@): this function is deprecated and should be
+ // removed, see crbug.com/372316.
virtual crypto::RSAPrivateKey* FindPrivateKey(
const std::vector<uint8>& key) = 0;
+ // Looks for the private key associated with |key| in the |slot|
+ // and returns it if it can be found. Returns NULL otherwise.
+ // Caller takes ownership.
+ virtual crypto::RSAPrivateKey* FindPrivateKeyInSlot(
+ const std::vector<uint8>& key,
+ PK11SlotInfo* slot) = 0;
+
// Checks whether the public key is present in the file system.
virtual bool IsPublicKeyPresent() = 0;
@@ -63,6 +74,9 @@ class OwnerKeyUtilImpl : public OwnerKeyUtil {
virtual bool ImportPublicKey(std::vector<uint8>* output) OVERRIDE;
virtual crypto::RSAPrivateKey* FindPrivateKey(
const std::vector<uint8>& key) OVERRIDE;
+ virtual crypto::RSAPrivateKey* FindPrivateKeyInSlot(
+ const std::vector<uint8>& key,
+ PK11SlotInfo* slot) OVERRIDE;
virtual bool IsPublicKeyPresent() OVERRIDE;
protected:
diff --git a/chrome/browser/chromeos/settings/session_manager_operation.cc b/chrome/browser/chromeos/settings/session_manager_operation.cc
index b95d283..f8ec443 100644
--- a/chrome/browser/chromeos/settings/session_manager_operation.cc
+++ b/chrome/browser/chromeos/settings/session_manager_operation.cc
@@ -11,8 +11,11 @@
#include "base/stl_util.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/chromeos/login/users/user.h"
+#include "chrome/browser/chromeos/login/users/user_manager.h"
#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
#include "chrome/browser/chromeos/settings/owner_key_util.h"
+#include "chrome/browser/net/nss_context.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/rsa_private_key.h"
@@ -72,16 +75,19 @@ void SessionManagerOperation::ReportResult(
void SessionManagerOperation::EnsureOwnerKey(const base::Closure& callback) {
if (force_key_load_ || !owner_key_.get() || !owner_key_->public_key()) {
scoped_refptr<base::TaskRunner> task_runner =
- content::BrowserThread::GetBlockingPool()->
- GetTaskRunnerWithShutdownBehavior(
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
+ content::BrowserThread::GetBlockingPool()
+ ->GetTaskRunnerWithShutdownBehavior(
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
base::PostTaskAndReplyWithResult(
task_runner.get(),
FROM_HERE,
base::Bind(&SessionManagerOperation::LoadOwnerKey,
- owner_key_util_, owner_key_),
+ owner_key_util_,
+ owner_key_,
+ slot_),
base::Bind(&SessionManagerOperation::StoreOwnerKey,
- weak_factory_.GetWeakPtr(), callback));
+ weak_factory_.GetWeakPtr(),
+ callback));
} else {
callback.Run();
}
@@ -90,7 +96,8 @@ void SessionManagerOperation::EnsureOwnerKey(const base::Closure& callback) {
// static
scoped_refptr<OwnerKey> SessionManagerOperation::LoadOwnerKey(
scoped_refptr<OwnerKeyUtil> util,
- scoped_refptr<OwnerKey> current_key) {
+ scoped_refptr<OwnerKey> current_key,
+ PK11SlotInfo* slot) {
scoped_ptr<std::vector<uint8> > public_key;
scoped_ptr<crypto::RSAPrivateKey> private_key;
@@ -109,7 +116,7 @@ scoped_refptr<OwnerKey> SessionManagerOperation::LoadOwnerKey(
}
if (public_key.get() && !private_key.get()) {
- private_key.reset(util->FindPrivateKey(*public_key));
+ private_key.reset(util->FindPrivateKeyInSlot(*public_key, slot));
if (!private_key.get())
VLOG(1) << "Failed to load private owner key.";
}
diff --git a/chrome/browser/chromeos/settings/session_manager_operation.h b/chrome/browser/chromeos/settings/session_manager_operation.h
index f15e0eb..6d7d566 100644
--- a/chrome/browser/chromeos/settings/session_manager_operation.h
+++ b/chrome/browser/chromeos/settings/session_manager_operation.h
@@ -11,6 +11,7 @@
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/chromeos/policy/device_cloud_policy_validator.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h"
+#include "net/cert/x509_util_nss.h"
namespace enterprise_management {
class ChromeDeviceSettingsProto;
@@ -66,6 +67,9 @@ class SessionManagerOperation {
force_key_load_ = force_key_load;
}
+ void set_username(const std::string& username) { username_ = username; }
+ void set_slot(PK11SlotInfo* slot) { slot_ = slot; }
+
protected:
// Runs the operation. The result is reported through |callback_|.
virtual void Run() = 0;
@@ -88,7 +92,8 @@ class SessionManagerOperation {
// Loads the owner key from disk. Must be run on a thread that can do I/O.
static scoped_refptr<OwnerKey> LoadOwnerKey(
scoped_refptr<OwnerKeyUtil> util,
- scoped_refptr<OwnerKey> current_key);
+ scoped_refptr<OwnerKey> current_key,
+ PK11SlotInfo* slot);
// Stores the owner key loaded by LoadOwnerKey and calls |callback|.
void StoreOwnerKey(const base::Closure& callback,
@@ -112,6 +117,8 @@ class SessionManagerOperation {
scoped_refptr<OwnerKey> owner_key_;
bool force_key_load_;
+ std::string username_;
+ PK11SlotInfo* slot_;
bool is_loading_;
scoped_ptr<enterprise_management::PolicyData> policy_data_;
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 6bca265..90cfa30 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -65,6 +65,7 @@
#include "chrome/browser/policy/cloud/user_cloud_policy_invalidator_factory.h"
#include "chrome/browser/policy/schema_registry_service_factory.h"
#if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/ownership/owner_settings_service_factory.h"
#include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
#include "chrome/browser/chromeos/policy/recommendation_restorer_factory.h"
#include "chrome/browser/chromeos/policy/user_cloud_policy_manager_factory_chromeos.h"
@@ -214,6 +215,7 @@ EnsureBrowserContextKeyedServiceFactoriesBuilt() {
policy::ProfilePolicyConnectorFactory::GetInstance();
#if defined(ENABLE_CONFIGURATION_POLICY)
#if defined(OS_CHROMEOS)
+ chromeos::OwnerSettingsServiceFactory::GetInstance();
policy::PolicyCertServiceFactory::GetInstance();
policy::RecommendationRestorerFactory::GetInstance();
policy::UserCloudPolicyManagerFactoryChromeOS::GetInstance();
diff --git a/chrome/chrome_browser_chromeos.gypi b/chrome/chrome_browser_chromeos.gypi
index 7da1c7f..6e41a27 100644
--- a/chrome/chrome_browser_chromeos.gypi
+++ b/chrome/chrome_browser_chromeos.gypi
@@ -746,6 +746,10 @@
'browser/chromeos/options/wifi_config_view.h',
'browser/chromeos/options/wimax_config_view.cc',
'browser/chromeos/options/wimax_config_view.h',
+ 'browser/chromeos/ownership/owner_settings_service.cc',
+ 'browser/chromeos/ownership/owner_settings_service.h',
+ 'browser/chromeos/ownership/owner_settings_service_factory.cc',
+ 'browser/chromeos/ownership/owner_settings_service_factory.h',
'browser/chromeos/policy/app_pack_updater.cc',
'browser/chromeos/policy/app_pack_updater.h',
'browser/chromeos/policy/auto_enrollment_client.cc',
diff --git a/crypto/rsa_private_key.h b/crypto/rsa_private_key.h
index 4453845..cb19067 100644
--- a/crypto/rsa_private_key.h
+++ b/crypto/rsa_private_key.h
@@ -206,6 +206,16 @@ class CRYPTO_EXPORT RSAPrivateKey {
// created in the key database.
static RSAPrivateKey* FindFromPublicKeyInfo(
const std::vector<uint8>& input);
+
+ // Import an existing public key, and then search for the private
+ // half in the slot specified by |slot|. The format of the public
+ // key blob is is an X509 SubjectPublicKeyInfo block. This can return
+ // NULL if initialization fails or the private key cannot be found.
+ // The caller takes ownership of the returned object, but nothing new
+ // is created in the slot.
+ static RSAPrivateKey* FindFromPublicKeyInfoInSlot(
+ const std::vector<uint8>& input,
+ PK11SlotInfo* slot);
#endif
#if defined(USE_OPENSSL)
@@ -254,6 +264,14 @@ class CRYPTO_EXPORT RSAPrivateKey {
bool sensitive);
#endif
+#if defined(USE_NSS)
+ // Import an existing public key. The format of the public key blob
+ // is an X509 SubjectPublicKeyInfo block. This can return NULL if
+ // initialization fails. The caller takes ownership of the returned
+ // object. Note that this method doesn't initialize the |key_| member.
+ static RSAPrivateKey* InitPublicPart(const std::vector<uint8>& input);
+#endif
+
#if defined(USE_OPENSSL)
EVP_PKEY* key_;
#else
diff --git a/crypto/rsa_private_key_nss.cc b/crypto/rsa_private_key_nss.cc
index bd54c2e..078544d 100644
--- a/crypto/rsa_private_key_nss.cc
+++ b/crypto/rsa_private_key_nss.cc
@@ -38,6 +38,37 @@ static bool ReadAttribute(SECKEYPrivateKey* key,
return true;
}
+#if defined(USE_NSS)
+struct PublicKeyInfoDeleter {
+ inline void operator()(CERTSubjectPublicKeyInfo* spki) {
+ SECKEY_DestroySubjectPublicKeyInfo(spki);
+ }
+};
+
+typedef scoped_ptr<CERTSubjectPublicKeyInfo, PublicKeyInfoDeleter>
+ ScopedPublicKeyInfo;
+
+// The function decodes RSA public key from the |input|.
+crypto::ScopedSECKEYPublicKey GetRSAPublicKey(const std::vector<uint8>& input) {
+ // First, decode and save the public key.
+ SECItem key_der;
+ key_der.type = siBuffer;
+ key_der.data = const_cast<unsigned char*>(&input[0]);
+ key_der.len = input.size();
+
+ ScopedPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der));
+ if (!spki)
+ return crypto::ScopedSECKEYPublicKey();
+
+ crypto::ScopedSECKEYPublicKey result(SECKEY_ExtractPublicKey(spki.get()));
+
+ // Make sure the key is an RSA key.. If not, that's an error.
+ if (!result || result->keyType != rsaKey)
+ return crypto::ScopedSECKEYPublicKey();
+ return result.Pass();
+}
+#endif // defined(USE_NSS)
+
} // namespace
namespace crypto {
@@ -112,35 +143,9 @@ RSAPrivateKey* RSAPrivateKey::CreateFromKey(SECKEYPrivateKey* key) {
// static
RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
const std::vector<uint8>& input) {
- EnsureNSSInit();
-
- scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-
- // First, decode and save the public key.
- SECItem key_der;
- key_der.type = siBuffer;
- key_der.data = const_cast<unsigned char*>(&input[0]);
- key_der.len = input.size();
-
- CERTSubjectPublicKeyInfo* spki =
- SECKEY_DecodeDERSubjectPublicKeyInfo(&key_der);
- if (!spki) {
- NOTREACHED();
- return NULL;
- }
-
- result->public_key_ = SECKEY_ExtractPublicKey(spki);
- SECKEY_DestroySubjectPublicKeyInfo(spki);
- if (!result->public_key_) {
- NOTREACHED();
- return NULL;
- }
-
- // Make sure the key is an RSA key. If not, that's an error
- if (result->public_key_->keyType != rsaKey) {
- NOTREACHED();
+ scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
+ if (!result)
return NULL;
- }
ScopedSECItem ck_id(
PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
@@ -166,6 +171,30 @@ RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfo(
// We didn't find the key.
return NULL;
}
+
+// static
+RSAPrivateKey* RSAPrivateKey::FindFromPublicKeyInfoInSlot(
+ const std::vector<uint8>& input,
+ PK11SlotInfo* slot) {
+ if (!slot)
+ return NULL;
+
+ scoped_ptr<RSAPrivateKey> result(InitPublicPart(input));
+ if (!result)
+ return NULL;
+
+ ScopedSECItem ck_id(
+ PK11_MakeIDFromPubKey(&(result->public_key_->u.rsa.modulus)));
+ if (!ck_id.get()) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ result->key_ = PK11_FindKeyByKeyID(slot, ck_id.get(), NULL);
+ if (!result->key_)
+ return NULL;
+ return result.release();
+}
#endif
RSAPrivateKey* RSAPrivateKey::Copy() const {
@@ -273,4 +302,20 @@ RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfoWithParams(
return result.release();
}
+#if defined(USE_NSS)
+// static
+RSAPrivateKey* RSAPrivateKey::InitPublicPart(const std::vector<uint8>& input) {
+ EnsureNSSInit();
+
+ scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey());
+ result->public_key_ = GetRSAPublicKey(input).release();
+ if (!result->public_key_) {
+ NOTREACHED();
+ return NULL;
+ }
+
+ return result.release();
+}
+#endif // defined(USE_NSS)
+
} // namespace crypto