Chromium Code Reviews| 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..ccd546c9c13254ef30b778d72f06d2e87942872e |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/login/quick_unlock/pin_storage.cc |
| @@ -0,0 +1,119 @@ |
| +// 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/strings/string_util.h" |
| +#include "chrome/common/pref_names.h" |
| +#include "chromeos/login/auth/key.h" |
| +#include "components/pref_registry/pref_registry_syncable.h" |
| +#include "components/prefs/pref_service.h" |
| +#include "crypto/random.h" |
| + |
| +namespace chromeos { |
| + |
| +namespace { |
| + |
| +const int kSaltByteSize = 16; |
| + |
| +std::string ComputeSecret(std::string pin, std::string salt) { |
|
achuithb
2016/05/16 23:05:10
Input params should be const std::string&. You mig
jdufault
2016/05/17 19:58:26
Converted input params to references.
Is there a
achuithb
2016/05/17 20:13:43
It saves a copy, and it's generally preferred for
|
| + Key key(pin); |
| + key.Transform(Key::KEY_TYPE_SALTED_PBKDF2_AES256_1234, salt); |
| + return key.GetSecret(); |
| +} |
| + |
| +} // namespace |
| + |
| +// static |
| +const base::TimeDelta PinStorage::kStrongAuthTimeout = |
| + base::TimeDelta::FromHours(24); |
| + |
| +// static |
| +void PinStorage::RegisterProfilePrefs( |
| + user_prefs::PrefRegistrySyncable* registry) { |
| + registry->RegisterStringPref(prefs::kQuickUnlockPinSalt, "", |
| + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| + registry->RegisterStringPref(prefs::kQuickUnlockPinSecret, "", |
| + user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| +} |
| + |
| +PinStorage::PinStorage(PrefService* pref_service) |
| + : pref_service_(pref_service) {} |
| + |
| +PinStorage::~PinStorage() {} |
| + |
| +void PinStorage::MarkStrongAuth() { |
| + last_strong_auth_ = base::Time::Now(); |
| + ResetUnlockAttemptCount(); |
| +} |
| + |
| +bool PinStorage::HasStrongAuth() const { |
| + return !last_strong_auth_.is_null(); |
| +} |
| + |
| +base::TimeDelta PinStorage::TimeSinceLastStrongAuth() const { |
| + DCHECK(!last_strong_auth_.is_null()); |
| + return base::Time::Now() - last_strong_auth_; |
| +} |
| + |
| +void PinStorage::AddUnlockAttempt() { |
| + ++attempt_count_; |
| +} |
| + |
| +void PinStorage::ResetUnlockAttemptCount() { |
| + attempt_count_ = 0; |
| +} |
| + |
| +int PinStorage::UnlockAttemptCount() const { |
| + return attempt_count_; |
| +} |
|
stevenjb
2016/05/16 22:19:08
This could be attempt_count() inlined in the heade
jdufault
2016/05/17 19:58:25
Done.
|
| + |
| +bool PinStorage::IsPinSet() const { |
| + return !PinSalt().empty() && !PinSecret().empty(); |
| +} |
| + |
| +void PinStorage::SetPin(const std::string& pin) { |
| + // Generate random salt. It needs to be base64 encoded because the pref |
| + // service requires a UTF8 string. |
| + std::string salt; |
| + crypto::RandBytes(base::WriteInto(&salt, kSaltByteSize + 1), kSaltByteSize); |
|
achuithb
2016/05/16 23:05:10
nit: Also make salt generation an anonymous functi
jdufault
2016/05/17 19:58:26
Done.
|
| + base::Base64Encode(salt, &salt); |
| + DCHECK(!salt.empty()); |
| + |
| + const std::string secret = ComputeSecret(pin, salt); |
| + |
| + pref_service_->SetString(prefs::kQuickUnlockPinSalt, salt); |
| + pref_service_->SetString(prefs::kQuickUnlockPinSecret, secret); |
| +} |
| + |
| +void PinStorage::RemovePin() { |
| + pref_service_->SetString(prefs::kQuickUnlockPinSalt, ""); |
| + pref_service_->SetString(prefs::kQuickUnlockPinSecret, ""); |
| +} |
| + |
| +std::string PinStorage::PinSalt() const { |
| + return pref_service_->GetString(prefs::kQuickUnlockPinSalt); |
| +} |
| + |
| +std::string PinStorage::PinSecret() const { |
| + return pref_service_->GetString(prefs::kQuickUnlockPinSecret); |
| +} |
| + |
| +bool PinStorage::IsPinAuthenticationAvailable() const { |
| + return IsPinSet() && UnlockAttemptCount() < kMaximumUnlockAttempts && |
| + HasStrongAuth() && TimeSinceLastStrongAuth() < kStrongAuthTimeout; |
| +} |
| + |
| +bool PinStorage::TryAuthenticatePin(const std::string& pin) { |
| + if (!IsPinAuthenticationAvailable()) |
| + return false; |
| + |
| + AddUnlockAttempt(); |
| + |
| + const std::string secret = ComputeSecret(pin, PinSalt()); |
| + return secret == PinSecret(); |
|
achuithb
2016/05/16 23:05:10
Inline ComputeSecret? (assuming you don't use the
jdufault
2016/05/17 19:58:26
Done. I initially did this, but thought it was a b
|
| +} |
| + |
| +} // namespace chromeos |