Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / chromeos / login / easy_unlock / easy_unlock_key_manager.cc
blobc1ba482f8700a591071a68b460737137f662102f
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_key_manager.h"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
13 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
15 namespace chromeos {
17 namespace {
19 const char kKeyBluetoothAddress[] = "bluetoothAddress";
20 const char kKeyPermitRecord[] = "permitRecord";
21 const char kKeyPermitId[] = "permitRecord.id";
22 const char kKeyPermitPermitId[] = "permitRecord.permitId";
23 const char kKeyPermitData[] = "permitRecord.data";
24 const char kKeyPermitType[] = "permitRecord.type";
25 const char kKeyPsk[] = "psk";
27 const char kKeyLabelPrefix[] = "easy-unlock-";
29 const char kPermitPermitIdFormat[] = "permit://google.com/easyunlock/v1/%s";
30 const char kPermitTypeLicence[] = "licence";
32 } // namespace
34 EasyUnlockKeyManager::EasyUnlockKeyManager()
35 : write_queue_deleter_(&write_operation_queue_),
36 read_queue_deleter_(&read_operation_queue_),
37 weak_ptr_factory_(this) {
40 EasyUnlockKeyManager::~EasyUnlockKeyManager() {
43 void EasyUnlockKeyManager::RefreshKeys(const UserContext& user_context,
44 const base::ListValue& remote_devices,
45 const RefreshKeysCallback& callback) {
46 base::Closure do_refresh_keys = base::Bind(
47 &EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent,
48 weak_ptr_factory_.GetWeakPtr(),
49 user_context,
50 base::Owned(remote_devices.DeepCopy()),
51 callback);
53 EasyUnlockTpmKeyManager* tpm_key_manager =
54 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser(
55 user_context.GetUserID());
56 if (!tpm_key_manager) {
57 LOG(ERROR) << "No TPM key manager.";
58 callback.Run(false);
59 return;
62 // Private TPM key is needed only when adding new keys.
63 if (remote_devices.empty() ||
64 tpm_key_manager->PrepareTpmKey(false /* check_private_key */,
65 do_refresh_keys)) {
66 do_refresh_keys.Run();
67 } else {
68 // In case Chrome is supposed to restart to apply user session flags, the
69 // Chrome restart will be postponed until Easy Sign-in keys are refreshed.
70 // This is to ensure that creating TPM key does not hang if TPM system
71 // loading takes too much time. Note that in normal circumstances the
72 // chances that TPM slot cannot be loaded should be extremely low.
73 // TODO(tbarzic): Add some metrics to measure if the timeout even gets hit.
74 tpm_key_manager->StartGetSystemSlotTimeoutMs(2000);
78 void EasyUnlockKeyManager::RefreshKeysWithTpmKeyPresent(
79 const UserContext& user_context,
80 base::ListValue* remote_devices,
81 const RefreshKeysCallback& callback) {
82 EasyUnlockTpmKeyManager* tpm_key_manager =
83 EasyUnlockTpmKeyManagerFactory::GetInstance()->GetForUser(
84 user_context.GetUserID());
85 std::string tpm_public_key =
86 tpm_key_manager->GetPublicTpmKey(user_context.GetUserID());
88 EasyUnlockDeviceKeyDataList devices;
89 if (!RemoteDeviceListToDeviceDataList(*remote_devices, &devices))
90 devices.clear();
92 write_operation_queue_.push_back(new EasyUnlockRefreshKeysOperation(
93 user_context, tpm_public_key, devices,
94 base::Bind(&EasyUnlockKeyManager::OnKeysRefreshed,
95 weak_ptr_factory_.GetWeakPtr(), callback)));
96 RunNextOperation();
99 void EasyUnlockKeyManager::GetDeviceDataList(
100 const UserContext& user_context,
101 const GetDeviceDataListCallback& callback) {
102 read_operation_queue_.push_back(new EasyUnlockGetKeysOperation(
103 user_context, base::Bind(&EasyUnlockKeyManager::OnKeysFetched,
104 weak_ptr_factory_.GetWeakPtr(), callback)));
105 RunNextOperation();
108 // static
109 void EasyUnlockKeyManager::DeviceDataToRemoteDeviceDictionary(
110 const std::string& user_id,
111 const EasyUnlockDeviceKeyData& data,
112 base::DictionaryValue* dict) {
113 dict->SetString(kKeyBluetoothAddress, data.bluetooth_address);
114 dict->SetString(kKeyPsk, data.psk);
115 scoped_ptr<base::DictionaryValue> permit_record(new base::DictionaryValue);
116 dict->Set(kKeyPermitRecord, permit_record.release());
117 dict->SetString(kKeyPermitId, data.public_key);
118 dict->SetString(kKeyPermitData, data.public_key);
119 dict->SetString(kKeyPermitType, kPermitTypeLicence);
120 dict->SetString(kKeyPermitPermitId,
121 base::StringPrintf(kPermitPermitIdFormat,
122 user_id.c_str()));
125 // static
126 bool EasyUnlockKeyManager::RemoteDeviceDictionaryToDeviceData(
127 const base::DictionaryValue& dict,
128 EasyUnlockDeviceKeyData* data) {
129 std::string bluetooth_address;
130 std::string public_key;
131 std::string psk;
133 if (!dict.GetString(kKeyBluetoothAddress, &bluetooth_address) ||
134 !dict.GetString(kKeyPermitId, &public_key) ||
135 !dict.GetString(kKeyPsk, &psk)) {
136 return false;
139 data->bluetooth_address.swap(bluetooth_address);
140 data->public_key.swap(public_key);
141 data->psk.swap(psk);
142 return true;
145 // static
146 void EasyUnlockKeyManager::DeviceDataListToRemoteDeviceList(
147 const std::string& user_id,
148 const EasyUnlockDeviceKeyDataList& data_list,
149 base::ListValue* device_list) {
150 device_list->Clear();
151 for (size_t i = 0; i < data_list.size(); ++i) {
152 scoped_ptr<base::DictionaryValue> device_dict(new base::DictionaryValue);
153 DeviceDataToRemoteDeviceDictionary(
154 user_id, data_list[i], device_dict.get());
155 device_list->Append(device_dict.release());
159 // static
160 bool EasyUnlockKeyManager::RemoteDeviceListToDeviceDataList(
161 const base::ListValue& device_list,
162 EasyUnlockDeviceKeyDataList* data_list) {
163 EasyUnlockDeviceKeyDataList parsed_devices;
164 for (base::ListValue::const_iterator it = device_list.begin();
165 it != device_list.end();
166 ++it) {
167 const base::DictionaryValue* dict;
168 if (!(*it)->GetAsDictionary(&dict) || !dict)
169 return false;
171 EasyUnlockDeviceKeyData data;
172 if (!RemoteDeviceDictionaryToDeviceData(*dict, &data))
173 return false;
175 parsed_devices.push_back(data);
178 data_list->swap(parsed_devices);
179 return true;
182 // static
183 std::string EasyUnlockKeyManager::GetKeyLabel(size_t key_index) {
184 return base::StringPrintf("%s%zu", kKeyLabelPrefix, key_index);
187 void EasyUnlockKeyManager::RunNextOperation() {
188 if (pending_write_operation_ || pending_read_operation_)
189 return;
191 if (!write_operation_queue_.empty()) {
192 pending_write_operation_ = make_scoped_ptr(write_operation_queue_.front());
193 write_operation_queue_.pop_front();
194 pending_write_operation_->Start();
195 } else if (!read_operation_queue_.empty()) {
196 pending_read_operation_ = make_scoped_ptr(read_operation_queue_.front());
197 read_operation_queue_.pop_front();
198 pending_read_operation_->Start();
202 void EasyUnlockKeyManager::OnKeysRefreshed(const RefreshKeysCallback& callback,
203 bool refresh_success) {
204 if (!callback.is_null())
205 callback.Run(refresh_success);
207 DCHECK(pending_write_operation_);
208 pending_write_operation_.reset();
209 RunNextOperation();
212 void EasyUnlockKeyManager::OnKeysFetched(
213 const GetDeviceDataListCallback& callback,
214 bool fetch_success,
215 const EasyUnlockDeviceKeyDataList& fetched_data) {
216 if (!callback.is_null())
217 callback.Run(fetch_success, fetched_data);
219 DCHECK(pending_read_operation_);
220 pending_read_operation_.reset();
221 RunNextOperation();
224 } // namespace chromeos