Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: chrome/browser/chromeos/login/quick_unlock/pin_backend.cc

Issue 2809993004: cros: Implement cryptohome backend for pin.
Patch Set: Address comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/chromeos/login/quick_unlock/pin_backend.h"
6
7 #include "base/bind.h"
8 #include "base/threading/thread_task_runner_handle.h"
9 #include "chrome/browser/chromeos/login/quick_unlock/pin_storage_prefs.h"
10 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
11 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
12 #include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
13 #include "chromeos/cryptohome/cryptohome_parameters.h"
14 #include "chromeos/cryptohome/homedir_methods.h"
15 #include "chromeos/cryptohome/system_salt_getter.h"
16 #include "chromeos/login/auth/user_context.h"
17 #include "components/signin/core/account_id/account_id.h"
18
19 namespace chromeos {
20 namespace quick_unlock {
21
22 namespace {
23
24 constexpr const char* kCryptohomePinLabel = "pin_label";
25
26 void DoNothingCryptohome(bool success, cryptohome::MountError return_code) {}
27
28 // Returns true if there is a KeyDefinition instance in cryptohome which has the
29 // PIN label.
30 void HasCryptohomePinKey(
31 const PinBackend::BoolCallback& callback,
32 bool success,
33 cryptohome::MountError return_code,
34 const std::vector<cryptohome::KeyDefinition>& key_definitions) {
35 for (const cryptohome::KeyDefinition& definition : key_definitions) {
36 if (definition.label == kCryptohomePinLabel) {
37 callback.Run(true);
38 return;
39 }
40 }
41
42 callback.Run(false);
43 }
44
45 class CryptohomeBackend {
46 public:
47 CryptohomeBackend();
48 ~CryptohomeBackend();
49
50 void EnsurePinIsNotInCryptohome(const AccountId& account_id,
51 const UserContext& user_context) const;
52 void IsPinSetInCryptohome(const AccountId& account_id,
53 const PinBackend::BoolCallback& result) const;
54 void SetPin(const UserContext& user_context, const std::string& pin);
55 void RemovePin(const UserContext& user_context);
56 bool NeedsStrongAuth() const;
57
58 private:
59 void OnSystemSaltObtained(const std::string& system_salt);
60 // Called when we add or remove a key from cryptohome.
61 void OnCryptohomeKeyChange(bool success, cryptohome::MountError return_code);
62
63 void SetIsPinSet(bool is_set);
64
65 private:
66 bool salt_obtained_ = false;
67 std::string system_salt_;
68 std::vector<base::Closure> system_salt_callbacks_;
69
70 base::WeakPtrFactory<CryptohomeBackend> weak_factory_{this};
71
72 DISALLOW_COPY_AND_ASSIGN(CryptohomeBackend);
73 };
74
75 CryptohomeBackend::CryptohomeBackend() {
76 SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
77 &CryptohomeBackend::OnSystemSaltObtained, weak_factory_.GetWeakPtr()));
78 }
79
80 CryptohomeBackend::~CryptohomeBackend() = default;
81
82 void CryptohomeBackend::IsPinSetInCryptohome(
83 const AccountId& account_id,
84 const PinBackend::BoolCallback& callback) const {
85 cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx(
86 cryptohome::Identification(account_id), kCryptohomePinLabel,
87 base::Bind(&HasCryptohomePinKey, callback));
88 }
89
90 void CryptohomeBackend::SetPin(const UserContext& user_context,
91 const std::string& pin) {
92 // Rerun this method only after we have system salt.
93 if (!salt_obtained_) {
94 system_salt_callbacks_.push_back(base::Bind(&CryptohomeBackend::SetPin,
95 weak_factory_.GetWeakPtr(),
96 user_context, pin));
97 return;
98 }
99
100 const std::string pin_secret = PinBackend::ComputeSecret(pin, system_salt_);
101
102 const cryptohome::Identification id(user_context.GetAccountId());
103 const cryptohome::Authorization auth(user_context.GetKey()->GetSecret(), "");
104 const cryptohome::KeyDefinition key_def(pin_secret, kCryptohomePinLabel,
105 cryptohome::PRIV_DEFAULT);
106 cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
107 id, auth, key_def, true /*replace_existing*/,
108 base::Bind(&DoNothingCryptohome));
109 }
110
111 void CryptohomeBackend::OnSystemSaltObtained(const std::string& system_salt) {
112 salt_obtained_ = true;
113 system_salt_ = system_salt;
114 for (const auto& callback : system_salt_callbacks_)
115 callback.Run();
116 system_salt_callbacks_.clear();
117 }
118
119 void CryptohomeBackend::RemovePin(const UserContext& user_context) {
120 // Rerun this method only after we have system salt.
121 if (!salt_obtained_) {
122 system_salt_callbacks_.push_back(base::Bind(&CryptohomeBackend::RemovePin,
123 weak_factory_.GetWeakPtr(),
124 user_context));
125 return;
126 }
127
128 // Remove any PIN data from cryptohome.
129 const cryptohome::Identification id(user_context.GetAccountId());
130 const cryptohome::Authorization auth(user_context.GetKey()->GetSecret(), "");
131 cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
132 id, auth, kCryptohomePinLabel, base::Bind(&DoNothingCryptohome));
133 }
134
135 CryptohomeBackend* g_cryptohome_backend_ = nullptr;
136
137 CryptohomeBackend* GetCryptohomeBackend() {
138 if (!g_cryptohome_backend_)
139 g_cryptohome_backend_ = new CryptohomeBackend();
140 return g_cryptohome_backend_;
141 }
142
143 QuickUnlockStorage* GetPrefsBackend(const AccountId& account_id) {
144 return QuickUnlockFactory::GetForAccountId(account_id);
145 }
146
147 void SendResponse(const PinBackend::BoolCallback& result, bool value) {
148 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
149 base::Bind(result, value));
150 }
151
152 } // namespace
153
154 // static
155 void PinBackend::IsSet(const AccountId& account_id,
156 const BoolCallback& result) {
157 if (GetPinStorageType() == PinStorageType::kCryptohome) {
158 GetCryptohomeBackend()->IsPinSetInCryptohome(account_id, result);
159 } else {
160 QuickUnlockStorage* storage = GetPrefsBackend(account_id);
161 DCHECK(storage);
162 SendResponse(result, storage->pin_storage_prefs()->IsPinSet());
163 }
164 }
165
166 // static
167 void PinBackend::Set(const UserContext& user_context, const std::string& pin) {
168 QuickUnlockStorage* storage = GetPrefsBackend(user_context.GetAccountId());
169 DCHECK(storage);
170
171 // Make sure to remove the other storage pin.
172 if (GetPinStorageType() == PinStorageType::kCryptohome) {
173 GetCryptohomeBackend()->SetPin(user_context, pin);
174 storage->pin_storage_prefs()->RemovePin();
175 } else {
176 storage->pin_storage_prefs()->SetPin(pin);
177 GetCryptohomeBackend()->RemovePin(user_context);
178 }
179 }
180
181 // static
182 void PinBackend::Remove(const UserContext& user_context) {
183 GetCryptohomeBackend()->RemovePin(user_context);
184
185 QuickUnlockStorage* storage = GetPrefsBackend(user_context.GetAccountId());
186 DCHECK(storage);
187 storage->pin_storage_prefs()->RemovePin();
188 }
189
190 // static
191 void PinBackend::CanAuthenticate(const AccountId& account_id,
192 const BoolCallback& result) {
193 if (GetPinStorageType() == PinStorageType::kCryptohome) {
194 GetCryptohomeBackend()->IsPinSetInCryptohome(account_id, result);
195 } else {
196 QuickUnlockStorage* storage = GetPrefsBackend(account_id);
197 if (!storage) {
198 SendResponse(result, false);
199 } else {
200 SendResponse(
201 result,
202 storage->HasStrongAuth() &&
203 storage->pin_storage_prefs()->IsPinAuthenticationAvailable());
204 }
205 }
206 }
207
208 // static
209 void PinBackend::TryAuthenticate(const AccountId& account_id,
210 const std::string& pin,
211 const BoolCallback& result) {
212 if (GetPinStorageType() == PinStorageType::kCryptohome) {
213 // TODO(jdufalt): Refactor login auth such that typing a user password does
214 // not run crypthome check with wildcard key label. That means we will be
215 // forced to run an authentication check here.
216 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
217 base::Bind(result, false));
218 } else {
219 QuickUnlockStorage* storage = GetPrefsBackend(account_id);
220 DCHECK(storage);
221
222 if (!storage->HasStrongAuth()) {
223 SendResponse(result, false);
224 } else {
225 SendResponse(result,
226 storage->pin_storage_prefs()->TryAuthenticatePin(pin));
227 }
228 }
229 }
230
231 // static
232 void PinBackend::NotifyAuthentication(const AccountId& account_id) {
233 // Nothing to do for cryptohome backend.
234
235 if (GetPinStorageType() == PinStorageType::kPrefs) {
236 QuickUnlockStorage* storage = GetPrefsBackend(account_id);
237 if (!storage)
238 return;
239
240 storage->pin_storage_prefs()->ResetUnlockAttemptCount();
241 }
242 }
243
244 // static
245 std::string PinBackend::ComputeSecret(const std::string& pin,
246 const std::string& salt) {
247 Key key(pin);
248 key.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, salt);
249 return key.GetSecret();
250 }
251
252 // static
253 void PinBackend::ResetForTesting() {
254 if (g_cryptohome_backend_)
255 delete g_cryptohome_backend_;
256 g_cryptohome_backend_ = nullptr;
257 }
258
259 } // namespace quick_unlock
260 } // namespace chromeos
OLDNEW
« no previous file with comments | « chrome/browser/chromeos/login/quick_unlock/pin_backend.h ('k') | chrome/browser/chromeos/login/quick_unlock/pin_storage.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698