Commit cc7df610 authored by tbarzic's avatar tbarzic Committed by Commit bot

This adds utility for creating user-specific RSA key pair in system TPM slot

that is used for easy sign-in protocol, and for signing data provided by
Easy Unlock app using the created private key.

Per user public keys are kept in the local state and added to challenge data when challenges
are created (while resetting cryptohome sign-in secrets).
During challenge creation, existence of the Easy Sign-in TPM key is
checked for user, and the key pair is created if necessary.
Additionally, key pair presence is ensured when EasyUnlockService is
started after user log in. This is done to handle the case where Easy Unlock
has previously been set up. At this time, it is verified that
the private key actually
exists in the TPM slot.

Mapping from user id to public TPM key is kept in local state
so it can be accessed on sign in screen (as it will be needed before a user logs in;
the public key is used to identify the private key in the system slot)

BUG=409027
TEST=Confirmed easy sign-in works

Review URL: https://codereview.chromium.org/729803002

Cr-Commit-Position: refs/heads/master@{#308431}
parent 5cc20bac
...@@ -35,35 +35,6 @@ const int kEasyUnlockKeyRevision = 1; ...@@ -35,35 +35,6 @@ const int kEasyUnlockKeyRevision = 1;
const int kEasyUnlockKeyPrivileges = const int kEasyUnlockKeyPrivileges =
cryptohome::PRIV_MOUNT | cryptohome::PRIV_ADD | cryptohome::PRIV_REMOVE; cryptohome::PRIV_MOUNT | cryptohome::PRIV_ADD | cryptohome::PRIV_REMOVE;
// TODO(xiyuan): Use real keys. http://crbug.com/409027
const char kTpmPubKey[] = {
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xdc, 0xfa, 0x10,
0xff, 0xa7, 0x46, 0x65, 0xae, 0xef, 0x87, 0x09, 0x74, 0xea, 0x99, 0xb2,
0xce, 0x54, 0x54, 0x7c, 0x67, 0xf4, 0x2a, 0xaa, 0x6d, 0xd0, 0x1a, 0x2e,
0xd3, 0x1f, 0xd2, 0xc2, 0x42, 0xaf, 0x5d, 0x96, 0x0b, 0x1f, 0x89, 0x6e,
0xfb, 0xa3, 0x54, 0x3d, 0x65, 0x54, 0xb7, 0xb1, 0x26, 0x87, 0xa5, 0xc6,
0x88, 0x56, 0x8f, 0x32, 0xe0, 0x26, 0xc5, 0x32, 0xd2, 0x59, 0x93, 0xb9,
0x7a, 0x7c, 0x28, 0x42, 0xec, 0x2b, 0x8e, 0x12, 0x35, 0xee, 0xe2, 0x41,
0x4d, 0x25, 0x80, 0x6c, 0x6f, 0xba, 0xe4, 0x38, 0x95, 0x4e, 0xba, 0x9d,
0x27, 0x55, 0xdf, 0xfe, 0xeb, 0x1b, 0x47, 0x70, 0x09, 0x57, 0x81, 0x5a,
0x8a, 0x23, 0x3f, 0x97, 0xb1, 0xa2, 0xc7, 0x14, 0xb3, 0xe2, 0xbe, 0x2e,
0x42, 0xd8, 0xbe, 0x30, 0xb1, 0x96, 0x15, 0x82, 0xea, 0x99, 0x48, 0x91,
0x0e, 0x0c, 0x79, 0x7c, 0x50, 0xfc, 0x4b, 0xb4, 0x55, 0xf0, 0xfc, 0x45,
0xe5, 0xe3, 0x4e, 0x63, 0x96, 0xac, 0x5b, 0x2d, 0x46, 0x23, 0x93, 0x65,
0xc7, 0xf3, 0xda, 0xaf, 0x09, 0x09, 0x40, 0x0d, 0x61, 0xcf, 0x9e, 0x0c,
0xa8, 0x08, 0x3e, 0xaf, 0x33, 0x5a, 0x6f, 0xce, 0xb6, 0x86, 0x3c, 0x1c,
0xc0, 0xcf, 0x5a, 0x17, 0x1a, 0xff, 0x35, 0xd9, 0x7e, 0xcb, 0x60, 0xef,
0x25, 0x1c, 0x7e, 0xc2, 0xc8, 0xa5, 0x88, 0x36, 0x1d, 0xc4, 0x12, 0x66,
0xa4, 0xb7, 0xed, 0x38, 0xb0, 0x26, 0xce, 0x0d, 0x53, 0x78, 0x64, 0x49,
0xdb, 0xb1, 0x1a, 0x06, 0xea, 0x33, 0xcc, 0xf1, 0xec, 0xa5, 0x75, 0x20,
0x1e, 0xd1, 0xaa, 0x47, 0x3e, 0xd1, 0x18, 0x7e, 0xc1, 0xd8, 0xa7, 0x44,
0xea, 0x34, 0x5b, 0xed, 0x7e, 0xa0, 0x0e, 0xe4, 0xe8, 0x1b, 0xba, 0x46,
0x48, 0x60, 0x1d, 0xd5, 0x37, 0xdc, 0x91, 0x01, 0x5d, 0x31, 0xf0, 0xc2,
0xc1, 0x02, 0x03, 0x01, 0x00, 0x01
};
} // namespace } // namespace
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
...@@ -262,9 +233,11 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnChallengeGenerated( ...@@ -262,9 +233,11 @@ void EasyUnlockCreateKeysOperation::ChallengeCreator::OnChallengeGenerated(
EasyUnlockCreateKeysOperation::EasyUnlockCreateKeysOperation( EasyUnlockCreateKeysOperation::EasyUnlockCreateKeysOperation(
const UserContext& user_context, const UserContext& user_context,
const std::string& tpm_public_key,
const EasyUnlockDeviceKeyDataList& devices, const EasyUnlockDeviceKeyDataList& devices,
const CreateKeysCallback& callback) const CreateKeysCallback& callback)
: user_context_(user_context), : user_context_(user_context),
tpm_public_key_(tpm_public_key),
devices_(devices), devices_(devices),
callback_(callback), callback_(callback),
key_creation_index_(0), key_creation_index_(0),
...@@ -318,7 +291,7 @@ void EasyUnlockCreateKeysOperation::CreateKeyForDeviceAtIndex(size_t index) { ...@@ -318,7 +291,7 @@ void EasyUnlockCreateKeysOperation::CreateKeyForDeviceAtIndex(size_t index) {
challenge_creator_.reset(new ChallengeCreator( challenge_creator_.reset(new ChallengeCreator(
user_key, user_key,
raw_session_key, raw_session_key,
std::string(kTpmPubKey, arraysize(kTpmPubKey)), tpm_public_key_,
device, device,
base::Bind(&EasyUnlockCreateKeysOperation::OnChallengeCreated, base::Bind(&EasyUnlockCreateKeysOperation::OnChallengeCreated,
weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(),
......
...@@ -24,6 +24,7 @@ class EasyUnlockCreateKeysOperation { ...@@ -24,6 +24,7 @@ class EasyUnlockCreateKeysOperation {
typedef base::Callback<void (bool success)> CreateKeysCallback; typedef base::Callback<void (bool success)> CreateKeysCallback;
EasyUnlockCreateKeysOperation( EasyUnlockCreateKeysOperation(
const UserContext& user_context, const UserContext& user_context,
const std::string& tpm_public_key,
const EasyUnlockDeviceKeyDataList& devices, const EasyUnlockDeviceKeyDataList& devices,
const CreateKeysCallback& callback); const CreateKeysCallback& callback);
~EasyUnlockCreateKeysOperation(); ~EasyUnlockCreateKeysOperation();
...@@ -45,6 +46,7 @@ class EasyUnlockCreateKeysOperation { ...@@ -45,6 +46,7 @@ class EasyUnlockCreateKeysOperation {
cryptohome::MountError return_code); cryptohome::MountError return_code);
UserContext user_context_; UserContext user_context_;
std::string tpm_public_key_;
EasyUnlockDeviceKeyDataList devices_; EasyUnlockDeviceKeyDataList devices_;
CreateKeysCallback callback_; CreateKeysCallback callback_;
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
namespace chromeos { namespace chromeos {
...@@ -45,14 +47,55 @@ void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context, ...@@ -45,14 +47,55 @@ void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context,
// Must have the secret. // Must have the secret.
DCHECK(!user_context.GetKey()->GetSecret().empty()); DCHECK(!user_context.GetKey()->GetSecret().empty());
base::Closure do_refresh_keys = base::Bind(
&EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent,
weak_ptr_factory_.GetWeakPtr(),
user_context,
base::Owned(remote_devices.DeepCopy()),
callback);
EasyUnlockTpmKeyManager* tpm_key_manager =
EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser(
user_context.GetUserID());
if (!tpm_key_manager) {
LOG(ERROR) << "No TPM key manager.";
callback.Run(false);
return;
}
if (tpm_key_manager->PrepareTpmKey(false /* check_private_key */,
do_refresh_keys)) {
do_refresh_keys.Run();
} else {
// In case Chrome is supposed to restart to apply user session flags, the
// Chrome restart will be postponed until Easy Sign-in keys are refreshed.
// This is to ensure that creating TPM key does not hang if TPM system
// loading takes too much time. Note that in normal circumstances the
// chances that TPM slot cannot be loaded should be extremely low.
// TODO(tbarzic): Add some metrics to measure if the timeout even gets hit.
tpm_key_manager->StartGetSystemSlotTimeoutMs(2000);
}
}
void EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent(
const UserContext& user_context,
base::ListValue* remote_devices,
const RefreshKeysCallback& callback) {
EasyUnlockTpmKeyManager* tpm_key_manager =
EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser(
user_context.GetUserID());
std::string tpm_public_key =
tpm_key_manager->GetPublicTpmKey(user_context.GetUserID());
EasyUnlockDeviceKeyDataList devices; EasyUnlockDeviceKeyDataList devices;
if (!RemoteDeviceListToDeviceDataList(remote_devices, &devices)) if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices))
devices.clear(); devices.clear();
// Only one pending request. // Only one pending request.
DCHECK(!HasPendingOperations()); DCHECK(!HasPendingOperations());
create_keys_op_.reset(new EasyUnlockCreateKeysOperation( create_keys_op_.reset(new EasyUnlockCreateKeysOperation(
user_context, user_context,
tpm_public_key,
devices, devices,
base::Bind(&EasyUnlockKeyManager::OnKeysCreated, base::Bind(&EasyUnlockKeyManager::OnKeysCreated,
weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(),
......
...@@ -82,6 +82,10 @@ class EasyUnlockKeyManager { ...@@ -82,6 +82,10 @@ class EasyUnlockKeyManager {
static std::string GetKeyLabel(size_t key_index); static std::string GetKeyLabel(size_t key_index);
private: private:
void RefreshKeysWithTpmKeyPresent(const UserContext& user_context,
base::ListValue* remote_devices,
const RefreshKeysCallback& callback);
// Returns true if there are pending operations. // Returns true if there are pending operations.
bool HasPendingOperations() const; bool HasPendingOperations() const;
......
// 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_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_H_
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/keyed_service/core/keyed_service.h"
#include "crypto/scoped_nss_types.h"
class PrefRegistrySimple;
class PrefService;
// Manages per user RSA keys stored in system TPM slot used in easy signin
// protocol. The keys are used to sign a nonce exchanged during signin.
class EasyUnlockTpmKeyManager : public KeyedService {
public:
// Registers local state prefs used to store public RSA keys per user.
static void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
// Clears local state for user. Should be called when a user is removed.
static void ResetLocalStateForUser(const std::string& user_id);
// |user_id|: Id for the user associated with the service. Empty for signin
// service.
// |local_state|: The local state prefs.
EasyUnlockTpmKeyManager(const std::string& user_id, PrefService* local_state);
~EasyUnlockTpmKeyManager() override;
// Checks if the RSA public key is set in the local state. If not, creates
// one. If the key presence can be confirmed, immediately returns true and
// |callback| never gets called, otherwise returns false (callback is called
// when the key presence is confirmed).
// Must not be called for signin profile.
// |check_private_key|: If public RSA key is set in the local state, whether
// the method should confirm that the private key is present in the system
// slot. If the private key cannot be found, a new key pair will be
// created for the user.
// Note: Checking TPM for the private key is more expensive than only
// checking local state, so setting this to |false| should be preferable.
// Generally, if public key is set in local state, the private key should
// be present in the system TPM slot. This is used to make sure that easy
// signin does not remain permanently broken if something goes wrong.
// |callback|: If the method cannot return immediately, called when the key
// pair presence is confirmed (or a key pair for the user is created).
bool PrepareTpmKey(bool check_private_key,
const base::Closure& callback);
// If called, posts a delayed task that cancels |PrepareTpmKey| and all other
// started timeouts in case getting system slot takes more than |timeout_ms|.
// In the case getting system slot times out, |PrepareTpmKey| callback will
// be called with an empty public key.
// Must be called after |PrepareTpmKey| to have the intended effect.
bool StartGetSystemSlotTimeoutMs(size_t timeout_ms);
// Gets the public RSA key for user. The key is retrieved from local state.
std::string GetPublicTpmKey(const std::string& user_id);
// Signs |data| using private RSA key associated with |user_id| stored in TPM
// system slot.
void SignUsingTpmKey(
const std::string& user_id,
const std::string& data,
const base::Callback<void(const std::string& data)> callback);
private:
enum CreateTpmKeyState {
CREATE_TPM_KEY_NOT_STARTED,
CREATE_TPM_KEY_WAITING_FOR_SYSTEM_SLOT,
CREATE_TPM_KEY_GOT_SYSTEM_SLOT,
CREATE_TPM_KEY_DONE
};
// Utility method for setting public key values in local state.
// Note that the keys are saved base64 encoded.
void SetKeyInLocalState(const std::string& user_id,
const std::string& value);
// Called when TPM system slot is initialized and ready to be used.
// It creates RSA key pair for the user in the system slot.
// When the key pair is created, |OnTpmKeyCreated| will be called with the
// created public key.
// The key will not be created if |public_key| is non-empty and the associated
// private key can be found in the slot. Instead |OnTpmKeyCreated| will be
// called with |public_key|.
void CreateKeyInSystemSlot(const std::string& public_key,
crypto::ScopedPK11Slot system_slot);
// Called when TPM system slot is initialized and ready to be used.
// It schedules data signing operation on a worker thread. The data is signed
// by a private key stored in |system_slot| and identified by |public_key|
// (a private key that is part of the same RSA key pair as |public_key|).
// Once data is signed |callback| is called with the signed data.
void SignDataWithSystemSlot(
const std::string& public_key,
const std::string& data,
const base::Callback<void(const std::string& data)> callback,
crypto::ScopedPK11Slot system_slot);
// Called when a RSA key pair is created for a user in TPM system slot.
// It saves the pulic key in the local state and runs queued up
// |PrepareTpmKey| callbacks.
void OnTpmKeyCreated(const std::string& public_key);
// Called when data signing requested in |SignUsingTpmKey| is done.
// It runs |callback| with the created |signature|. On error the callback will
// be run with an empty string.
void OnDataSigned(
const base::Callback<void(const std::string&)>& callback,
const std::string& signature);
std::string user_id_;
PrefService* local_state_;
// The current TPM key creation state. If key creation is in progress,
// callbacks for further |PrepareTpmKey| will be queued up and run when the
// key is created. All queued callbacks will be run with the same key value.
CreateTpmKeyState create_tpm_key_state_;
// Queued up |PrepareTpmKey| callbacks.
std::vector<base::Closure> prepare_tpm_key_callbacks_;
base::WeakPtrFactory<EasyUnlockTpmKeyManager> get_tpm_slot_weak_ptr_factory_;
base::WeakPtrFactory<EasyUnlockTpmKeyManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockTpmKeyManager);
};
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_H_
// 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/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
#include "base/memory/singleton.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/profiles/incognito_helpers.h"
#include "chrome/browser/profiles/profile.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/user_manager/user.h"
namespace {
PrefService* GetLocalState() {
return g_browser_process ? g_browser_process->local_state() : NULL;
}
} // namespace
// static
EasyUnlockTpmKeyManagerFactory* EasyUnlockTpmKeyManagerFactory::GetInstance() {
return Singleton<EasyUnlockTpmKeyManagerFactory>::get();
}
// static
EasyUnlockTpmKeyManager* EasyUnlockTpmKeyManagerFactory::Get(
content::BrowserContext* browser_context) {
return static_cast<EasyUnlockTpmKeyManager*>(
EasyUnlockTpmKeyManagerFactory::GetInstance()
->GetServiceForBrowserContext(browser_context, true));
}
EasyUnlockTpmKeyManager* EasyUnlockTpmKeyManagerFactory::GetForUser(
const std::string& user_id) {
const user_manager::User* user =
user_manager::UserManager::Get()->FindUser(user_id);
if (!user)
return NULL;
Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
if (!profile)
return NULL;
return EasyUnlockTpmKeyManagerFactory::Get(profile);
}
EasyUnlockTpmKeyManagerFactory::EasyUnlockTpmKeyManagerFactory()
: BrowserContextKeyedServiceFactory(
"EasyUnlockTpmKeyManager",
BrowserContextDependencyManager::GetInstance()) {
}
EasyUnlockTpmKeyManagerFactory::~EasyUnlockTpmKeyManagerFactory() {
}
KeyedService* EasyUnlockTpmKeyManagerFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
user_manager::User* user = NULL;
if (!chromeos::ProfileHelper::IsSigninProfile(profile))
user = chromeos::ProfileHelper::Get()->GetUserByProfile(profile);
return new EasyUnlockTpmKeyManager(user ? user->email() : std::string(),
GetLocalState());
}
content::BrowserContext* EasyUnlockTpmKeyManagerFactory::GetBrowserContextToUse(
content::BrowserContext* context) const {
return chrome::GetBrowserContextRedirectedInIncognito(context);
}
// 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_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_FACTORY_H_
#include <string>
#include "base/macros.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
namespace content {
class BrowserContext;
}
template <typename T> struct DefaultSingletonTraits;
class EasyUnlockTpmKeyManager;
// Singleton factory that builds and owns all EasyUnlockTpmKeyManager services.
class EasyUnlockTpmKeyManagerFactory
: public BrowserContextKeyedServiceFactory {
public:
static EasyUnlockTpmKeyManagerFactory* GetInstance();
static EasyUnlockTpmKeyManager* Get(content::BrowserContext* context);
static EasyUnlockTpmKeyManager* GetForUser(const std::string& user_id);
private:
friend struct DefaultSingletonTraits<EasyUnlockTpmKeyManagerFactory>;
EasyUnlockTpmKeyManagerFactory();
~EasyUnlockTpmKeyManagerFactory() override;
// BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
content::BrowserContext* GetBrowserContextToUse(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockTpmKeyManagerFactory);
};
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TPM_KEY_MANAGER_FACTORY_H_
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/chromeos_utils.h" #include "chrome/browser/chromeos/chromeos_utils.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
#include "chrome/browser/ui/webui/options/chromeos/user_image_source.h" #include "chrome/browser/ui/webui/options/chromeos/user_image_source.h"
#include "components/user_manager/user.h" #include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h" #include "components/user_manager/user_manager.h"
...@@ -607,12 +609,31 @@ bool EasyUnlockPrivateGetSignInChallengeFunction::RunAsync() { ...@@ -607,12 +609,31 @@ bool EasyUnlockPrivateGetSignInChallengeFunction::RunAsync() {
easy_unlock_private::GetSignInChallenge::Params::Create(*args_)); easy_unlock_private::GetSignInChallenge::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get()); EXTENSION_FUNCTION_VALIDATE(params.get());
#if defined(OS_CHROMEOS)
Profile* profile = Profile::FromBrowserContext(browser_context()); Profile* profile = Profile::FromBrowserContext(browser_context());
const std::string challenge = const std::string challenge =
EasyUnlockService::Get(profile)->GetChallenge(); EasyUnlockService::Get(profile)->GetChallenge();
// TODO(tbarzic): Implement nonce signing. if (!challenge.empty() && !params->nonce.empty()) {
OnDone(challenge, std::string() /* signed_nonce */); EasyUnlockTpmKeyManager* key_manager =
EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile);
if (!key_manager) {
SetError("No EasyUnlockTpmKeyManager.");
return false;
}
key_manager->SignUsingTpmKey(
EasyUnlockService::Get(profile)->GetUserEmail(),
params->nonce,
base::Bind(&EasyUnlockPrivateGetSignInChallengeFunction::OnDone,
this,
challenge));
} else {
OnDone(challenge, std::string());
}
return true; return true;
#else // if !defined(OS_CHROMEOS)
SetError("Sign-in not supported.");
return false;
#endif // defined(OS_CHROMEOS)
} }
void EasyUnlockPrivateGetSignInChallengeFunction::OnDone( void EasyUnlockPrivateGetSignInChallengeFunction::OnDone(
......
...@@ -40,10 +40,13 @@ ...@@ -40,10 +40,13 @@
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "base/sys_info.h" #include "base/sys_info.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h" #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
#include "chrome/browser/chromeos/login/session/user_session_manager.h" #include "chrome/browser/chromeos/login/session/user_session_manager.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h" #include "chromeos/dbus/power_manager_client.h"
#include "components/user_manager/user_manager.h"
#endif #endif
namespace { namespace {
...@@ -198,6 +201,7 @@ EasyUnlockService::EasyUnlockService(Profile* profile) ...@@ -198,6 +201,7 @@ EasyUnlockService::EasyUnlockService(Profile* profile)
: profile_(profile), : profile_(profile),
bluetooth_detector_(new BluetoothDetector(this)), bluetooth_detector_(new BluetoothDetector(this)),
shut_down_(false), shut_down_(false),
tpm_key_checked_(false),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
extensions::ExtensionSystem::Get(profile_)->ready().Post( extensions::ExtensionSystem::Get(profile_)->ready().Post(
FROM_HERE, FROM_HERE,
...@@ -232,6 +236,9 @@ void EasyUnlockService::RegisterProfilePrefs( ...@@ -232,6 +236,9 @@ void EasyUnlockService::RegisterProfilePrefs(
// static // static
void EasyUnlockService::RegisterPrefs(PrefRegistrySimple* registry) { void EasyUnlockService::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState); registry->RegisterDictionaryPref(prefs::kEasyUnlockHardlockState);
#if defined(OS_CHROMEOS)
EasyUnlockTpmKeyManager::RegisterLocalStatePrefs(registry);
#endif
} }
// static // static
...@@ -244,6 +251,10 @@ void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) { ...@@ -244,6 +251,10 @@ void EasyUnlockService::ResetLocalStateForUser(const std::string& user_id) {
DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState); DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
update->RemoveWithoutPathExpansion(user_id, NULL); update->RemoveWithoutPathExpansion(user_id, NULL);
#if defined(OS_CHROMEOS)
EasyUnlockTpmKeyManager::ResetLocalStateForUser(user_id);
#endif
} }
bool EasyUnlockService::IsAllowed() { bool EasyUnlockService::IsAllowed() {
...@@ -554,6 +565,7 @@ void EasyUnlockService::ReloadApp() { ...@@ -554,6 +565,7 @@ void EasyUnlockService::ReloadApp() {
void EasyUnlockService::UpdateAppState() { void EasyUnlockService::UpdateAppState() {
if (IsAllowed()) { if (IsAllowed()) {
EnsureTpmKeyPresentIfNeeded();
LoadApp(); LoadApp();
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
...@@ -691,3 +703,25 @@ void EasyUnlockService::PrepareForSuspend() { ...@@ -691,3 +703,25 @@ void EasyUnlockService::PrepareForSuspend() {
EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING); EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING);
} }
} }
void EasyUnlockService::EnsureTpmKeyPresentIfNeeded() {
if (tpm_key_checked_ || GetType() != TYPE_REGULAR || GetUserEmail().empty())
return;
#if defined(OS_CHROMEOS)
// If this is called before the session is started, the chances are Chrome
// is restarting in order to apply user flags. Don't check TPM keys in this
// case.
if (!user_manager::UserManager::Get() ||
!user_manager::UserManager::Get()->IsSessionStarted())
return;
// TODO(tbarzic): Set check_private_key only if previous sign-in attempt
// failed.
EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile_)
->PrepareTpmKey(true /* check_private_key */,
base::Closure());
#endif // defined(OS_CHROMEOS)
tpm_key_checked_ = true;
}
...@@ -255,6 +255,8 @@ class EasyUnlockService : public KeyedService { ...@@ -255,6 +255,8 @@ class EasyUnlockService : public KeyedService {
// Updates the service to state for handling system suspend. // Updates the service to state for handling system suspend.
void PrepareForSuspend(); void PrepareForSuspend();
void EnsureTpmKeyPresentIfNeeded();
Profile* profile_; Profile* profile_;
// Created lazily in |GetScreenlockStateHandler|. // Created lazily in |GetScreenlockStateHandler|.
...@@ -275,6 +277,8 @@ class EasyUnlockService : public KeyedService { ...@@ -275,6 +277,8 @@ class EasyUnlockService : public KeyedService {
// Whether the service has been shut down. // Whether the service has been shut down.
bool shut_down_; bool shut_down_;
bool tpm_key_checked_;
ObserverList<EasyUnlockServiceObserver> observers_; ObserverList<EasyUnlockServiceObserver> observers_;
base::WeakPtrFactory<EasyUnlockService> weak_ptr_factory_; base::WeakPtrFactory<EasyUnlockService> weak_ptr_factory_;
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/extensions_browser_client.h"
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
#include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/profiles/profile_helper.h"
#include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h" #include "chrome/browser/signin/easy_unlock_service_signin_chromeos.h"
#endif #endif
...@@ -36,6 +37,9 @@ EasyUnlockServiceFactory::EasyUnlockServiceFactory() ...@@ -36,6 +37,9 @@ EasyUnlockServiceFactory::EasyUnlockServiceFactory()
BrowserContextDependencyManager::GetInstance()) { BrowserContextDependencyManager::GetInstance()) {
DependsOn( DependsOn(
extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory()); extensions::ExtensionsBrowserClient::Get()->GetExtensionSystemFactory());
#if defined(OS_CHROMEOS)
DependsOn(EasyUnlockTpmKeyManagerFactory::GetInstance());
#endif
} }
EasyUnlockServiceFactory::~EasyUnlockServiceFactory() { EasyUnlockServiceFactory::~EasyUnlockServiceFactory() {
......
...@@ -166,13 +166,10 @@ void EasyUnlockServiceRegular::SetRemoteDevices( ...@@ -166,13 +166,10 @@ void EasyUnlockServiceRegular::SetRemoteDevices(
!devices.empty()) { !devices.empty()) {
// We may already have the password cached, so proceed to create the // We may already have the password cached, so proceed to create the
// cryptohome keys for sign-in or the system will be hardlocked. // cryptohome keys for sign-in or the system will be hardlocked.
chromeos::UserContext* user_context = chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager()
short_lived_user_context_->user_context(); ->RefreshKeys(
chromeos::EasyUnlockKeyManager* key_manager = *short_lived_user_context_->user_context(),
chromeos::UserSessionManager::GetInstance()->GetEasyUnlockKeyManager(); devices,
key_manager->RefreshKeys(
*user_context, devices,
base::Bind(&EasyUnlockServiceRegular::OnKeysRefreshedForSetDevices, base::Bind(&EasyUnlockServiceRegular::OnKeysRefreshedForSetDevices,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} else { } else {
......
...@@ -423,6 +423,10 @@ ...@@ -423,6 +423,10 @@
'browser/chromeos/login/easy_unlock/easy_unlock_reauth.h', 'browser/chromeos/login/easy_unlock/easy_unlock_reauth.h',
'browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc', 'browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.h', 'browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.h',
'browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h',
'browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h',
'browser/chromeos/login/easy_unlock/easy_unlock_types.cc', 'browser/chromeos/login/easy_unlock/easy_unlock_types.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_types.h', 'browser/chromeos/login/easy_unlock/easy_unlock_types.h',
'browser/chromeos/login/easy_unlock/short_lived_user_context.cc', 'browser/chromeos/login/easy_unlock/short_lived_user_context.cc',
......
...@@ -191,6 +191,7 @@ ...@@ -191,6 +191,7 @@
'browser/chromeos/locale_change_guard_unittest.cc', 'browser/chromeos/locale_change_guard_unittest.cc',
'browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc', 'browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc',
'browser/chromeos/login/auth/online_attempt_unittest.cc', 'browser/chromeos/login/auth/online_attempt_unittest.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_unittest.cc',
'browser/chromeos/login/error_screens_histogram_helper_unittest.cc', 'browser/chromeos/login/error_screens_histogram_helper_unittest.cc',
'browser/chromeos/login/existing_user_controller_auto_login_unittest.cc', 'browser/chromeos/login/existing_user_controller_auto_login_unittest.cc',
'browser/chromeos/login/hwid_checker_unittest.cc', 'browser/chromeos/login/hwid_checker_unittest.cc',
......
...@@ -2291,6 +2291,10 @@ const char kBrowserAddPersonEnabled[] = "profile.add_person_enabled"; ...@@ -2291,6 +2291,10 @@ const char kBrowserAddPersonEnabled[] = "profile.add_person_enabled";
// A dictionary that maps user id to hardlock state. // A dictionary that maps user id to hardlock state.
const char kEasyUnlockHardlockState[] = "easy_unlock.hardlock_state"; const char kEasyUnlockHardlockState[] = "easy_unlock.hardlock_state";
// A dictionary that maps user id to public part of RSA key pair used by
// Easy Sign-in for the user.
const char kEasyUnlockLocalStateTpmKeys[] = "easy_unlock.public_tpm_keys";
// The beginning of time span when we count user's "Nope" for the password // The beginning of time span when we count user's "Nope" for the password
// bubble. // bubble.
const char kPasswordBubbleTimeStamp[] = "password_bubble.timestamp"; const char kPasswordBubbleTimeStamp[] = "password_bubble.timestamp";
......
...@@ -810,6 +810,7 @@ extern const char kBrowserGuestModeEnabled[]; ...@@ -810,6 +810,7 @@ extern const char kBrowserGuestModeEnabled[];
extern const char kBrowserAddPersonEnabled[]; extern const char kBrowserAddPersonEnabled[];
extern const char kEasyUnlockHardlockState[]; extern const char kEasyUnlockHardlockState[];
extern const char kEasyUnlockLocalStateTpmKeys[];
extern const char kPasswordBubbleTimeStamp[]; extern const char kPasswordBubbleTimeStamp[];
extern const char kPasswordBubbleNopesCount[]; extern const char kPasswordBubbleNopesCount[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment