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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/chromeos/login/quick_unlock/pin_backend.cc
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_backend.cc b/chrome/browser/chromeos/login/quick_unlock/pin_backend.cc
new file mode 100644
index 0000000000000000000000000000000000000000..d8010404f5b9c00bf342022776811985349046ef
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/pin_backend.cc
@@ -0,0 +1,260 @@
+// Copyright 2017 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/quick_unlock/pin_backend.h"
+
+#include "base/bind.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "chrome/browser/chromeos/login/quick_unlock/pin_storage_prefs.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_factory.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_storage.h"
+#include "chrome/browser/chromeos/login/quick_unlock/quick_unlock_utils.h"
+#include "chromeos/cryptohome/cryptohome_parameters.h"
+#include "chromeos/cryptohome/homedir_methods.h"
+#include "chromeos/cryptohome/system_salt_getter.h"
+#include "chromeos/login/auth/user_context.h"
+#include "components/signin/core/account_id/account_id.h"
+
+namespace chromeos {
+namespace quick_unlock {
+
+namespace {
+
+constexpr const char* kCryptohomePinLabel = "pin_label";
+
+void DoNothingCryptohome(bool success, cryptohome::MountError return_code) {}
+
+// Returns true if there is a KeyDefinition instance in cryptohome which has the
+// PIN label.
+void HasCryptohomePinKey(
+ const PinBackend::BoolCallback& callback,
+ bool success,
+ cryptohome::MountError return_code,
+ const std::vector<cryptohome::KeyDefinition>& key_definitions) {
+ for (const cryptohome::KeyDefinition& definition : key_definitions) {
+ if (definition.label == kCryptohomePinLabel) {
+ callback.Run(true);
+ return;
+ }
+ }
+
+ callback.Run(false);
+}
+
+class CryptohomeBackend {
+ public:
+ CryptohomeBackend();
+ ~CryptohomeBackend();
+
+ void EnsurePinIsNotInCryptohome(const AccountId& account_id,
+ const UserContext& user_context) const;
+ void IsPinSetInCryptohome(const AccountId& account_id,
+ const PinBackend::BoolCallback& result) const;
+ void SetPin(const UserContext& user_context, const std::string& pin);
+ void RemovePin(const UserContext& user_context);
+ bool NeedsStrongAuth() const;
+
+ private:
+ void OnSystemSaltObtained(const std::string& system_salt);
+ // Called when we add or remove a key from cryptohome.
+ void OnCryptohomeKeyChange(bool success, cryptohome::MountError return_code);
+
+ void SetIsPinSet(bool is_set);
+
+ private:
+ bool salt_obtained_ = false;
+ std::string system_salt_;
+ std::vector<base::Closure> system_salt_callbacks_;
+
+ base::WeakPtrFactory<CryptohomeBackend> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(CryptohomeBackend);
+};
+
+CryptohomeBackend::CryptohomeBackend() {
+ SystemSaltGetter::Get()->GetSystemSalt(base::Bind(
+ &CryptohomeBackend::OnSystemSaltObtained, weak_factory_.GetWeakPtr()));
+}
+
+CryptohomeBackend::~CryptohomeBackend() = default;
+
+void CryptohomeBackend::IsPinSetInCryptohome(
+ const AccountId& account_id,
+ const PinBackend::BoolCallback& callback) const {
+ cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx(
+ cryptohome::Identification(account_id), kCryptohomePinLabel,
+ base::Bind(&HasCryptohomePinKey, callback));
+}
+
+void CryptohomeBackend::SetPin(const UserContext& user_context,
+ const std::string& pin) {
+ // Rerun this method only after we have system salt.
+ if (!salt_obtained_) {
+ system_salt_callbacks_.push_back(base::Bind(&CryptohomeBackend::SetPin,
+ weak_factory_.GetWeakPtr(),
+ user_context, pin));
+ return;
+ }
+
+ const std::string pin_secret = PinBackend::ComputeSecret(pin, system_salt_);
+
+ const cryptohome::Identification id(user_context.GetAccountId());
+ const cryptohome::Authorization auth(user_context.GetKey()->GetSecret(), "");
+ const cryptohome::KeyDefinition key_def(pin_secret, kCryptohomePinLabel,
+ cryptohome::PRIV_DEFAULT);
+ cryptohome::HomedirMethods::GetInstance()->AddKeyEx(
+ id, auth, key_def, true /*replace_existing*/,
+ base::Bind(&DoNothingCryptohome));
+}
+
+void CryptohomeBackend::OnSystemSaltObtained(const std::string& system_salt) {
+ salt_obtained_ = true;
+ system_salt_ = system_salt;
+ for (const auto& callback : system_salt_callbacks_)
+ callback.Run();
+ system_salt_callbacks_.clear();
+}
+
+void CryptohomeBackend::RemovePin(const UserContext& user_context) {
+ // Rerun this method only after we have system salt.
+ if (!salt_obtained_) {
+ system_salt_callbacks_.push_back(base::Bind(&CryptohomeBackend::RemovePin,
+ weak_factory_.GetWeakPtr(),
+ user_context));
+ return;
+ }
+
+ // Remove any PIN data from cryptohome.
+ const cryptohome::Identification id(user_context.GetAccountId());
+ const cryptohome::Authorization auth(user_context.GetKey()->GetSecret(), "");
+ cryptohome::HomedirMethods::GetInstance()->RemoveKeyEx(
+ id, auth, kCryptohomePinLabel, base::Bind(&DoNothingCryptohome));
+}
+
+CryptohomeBackend* g_cryptohome_backend_ = nullptr;
+
+CryptohomeBackend* GetCryptohomeBackend() {
+ if (!g_cryptohome_backend_)
+ g_cryptohome_backend_ = new CryptohomeBackend();
+ return g_cryptohome_backend_;
+}
+
+QuickUnlockStorage* GetPrefsBackend(const AccountId& account_id) {
+ return QuickUnlockFactory::GetForAccountId(account_id);
+}
+
+void SendResponse(const PinBackend::BoolCallback& result, bool value) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(result, value));
+}
+
+} // namespace
+
+// static
+void PinBackend::IsSet(const AccountId& account_id,
+ const BoolCallback& result) {
+ if (GetPinStorageType() == PinStorageType::kCryptohome) {
+ GetCryptohomeBackend()->IsPinSetInCryptohome(account_id, result);
+ } else {
+ QuickUnlockStorage* storage = GetPrefsBackend(account_id);
+ DCHECK(storage);
+ SendResponse(result, storage->pin_storage_prefs()->IsPinSet());
+ }
+}
+
+// static
+void PinBackend::Set(const UserContext& user_context, const std::string& pin) {
+ QuickUnlockStorage* storage = GetPrefsBackend(user_context.GetAccountId());
+ DCHECK(storage);
+
+ // Make sure to remove the other storage pin.
+ if (GetPinStorageType() == PinStorageType::kCryptohome) {
+ GetCryptohomeBackend()->SetPin(user_context, pin);
+ storage->pin_storage_prefs()->RemovePin();
+ } else {
+ storage->pin_storage_prefs()->SetPin(pin);
+ GetCryptohomeBackend()->RemovePin(user_context);
+ }
+}
+
+// static
+void PinBackend::Remove(const UserContext& user_context) {
+ GetCryptohomeBackend()->RemovePin(user_context);
+
+ QuickUnlockStorage* storage = GetPrefsBackend(user_context.GetAccountId());
+ DCHECK(storage);
+ storage->pin_storage_prefs()->RemovePin();
+}
+
+// static
+void PinBackend::CanAuthenticate(const AccountId& account_id,
+ const BoolCallback& result) {
+ if (GetPinStorageType() == PinStorageType::kCryptohome) {
+ GetCryptohomeBackend()->IsPinSetInCryptohome(account_id, result);
+ } else {
+ QuickUnlockStorage* storage = GetPrefsBackend(account_id);
+ if (!storage) {
+ SendResponse(result, false);
+ } else {
+ SendResponse(
+ result,
+ storage->HasStrongAuth() &&
+ storage->pin_storage_prefs()->IsPinAuthenticationAvailable());
+ }
+ }
+}
+
+// static
+void PinBackend::TryAuthenticate(const AccountId& account_id,
+ const std::string& pin,
+ const BoolCallback& result) {
+ if (GetPinStorageType() == PinStorageType::kCryptohome) {
+ // TODO(jdufalt): Refactor login auth such that typing a user password does
+ // not run crypthome check with wildcard key label. That means we will be
+ // forced to run an authentication check here.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(result, false));
+ } else {
+ QuickUnlockStorage* storage = GetPrefsBackend(account_id);
+ DCHECK(storage);
+
+ if (!storage->HasStrongAuth()) {
+ SendResponse(result, false);
+ } else {
+ SendResponse(result,
+ storage->pin_storage_prefs()->TryAuthenticatePin(pin));
+ }
+ }
+}
+
+// static
+void PinBackend::NotifyAuthentication(const AccountId& account_id) {
+ // Nothing to do for cryptohome backend.
+
+ if (GetPinStorageType() == PinStorageType::kPrefs) {
+ QuickUnlockStorage* storage = GetPrefsBackend(account_id);
+ if (!storage)
+ return;
+
+ storage->pin_storage_prefs()->ResetUnlockAttemptCount();
+ }
+}
+
+// static
+std::string PinBackend::ComputeSecret(const std::string& pin,
+ const std::string& salt) {
+ Key key(pin);
+ key.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, salt);
+ return key.GetSecret();
+}
+
+// static
+void PinBackend::ResetForTesting() {
+ if (g_cryptohome_backend_)
+ delete g_cryptohome_backend_;
+ g_cryptohome_backend_ = nullptr;
+}
+
+} // namespace quick_unlock
+} // namespace chromeos
« 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