This source file includes following definitions.
- CreateSecurePasswordHash
- EncodePasswordHashRecord
- DecodePasswordHashRecord
- RegisterLocalAuthPrefs
- SetLocalAuthCredentials
- SetLocalAuthCredentials
- ValidateLocalAuthCredentials
- ValidateLocalAuthCredentials
#include "chrome/browser/signin/local_auth.h"
#include "base/base64.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/pref_names.h"
#include "components/os_crypt/os_crypt.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "crypto/random.h"
#include "crypto/secure_util.h"
#include "crypto/symmetric_key.h"
namespace {
const char kHash1Encoding = '1';
const unsigned kHash1Bits = 256;
const unsigned kHash1Bytes = kHash1Bits / 8;
const unsigned kHash1IterationCount = 100000;
std::string CreateSecurePasswordHash(const std::string& salt,
const std::string& password,
char encoding) {
DCHECK_EQ(kHash1Bytes, salt.length());
DCHECK_EQ(kHash1Encoding, encoding);
base::Time start_time = base::Time::Now();
scoped_ptr<crypto::SymmetricKey> password_key(
crypto::SymmetricKey::DeriveKeyFromPassword(
crypto::SymmetricKey::AES,
password, salt,
kHash1IterationCount, kHash1Bits));
std::string password_hash;
const bool success = password_key->GetRawKey(&password_hash);
DCHECK(success);
DCHECK_EQ(kHash1Bytes, password_hash.length());
UMA_HISTOGRAM_TIMES("PasswordHash.CreateTime",
base::Time::Now() - start_time);
return password_hash;
}
std::string EncodePasswordHashRecord(const std::string& record,
char encoding) {
DCHECK_EQ(kHash1Encoding, encoding);
std::string encoded;
const bool success = OSCrypt::EncryptString(record, &encoded);
DCHECK(success);
std::string encoded64;
base::Base64Encode(encoded, &encoded64);
encoded64.insert(0, &encoding, sizeof(encoding));
return encoded64;
}
bool DecodePasswordHashRecord(const std::string& encoded,
std::string* decoded,
char* encoding) {
if (encoded.length() < 1)
return false;
*encoding = encoded[0];
if (*encoding != kHash1Encoding)
return false;
std::string unbase64;
if (!base::Base64Decode(encoded.substr(1), &unbase64))
return false;
return OSCrypt::DecryptString(unbase64, decoded);
}
}
namespace chrome {
void RegisterLocalAuthPrefs(user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterStringPref(
prefs::kGoogleServicesPasswordHash,
std::string(),
user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}
void SetLocalAuthCredentials(size_t info_index,
const std::string& password) {
DCHECK(password.length());
std::string salt_str;
crypto::RandBytes(WriteInto(&salt_str, kHash1Bytes + 1), kHash1Bytes);
DCHECK_EQ(kHash1Bytes, salt_str.length());
std::string password_hash = CreateSecurePasswordHash(
salt_str, password, kHash1Encoding);
DCHECK_EQ(kHash1Bytes, password_hash.length());
std::string record;
record.append(salt_str);
record.append(password_hash);
std::string encoded = EncodePasswordHashRecord(record, kHash1Encoding);
ProfileInfoCache& info =
g_browser_process->profile_manager()->GetProfileInfoCache();
info.SetLocalAuthCredentialsOfProfileAtIndex(info_index, encoded);
}
void SetLocalAuthCredentials(const Profile* profile,
const std::string& password) {
DCHECK(profile);
ProfileInfoCache& info =
g_browser_process->profile_manager()->GetProfileInfoCache();
size_t info_index = info.GetIndexOfProfileWithPath(profile->GetPath());
if (info_index == std::string::npos) {
NOTREACHED();
return;
}
SetLocalAuthCredentials(info_index, password);
}
bool ValidateLocalAuthCredentials(size_t info_index,
const std::string& password) {
std::string record;
char encoding;
ProfileInfoCache& info =
g_browser_process->profile_manager()->GetProfileInfoCache();
std::string encodedhash =
info.GetLocalAuthCredentialsOfProfileAtIndex(info_index);
if (encodedhash.length() == 0 && password.length() == 0)
return true;
if (!DecodePasswordHashRecord(encodedhash, &record, &encoding))
return false;
std::string password_hash;
const char* password_saved;
const char* password_check;
size_t password_length;
if (encoding == '1') {
if (record.length() != 2 * kHash1Bytes)
return false;
std::string salt_str(record.data(), kHash1Bytes);
password_saved = record.data() + kHash1Bytes;
password_hash = CreateSecurePasswordHash(salt_str, password, encoding);
password_check = password_hash.data();
password_length = kHash1Bytes;
} else {
return false;
}
return crypto::SecureMemEqual(password_saved, password_check,
password_length);
}
bool ValidateLocalAuthCredentials(const Profile* profile,
const std::string& password) {
DCHECK(profile);
ProfileInfoCache& info =
g_browser_process->profile_manager()->GetProfileInfoCache();
size_t info_index = info.GetIndexOfProfileWithPath(profile->GetPath());
if (info_index == std::string::npos) {
NOTREACHED();
return false;
}
return ValidateLocalAuthCredentials(info_index, password);
}
}