summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-09 22:24:48 +0000
committerzelidrag@chromium.org <zelidrag@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-09 22:24:48 +0000
commit29d563d34c595bc095489a708eebc7638787bb9e (patch)
treece6bc9027eaa4d28fab427ea318462f8555d1ffd
parentac51d40544a116c969ba2b5f116d3b7bf52f7e92 (diff)
downloadchromium_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.cc9
-rw-r--r--chrome/browser/chromeos/login/auth_attempt_state.cc2
-rw-r--r--chrome/browser/chromeos/login/authenticator.h4
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.cc11
-rw-r--r--chrome/browser/chromeos/login/google_authenticator.h2
-rw-r--r--chrome/browser/chromeos/login/login_performer.cc2
-rw-r--r--chrome/browser/chromeos/login/login_utils.cc37
-rw-r--r--chrome/browser/chromeos/login/login_utils.h3
-rw-r--r--chrome/browser/chromeos/login/mock_authenticator.h10
-rw-r--r--chrome/browser/chromeos/login/parallel_authenticator.cc110
-rw-r--r--chrome/browser/chromeos/login/parallel_authenticator.h13
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).