diff options
author | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-09 22:24:48 +0000 |
---|---|---|
committer | zelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-08-09 22:24:48 +0000 |
commit | 29d563d34c595bc095489a708eebc7638787bb9e (patch) | |
tree | ce6bc9027eaa4d28fab427ea318462f8555d1ffd | |
parent | ac51d40544a116c969ba2b5f116d3b7bf52f7e92 (diff) | |
download | chromium_src-29d563d34c595bc095489a708eebc7638787bb9e.zip chromium_src-29d563d34c595bc095489a708eebc7638787bb9e.tar.gz chromium_src-29d563d34c595bc095489a708eebc7638787bb9e.tar.bz2 |
Merge 96031 - Encrypted OAuth1 all access token and secret with system salt for now, will replace this with user suplemental key once that gets exposed from cryptohome.
Also fixed crash on re-adding the same user to the system.
BUG=chromium-os:18634, chromium-os:18551
TEST=open /home/cronos/user/Preferences and make sure oauth token and secert are encrypted now
Review URL: http://codereview.chromium.org/7584026
TBR=zelidrag@chromium.org
Review URL: http://codereview.chromium.org/7607017
git-svn-id: svn://svn.chromium.org/chrome/branches/835/src@96085 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/chromeos/cros/cryptohome_library.cc | 9 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/auth_attempt_state.cc | 2 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/authenticator.h | 4 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/google_authenticator.cc | 11 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/google_authenticator.h | 2 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/login_performer.cc | 2 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/login_utils.cc | 37 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/login_utils.h | 3 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/mock_authenticator.h | 10 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/parallel_authenticator.cc | 110 | ||||
-rw-r--r-- | chrome/browser/chromeos/login/parallel_authenticator.h | 13 |
11 files changed, 148 insertions, 55 deletions
diff --git a/chrome/browser/chromeos/cros/cryptohome_library.cc b/chrome/browser/chromeos/cros/cryptohome_library.cc index 71984b9..29c62c9 100644 --- a/chrome/browser/chromeos/cros/cryptohome_library.cc +++ b/chrome/browser/chromeos/cros/cryptohome_library.cc @@ -11,6 +11,10 @@ #include "chrome/common/chrome_switches.h" #include "content/browser/browser_thread.h" +namespace { + const char kStubSystemSalt[] = "stub_system_salt"; +} + namespace chromeos { // This class handles the interaction with the ChromeOS cryptohome library APIs. @@ -349,8 +353,9 @@ class CryptohomeLibraryStubImpl : public CryptohomeLibrary { CryptohomeBlob GetSystemSalt() { CryptohomeBlob salt = CryptohomeBlob(); - salt.push_back(0); - salt.push_back(0); + for (size_t i = 0; i < strlen(kStubSystemSalt); i++) + salt.push_back(static_cast<unsigned char>(kStubSystemSalt[i])); + return salt; } diff --git a/chrome/browser/chromeos/login/auth_attempt_state.cc b/chrome/browser/chromeos/login/auth_attempt_state.cc index 7e1299f..a67b802 100644 --- a/chrome/browser/chromeos/login/auth_attempt_state.cc +++ b/chrome/browser/chromeos/login/auth_attempt_state.cc @@ -57,7 +57,7 @@ AuthAttemptState::AuthAttemptState(const std::string& username, password(password), ascii_hash(ascii_hash), unlock(true), - online_complete_(true), + online_complete_(false), online_outcome_(LoginFailure::NONE), credentials_(GaiaAuthConsumer::ClientLoginResult()), hosted_policy_(GaiaAuthFetcher::HostedAccountsAllowed), diff --git a/chrome/browser/chromeos/login/authenticator.h b/chrome/browser/chromeos/login/authenticator.h index 8ea2186..8099df6 100644 --- a/chrome/browser/chromeos/login/authenticator.h +++ b/chrome/browser/chromeos/login/authenticator.h @@ -97,6 +97,10 @@ class Authenticator : public base::RefCountedThreadSafe<Authenticator> { virtual void VerifyOAuth1AccessToken(const std::string& oauth1_access_token, const std::string& oauth1_secret) = 0; + // OAuth token encryption helpers. + virtual std::string EncryptToken(const std::string& token) = 0; + virtual std::string DecryptToken(const std::string& encrypted_token) = 0; + // Profile (usually off the record ) that was used to perform the last // authentication process. Profile* authentication_profile() { return authentication_profile_; } diff --git a/chrome/browser/chromeos/login/google_authenticator.cc b/chrome/browser/chromeos/login/google_authenticator.cc index 599a2e2..d097430 100644 --- a/chrome/browser/chromeos/login/google_authenticator.cc +++ b/chrome/browser/chromeos/login/google_authenticator.cc @@ -412,6 +412,17 @@ void GoogleAuthenticator::VerifyOAuth1AccessToken( NOTIMPLEMENTED(); } +std::string GoogleAuthenticator::EncryptToken(const std::string& unused) { + NOTIMPLEMENTED(); + return std::string(); +} + +std::string GoogleAuthenticator::DecryptToken(const std::string& unused) { + NOTIMPLEMENTED(); + return std::string(); +} + + void GoogleAuthenticator::LoadSystemSalt() { if (!system_salt_.empty()) return; diff --git a/chrome/browser/chromeos/login/google_authenticator.h b/chrome/browser/chromeos/login/google_authenticator.h index 93d96cd..135aebf 100644 --- a/chrome/browser/chromeos/login/google_authenticator.h +++ b/chrome/browser/chromeos/login/google_authenticator.h @@ -118,6 +118,8 @@ class GoogleAuthenticator : public Authenticator, public GaiaAuthConsumer { const std::string& login_captcha) OVERRIDE; virtual void VerifyOAuth1AccessToken(const std::string& auth1_token, const std::string& oauth1_secret) OVERRIDE; + virtual std::string EncryptToken(const std::string& token) OVERRIDE; + virtual std::string DecryptToken(const std::string& encrypted_token) OVERRIDE; // Callbacks from GaiaAuthFetcher virtual void OnClientLoginFailure( diff --git a/chrome/browser/chromeos/login/login_performer.cc b/chrome/browser/chromeos/login/login_performer.cc index 9e9220b..161684d 100644 --- a/chrome/browser/chromeos/login/login_performer.cc +++ b/chrome/browser/chromeos/login/login_performer.cc @@ -178,6 +178,8 @@ void LoginPerformer::OnProfileCreated(Profile* profile, Status status) { // was performed via ClientLogin. We don't need this in the case when // we use extension + OAuth1 access token check flow. LoginUtils::Get()->FetchCookies(profile, credentials_); + } else { + LoginUtils::Get()->StartTokenServices(profile); } LoginUtils::Get()->StartSync(profile, credentials_); credentials_ = GaiaAuthConsumer::ClientLoginResult(); diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index f99068c..bee27e2 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -281,6 +281,10 @@ class LoginUtilsImpl : public LoginUtils, Profile* profile, const GaiaAuthConsumer::ClientLoginResult& credentials) OVERRIDE; + // Starts process of fetching OAuth2 tokens (based on OAuth1 tokens found + // in |user_profile|) and kicks off internal services that depend on them. + virtual void StartTokenServices(Profile* user_profile) OVERRIDE; + // Supply credentials for sync and others to use. virtual void StartSync( Profile* profile, @@ -585,6 +589,16 @@ void LoginUtilsImpl::FetchCookies( cf->AttemptFetch(credentials.data); } +void LoginUtilsImpl::StartTokenServices(Profile* user_profile) { + std::string oauth1_token; + std::string oauth1_secret; + if (!ReadOAuth1AccessToken(user_profile, &oauth1_token, &oauth1_secret)) + return; + + FetchSecondaryTokens(user_profile->GetOffTheRecordProfile(), oauth1_token, + oauth1_secret); +} + void LoginUtilsImpl::StartSync( Profile* user_profile, const GaiaAuthConsumer::ClientLoginResult& credentials) { @@ -867,14 +881,21 @@ void LoginUtilsImpl::FetchSecondaryTokens(Profile* offrecord_profile, } bool LoginUtilsImpl::ReadOAuth1AccessToken(Profile* user_profile, - std::string* token, - std::string* secret) { + std::string* token, + std::string* secret) { PrefService* pref_service = user_profile->GetPrefs(); - *token = pref_service->GetString(prefs::kOAuth1Token); - *secret = pref_service->GetString(prefs::kOAuth1Secret); - if (!token->length() || !secret->length()) + std::string encoded_token = pref_service->GetString(prefs::kOAuth1Token); + std::string encoded_secret = pref_service->GetString(prefs::kOAuth1Secret); + if (!encoded_token.length() || !encoded_secret.length()) + return false; + + std::string decoded_token = authenticator_->DecryptToken(encoded_token); + std::string decoded_secret = authenticator_->DecryptToken(encoded_secret); + if (!decoded_token.length() || !decoded_secret.length()) return false; + *token = decoded_token; + *secret = decoded_secret; return true; } @@ -883,8 +904,10 @@ void LoginUtilsImpl::StoreOAuth1AccessToken(Profile* user_profile, const std::string& secret) { // First store OAuth1 token + service for the current user profile... PrefService* pref_service = user_profile->GetPrefs(); - pref_service->SetString(prefs::kOAuth1Token, token); - pref_service->SetString(prefs::kOAuth1Secret, secret); + pref_service->SetString(prefs::kOAuth1Token, + authenticator_->EncryptToken(token)); + pref_service->SetString(prefs::kOAuth1Secret, + authenticator_->EncryptToken(secret)); // ...then record the presence of valid OAuth token for this account in local // state as well. diff --git a/chrome/browser/chromeos/login/login_utils.h b/chrome/browser/chromeos/login/login_utils.h index 82c0f67..a47fc2d 100644 --- a/chrome/browser/chromeos/login/login_utils.h +++ b/chrome/browser/chromeos/login/login_utils.h @@ -81,6 +81,9 @@ class LoginUtils { Profile* profile, const GaiaAuthConsumer::ClientLoginResult& credentials) = 0; + // Starts OAuth2 token retrieval and kicks off services that depend on it. + virtual void StartTokenServices(Profile* profile) = 0; + // Supply credentials for sync and others to use. virtual void StartSync( Profile* profile, diff --git a/chrome/browser/chromeos/login/mock_authenticator.h b/chrome/browser/chromeos/login/mock_authenticator.h index 702b410..ed7a766 100644 --- a/chrome/browser/chromeos/login/mock_authenticator.h +++ b/chrome/browser/chromeos/login/mock_authenticator.h @@ -67,6 +67,14 @@ class MockAuthenticator : public Authenticator { const std::string& login_token, const std::string& login_captcha) {} + virtual std::string EncryptToken(const std::string& token) { + return std::string(); + } + + virtual std::string DecryptToken(const std::string& encrypted_token) { + return std::string(); + } + virtual void VerifyOAuth1AccessToken(const std::string& oauth1_access_token, const std::string& oauth1_secret) {} @@ -104,6 +112,8 @@ class MockLoginUtils : public LoginUtils { Profile* profile, const GaiaAuthConsumer::ClientLoginResult& credentials) {} + virtual void StartTokenServices(Profile* profile) {} + virtual void StartSync( Profile* profile, const GaiaAuthConsumer::ClientLoginResult& credentials) {} diff --git a/chrome/browser/chromeos/login/parallel_authenticator.cc b/chrome/browser/chromeos/login/parallel_authenticator.cc index c269d5b..ae245f4 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator.cc +++ b/chrome/browser/chromeos/login/parallel_authenticator.cc @@ -12,9 +12,10 @@ #include "base/file_util.h" #include "base/logging.h" #include "base/path_service.h" +#include "base/rand_util.h" +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/synchronization/lock.h" -#include "crypto/sha2.h" #include "chrome/browser/chromeos/cros/cryptohome_library.h" #include "chrome/browser/chromeos/login/auth_response_handler.h" #include "chrome/browser/chromeos/login/authentication_notification_details.h" @@ -30,6 +31,9 @@ #include "chrome/common/net/gaia/gaia_constants.h" #include "content/browser/browser_thread.h" #include "content/common/notification_service.h" +#include "crypto/encryptor.h" +#include "crypto/sha2.h" +#include "crypto/symmetric_key.h" #include "net/base/load_flags.h" #include "net/base/net_errors.h" #include "net/url_request/url_request_status.h" @@ -53,6 +57,7 @@ const int ParallelAuthenticator::kClientLoginTimeoutMs = 10000; const int ParallelAuthenticator::kLocalaccountRetryIntervalMs = 20; const int kPassHashLen = 32; +const size_t kKeySize = 16; ParallelAuthenticator::ParallelAuthenticator(LoginStatusConsumer* consumer) : Authenticator(consumer), @@ -130,13 +135,15 @@ bool ParallelAuthenticator::CompleteLogin(Profile* profile, BrowserThread::UI, FROM_HERE, NewRunnableMethod(mounter_.get(), &CryptohomeOp::Initiate)); - // For login completion, we just need to resolve the current auth, - // attempt state. - // TODO(zelidrag): Investigate if this business be moved to UI thread instead. - BrowserThread::PostTask( - BrowserThread::IO, FROM_HERE, - NewRunnableMethod(this, - &ParallelAuthenticator::ResolveLoginCompletionStatus)); + // For login completion of a new user, we just need to resolve the current + // auth attempt state, the rest of OAuth related tasks will be done in + // parallel. + if (!UserManager::Get()->IsKnownUser(canonicalized)) { + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + NewRunnableMethod(this, + &ParallelAuthenticator::ResolveLoginCompletionStatus)); + } BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, @@ -675,52 +682,79 @@ void ParallelAuthenticator::SetLocalaccount(const std::string& new_name) { } } +std::string ParallelAuthenticator::EncryptToken(const std::string& token) { + // TODO(zelidrag): Replace salt with + scoped_ptr<crypto::SymmetricKey> key( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, UserSupplementalKeyAsAscii(), + SaltAsAscii(), 1000, 256)); + crypto::Encryptor encryptor; + if (!encryptor.Init(key.get(), crypto::Encryptor::CTR, std::string())) + return std::string(); + + std::string nonce = SaltAsAscii().substr(0, kKeySize); + std::string encoded_token; + CHECK(encryptor.SetCounter(nonce)); + if (!encryptor.Encrypt(token, &encoded_token)) + return std::string(); + + return StringToLowerASCII(base::HexEncode( + reinterpret_cast<const void*>(encoded_token.data()), + encoded_token.size())); +} + +std::string ParallelAuthenticator::DecryptToken( + const std::string& encrypted_token_hex) { + std::vector<uint8> encrypted_token_bytes; + if (!base::HexStringToBytes(encrypted_token_hex, &encrypted_token_bytes)) + return std::string(); + + std::string encrypted_token( + reinterpret_cast<char*>(encrypted_token_bytes.data()), + encrypted_token_bytes.size()); + scoped_ptr<crypto::SymmetricKey> key( + crypto::SymmetricKey::DeriveKeyFromPassword( + crypto::SymmetricKey::AES, UserSupplementalKeyAsAscii(), + SaltAsAscii(), 1000, 256)); + crypto::Encryptor encryptor; + if (!encryptor.Init(key.get(), crypto::Encryptor::CTR, std::string())) + return std::string(); + + std::string nonce = SaltAsAscii().substr(0, kKeySize); + std::string token; + CHECK(encryptor.SetCounter(nonce)); + if (!encryptor.Decrypt(encrypted_token, &token)) + return std::string(); + return token; +} + std::string ParallelAuthenticator::HashPassword(const std::string& password) { // Get salt, ascii encode, update sha with that, then update with ascii // of password, then end. std::string ascii_salt = SaltAsAscii(); - unsigned char passhash_buf[kPassHashLen]; - char ascii_buf[kPassHashLen + 1]; + char passhash_buf[kPassHashLen]; // Hash salt and password crypto::SHA256HashString(ascii_salt + password, &passhash_buf, sizeof(passhash_buf)); - std::vector<unsigned char> passhash(passhash_buf, - passhash_buf + sizeof(passhash_buf)); - BinaryToHex(passhash, - passhash.size() / 2, // only want top half, at least for now. - ascii_buf, - sizeof(ascii_buf)); - return std::string(ascii_buf, sizeof(ascii_buf) - 1); + return StringToLowerASCII(base::HexEncode( + reinterpret_cast<const void*>(passhash_buf), + sizeof(passhash_buf) / 2)); } std::string ParallelAuthenticator::SaltAsAscii() { LoadSystemSalt(); // no-op if it's already loaded. - unsigned int salt_len = system_salt_.size(); - char ascii_salt[2 * salt_len + 1]; - if (ParallelAuthenticator::BinaryToHex(system_salt_, - salt_len, - ascii_salt, - sizeof(ascii_salt))) { - return std::string(ascii_salt, sizeof(ascii_salt) - 1); - } - return std::string(); + return StringToLowerASCII(base::HexEncode( + reinterpret_cast<const void*>(system_salt_.data()), + system_salt_.size())); } -// static -bool ParallelAuthenticator::BinaryToHex( - const std::vector<unsigned char>& binary, - const unsigned int binary_len, - char* hex_string, - const unsigned int len) { - if (len < 2*binary_len) - return false; - memset(hex_string, 0, len); - for (uint i = 0, j = 0; i < binary_len; i++, j+=2) - snprintf(hex_string + j, len - j, "%02x", binary[i]); - return true; +std::string ParallelAuthenticator::UserSupplementalKeyAsAscii() { + // TODO(zelidrag, wad): http://crosbug.com/18633 - Replace this with the real + // user suplemental key gets exposed in from cryptolib. + return SaltAsAscii(); } void ParallelAuthenticator::ResolveLoginCompletionStatus() { diff --git a/chrome/browser/chromeos/login/parallel_authenticator.h b/chrome/browser/chromeos/login/parallel_authenticator.h index ab230e0..dffc253 100644 --- a/chrome/browser/chromeos/login/parallel_authenticator.h +++ b/chrome/browser/chromeos/login/parallel_authenticator.h @@ -147,6 +147,8 @@ class ParallelAuthenticator : public Authenticator, const std::string& login_captcha) OVERRIDE; virtual void VerifyOAuth1AccessToken(const std::string& oauth1_access_token, const std::string& oauth1_secret) OVERRIDE; + virtual std::string EncryptToken(const std::string& token) OVERRIDE; + virtual std::string DecryptToken(const std::string& encrypted_token) OVERRIDE; // AuthAttemptStateResolver overrides. // Attempts to make a decision and call back |consumer_| based on @@ -238,13 +240,10 @@ class ParallelAuthenticator : public Authenticator, // Returns the ascii encoding of the system salt. std::string SaltAsAscii(); - // Converts the binary data |binary| into an ascii hex string and stores - // it in |hex_string|. Not guaranteed to be NULL-terminated. - // Returns false if |hex_string| is too small, true otherwise. - static bool BinaryToHex(const std::vector<unsigned char>& binary, - const unsigned int binary_len, - char* hex_string, - const unsigned int len); + // Returns the ascii encoding of user supplemental key. + // TODO(zelidrag): http://crosbug.com/18905. Replace this with a key from + // nssdb instead. + std::string UserSupplementalKeyAsAscii(); // Signal login completion status for cases when a new user is added via // an external authentication provider (i.e. GAIA extension). |