Commit a0e92b08 authored by xiyuan's avatar xiyuan Committed by Commit bot

cros: Create cryptohome keys for Easy sign-in.

- Add code to add/remove/get cryptohome keys for Easy sign-in;
- Add an EasyUnlockKeyManager to wrap the operations and provide an API;
- Re-create crypthome keys with pairing data in user prefs on user sign-in;

BUG=394640,394641

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

Cr-Commit-Position: refs/heads/master@{#294901}
parent b5ddaba9
...@@ -6348,6 +6348,12 @@ Keep your key file in a safe place. You will need it to create new versions of y ...@@ -6348,6 +6348,12 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_FLAGS_ENABLE_FIRST_RUN_UI_TRANSITIONS_DESCRIPTION" desc="Description for the flag to enable animated transition in the first-run tutorial."> <message name="IDS_FLAGS_ENABLE_FIRST_RUN_UI_TRANSITIONS_DESCRIPTION" desc="Description for the flag to enable animated transition in the first-run tutorial.">
If enabled, transitions during first-run tutorial are animated. If enabled, transitions during first-run tutorial are animated.
</message> </message>
<message name="IDS_FLAGS_ENABLE_EASY_SIGNIN_NAME" desc="Name of the Enable Easy signin flag.">
Enable Easy sign-in
</message>
<message name="IDS_FLAGS_ENABLE_EASY_SIGNIN_DESCRIPTION" desc="Description of the Enable Easy signin flag.">
Easy sign-in allows you to sign in your Chromebook when in proximity to your phone.
</message>
</if> </if>
<message name="IDS_FLAGS_ENABLE_STREAMLINED_HOSTED_APPS_NAME" desc="Name of the flag to enable streamlined hosted apps."> <message name="IDS_FLAGS_ENABLE_STREAMLINED_HOSTED_APPS_NAME" desc="Name of the flag to enable streamlined hosted apps.">
Enable experimental streamlined hosted apps. Enable experimental streamlined hosted apps.
......
...@@ -938,6 +938,13 @@ const Experiment kExperiments[] = { ...@@ -938,6 +938,13 @@ const Experiment kExperiments[] = {
kOsCrOS, kOsCrOS,
SINGLE_VALUE_TYPE(chromeos::switches::kEnableTouchpadThreeFingerClick) SINGLE_VALUE_TYPE(chromeos::switches::kEnableTouchpadThreeFingerClick)
}, },
{
"enable-easy-signin",
IDS_FLAGS_ENABLE_EASY_SIGNIN_NAME,
IDS_FLAGS_ENABLE_EASY_SIGNIN_DESCRIPTION,
kOsCrOSOwnerOnly,
SINGLE_VALUE_TYPE(chromeos::switches::kEnableEasySignin),
},
#endif #endif
#if defined(USE_ASH) #if defined(USE_ASH)
{ {
......
// 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_CREATE_KEYS_OPERATION_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_CREATE_KEYS_OPERATION_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h"
#include "chromeos/login/auth/user_context.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
class UserContext;
// A class to create Easy unlock cryptohome keys for the given user and devices.
class EasyUnlockCreateKeysOperation {
public:
typedef base::Callback<void (bool success)> CreateKeysCallback;
EasyUnlockCreateKeysOperation(
const UserContext& user_context,
const EasyUnlockDeviceKeyDataList& devices,
const CreateKeysCallback& callback);
~EasyUnlockCreateKeysOperation();
void Start();
private:
class ChallengeCreator;
void CreateKeyForDeviceAtIndex(size_t index);
void OnChallengeCreated(size_t index, bool success);
void OnGetSystemSalt(size_t index,
const std::string& system_salt);
void OnKeyCreated(size_t index,
bool success,
cryptohome::MountError return_code);
UserContext user_context_;
EasyUnlockDeviceKeyDataList devices_;
CreateKeysCallback callback_;
// Index of the key to be created.
size_t key_creation_index_;
scoped_ptr<ChallengeCreator> challenge_creator_;
base::WeakPtrFactory<EasyUnlockCreateKeysOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockCreateKeysOperation);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_CREATE_KEYS_OPERATION_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_get_keys_operation.h"
#include <vector>
#include "base/bind.h"
#include "base/logging.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
#include "google_apis/gaia/gaia_auth_util.h"
namespace chromeos {
EasyUnlockGetKeysOperation::EasyUnlockGetKeysOperation(
const UserContext& user_context,
const GetKeysCallback& callback)
: user_context_(user_context),
callback_(callback),
key_index_(0),
weak_ptr_factory_(this) {
}
EasyUnlockGetKeysOperation::~EasyUnlockGetKeysOperation() {
}
void EasyUnlockGetKeysOperation::Start() {
// TODO(xiyuan): Use ListKeyEx.
key_index_ = 0;
GetKeyData();
}
void EasyUnlockGetKeysOperation::GetKeyData() {
std::string canonicalized =
gaia::CanonicalizeEmail(user_context_.GetUserID());
cryptohome::Identification id(canonicalized);
cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx(
id,
EasyUnlockKeyManager::GetKeyLabel(key_index_),
base::Bind(&EasyUnlockGetKeysOperation::OnGetKeyData,
weak_ptr_factory_.GetWeakPtr()));
}
void EasyUnlockGetKeysOperation::OnGetKeyData(
bool success,
cryptohome::MountError return_code,
const std::vector<cryptohome::KeyDefinition>& key_definitions) {
if (!success || key_definitions.empty()) {
// MOUNT_ERROR_KEY_FAILURE is considered as success. Other error codes are
// treated as failures.
if (return_code == cryptohome::MOUNT_ERROR_NONE ||
return_code == cryptohome::MOUNT_ERROR_KEY_FAILURE) {
callback_.Run(true, devices_);
return;
}
LOG(ERROR) << "Easy unlock failed to get key data, code=" << return_code;
callback_.Run(false, EasyUnlockDeviceKeyDataList());
return;
}
DCHECK_EQ(1u, key_definitions.size());
const std::vector<cryptohome::KeyDefinition::ProviderData>& provider_data =
key_definitions.front().provider_data;
EasyUnlockDeviceKeyData device;
for (size_t i = 0; i < provider_data.size(); ++i) {
const cryptohome::KeyDefinition::ProviderData& entry = provider_data[i];
if (entry.name == kEasyUnlockKeyMetaNameBluetoothAddress) {
if (entry.bytes)
device.bluetooth_address = *entry.bytes;
else
NOTREACHED();
} else if (entry.name == kEasyUnlockKeyMetaNamePubKey) {
if (entry.bytes)
device.public_key = *entry.bytes;
else
NOTREACHED();
} else if (entry.name == kEasyUnlockKeyMetaNamePsk) {
if (entry.bytes)
device.psk = *entry.bytes;
else
NOTREACHED();
} else if (entry.name == kEasyUnlockKeyMetaNameChallenge) {
if (entry.bytes)
device.challenge = *entry.bytes;
else
NOTREACHED();
} else if (entry.name == kEasyUnlockKeyMetaNameWrappedSecret) {
if (entry.bytes)
device.wrapped_secret = *entry.bytes;
else
NOTREACHED();
} else {
LOG(WARNING) << "Unknown Easy unlock key data entry, name="
<< entry.name;
}
}
devices_.push_back(device);
++key_index_;
GetKeyData();
}
} // namespace chromeos
// 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_GET_KEYS_OPERATION_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_GET_KEYS_OPERATION_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h"
#include "chromeos/cryptohome/homedir_methods.h"
#include "chromeos/login/auth/user_context.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
class EasyUnlockGetKeysOperation {
public:
typedef base::Callback<void(bool success,
const EasyUnlockDeviceKeyDataList& data_list)>
GetKeysCallback;
EasyUnlockGetKeysOperation(const UserContext& user_context,
const GetKeysCallback& callback);
~EasyUnlockGetKeysOperation();
void Start();
private:
void GetKeyData();
void OnGetKeyData(
bool success,
cryptohome::MountError return_code,
const std::vector<cryptohome::KeyDefinition>& key_definitions);
UserContext user_context_;
GetKeysCallback callback_;
size_t key_index_;
EasyUnlockDeviceKeyDataList devices_;
base::WeakPtrFactory<EasyUnlockGetKeysOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockGetKeysOperation);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_GET_KEYS_OPERATION_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_key_manager.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
namespace chromeos {
namespace {
const char kKeyBluetoothAddress[] = "bluetoothAddress";
const char kKeyPermitRecord[] = "permitRecord";
const char kKeyId[] = "id";
const char kKeyPermitId[] = "permitRecord.id";
const char kKeyPsk[] = "psk";
const char kKeyLabelPrefix[] = "easy-unlock-";
} // namespace
EasyUnlockKeyManager::EasyUnlockKeyManager()
: operation_id_(0),
weak_ptr_factory_(this) {
}
EasyUnlockKeyManager::~EasyUnlockKeyManager() {
STLDeleteContainerPairSecondPointers(get_keys_ops_.begin(),
get_keys_ops_.end());
}
void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context,
const base::ListValue& remote_devices,
const RefreshKeysCallback& callback) {
// Must have the secret.
DCHECK(!user_context.GetKey()->GetSecret().empty());
EasyUnlockDeviceKeyDataList devices;
if (!RemoteDeviceListToDeviceDataList(remote_devices, &devices))
devices.clear();
// Only one pending request.
DCHECK(!HasPendingOperations());
create_keys_op_.reset(new EasyUnlockCreateKeysOperation(
user_context,
devices,
base::Bind(&EasyUnlockKeyManager::OnKeysCreated,
weak_ptr_factory_.GetWeakPtr(),
user_context,
devices,
callback)));
create_keys_op_->Start();
}
void EasyUnlockKeyManager::RemoveKeys(const UserContext& user_context,
size_t start_index,
const RemoveKeysCallback& callback) {
// Must have the secret.
DCHECK(!user_context.GetKey()->GetSecret().empty());
// Only one pending request.
DCHECK(!HasPendingOperations());
remove_keys_op_.reset(
new EasyUnlockRemoveKeysOperation(
user_context,
start_index,
base::Bind(&EasyUnlockKeyManager::OnKeysRemoved,
weak_ptr_factory_.GetWeakPtr(),
callback)));
remove_keys_op_->Start();
}
void EasyUnlockKeyManager::GetDeviceDataList(
const UserContext& user_context,
const GetDeviceDataListCallback& callback) {
// No write operations.
DCHECK(!create_keys_op_ && !remove_keys_op_);
const int op_id = GetNextOperationId();
scoped_ptr<EasyUnlockGetKeysOperation> op(new EasyUnlockGetKeysOperation(
user_context,
base::Bind(&EasyUnlockKeyManager::OnKeysFetched,
weak_ptr_factory_.GetWeakPtr(),
op_id,
callback)));
op->Start();
get_keys_ops_[op_id] = op.release();
}
// static
void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary(
const EasyUnlockDeviceKeyData& data,
base::DictionaryValue* dict) {
dict->SetString(kKeyBluetoothAddress, data.bluetooth_address);
dict->SetString(kKeyPsk, data.psk);
scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue);
permit_record->SetString(kKeyId, data.public_key);
dict->Set(kKeyPermitRecord, permit_record.release());
}
// static
bool EasyUnlockKeyManager::RemoteDeviceDictionaryToDeviceData(
const base::DictionaryValue& dict,
EasyUnlockDeviceKeyData* data) {
std::string bluetooth_address;
std::string public_key;
std::string psk;
if (!dict.GetString(kKeyBluetoothAddress, &bluetooth_address) ||
!dict.GetString(kKeyPermitId, &public_key) ||
!dict.GetString(kKeyPsk, &psk)) {
return false;
}
data->bluetooth_address.swap(bluetooth_address);
data->public_key.swap(public_key);
data->psk.swap(psk);
return true;
}
// static
void EasyUnlockKeyManager::DeviceDataListToRemoteDeviceList(
const EasyUnlockDeviceKeyDataList& data_list,
base::ListValue* device_list) {
device_list->Clear();
for (size_t i = 0; i < data_list.size(); ++i) {
scoped_ptr<base::DictionaryValue> device_dict(new base::DictionaryValue);
DeviceDataToRemoteDeviceDictionary(data_list[i], device_dict.get());
device_list->Append(device_dict.release());
}
}
// static
bool EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
const base::ListValue& device_list,
EasyUnlockDeviceKeyDataList* data_list) {
EasyUnlockDeviceKeyDataList parsed_devices;
for (base::ListValue::const_iterator it = device_list.begin();
it != device_list.end();
++it) {
const base::DictionaryValue* dict;
if (!(*it)->GetAsDictionary(&dict) || !dict)
return false;
EasyUnlockDeviceKeyData data;
if (!RemoteDeviceDictionaryToDeviceData(*dict, &data))
return false;
parsed_devices.push_back(data);
}
data_list->swap(parsed_devices);
return true;
}
// static
std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) {
return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index);
}
bool EasyUnlockKeyManager::HasPendingOperations() const {
return create_keys_op_ || remove_keys_op_ || !get_keys_ops_.empty();
}
int EasyUnlockKeyManager::GetNextOperationId() {
return ++operation_id_;
}
void EasyUnlockKeyManager::OnKeysCreated(
const UserContext& user_context,
const EasyUnlockDeviceKeyDataList& devices,
const RefreshKeysCallback& callback,
bool create_success) {
scoped_ptr<EasyUnlockCreateKeysOperation> op = create_keys_op_.Pass();
if (!callback.is_null())
callback.Run(create_success);
// Remove extra existing keys.
RemoveKeys(user_context, devices.size(), RemoveKeysCallback());
}
void EasyUnlockKeyManager::OnKeysRemoved(const RemoveKeysCallback& callback,
bool remove_success) {
scoped_ptr<EasyUnlockRemoveKeysOperation> op = remove_keys_op_.Pass();
if (!callback.is_null())
callback.Run(remove_success);
}
void EasyUnlockKeyManager::OnKeysFetched(
int op_id,
const GetDeviceDataListCallback& callback,
bool fetch_success,
const EasyUnlockDeviceKeyDataList& fetched_data) {
std::map<int, EasyUnlockGetKeysOperation*>::iterator it =
get_keys_ops_.find(op_id);
scoped_ptr<EasyUnlockGetKeysOperation> op;
if (it != get_keys_ops_.end()) {
op.reset(it->second);
get_keys_ops_.erase(it);
} else {
NOTREACHED();
}
if (!callback.is_null())
callback.Run(fetch_success, fetched_data);
}
} // namespace chromeos
// 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_KEY_MANAGER_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_KEY_MANAGER_H_
#include <map>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_remove_keys_operation.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_types.h"
namespace base {
class DictionaryValue;
class ListValue;
}
namespace chromeos {
class UserContext;
// A class to manage Easy unlock cryptohome keys.
class EasyUnlockKeyManager {
public:
typedef EasyUnlockCreateKeysOperation::CreateKeysCallback RefreshKeysCallback;
typedef EasyUnlockRemoveKeysOperation::RemoveKeysCallback RemoveKeysCallback;
typedef EasyUnlockGetKeysOperation::GetKeysCallback GetDeviceDataListCallback;
EasyUnlockKeyManager();
~EasyUnlockKeyManager();
// Nukes existing Easy unlock keys and creates new ones for the given
// |remote_devices| and the given |user_context|. |user_context| must have
// secret to allow keys to be created.
void RefreshKeys(const UserContext& user_context,
const base::ListValue& remote_devices,
const RefreshKeysCallback& callback);
// Remove Easy unlock keys starting at the given index for the given
// |user_context|.
void RemoveKeys(const UserContext& user_context,
size_t start_index,
const RemoveKeysCallback& callback);
// Retrieves the remote device data from cryptohome keys for the given
// |user_context|.
void GetDeviceDataList(const UserContext& user_context,
const GetDeviceDataListCallback& callback);
// Helpers to convert between DeviceData and remote device dictionary.
// DeviceDataToRemoteDeviceDictionary fills the remote device dictionary and
// always succeeds. RemoteDeviceDictionaryToDeviceData returns false if the
// conversion fails (missing required propery). Note that
// EasyUnlockDeviceKeyData contains a sub set of the remote device dictionary.
static void DeviceDataToRemoteDeviceDictionary(
const EasyUnlockDeviceKeyData& data,
base::DictionaryValue* dict);
static bool RemoteDeviceDictionaryToDeviceData(
const base::DictionaryValue& dict,
EasyUnlockDeviceKeyData* data);
// Helpers to convert between EasyUnlockDeviceKeyDataList and remote devices
// ListValue.
static void DeviceDataListToRemoteDeviceList(
const EasyUnlockDeviceKeyDataList& data_list,
base::ListValue* device_list);
static bool RemoteDeviceListToDeviceDataList(
const base::ListValue& device_list,
EasyUnlockDeviceKeyDataList* data_list);
// Gets key label for the given key index.
static std::string GetKeyLabel(size_t key_index);
private:
// Returns true if there are pending operations.
bool HasPendingOperations() const;
// Returns the next operations id. Currently only used for get keys ops.
int GetNextOperationId();
// Callback invoked after create keys op.
void OnKeysCreated(const UserContext& user_context,
const EasyUnlockDeviceKeyDataList& devices,
const RefreshKeysCallback& callback,
bool create_success);
// Callback invoked after remove keys op.
void OnKeysRemoved(const RemoveKeysCallback& callback, bool remove_success);
// Callback invoked after get keys op.
void OnKeysFetched(int op_id,
const GetDeviceDataListCallback& callback,
bool fetch_success,
const EasyUnlockDeviceKeyDataList& fetched_data);
int operation_id_;
scoped_ptr<EasyUnlockCreateKeysOperation> create_keys_op_;
scoped_ptr<EasyUnlockRemoveKeysOperation> remove_keys_op_;
std::map<int, EasyUnlockGetKeysOperation*> get_keys_ops_;
base::WeakPtrFactory<EasyUnlockKeyManager> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockKeyManager);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_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_remove_keys_operation.h"
#include "base/bind.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
#include "chromeos/cryptohome/homedir_methods.h"
#include "google_apis/gaia/gaia_auth_util.h"
namespace chromeos {
EasyUnlockRemoveKeysOperation::EasyUnlockRemoveKeysOperation(
const UserContext& user_context,
size_t start_index,
const RemoveKeysCallback& callback)
: user_context_(user_context),
callback_(callback),
key_index_(start_index),
weak_ptr_factory_(this) {
// Must have the secret and callback.
DCHECK(!user_context_.GetKey()->GetSecret().empty());
DCHECK(!callback_.is_null());
}
EasyUnlockRemoveKeysOperation::~EasyUnlockRemoveKeysOperation() {
}
void EasyUnlockRemoveKeysOperation::Start() {
// TODO(xiyuan): Use ListKeyEx and delete by label instead of by index.
RemoveKey();
}
void EasyUnlockRemoveKeysOperation::RemoveKey() {
std::string canonicalized =
gaia::CanonicalizeEmail(user_context_.GetUserID());
cryptohome::Identification id(canonicalized);
const Key* const auth_key = user_context_.GetKey();
cryptohome::Authorization auth(auth_key->GetSecret(), auth_key->GetLabel());
cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
id,
auth,
EasyUnlockKeyManager::GetKeyLabel(key_index_),
base::Bind(&EasyUnlockRemoveKeysOperation::OnKeyRemoved,
weak_ptr_factory_.GetWeakPtr()));
}
void EasyUnlockRemoveKeysOperation::OnKeyRemoved(
bool success,
cryptohome::MountError return_code) {
if (success) {
++key_index_;
RemoveKey();
return;
}
// MOUNT_ERROR_KEY_FAILURE is considered as success. Other error codes are
// treated as failures.
if (return_code == cryptohome::MOUNT_ERROR_KEY_FAILURE) {
callback_.Run(true);
} else {
LOG(ERROR) << "Easy unlock remove keys operation failed, code="
<< return_code;
callback_.Run(false);
}
}
} // namespace chromeos
// 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_REMOVE_KEYS_OPERATION_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_REMOVE_KEYS_OPERATION_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/login/auth/user_context.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace chromeos {
class UserContext;
// A class to remove existing Easy unlock cryptohome keys starting at given
// index.
class EasyUnlockRemoveKeysOperation {
public:
typedef base::Callback<void (bool success)> RemoveKeysCallback;
EasyUnlockRemoveKeysOperation(
const UserContext& user_context,
size_t start_index,
const RemoveKeysCallback& callback);
~EasyUnlockRemoveKeysOperation();
void Start();
private:
void RemoveKey();
void OnKeyRemoved(bool success, cryptohome::MountError return_code);
UserContext user_context_;
RemoveKeysCallback callback_;
size_t key_index_;
base::WeakPtrFactory<EasyUnlockRemoveKeysOperation> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(EasyUnlockRemoveKeysOperation);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_REMOVE_KEYS_OPERATION_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_types.h"
namespace chromeos {
const char kEasyUnlockKeyMetaNameBluetoothAddress[] = "eu.btaddr";
const char kEasyUnlockKeyMetaNamePsk[] = "eu.psk";
const char kEasyUnlockKeyMetaNamePubKey[] = "eu.pubkey";
const char kEasyUnlockKeyMetaNameChallenge[] = "eu.C";
const char kEasyUnlockKeyMetaNameWrappedSecret[] = "eu.WUK";
EasyUnlockDeviceKeyData::EasyUnlockDeviceKeyData() {
}
EasyUnlockDeviceKeyData::~EasyUnlockDeviceKeyData() {
}
} // namespace chromeos
// 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_TYPES_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TYPES_H_
#include <string>
#include <vector>
namespace chromeos {
extern const char kEasyUnlockKeyMetaNameBluetoothAddress[];
extern const char kEasyUnlockKeyMetaNamePsk[];
extern const char kEasyUnlockKeyMetaNamePubKey[];
extern const char kEasyUnlockKeyMetaNameChallenge[];
extern const char kEasyUnlockKeyMetaNameWrappedSecret[];
// Device data that is stored with cryptohome keys.
struct EasyUnlockDeviceKeyData {
EasyUnlockDeviceKeyData();
~EasyUnlockDeviceKeyData();
// Bluetooth address of the remote device.
std::string bluetooth_address;
// Public key of the remote device.
std::string public_key;
// Key to establish a secure channel with the remote device.
std::string psk;
// Challenge bytes to be sent to the phone.
std::string challenge;
// Wrapped secret to mount cryptohome home.
std::string wrapped_secret;
};
typedef std::vector<EasyUnlockDeviceKeyData> EasyUnlockDeviceKeyDataList;
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_EASY_UNLOCK_EASY_UNLOCK_TYPES_H_
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "chrome/browser/chromeos/boot_times_loader.h" #include "chrome/browser/chromeos/boot_times_loader.h"
#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/input_method/input_method_util.h"
#include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h" #include "chrome/browser/chromeos/login/demo_mode/demo_app_launcher.h"
#include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
#include "chrome/browser/chromeos/login/profile_auth_data.h" #include "chrome/browser/chromeos/login/profile_auth_data.h"
#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h" #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter.h"
#include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h" #include "chrome/browser/chromeos/login/saml/saml_offline_signin_limiter_factory.h"
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/rlz/rlz.h" #include "chrome/browser/rlz/rlz.h"
#include "chrome/browser/signin/easy_unlock_service.h"
#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/common/chrome_switches.h" #include "chrome/common/chrome_switches.h"
#include "chrome/common/logging_chrome.h" #include "chrome/common/logging_chrome.h"
...@@ -792,6 +794,8 @@ void UserSessionManager::FinalizePrepareProfile(Profile* profile) { ...@@ -792,6 +794,8 @@ void UserSessionManager::FinalizePrepareProfile(Profile* profile) {
// resolved. // resolved.
if (delegate_) if (delegate_)
delegate_->OnProfilePrepared(profile); delegate_->OnProfilePrepared(profile);
UpdateEasyUnlockKeys(profile);
} }
void UserSessionManager::InitSessionRestoreStrategy() { void UserSessionManager::InitSessionRestoreStrategy() {
...@@ -991,6 +995,34 @@ void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() { ...@@ -991,6 +995,34 @@ void UserSessionManager::NotifyPendingUserSessionsRestoreFinished() {
PendingUserSessionsRestoreFinished()); PendingUserSessionsRestoreFinished());
} }
void UserSessionManager::UpdateEasyUnlockKeys(Profile* user_profile) {
if (!GetEasyUnlockKeyManager())
return;
// Only update Easy unlock keys for regular user.
if (user_context_.GetUserType() != user_manager::USER_TYPE_REGULAR)
return;
// |user_context_| and |user_profile| must belong to the same user.
DCHECK_EQ(SigninManagerFactory::GetForProfile(user_profile)
->GetAuthenticatedAccountId(),
user_context_.GetUserID());
const base::ListValue* device_list = NULL;
if (EasyUnlockService::Get(user_profile))
device_list = EasyUnlockService::Get(user_profile)->GetRemoteDevices();
if (device_list) {
easy_unlock_key_manager_->RefreshKeys(
user_context_,
*device_list,
EasyUnlockKeyManager::RefreshKeysCallback());
} else {
easy_unlock_key_manager_->RemoveKeys(
user_context_, 0, EasyUnlockKeyManager::RemoveKeysCallback());
}
}
void UserSessionManager::ActiveUserChanged( void UserSessionManager::ActiveUserChanged(
const user_manager::User* active_user) { const user_manager::User* active_user) {
Profile* profile = ProfileHelper::Get()->GetProfileByUser(active_user); Profile* profile = ProfileHelper::Get()->GetProfileByUser(active_user);
...@@ -1016,4 +1048,16 @@ UserSessionManager::GetDefaultIMEState(Profile* profile) { ...@@ -1016,4 +1048,16 @@ UserSessionManager::GetDefaultIMEState(Profile* profile) {
return state; return state;
} }
EasyUnlockKeyManager* UserSessionManager::GetEasyUnlockKeyManager() {
if (!CommandLine::ForCurrentProcess()
->HasSwitch(chromeos::switches::kEnableEasySignin)) {
return NULL;
}
if (!easy_unlock_key_manager_)
easy_unlock_key_manager_.reset(new EasyUnlockKeyManager);
return easy_unlock_key_manager_.get();
}
} // namespace chromeos } // namespace chromeos
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <string> #include <string>
#include "base/basictypes.h" #include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
...@@ -33,6 +34,8 @@ class User; ...@@ -33,6 +34,8 @@ class User;
namespace chromeos { namespace chromeos {
class EasyUnlockKeyManager;
class UserSessionManagerDelegate { class UserSessionManagerDelegate {
public: public:
// Called after profile is loaded and prepared for the session. // Called after profile is loaded and prepared for the session.
...@@ -152,6 +155,9 @@ class UserSessionManager ...@@ -152,6 +155,9 @@ class UserSessionManager
scoped_refptr<input_method::InputMethodManager::State> GetDefaultIMEState( scoped_refptr<input_method::InputMethodManager::State> GetDefaultIMEState(
Profile* profile); Profile* profile);
// Note this could return NULL if not enabled.
EasyUnlockKeyManager* GetEasyUnlockKeyManager();
private: private:
friend struct DefaultSingletonTraits<UserSessionManager>; friend struct DefaultSingletonTraits<UserSessionManager>;
...@@ -235,6 +241,9 @@ class UserSessionManager ...@@ -235,6 +241,9 @@ class UserSessionManager
// Notifies observers that user pending sessions restore has finished. // Notifies observers that user pending sessions restore has finished.
void NotifyPendingUserSessionsRestoreFinished(); void NotifyPendingUserSessionsRestoreFinished();
// Update Easy unlock cryptohome keys using the pairing data in user prefs.
void UpdateEasyUnlockKeys(Profile* user_profile);
UserSessionManagerDelegate* delegate_; UserSessionManagerDelegate* delegate_;
// Authentication/user context. // Authentication/user context.
...@@ -281,6 +290,9 @@ class UserSessionManager ...@@ -281,6 +290,9 @@ class UserSessionManager
std::map<Profile*, scoped_refptr<input_method::InputMethodManager::State> > std::map<Profile*, scoped_refptr<input_method::InputMethodManager::State> >
default_ime_states_; default_ime_states_;
// Manages Easy unlock cryptohome keys.
scoped_ptr<EasyUnlockKeyManager> easy_unlock_key_manager_;
DISALLOW_COPY_AND_ASSIGN(UserSessionManager); DISALLOW_COPY_AND_ASSIGN(UserSessionManager);
}; };
......
...@@ -541,6 +541,16 @@ ...@@ -541,6 +541,16 @@
'browser/chromeos/login/default_pinned_apps_field_trial.h', 'browser/chromeos/login/default_pinned_apps_field_trial.h',
'browser/chromeos/login/demo_mode/demo_app_launcher.cc', 'browser/chromeos/login/demo_mode/demo_app_launcher.cc',
'browser/chromeos/login/demo_mode/demo_app_launcher.h', 'browser/chromeos/login/demo_mode/demo_app_launcher.h',
'browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_create_keys_operation.h',
'browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_get_keys_operation.h',
'browser/chromeos/login/easy_unlock/easy_unlock_key_manager.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h',
'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_types.cc',
'browser/chromeos/login/easy_unlock/easy_unlock_types.h',
'browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc', 'browser/chromeos/login/enrollment/auto_enrollment_check_screen.cc',
'browser/chromeos/login/enrollment/auto_enrollment_check_screen.h', 'browser/chromeos/login/enrollment/auto_enrollment_check_screen.h',
'browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h', 'browser/chromeos/login/enrollment/auto_enrollment_check_screen_actor.h',
......
...@@ -80,6 +80,9 @@ const char kEnableChromeVoxNext[] = "enable-chromevox-next"; ...@@ -80,6 +80,9 @@ const char kEnableChromeVoxNext[] = "enable-chromevox-next";
// locate the device. // locate the device.
const char kEnableConsumerManagement[] = "enable-consumer-management"; const char kEnableConsumerManagement[] = "enable-consumer-management";
// Enable Easy sign-in.
const char kEnableEasySignin[] = "enable-easy-signin";
// If this switch is set, Chrome OS login screen uses |EmbeddedSignin| endpoint // If this switch is set, Chrome OS login screen uses |EmbeddedSignin| endpoint
// of GAIA. // of GAIA.
const char kEnableEmbeddedSignin[] = "enable-embedded-signin"; const char kEnableEmbeddedSignin[] = "enable-embedded-signin";
......
...@@ -43,6 +43,7 @@ CHROMEOS_EXPORT extern const char kEnableCarrierSwitching[]; ...@@ -43,6 +43,7 @@ CHROMEOS_EXPORT extern const char kEnableCarrierSwitching[];
CHROMEOS_EXPORT extern const char kEnableChromeVoxNext[]; CHROMEOS_EXPORT extern const char kEnableChromeVoxNext[];
CHROMEOS_EXPORT extern const char kEnableConsumerManagement[]; CHROMEOS_EXPORT extern const char kEnableConsumerManagement[];
CHROMEOS_EXPORT extern const char kEnableEmbeddedSignin[]; CHROMEOS_EXPORT extern const char kEnableEmbeddedSignin[];
CHROMEOS_EXPORT extern const char kEnableEasySignin[];
CHROMEOS_EXPORT extern const char kEnableExtensionAssetsSharing[]; CHROMEOS_EXPORT extern const char kEnableExtensionAssetsSharing[];
CHROMEOS_EXPORT extern const char kEnableFirstRunUITransitions[]; CHROMEOS_EXPORT extern const char kEnableFirstRunUITransitions[];
CHROMEOS_EXPORT extern const char kEnableKioskMode[]; CHROMEOS_EXPORT extern const char kEnableKioskMode[];
......
...@@ -86,6 +86,17 @@ KeyDefinition::ProviderData::ProviderData(const ProviderData& other) ...@@ -86,6 +86,17 @@ KeyDefinition::ProviderData::ProviderData(const ProviderData& other)
bytes.reset(new std::string(*other.bytes)); bytes.reset(new std::string(*other.bytes));
} }
KeyDefinition::ProviderData::ProviderData(const std::string& name, int64 number)
: name(name),
number(new int64(number)) {
}
KeyDefinition::ProviderData::ProviderData(const std::string& name,
const std::string& bytes)
: name(name),
bytes(new std::string(bytes)) {
}
void KeyDefinition::ProviderData::operator=(const ProviderData& other) { void KeyDefinition::ProviderData::operator=(const ProviderData& other) {
name = other.name; name = other.name;
number.reset(other.number ? new int64(*other.number) : NULL); number.reset(other.number ? new int64(*other.number) : NULL);
......
...@@ -85,6 +85,8 @@ struct CHROMEOS_EXPORT KeyDefinition { ...@@ -85,6 +85,8 @@ struct CHROMEOS_EXPORT KeyDefinition {
ProviderData(); ProviderData();
explicit ProviderData(const std::string& name); explicit ProviderData(const std::string& name);
explicit ProviderData(const ProviderData& other); explicit ProviderData(const ProviderData& other);
ProviderData(const std::string& name, int64 number);
ProviderData(const std::string& name, const std::string& bytes);
void operator=(const ProviderData& other); void operator=(const ProviderData& other);
~ProviderData(); ~ProviderData();
......
...@@ -44446,6 +44446,7 @@ To add a new entry, add it with any value and run test to compute valid value. ...@@ -44446,6 +44446,7 @@ To add a new entry, add it with any value and run test to compute valid value.
<int value="-1930720286" label="nacl-debug-mask"/> <int value="-1930720286" label="nacl-debug-mask"/>
<int value="-1928198763" label="enable-async-dns"/> <int value="-1928198763" label="enable-async-dns"/>
<int value="-1925117279" label="disable-quic-https"/> <int value="-1925117279" label="disable-quic-https"/>
<int value="-1911153473" label="enable-easy-signin"/>
<int value="-1888273969" label="tab-capture-upscale-quality"/> <int value="-1888273969" label="tab-capture-upscale-quality"/>
<int value="-1876881908" <int value="-1876881908"
label="disable-infobar-for-protected-media-identifier"/> label="disable-infobar-for-protected-media-identifier"/>
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