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

Unified Diff: chrome/browser/chromeos/login/quick_unlock/pin_storage.cc

Issue 1977923002: Implement pin storage backend. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@lkgr
Patch Set: Created 4 years, 7 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_storage.cc
diff --git a/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc b/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc
new file mode 100644
index 0000000000000000000000000000000000000000..3dbfd6cd4a4779b610c5aff6b0a4e7d84429d758
--- /dev/null
+++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc
@@ -0,0 +1,166 @@
+// Copyright 2016 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_storage.h"
+
+#include "base/base64.h"
+#include "base/lazy_instance.h"
+#include "base/strings/string_util.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/common/pref_names.h"
+#include "chromeos/login/auth/key.h"
+#include "components/prefs/pref_service.h"
+#include "crypto/random.h"
+#include "extensions/browser/browser_context_keyed_api_factory.h"
+
+namespace chromeos {
+
+namespace {
+
+const int kSaltByteSize = 16;
+
+class PinStorageImpl : public PinStorage,
+ public extensions::BrowserContextKeyedAPI {
+ public:
+ explicit PinStorageImpl(content::BrowserContext* context);
+ ~PinStorageImpl() override;
achuithb 2016/05/13 23:34:56 Can this be protected?
jdufault 2016/05/16 22:08:47 Done.
+
+ // PinStorage implementation:
achuithb 2016/05/13 23:34:56 Everything below here can be private, right?
jdufault 2016/05/16 22:08:47 Done.
+ void MarkStrongAuth() override;
+ base::TimeDelta TimeSinceLastStrongAuth() override;
+
+ void AddUnlockAttempt() override;
+ void ResetUnlockAttemptCount() override;
+ int UnlockAttemptCount() override;
achuithb 2016/05/13 23:34:56 const
jdufault 2016/05/16 22:08:47 Done.
+
+ // PIN storage management.
+ bool HasPin() const override;
+ void SetPin(const std::string& raw_pin) override;
+ void RemovePin() override;
+
+ // The salt and hash for the pin. These methods can only be called if HasPin
+ // returns true.
+ std::string pin_salt() const override;
+ std::string pin_secret() const override;
+
+ // Fetches an instance for the given context.
+ static PinStorageImpl* Get(content::BrowserContext* context);
+
+ // BrowserContextKeyedAPI implementation:
+ static extensions::BrowserContextKeyedAPIFactory<PinStorageImpl>*
+ GetFactoryInstance();
+ static const bool kServiceIsCreatedWithBrowserContext = false;
+
+ private:
+ PrefService* pref_service_;
+ int attempt_count_;
+ base::Time last_strong_auth_;
achuithb 2016/05/13 23:34:57 should this be initialized to something?
jdufault 2016/05/16 22:08:47 It's default constructed to the "null" time (IsPin
+
+ friend class extensions::BrowserContextKeyedAPIFactory<PinStorageImpl>;
+ // BrowserContextKeyedAPI implementation:
+ static const char* service_name() { return "PinStorageImpl"; }
+
+ DISALLOW_COPY_AND_ASSIGN(PinStorageImpl);
+};
+
+static base::LazyInstance<
+ extensions::BrowserContextKeyedAPIFactory<PinStorageImpl>>
+ g_factory = LAZY_INSTANCE_INITIALIZER;
+
+// static
+extensions::BrowserContextKeyedAPIFactory<PinStorageImpl>*
+PinStorageImpl::GetFactoryInstance() {
+ return g_factory.Pointer();
+}
+
+// static
+PinStorageImpl* PinStorageImpl::Get(content::BrowserContext* context) {
+ return extensions::BrowserContextKeyedAPIFactory<PinStorageImpl>::Get(
+ context);
+}
+
+PinStorageImpl::PinStorageImpl(content::BrowserContext* context)
+ : pref_service_(Profile::FromBrowserContext(context)->GetPrefs()),
+ attempt_count_(0) {}
achuithb 2016/05/13 23:34:56 move to class
jdufault 2016/05/16 22:08:47 Done.
+
+PinStorageImpl::~PinStorageImpl() {}
+
+void PinStorageImpl::MarkStrongAuth() {
+ last_strong_auth_ = base::Time::Now();
+}
+
+base::TimeDelta PinStorageImpl::TimeSinceLastStrongAuth() {
+ // TODO: Verify last_strong_auth_ has a good initial value.
+ return base::Time::Now() - last_strong_auth_;
+}
+
+void PinStorageImpl::AddUnlockAttempt() {
+ ++attempt_count_;
+}
+
+void PinStorageImpl::ResetUnlockAttemptCount() {
+ attempt_count_ = 0;
+}
+
+int PinStorageImpl::UnlockAttemptCount() {
+ return attempt_count_;
+}
+
+bool PinStorageImpl::HasPin() const {
+ return !pin_salt().empty() && !pin_secret().empty();
+}
+
+void PinStorageImpl::SetPin(const std::string& raw_pin) {
achuithb 2016/05/13 23:34:56 This method is probably the most significant bit o
jdufault 2016/05/16 22:08:48 I haven't been able to figure out any tests that w
+ // Compute salt. base64 encode it so it is a UTF8 string, which is required by
achuithb 2016/05/13 23:34:57 Generate random salt.
jdufault 2016/05/16 22:08:48 Done.
+ // the pref service.
+ std::string salt;
+ crypto::RandBytes(base::WriteInto(&salt, kSaltByteSize + 1), kSaltByteSize);
+ base::Base64Encode(salt, &salt);
+ DCHECK(!salt.empty());
+
+ // Compute secret.
+ Key key(raw_pin);
+ key.Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt);
+ std::string secret = key.GetSecret();
achuithb 2016/05/13 23:34:57 const
jdufault 2016/05/16 22:08:47 Done.
+
+ // Store them.
+ pref_service_->SetString(prefs::kQuickUnlockPinSalt, salt);
+ pref_service_->SetString(prefs::kQuickUnlockPinSecret, secret);
+}
+
+void PinStorageImpl::RemovePin() {
+ // Clear prefs to their default values.
+ pref_service_->SetString(prefs::kQuickUnlockPinSalt, "");
+ pref_service_->SetString(prefs::kQuickUnlockPinSecret, "");
+}
+
+std::string PinStorageImpl::pin_salt() const {
achuithb 2016/05/13 23:34:56 PinSalt?
jdufault 2016/05/16 22:08:48 Done.
+ return pref_service_->GetString(prefs::kQuickUnlockPinSalt);
+}
+
+std::string PinStorageImpl::pin_secret() const {
achuithb 2016/05/13 23:34:57 PinSecret?
jdufault 2016/05/16 22:08:47 Done.
+ return pref_service_->GetString(prefs::kQuickUnlockPinSecret);
+}
+
+} // namespace
+
+PinStorage::PinStorage() {}
+
+PinStorage::~PinStorage() {}
+
+// static
+void PinStorage::RegisterProfilePrefs(
+ user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterStringPref(prefs::kQuickUnlockPinSalt, "",
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
achuithb 2016/05/13 23:34:57 Do we want this to be syncable?
jdufault 2016/05/16 22:08:47 Security is fine with it, but we're still not sure
+ registry->RegisterStringPref(prefs::kQuickUnlockPinSecret, "",
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
+}
+
+// static
+PinStorage* PinStorage::GetInstance(Profile* profile) {
+ return PinStorageImpl::Get(profile);
+}
+
+} // namespace chromeos

Powered by Google App Engine
This is Rietveld 408576698