diff options
| author | bartfab <bartfab@chromium.org> | 2014-09-03 16:59:47 -0700 |
|---|---|---|
| committer | Commit bot <commit-bot@chromium.org> | 2014-09-04 00:34:38 +0000 |
| commit | 37e866f487685f176c1861ecc507a2f25e2c1a33 (patch) | |
| tree | 49d4f747ac5bcaca061dbeb28660ec9ef74337e1 | |
| parent | 8d0540250a09769fa5f3a323302ceb4a0d498a51 (diff) | |
| download | chromium_src-37e866f487685f176c1861ecc507a2f25e2c1a33.zip chromium_src-37e866f487685f176c1861ecc507a2f25e2c1a33.tar.gz chromium_src-37e866f487685f176c1861ecc507a2f25e2c1a33.tar.bz2 | |
Make CryptohomeAuthenticator's Login*() methods work with pre-hashed keys
When a user's cryptohome directory is created with a pre-hashed key,
the credentials provided need to be hashed in the same way whenever the
crypthome is to be unlocked/mounted. This CL updates the Login*() methods
in CryptohomeAuthenticator to retrieve key metadata and apply the correct
hashing algorithm to the given credentials. Follow-up CLs will update
the other CryptohomeAuthenticator methods to also work with pre-hashed
keys.
BUG=367847
TEST=Extended unit tests
Review URL: https://codereview.chromium.org/517653002
Cr-Commit-Position: refs/heads/master@{#293227}
| -rw-r--r-- | chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc | 172 | ||||
| -rw-r--r-- | chromeos/cryptohome/mock_homedir_methods.cc | 8 | ||||
| -rw-r--r-- | chromeos/cryptohome/mock_homedir_methods.h | 1 | ||||
| -rw-r--r-- | chromeos/login/auth/cryptohome_authenticator.cc | 232 | ||||
| -rw-r--r-- | chromeos/login/auth/cryptohome_authenticator.h | 2 |
5 files changed, 321 insertions, 94 deletions
diff --git a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc index 634cd41..454ffdc 100644 --- a/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc +++ b/chrome/browser/chromeos/login/auth/cryptohome_authenticator_unittest.cc @@ -6,11 +6,14 @@ #include <string> +#include "base/basictypes.h" #include "base/command_line.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" +#include "base/run_loop.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "chrome/browser/chromeos/login/users/fake_user_manager.h" @@ -31,6 +34,7 @@ #include "chromeos/cryptohome/mock_homedir_methods.h" #include "chromeos/cryptohome/system_salt_getter.h" #include "chromeos/dbus/cros_disks_client.h" +#include "chromeos/dbus/cryptohome/rpc.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "chromeos/login/auth/key.h" @@ -52,12 +56,19 @@ using ::testing::Invoke; using ::testing::Return; +using ::testing::WithArg; using ::testing::_; namespace chromeos { namespace { +// Label under which the user's key is stored. +const char kCryptohomeGAIAKeyLabel[] = "gaia"; + +// Salt used by pre-hashed key. +const char kSalt[] = "SALT $$"; + // An owner key in PKCS#8 PrivateKeyInfo for testing owner checks. const uint8 kOwnerPrivateKey[] = { 0x30, 0x82, 0x01, 0x53, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, @@ -132,10 +143,9 @@ class CryptohomeAuthenticatorTest : public testing::Test { ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, &profile_); - transformed_key_ = *user_context_.GetKey(); - transformed_key_.Transform(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, - SystemSaltGetter::ConvertRawSaltToHexString( - FakeCryptohomeClient::GetStubSystemSalt())); + CreateTransformedKey(Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, + SystemSaltGetter::ConvertRawSaltToHexString( + FakeCryptohomeClient::GetStubSystemSalt())); } virtual ~CryptohomeAuthenticatorTest() {} @@ -173,6 +183,12 @@ class CryptohomeAuthenticatorTest : public testing::Test { mock_homedir_methods_ = NULL; } + void CreateTransformedKey(Key::KeyType type, const std::string& salt) { + user_context_with_transformed_key_ = user_context_; + user_context_with_transformed_key_.GetKey()->Transform(type, salt); + transformed_key_ = *user_context_with_transformed_key_.GetKey(); + } + base::FilePath PopulateTempFile(const char* data, int data_len) { base::FilePath out; FILE* tmp_file = base::CreateAndOpenTemporaryFile(&out); @@ -240,6 +256,57 @@ class CryptohomeAuthenticatorTest : public testing::Test { .RetiresOnSaturation(); } + void ExpectGetKeyDataExCall(scoped_ptr<int64> key_type, + scoped_ptr<std::string> salt) { + key_data_.clear(); + key_data_.push_back(new cryptohome::RetrievedKeyData( + cryptohome::RetrievedKeyData::TYPE_PASSWORD, + kCryptohomeGAIAKeyLabel, + 1)); + key_data_.front()->privileges = cryptohome::PRIV_DEFAULT; + key_data_.front()->authorization_types.push_back( + cryptohome::RetrievedKeyData::AUTHORIZATION_TYPE_HMACSHA256); + if (key_type) { + scoped_ptr<cryptohome::RetrievedKeyData::ProviderData> provider_data( + new cryptohome::RetrievedKeyData::ProviderData("type")); + provider_data->number = key_type.Pass(); + key_data_.front()->provider_data.push_back(provider_data.release()); + } + if (salt) { + scoped_ptr<cryptohome::RetrievedKeyData::ProviderData> provider_data( + new cryptohome::RetrievedKeyData::ProviderData("salt")); + provider_data->bytes = salt.Pass(); + key_data_.front()->provider_data.push_back(provider_data.release()); + } + EXPECT_CALL(*mock_homedir_methods_, GetKeyDataEx( + cryptohome::Identification(user_context_.GetUserID()), + kCryptohomeGAIAKeyLabel, + _)) + .WillOnce(WithArg<2>(Invoke( + this, + &CryptohomeAuthenticatorTest::InvokeGetDataExCallback))); + } + + void ExpectMountExCall(bool expect_create_attempt) { + const cryptohome::KeyDefinition auth_key(transformed_key_.GetSecret(), + std::string(), + cryptohome::PRIV_DEFAULT); + cryptohome::MountParameters mount(false /* ephemeral */); + if (expect_create_attempt) { + mount.create_keys.push_back(cryptohome::KeyDefinition( + transformed_key_.GetSecret(), + kCryptohomeGAIAKeyLabel, + cryptohome::PRIV_DEFAULT)); + } + EXPECT_CALL(*mock_homedir_methods_, + MountEx(cryptohome::Identification(user_context_.GetUserID()), + cryptohome::Authorization(auth_key), + mount, + _)) + .Times(1) + .RetiresOnSaturation(); + } + void RunResolve(CryptohomeAuthenticator* auth) { auth->Resolve(); base::MessageLoop::current()->RunUntilIdle(); @@ -263,8 +330,11 @@ class CryptohomeAuthenticatorTest : public testing::Test { content::TestBrowserThreadBundle thread_bundle_; UserContext user_context_; + UserContext user_context_with_transformed_key_; Key transformed_key_; + ScopedVector<cryptohome::RetrievedKeyData> key_data_; + ScopedDeviceSettingsTestHelper device_settings_test_helper_; ScopedTestCrosSettings test_cros_settings_; @@ -283,6 +353,14 @@ class CryptohomeAuthenticatorTest : public testing::Test { FakeCryptohomeClient* fake_cryptohome_client_; scoped_refptr<ownership::MockOwnerKeyUtil> owner_key_util_; + + private: + void InvokeGetDataExCallback( + const cryptohome::HomedirMethods::GetKeyDataCallback& callback) { + callback.Run(true /* success */, + cryptohome::MOUNT_ERROR_NONE, + key_data_.Pass()); + } }; TEST_F(CryptohomeAuthenticatorTest, OnAuthSuccess) { @@ -533,7 +611,7 @@ TEST_F(CryptohomeAuthenticatorTest, DriveRetailModeLoginButFail) { } TEST_F(CryptohomeAuthenticatorTest, DriveDataResync) { - UserContext expected_user_context(user_context_); + UserContext expected_user_context(user_context_with_transformed_key_); expected_user_context.SetUserIDHash( cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername); ExpectLoginSuccess(expected_user_context); @@ -548,20 +626,8 @@ TEST_F(CryptohomeAuthenticatorTest, DriveDataResync) { // Set up mock homedir methods to respond successfully to a cryptohome create // attempt. - const cryptohome::KeyDefinition auth_key(transformed_key_.GetSecret(), - std::string(), - cryptohome::PRIV_DEFAULT); - cryptohome::MountParameters mount(false /* ephemeral */); - mount.create_keys.push_back(cryptohome::KeyDefinition( - transformed_key_.GetSecret(), - "gaia", - cryptohome::PRIV_DEFAULT)); - EXPECT_CALL(*mock_homedir_methods_, - MountEx(cryptohome::Identification(user_context_.GetUserID()), - cryptohome::Authorization(auth_key), - mount, - _)) - .Times(1); + ExpectGetKeyDataExCall(scoped_ptr<int64>(), scoped_ptr<std::string>()); + ExpectMountExCall(true /* expect_create_attempt */); state_->PresetOnlineLoginStatus(AuthFailure::AuthFailureNone()); SetAttemptState(auth_.get(), state_.release()); @@ -598,7 +664,7 @@ TEST_F(CryptohomeAuthenticatorTest, DriveRequestOldPassword) { } TEST_F(CryptohomeAuthenticatorTest, DriveDataRecover) { - UserContext expected_user_context(user_context_); + UserContext expected_user_context(user_context_with_transformed_key_); expected_user_context.SetUserIDHash( cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername); ExpectLoginSuccess(expected_user_context); @@ -615,14 +681,8 @@ TEST_F(CryptohomeAuthenticatorTest, DriveDataRecover) { // Set up mock homedir methods to respond successfully to a cryptohome mount // attempt. - const cryptohome::KeyDefinition auth_key(transformed_key_.GetSecret(), - std::string(), - cryptohome::PRIV_DEFAULT); - EXPECT_CALL(*mock_homedir_methods_, - MountEx(cryptohome::Identification(user_context_.GetUserID()), - cryptohome::Authorization(auth_key), - cryptohome::MountParameters(false /* ephemeral */), - _)); + ExpectGetKeyDataExCall(scoped_ptr<int64>(), scoped_ptr<std::string>()); + ExpectMountExCall(false /* expect_create_attempt */); state_->PresetOnlineLoginStatus(AuthFailure::AuthFailureNone()); SetAttemptState(auth_.get(), state_.release()); @@ -676,7 +736,7 @@ TEST_F(CryptohomeAuthenticatorTest, ResolveCreateNew) { } TEST_F(CryptohomeAuthenticatorTest, DriveCreateForNewUser) { - UserContext expected_user_context(user_context_); + UserContext expected_user_context(user_context_with_transformed_key_); expected_user_context.SetUserIDHash( cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername); ExpectLoginSuccess(expected_user_context); @@ -684,19 +744,8 @@ TEST_F(CryptohomeAuthenticatorTest, DriveCreateForNewUser) { // Set up mock homedir methods to respond successfully to a cryptohome create // attempt. - const cryptohome::KeyDefinition auth_key(transformed_key_.GetSecret(), - std::string(), - cryptohome::PRIV_DEFAULT); - cryptohome::MountParameters mount(false /* ephemeral */); - mount.create_keys.push_back(cryptohome::KeyDefinition( - transformed_key_.GetSecret(), - "gaia", - cryptohome::PRIV_DEFAULT)); - EXPECT_CALL(*mock_homedir_methods_, - MountEx(cryptohome::Identification(user_context_.GetUserID()), - cryptohome::Authorization(auth_key), - mount, - _)); + ExpectGetKeyDataExCall(scoped_ptr<int64>(), scoped_ptr<std::string>()); + ExpectMountExCall(true /* expect_create_attempt */); // Set up state as though a cryptohome mount attempt has occurred // and been rejected because the user doesn't exist; additionally, @@ -749,4 +798,43 @@ TEST_F(CryptohomeAuthenticatorTest, DriveUnlock) { base::MessageLoop::current()->Run(); } +TEST_F(CryptohomeAuthenticatorTest, DriveLoginWithPreHashedPassword) { + CreateTransformedKey(Key::KEY_TYPE_SALTED_SHA256, kSalt); + + UserContext expected_user_context(user_context_with_transformed_key_); + expected_user_context.SetUserIDHash( + cryptohome::MockAsyncMethodCaller::kFakeSanitizedUsername); + ExpectLoginSuccess(expected_user_context); + FailOnLoginFailure(); + + // Set up mock homedir methods to respond with key metadata indicating that a + // pre-hashed key was used to create the cryptohome and allow a successful + // mount when this pre-hashed key is used. + + ExpectGetKeyDataExCall( + make_scoped_ptr(new int64(Key::KEY_TYPE_SALTED_SHA256)), + make_scoped_ptr(new std::string(kSalt))); + ExpectMountExCall(false /* expect_create_attempt */); + + auth_->AuthenticateToLogin(NULL, user_context_); + base::RunLoop().Run(); +} + +TEST_F(CryptohomeAuthenticatorTest, FailLoginWithMissingSalt) { + CreateTransformedKey(Key::KEY_TYPE_SALTED_SHA256, kSalt); + + FailOnLoginSuccess(); + ExpectLoginFailure(AuthFailure(AuthFailure::COULD_NOT_MOUNT_CRYPTOHOME)); + + // Set up mock homedir methods to respond with key metadata indicating that a + // pre-hashed key was used to create the cryptohome but without the required + // salt. + ExpectGetKeyDataExCall( + make_scoped_ptr(new int64(Key::KEY_TYPE_SALTED_SHA256)), + scoped_ptr<std::string>()); + + auth_->AuthenticateToLogin(NULL, user_context_); + base::RunLoop().Run(); +} + } // namespace chromeos diff --git a/chromeos/cryptohome/mock_homedir_methods.cc b/chromeos/cryptohome/mock_homedir_methods.cc index 0cb4a38..db6edb5 100644 --- a/chromeos/cryptohome/mock_homedir_methods.cc +++ b/chromeos/cryptohome/mock_homedir_methods.cc @@ -4,6 +4,8 @@ #include "chromeos/cryptohome/mock_homedir_methods.h" +#include "base/memory/scoped_vector.h" +#include "chromeos/cryptohome/cryptohome_parameters.h" #include "chromeos/cryptohome/mock_async_method_caller.h" using ::testing::Invoke; @@ -20,6 +22,8 @@ MockHomedirMethods::~MockHomedirMethods() {} void MockHomedirMethods::SetUp(bool success, MountError return_code) { success_ = success; return_code_ = return_code; + ON_CALL(*this, GetKeyDataEx(_, _, _)).WillByDefault( + WithArgs<2>(Invoke(this, &MockHomedirMethods::DoGetDataCallback))); ON_CALL(*this, CheckKeyEx(_, _, _)).WillByDefault( WithArgs<2>(Invoke(this, &MockHomedirMethods::DoCallback))); ON_CALL(*this, MountEx(_, _, _, _)).WillByDefault( @@ -36,6 +40,10 @@ void MockHomedirMethods::DoCallback(const Callback& callback) { callback.Run(success_, return_code_); } +void MockHomedirMethods::DoGetDataCallback(const GetKeyDataCallback& callback) { + callback.Run(success_, return_code_, ScopedVector<RetrievedKeyData>()); +} + void MockHomedirMethods::DoMountCallback(const MountCallback& callback) { callback.Run( success_, return_code_, MockAsyncMethodCaller::kFakeSanitizedUsername); diff --git a/chromeos/cryptohome/mock_homedir_methods.h b/chromeos/cryptohome/mock_homedir_methods.h index 1798911..8647744 100644 --- a/chromeos/cryptohome/mock_homedir_methods.h +++ b/chromeos/cryptohome/mock_homedir_methods.h @@ -57,6 +57,7 @@ class CHROMEOS_EXPORT MockHomedirMethods : public HomedirMethods { MountError return_code_; void DoCallback(const Callback& callback); + void DoGetDataCallback(const GetKeyDataCallback& callback); void DoMountCallback(const MountCallback& callback); DISALLOW_COPY_AND_ASSIGN(MockHomedirMethods); diff --git a/chromeos/login/auth/cryptohome_authenticator.cc b/chromeos/login/auth/cryptohome_authenticator.cc index fffa216..d00cf29 100644 --- a/chromeos/login/auth/cryptohome_authenticator.cc +++ b/chromeos/login/auth/cryptohome_authenticator.cc @@ -4,6 +4,7 @@ #include "chromeos/login/auth/cryptohome_authenticator.h" +#include "base/basictypes.h" #include "base/bind.h" #include "base/files/file_path.h" #include "base/location.h" @@ -30,6 +31,14 @@ namespace { // The label used for the key derived from the user's GAIA credentials. const char kCryptohomeGAIAKeyLabel[] = "gaia"; +// The name under which the type of key generated from the user's GAIA +// credentials is stored. +const char kKeyProviderDataTypeName[] = "type"; + +// The name under which the salt used to generate a key from the user's GAIA +// credentials is stored. +const char kKeyProviderDataSaltName[] = "salt"; + // Hashes |key| with |system_salt| if it its type is KEY_TYPE_PASSWORD_PLAIN. // Returns the keys unmodified otherwise. scoped_ptr<Key> TransformKeyIfNeeded(const Key& key, @@ -73,14 +82,25 @@ void TriggerResolveWithLoginTimeMarker( TriggerResolve(attempt, resolver, success, return_code); } -void TriggerResolveWithHashAndLoginTimeMarker( - const std::string& marker_name, - AuthAttemptState* attempt, - scoped_refptr<CryptohomeAuthenticator> resolver, - bool success, - cryptohome::MountError return_code, - const std::string& mount_hash) { - chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker(marker_name, false); +// Records an error in accessing the user's cryptohome with the given key and +// calls resolver->Resolve() after adding a login time marker. +void RecordKeyErrorAndResolve(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver) { + chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("CryptohomeMount-End", + false); + attempt->RecordCryptohomeStatus(false /* success */, + cryptohome::MOUNT_ERROR_KEY_FAILURE); + resolver->Resolve(); +} + +// Callback invoked when cryptohome's MountEx() method has finished. +void OnMount(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool success, + cryptohome::MountError return_code, + const std::string& mount_hash) { + chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker("CryptohomeMount-End", + false); attempt->RecordCryptohomeStatus(success, return_code); if (success) attempt->RecordUsernameHash(mount_hash); @@ -89,20 +109,23 @@ void TriggerResolveWithHashAndLoginTimeMarker( resolver->Resolve(); } -// Calls cryptohome's mount method. -void Mount(AuthAttemptState* attempt, - scoped_refptr<CryptohomeAuthenticator> resolver, - bool ephemeral, - bool create_if_nonexistent, - const std::string& system_salt) { - chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( - "CryptohomeMount-Start", false); +// Calls cryptohome's MountEx() method. The key in |attempt->user_context| must +// not be a plain text password. If the user provided a plain text password, +// that password must be transformed to another key type (by salted hashing) +// before calling this method. +void DoMount(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent) { + const Key* key = attempt->user_context.GetKey(); + // If the |key| is a plain text password, crash rather than attempting to + // mount the cryptohome with a plain text password. + CHECK_NE(Key::KEY_TYPE_PASSWORD_PLAIN, key->GetKeyType()); + // Set state that username_hash is requested here so that test implementation // that returns directly would not generate 2 OnLoginSucces() calls. attempt->UsernameHashRequested(); - scoped_ptr<Key> key = - TransformKeyIfNeeded(*attempt->user_context.GetKey(), system_salt); // Set the authentication's key label to an empty string, which is a wildcard // allowing any key to match. This is necessary because cryptohomes created by // Chrome OS M38 and older will have a legacy key with no label while those @@ -123,10 +146,127 @@ void Mount(AuthAttemptState* attempt, cryptohome::Identification(attempt->user_context.GetUserID()), cryptohome::Authorization(auth_key), mount, - base::Bind(&TriggerResolveWithHashAndLoginTimeMarker, - "CryptohomeMount-End", + base::Bind(&OnMount, attempt, resolver)); +} + +// Callback invoked when the system salt has been retrieved. Transforms the key +// in |attempt->user_context| using Chrome's default hashing algorithm and the +// system salt, then calls MountEx(). +void OnGetSystemSalt(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent, + const std::string& system_salt) { + DCHECK_EQ(Key::KEY_TYPE_PASSWORD_PLAIN, + attempt->user_context.GetKey()->GetKeyType()); + + attempt->user_context.GetKey()->Transform( + Key::KEY_TYPE_SALTED_SHA256_TOP_HALF, + system_salt); + + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); +} + +// Callback invoked when cryptohome's GetKeyDataEx() method has finished. +// * If GetKeyDataEx() returned metadata indicating the hashing algorithm and +// salt that were used to generate the key for this user's cryptohome, +// transforms the key in |attempt->user_context| with the same parameters. +// * Otherwise, starts the retrieval of the system salt so that the key in +// |attempt->user_context| can be transformed with Chrome's default hashing +// algorithm and the system salt. +// The resulting key is then passed to cryptohome's MountEx(). +void OnGetKeyDataEx(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent, + bool success, + cryptohome::MountError return_code, + ScopedVector<cryptohome::RetrievedKeyData> key_data) { + if (success) { + if (key_data.size() == 1) { + cryptohome::RetrievedKeyData* key_data_entry = key_data.front(); + DCHECK_EQ(kCryptohomeGAIAKeyLabel, key_data_entry->label); + + // Extract the key type and salt from |key_data|, if present. + scoped_ptr<int64> type; + scoped_ptr<std::string> salt; + for (ScopedVector<cryptohome::RetrievedKeyData::ProviderData>:: + const_iterator it = key_data_entry->provider_data.begin(); + it != key_data_entry->provider_data.end(); ++it) { + if ((*it)->name == kKeyProviderDataTypeName) { + if ((*it)->number) + type.reset(new int64(*(*it)->number)); + else + NOTREACHED(); + } else if ((*it)->name == kKeyProviderDataSaltName) { + if ((*it)->bytes) + salt.reset(new std::string(*(*it)->bytes)); + else + NOTREACHED(); + } + } + + if (type) { + if (*type < 0 || *type >= Key::KEY_TYPE_COUNT) { + LOG(ERROR) << "Invalid key type: " << *type; + RecordKeyErrorAndResolve(attempt, resolver); + return; + } + + if (!salt) { + LOG(ERROR) << "Missing salt."; + RecordKeyErrorAndResolve(attempt, resolver); + return; + } + + attempt->user_context.GetKey()->Transform( + static_cast<Key::KeyType>(*type), + *salt); + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + return; + } + } else { + LOG(ERROR) << "GetKeyDataEx() returned " << key_data.size() + << " entries."; + } + } + + SystemSaltGetter::Get()->GetSystemSalt(base::Bind(&OnGetSystemSalt, + attempt, + resolver, + ephemeral, + create_if_nonexistent)); +} + +// Starts the process that will mount a user's cryptohome. +// * If the key in |attempt->user_context| is not a plain text password, +// cryptohome's MountEx() method is called directly with the key. +// * Otherwise, the key must be transformed (by salted hashing) before being +// passed to MountEx(). In that case, cryptohome's GetKeyDataEx() method is +// called to retrieve metadata indicating the hashing algorithm and salt that +// were used to generate the key for this user's cryptohome and the key is +// transformed accordingly before calling MountEx(). +void StartMount(AuthAttemptState* attempt, + scoped_refptr<CryptohomeAuthenticator> resolver, + bool ephemeral, + bool create_if_nonexistent) { + chromeos::LoginEventRecorder::Get()->AddLoginTimeMarker( + "CryptohomeMount-Start", false); + + if (attempt->user_context.GetKey()->GetKeyType() != + Key::KEY_TYPE_PASSWORD_PLAIN) { + DoMount(attempt, resolver, ephemeral, create_if_nonexistent); + return; + } + + cryptohome::HomedirMethods::GetInstance()->GetKeyDataEx( + cryptohome::Identification(attempt->user_context.GetUserID()), + kCryptohomeGAIAKeyLabel, + base::Bind(&OnGetKeyDataEx, attempt, - resolver)); + resolver, + ephemeral, + create_if_nonexistent)); } // Calls cryptohome's mount method for guest and also get the user hash from @@ -252,12 +392,10 @@ void CryptohomeAuthenticator::AuthenticateToLogin( // Reset the verified flag. owner_is_verified_ = false; - SystemSaltGetter::Get()->GetSystemSalt( - base::Bind(&Mount, - current_state_.get(), - scoped_refptr<CryptohomeAuthenticator>(this), - false /* ephemeral */, - false /* create_if_nonexistent */)); + StartMount(current_state_.get(), + scoped_refptr<CryptohomeAuthenticator>(this), + false /* ephemeral */, + false /* create_if_nonexistent */); } void CryptohomeAuthenticator::CompleteLogin(Profile* profile, @@ -272,12 +410,10 @@ void CryptohomeAuthenticator::CompleteLogin(Profile* profile, // Reset the verified flag. owner_is_verified_ = false; - SystemSaltGetter::Get()->GetSystemSalt( - base::Bind(&Mount, - current_state_.get(), - scoped_refptr<CryptohomeAuthenticator>(this), - false /* ephemeral */, - false /* create_if_nonexistent */)); + StartMount(current_state_.get(), + scoped_refptr<CryptohomeAuthenticator>(this), + false /* ephemeral */, + false /* create_if_nonexistent */); // For login completion from extension, we just need to resolve the current // auth attempt state, the rest of OAuth related tasks will be done in @@ -312,12 +448,10 @@ void CryptohomeAuthenticator::LoginAsSupervisedUser( false, // online_complete false)); // user_is_new remove_user_data_on_failure_ = false; - SystemSaltGetter::Get()->GetSystemSalt( - base::Bind(&Mount, - current_state_.get(), - scoped_refptr<CryptohomeAuthenticator>(this), - false /* ephemeral */, - false /* create_if_nonexistent */)); + StartMount(current_state_.get(), + scoped_refptr<CryptohomeAuthenticator>(this), + false /* ephemeral */, + false /* create_if_nonexistent */); } void CryptohomeAuthenticator::LoginRetailMode() { @@ -361,12 +495,10 @@ void CryptohomeAuthenticator::LoginAsPublicSession( false)); // user_is_new remove_user_data_on_failure_ = false; ephemeral_mount_attempted_ = true; - SystemSaltGetter::Get()->GetSystemSalt( - base::Bind(&Mount, - current_state_.get(), - scoped_refptr<CryptohomeAuthenticator>(this), - true /* ephemeral */, - true /* create_if_nonexistent */)); + StartMount(current_state_.get(), + scoped_refptr<CryptohomeAuthenticator>(this), + true /* ephemeral */, + true /* create_if_nonexistent */); } void CryptohomeAuthenticator::LoginAsKioskAccount( @@ -569,12 +701,10 @@ void CryptohomeAuthenticator::Resolve() { create_if_nonexistent = true; case RECOVER_MOUNT: current_state_->ResetCryptohomeStatus(); - SystemSaltGetter::Get()->GetSystemSalt( - base::Bind(&Mount, - current_state_.get(), - scoped_refptr<CryptohomeAuthenticator>(this), - false /*ephemeral*/, - create_if_nonexistent)); + StartMount(current_state_.get(), + scoped_refptr<CryptohomeAuthenticator>(this), + false /*ephemeral*/, + create_if_nonexistent); break; case NEED_OLD_PW: task_runner_->PostTask( diff --git a/chromeos/login/auth/cryptohome_authenticator.h b/chromeos/login/auth/cryptohome_authenticator.h index d003b83..cd01ac4 100644 --- a/chromeos/login/auth/cryptohome_authenticator.h +++ b/chromeos/login/auth/cryptohome_authenticator.h @@ -7,9 +7,9 @@ #include <string> -#include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/gtest_prod_util.h" +#include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "base/task_runner.h" |
