diff options
25 files changed, 158 insertions, 757 deletions
diff --git a/chrome/browser/chromeos/login/login_utils.cc b/chrome/browser/chromeos/login/login_utils.cc index ea9a18b..733aa08 100644 --- a/chrome/browser/chromeos/login/login_utils.cc +++ b/chrome/browser/chromeos/login/login_utils.cc @@ -921,11 +921,8 @@ void LoginUtilsImpl::StartSignedInServices( // data encrypted with the user's GAIA password. ProfileSyncService* sync_service = ProfileSyncServiceFactory::GetInstance()->GetForProfile(user_profile); - if (sync_service) { - sync_service->SetPassphrase(password_, - ProfileSyncService::IMPLICIT, - ProfileSyncService::INTERNAL); - } + if (sync_service) + sync_service->SetPassphrase(password_, false); } password_.clear(); TokenService* token_service = user_profile->GetTokenService(); diff --git a/chrome/browser/chromeos/login/screen_locker.cc b/chrome/browser/chromeos/login/screen_locker.cc index a751ba5..75aa7db4 100644 --- a/chrome/browser/chromeos/login/screen_locker.cc +++ b/chrome/browser/chromeos/login/screen_locker.cc @@ -271,9 +271,7 @@ void ScreenLocker::OnLoginSuccess( ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile)); if (service && !service->HasSyncSetupCompleted()) { // If sync has failed somehow, try setting the sync passphrase here. - service->SetPassphrase(password, - ProfileSyncService::IMPLICIT, - ProfileSyncService::INTERNAL); + service->SetPassphrase(password, false); } } DBusThreadManager::Get()->GetPowerManagerClient()-> diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc index 151e630..ecbbf11 100644 --- a/chrome/browser/sync/glue/sync_backend_host.cc +++ b/chrome/browser/sync/glue/sync_backend_host.cc @@ -82,8 +82,7 @@ class SyncBackendHost::Core virtual void OnPassphraseRequired( sync_api::PassphraseRequiredReason reason, const sync_pb::EncryptedData& pending_keys) OVERRIDE; - virtual void OnPassphraseAccepted() OVERRIDE; - virtual void OnBootstrapTokenUpdated( + virtual void OnPassphraseAccepted( const std::string& bootstrap_token) OVERRIDE; virtual void OnStopSyncingPermanently() OVERRIDE; virtual void OnUpdatedToken(const std::string& token) OVERRIDE; @@ -126,9 +125,7 @@ class SyncBackendHost::Core // Called to set the passphrase on behalf of // SyncBackendHost::SupplyPassphrase. - void DoSetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided); + void DoSetPassphrase(const std::string& passphrase, bool is_explicit); // Called to turn on encryption of all sync data as well as // reencrypt everything. @@ -324,8 +321,7 @@ void SyncBackendHost::StartSyncingWithServer() { } void SyncBackendHost::SetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided) { + bool is_explicit) { if (!IsNigoriEnabled()) { SLOG(WARNING) << "Silently dropping SetPassphrase request."; return; @@ -337,7 +333,7 @@ void SyncBackendHost::SetPassphrase(const std::string& passphrase, // If encryption is enabled and we've got a SetPassphrase sync_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(&SyncBackendHost::Core::DoSetPassphrase, core_.get(), - passphrase, is_explicit, user_provided)); + passphrase, is_explicit)); } void SyncBackendHost::StopSyncManagerForShutdown( @@ -806,23 +802,14 @@ void SyncBackendHost::Core::OnPassphraseRequired( &SyncBackendHost::NotifyPassphraseRequired, reason, pending_keys); } -void SyncBackendHost::Core::OnPassphraseAccepted() { - if (!sync_loop_) - return; - DCHECK_EQ(MessageLoop::current(), sync_loop_); - host_.Call( - FROM_HERE, - &SyncBackendHost::NotifyPassphraseAccepted); -} - -void SyncBackendHost::Core::OnBootstrapTokenUpdated( +void SyncBackendHost::Core::OnPassphraseAccepted( const std::string& bootstrap_token) { if (!sync_loop_) return; DCHECK_EQ(MessageLoop::current(), sync_loop_); host_.Call( FROM_HERE, - &SyncBackendHost::PersistEncryptionBootstrapToken, bootstrap_token); + &SyncBackendHost::NotifyPassphraseAccepted, bootstrap_token); } void SyncBackendHost::Core::OnStopSyncingPermanently() { @@ -992,10 +979,9 @@ void SyncBackendHost::Core::DoRequestCleanupDisabledTypes() { } void SyncBackendHost::Core::DoSetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided) { + bool is_explicit) { DCHECK_EQ(MessageLoop::current(), sync_loop_); - sync_manager_->SetPassphrase(passphrase, is_explicit, user_provided); + sync_manager_->SetPassphrase(passphrase, is_explicit); } void SyncBackendHost::Core::DoEnableEncryptEverything() { @@ -1196,7 +1182,8 @@ void SyncBackendHost::NotifyPassphraseRequired( frontend_->OnPassphraseRequired(reason, pending_keys); } -void SyncBackendHost::NotifyPassphraseAccepted() { +void SyncBackendHost::NotifyPassphraseAccepted( + const std::string& bootstrap_token) { if (!frontend_) return; @@ -1204,6 +1191,8 @@ void SyncBackendHost::NotifyPassphraseAccepted() { // Clear our cache of the cryptographer's pending keys. cached_pending_keys_.clear_blob(); + + PersistEncryptionBootstrapToken(bootstrap_token); frontend_->OnPassphraseAccepted(); } diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h index bc2dbbf..1fd547d 100644 --- a/chrome/browser/sync/glue/sync_backend_host.h +++ b/chrome/browser/sync/glue/sync_backend_host.h @@ -178,18 +178,11 @@ class SyncBackendHost { virtual void StartSyncingWithServer(); // Called on |frontend_loop_| to asynchronously set the passphrase. - // |is_explicit| is true if the call is in response to the user setting a - // custom explicit passphrase as opposed to implicitly (from the users' - // perspective) using their Google Account password. An implicit SetPassphrase - // will *not* override an explicit passphrase set previously. Note that - // if the data is encrypted with an old Google Account password, the user - // may still have to provide a "implicit" passphrase. - // |user_provided| corresponds to the user having manually provided this - // passphrase. It should only be false for passphrases intercepted from the - // Google Sign-in Success notification and true otherwise. - void SetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided); + // |is_explicit| is true if the call is in response to the user explicitly + // setting a passphrase as opposed to implicitly (from the users' perspective) + // using their Google Account password. An implicit SetPassphrase will *not* + // *not* override an explicit passphrase set previously. + void SetPassphrase(const std::string& passphrase, bool is_explicit); // Called on |frontend_loop_| to kick off shutdown procedure. After this, // no further sync activity will occur with the sync server and no further @@ -413,7 +406,7 @@ class SyncBackendHost { sync_pb::EncryptedData pending_keys); // Invoked when the passphrase provided by the user has been accepted. - void NotifyPassphraseAccepted(); + void NotifyPassphraseAccepted(const std::string& bootstrap_token); // Invoked when an updated token is available from the sync server. void NotifyUpdatedToken(const std::string& token); diff --git a/chrome/browser/sync/internal_api/debug_info_event_listener.cc b/chrome/browser/sync/internal_api/debug_info_event_listener.cc index d783dee..239e42b 100644 --- a/chrome/browser/sync/internal_api/debug_info_event_listener.cc +++ b/chrome/browser/sync/internal_api/debug_info_event_listener.cc @@ -48,13 +48,9 @@ void DebugInfoEventListener::OnPassphraseRequired( CreateAndAddEvent(sync_pb::DebugEventInfo::PASSPHRASE_REQUIRED); } -void DebugInfoEventListener::OnPassphraseAccepted() { - CreateAndAddEvent(sync_pb::DebugEventInfo::PASSPHRASE_ACCEPTED); -} - -void DebugInfoEventListener::OnBootstrapTokenUpdated( +void DebugInfoEventListener::OnPassphraseAccepted( const std::string& bootstrap_token) { - CreateAndAddEvent(sync_pb::DebugEventInfo::BOOTSTRAP_TOKEN_UPDATED); + CreateAndAddEvent(sync_pb::DebugEventInfo::PASSPHRASE_ACCEPTED); } void DebugInfoEventListener::OnStopSyncingPermanently() { diff --git a/chrome/browser/sync/internal_api/debug_info_event_listener.h b/chrome/browser/sync/internal_api/debug_info_event_listener.h index a4daa18..98ecfdf 100644 --- a/chrome/browser/sync/internal_api/debug_info_event_listener.h +++ b/chrome/browser/sync/internal_api/debug_info_event_listener.h @@ -40,8 +40,7 @@ class DebugInfoEventListener : public sync_api::SyncManager::Observer, virtual void OnPassphraseRequired( sync_api::PassphraseRequiredReason reason, const sync_pb::EncryptedData& pending_keys) OVERRIDE; - virtual void OnPassphraseAccepted() OVERRIDE; - virtual void OnBootstrapTokenUpdated( + virtual void OnPassphraseAccepted( const std::string& bootstrap_token) OVERRIDE; virtual void OnStopSyncingPermanently() OVERRIDE; virtual void OnUpdatedToken(const std::string& token) OVERRIDE; diff --git a/chrome/browser/sync/internal_api/sync_manager.cc b/chrome/browser/sync/internal_api/sync_manager.cc index 3cad23f..09739d2 100644 --- a/chrome/browser/sync/internal_api/sync_manager.cc +++ b/chrome/browser/sync/internal_api/sync_manager.cc @@ -241,19 +241,7 @@ class SyncManager::SyncInternal // Try to set the current passphrase to |passphrase|, and record whether // it is an explicit passphrase or implicitly using gaia in the Nigori // node. - // |is_explicit| is true if the call is in response to the user setting a - // custom explicit passphrase as opposed to implicitly (from the users' - // perspective) using their Google Account password. Once an explicit - // passphrase is set, it can never be overwritten (not even by another - // explicit passphrase). - // |user_provided| is true corresponds to the user having manually provided - // this passphrase. It should only be false for passphrases intercepted - // from the Google Sign-in Success notification. Note that if the data is - // encrypted with an old Google Account password, the user may still have to - // provide an "implicit" passphrase. - void SetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided); + void SetPassphrase(const std::string& passphrase, bool is_explicit); // Call periodically from a database-safe thread to persist recent changes // to the syncapi model. @@ -398,25 +386,6 @@ class SyncManager::SyncInternal // available. void RaiseAuthNeededEvent(); - // Helpers for SetPassphrase. TODO(rsimha): make these the public methods - // eventually and have them replace SetPassphrase(..). - // These correspond to setting a passphrase for decryption (when we have - // pending keys) or setting a passphrase for encryption (we do not have - // pending keys). - bool SetDecryptionPassphrase( - const KeyParams& key_params, - bool nigori_has_explicit_passphrase, - bool is_explicit, - bool user_provided, - Cryptographer* cryptographer, - std::string *new_bootstrap_token); - bool SetEncryptionPassphrase( - const KeyParams& key_params, - bool nigori_has_explicit_passphrase, - bool is_explicit, - Cryptographer* cryptographer, - std::string *new_bootstrap_token); - // Internal callback of UpdateCryptographerAndNigoriCallback. void UpdateCryptographerAndNigoriCallback( const base::Callback<void(bool)>& done_callback, @@ -773,10 +742,9 @@ void SyncManager::StartSyncingNormally() { } void SyncManager::SetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided) { + bool is_explicit) { DCHECK(thread_checker_.CalledOnValidThread()); - data_->SetPassphrase(passphrase, is_explicit, user_provided); + data_->SetPassphrase(passphrase, is_explicit); } void SyncManager::EnableEncryptEverything() { @@ -1200,8 +1168,7 @@ void SyncManager::SyncInternal::RaiseAuthNeededEvent() { } void SyncManager::SyncInternal::SetPassphrase( - const std::string& passphrase, bool is_explicit, bool user_provided) { - DCHECK(user_provided || !is_explicit); + const std::string& passphrase, bool is_explicit) { // We do not accept empty passphrases. if (passphrase.empty()) { DVLOG(1) << "Rejecting empty passphrase."; @@ -1219,7 +1186,7 @@ void SyncManager::SyncInternal::SetPassphrase( // All accesses to the cryptographer are protected by a transaction. WriteTransaction trans(FROM_HERE, GetUserShare()); Cryptographer* cryptographer = trans.GetCryptographer(); - KeyParams key_params = {"localhost", "dummy", passphrase}; + KeyParams params = {"localhost", "dummy", passphrase}; WriteNode node(&trans); if (!node.InitByTagLookup(kNigoriTag)) { @@ -1227,83 +1194,49 @@ void SyncManager::SyncInternal::SetPassphrase( NOTREACHED(); return; } - bool nigori_has_explicit_passphrase = - node.GetNigoriSpecifics().using_explicit_passphrase(); - - // There are five cases to handle here: - // 1. The user has no pending keys and is setting their current GAIA password - // as the encryption passphrase. This happens either during first time sync - // with a clean profile, or after re-authenticating on a profile that was - // already signed in with the cryptographer ready. - // 2. The user is overwriting an (already provided) implicit passphrase with - // an explicit (custom) passphrase. There are no pending keys. - // 3. We're using the current GAIA password to decrypt the pending keys. This - // happens when signing in to an account with a previously set implicit - // passphrase, where the data is already encrypted with the newest GAIA - // password. - // 4. The user is providing an old GAIA password to decrypt the pending keys. - // In this case, the user is using an implicit passphrase, but has changed - // their password since they last encrypted their data, and therefore - // their current GAIA password was unable to decrypt the data. This will - // happen when the user is setting up a new profile with a previously - // encrypted account (after changing passwords). - // 5. The user is providing a previously set explicit passphrase to decrypt - // the pending keys. - // Furthermore, we enforce the following: The bootstrap encryption token will - // always be derived from the newest GAIA password if the account is using - // an implicit passphrase (even if the data is encrypted with an old GAIA - // password). If the account is using an explicit (custom) passphrase, the - // bootstrap token will be derived from the most recently provided explicit - // passphrase (that was able to decrypt the data). - // TODO(rsimha): Fix the plumbing so we call these two methods separately and - // directly from the PSS API. It may also make sense to embed this logic - // within the cryptographer itself. http://crbug.com/108718 - std::string bootstrap_token; - bool success = false; - sync_pb::EncryptedData pending_keys; + if (cryptographer->has_pending_keys()) { - pending_keys = cryptographer->GetPendingKeys(); - // Handles cases 3, 4, and 5. - success = SetDecryptionPassphrase(key_params, - nigori_has_explicit_passphrase, - is_explicit, - user_provided, - cryptographer, - &bootstrap_token); - if (success) { - // Nudge the syncer so that encrypted datatype updates that were waiting - // for this passphrase get applied as soon as possible. - RequestNudge(FROM_HERE); + bool succeeded = false; + + // See if the explicit flag matches what is set in nigori. If not we dont + // even try the passphrase. Note: This could mean that we wont try setting + // the gaia password as passphrase if custom is elected by the user. Which + // is fine because nigori node has all the old passwords in it. + if (node.GetNigoriSpecifics().using_explicit_passphrase() == is_explicit) { + if (cryptographer->DecryptPendingKeys(params)) { + succeeded = true; + } else { + DVLOG(1) << "Passphrase failed to decrypt pending keys."; + } + } else { + DVLOG(1) << "Not trying the passphrase because the explicit flags dont " + << "match. Nigori node's explicit flag is " + << node.GetNigoriSpecifics().using_explicit_passphrase(); + } + + if (!succeeded) { + sync_pb::EncryptedData pending_keys; + if (cryptographer->has_pending_keys()) + pending_keys = cryptographer->GetPendingKeys(); + FOR_EACH_OBSERVER(SyncManager::Observer, observers_, + OnPassphraseRequired(sync_api::REASON_SET_PASSPHRASE_FAILED, + pending_keys)); + return; } + + // Nudge the syncer so that encrypted datatype updates that were waiting for + // this passphrase get applied as soon as possible. + RequestNudge(FROM_HERE); } else { - // Handles cases 1 and 2. - success = SetEncryptionPassphrase(key_params, - nigori_has_explicit_passphrase, - is_explicit, - cryptographer, - &bootstrap_token); - } - - // It's possible we need to change the bootstrap token even if we failed to - // set the passphrase (for example if we need to preserve the new GAIA - // passphrase). - if (!bootstrap_token.empty()) { - DVLOG(1) << "Bootstrap token updated."; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnBootstrapTokenUpdated(bootstrap_token)); - } + DVLOG(1) << "No pending keys, adding provided passphrase."; - if (!success) { - DVLOG(1) << "SetPassphrase failure, notifying and returning."; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseRequired(sync_api::REASON_SET_PASSPHRASE_FAILED, - pending_keys)); - return; + // Prevent an implicit SetPassphrase request from changing an explicitly + // set passphrase. + if (!is_explicit && node.GetNigoriSpecifics().using_explicit_passphrase()) + return; + + cryptographer->AddKey(params); } - DVLOG(1) << "SetPassphrase success, updating nigori and reencrypting."; - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, - OnPassphraseAccepted()); - DCHECK(cryptographer->is_ready()); // TODO(tim): Bug 58231. It would be nice if SetPassphrase didn't require // messing with the Nigori node, because we can't call SetPassphrase until @@ -1322,176 +1255,12 @@ void SyncManager::SyncInternal::SetPassphrase( // Does nothing if everything is already encrypted or the cryptographer has // pending keys. ReEncryptEverything(&trans); -} - -bool SyncManager::SyncInternal::SetEncryptionPassphrase( - const KeyParams& key_params, - bool nigori_has_explicit_passphrase, - bool is_explicit, - Cryptographer* cryptographer, - std::string *bootstrap_token) { - if (cryptographer->has_pending_keys()) { - LOG(ERROR) << "Attempt to set encryption passphrase failed because there " - << "were pending keys."; - return false; - } - if (!nigori_has_explicit_passphrase) { - // Case 1 and 2. Setting a new GAIA passphrase when there are no pending - // keys (1), or overwriting an implicit passphrase with a new explicit one - // (2) when there are no pending keys. - if (cryptographer->AddKey(key_params)) { - DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) - << " passphrase for encryption."; - cryptographer->GetBootstrapToken(bootstrap_token); - return true; - } else { - NOTREACHED() << "Failed to add key to cryptographer."; - return false; - } - } else { // nigori_has_explicit_passphrase == true - if (is_explicit) { - NOTREACHED() << "Attempting to change explicit passphrase when one has " - << "already been set."; - } else { - DVLOG(1) << "Ignoring implicit passphrase for encryption, explicit " - << "passphrase already set."; - } - return false; - } // nigori_has_explicit_passphrase - NOTREACHED(); - return false; -} -bool SyncManager::SyncInternal::SetDecryptionPassphrase( - const KeyParams& key_params, - bool nigori_has_explicit_passphrase, - bool is_explicit, - bool user_provided, - Cryptographer* cryptographer, - std::string *bootstrap_token) { - if (!cryptographer->has_pending_keys()) { - NOTREACHED() << "Attempt to set decryption passphrase failed because there " - << "were no pending keys."; - return false; - - } - if (!nigori_has_explicit_passphrase) { - if (!is_explicit) { - if (!user_provided) { - // Case 3. - if (cryptographer->DecryptPendingKeys(key_params)) { - DVLOG(1) << "Implicit internal passphrase accepted for decryption."; - cryptographer->GetBootstrapToken(bootstrap_token); - return true; - } else { - DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding " - << "anyways as default passphrase and persisting via " - << "bootstrap token."; - // Turns out we're encrypted with an old GAIA password, and we're - // actually in case 3. But, because this is the current GAIA - // password, we need to generate a new bootstrap token to preserve it. - // We build a temporary cryptographer to allow us to extract these - // params without polluting our current cryptographer. - Cryptographer temp_cryptographer; - temp_cryptographer.AddKey(key_params); - temp_cryptographer.GetBootstrapToken(bootstrap_token); - // We then set the new passphrase as the default passphrase of the - // real cryptographer, even though we have pending keys. This is safe, - // as although Cryptographer::is_initialized() will now be true, - // is_ready() will remain false due to having pending keys. - cryptographer->AddKey(key_params); - return false; - } - } else { // user_provided == true - if (cryptographer->is_initialized()) { - // We only want to change the default encryption key to the pending - // one if the pending keybag already contains the current default. - // This covers the case where a different client re-encrypted - // everything with a newer gaia passphrase (and hence the keybag - // contains keys from all previously used gaia passphrases). - // Otherwise, we're in a situation where the pending keys are - // encrypted with an old gaia passphrase, while the default is the - // current gaia passphrase. In that case, we preserve the default. - Cryptographer temp_cryptographer; - temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys()); - if (temp_cryptographer.DecryptPendingKeys(key_params)) { - // Check to see if the pending bag of keys contains the current - // default key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - if (temp_cryptographer.CanDecrypt(encrypted)) { - DVLOG(1) << "Implicit user provided passphrase accepted for " - << "decryption, overwriting default."; - // The pending keybag contains the current default. Go ahead - // and update the cryptographer, letting the default change. - // Case 3. - cryptographer->DecryptPendingKeys(key_params); - cryptographer->GetBootstrapToken(bootstrap_token); - return true; - } else { - // The pending keybag does not contain the current default - // encryption key. We want to restore the current default - // after decrypting the pending keys. - // Case 4. - DVLOG(1) << "Implicit user provided passphrase accepted for " - << "decryption, restoring implicit internal passphrase " - << "as default."; - std::string bootstrap_token_from_current_key; - cryptographer->GetBootstrapToken( - &bootstrap_token_from_current_key); - cryptographer->DecryptPendingKeys(key_params); - // Overwrite the default from the pending keys. - cryptographer->AddKeyFromBootstrapToken( - bootstrap_token_from_current_key); - return true; - } - } else { - DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; - return false; - } - } else if (cryptographer->DecryptPendingKeys(key_params)) { - // This can happpen if this is a client that has lost the credentials - // from the current gaia password, and has data encrypted with an old - // gaia password. We won't be able to re-encrypt to the most recent - // GAIA password, so for now just continue and initialize the - // cryptographer. - // This is a subset of case 4 that we don't handle properly yet. - // TODO(zea): trigger prompting for re-auth here. See part 2 of - // http://crbug.com/104508. - DVLOG(1) << "Implicit user provided passphrase accepted, initializing" - << " cryptographer."; - return true; - } else { - DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; - return false; - } - } // user_provided - } else { // is_explicit == true - // This can happen if the client changes their password, re-authed on - // another machine, and we only just now received the updated nigori. - DVLOG(1) << "Explicit passphrase failed to decrypt because nigori had " - << "implicit passphrase."; - return false; - } // is_explicit - } else { // nigori_has_explicit_passphrase == true - if (!is_explicit) { - DVLOG(1) << "Implicit passphrase rejected because nigori had explicit " - << "passphrase."; - return false; - } else { // is_explicit == true - // Case 5. - if (cryptographer->DecryptPendingKeys(key_params)) { - DVLOG(1) << "Explicit passphrase accepted for decryption."; - cryptographer->GetBootstrapToken(bootstrap_token); - return true; - } else { - DVLOG(1) << "Explicit passphrase failed to decrypt."; - return false; - } - } // is_explicit - } // nigori_has_explicit_passphrase - NOTREACHED(); - return false; + DVLOG(1) << "Passphrase accepted, bootstrapping encryption."; + std::string bootstrap_token; + cryptographer->GetBootstrapToken(&bootstrap_token); + FOR_EACH_OBSERVER(SyncManager::Observer, observers_, + OnPassphraseAccepted(bootstrap_token)); } bool SyncManager::SyncInternal::IsUsingExplicitPassphrase() { @@ -1620,7 +1389,8 @@ void SyncManager::SyncInternal::ReEncryptEverything(WriteTransaction* trans) { } // NOTE: We notify from within a transaction. - FOR_EACH_OBSERVER(SyncManager::Observer, observers_, OnEncryptionComplete()); + FOR_EACH_OBSERVER( + SyncManager::Observer, observers_, OnEncryptionComplete()); } SyncManager::~SyncManager() { diff --git a/chrome/browser/sync/internal_api/sync_manager.h b/chrome/browser/sync/internal_api/sync_manager.h index cfb466c..f0ece70 100644 --- a/chrome/browser/sync/internal_api/sync_manager.h +++ b/chrome/browser/sync/internal_api/sync_manager.h @@ -285,19 +285,11 @@ class SyncManager { const sync_pb::EncryptedData& pending_keys) = 0; // Called when the passphrase provided by the user has been accepted and is - // now used to encrypt sync data. - virtual void OnPassphraseAccepted() = 0; - - // |bootstrap_token| is an opaque base64 encoded representation of the key - // generated by the current passphrase, and is provided to the observer for - // persistence purposes and use in a future initialization of sync (e.g. - // after restart). The boostrap token will always be derived from the most - // recent GAIA password (for accounts with implicit passphrases), even if - // the data is still encrypted with an older GAIA password. For accounts - // with explicit passphrases, it will be the most recently seen custom - // passphrase. - virtual void OnBootstrapTokenUpdated( - const std::string& bootstrap_token) = 0; + // now used to encrypt sync data. |bootstrap_token| is an opaque base64 + // encoded representation of the key generated by the accepted passphrase, + // and is provided to the observer for persistence purposes and use in a + // future initialization of sync (e.g. after restart). + virtual void OnPassphraseAccepted(const std::string& bootstrap_token) = 0; // Called when initialization is complete to the point that SyncManager can // process changes. This does not necessarily mean authentication succeeded @@ -487,18 +479,11 @@ class SyncManager { // If the passphrase in invalid, OnPassphraseRequired will be fired. // Calling this metdod again is the appropriate course of action to "retry" // with a new passphrase. - // |is_explicit| is true if the call is in response to the user setting a - // custom explicit passphrase as opposed to implicitly (from the users' - // perspective) using their Google Account password. An implicit SetPassphrase - // will *not* override an explicit passphrase set previously. Note that - // if the data is encrypted with an old Google Account password, the user - // may still have to provide a "implicit" passphrase. - // |user_provided| corresponds to the user having manually provided this - // passphrase. It should only be false for passphrases intercepted from the - // Google Sign-in Success notification and true otherwise. - void SetPassphrase(const std::string& passphrase, - bool is_explicit, - bool user_provided); + // |is_explicit| is true if the call is in response to the user explicitly + // setting a passphrase as opposed to implicitly (from the users' perspective) + // using their Google Account password. An implicit SetPassphrase will *not* + // *not* override an explicit passphrase set previously. + void SetPassphrase(const std::string& passphrase, bool is_explicit); // Puts the SyncScheduler into a mode where no normal nudge or poll traffic // will occur, but calls to RequestConfig will be supported. If |callback| diff --git a/chrome/browser/sync/internal_api/syncapi_unittest.cc b/chrome/browser/sync/internal_api/syncapi_unittest.cc index 3125858..9a0b3d1 100644 --- a/chrome/browser/sync/internal_api/syncapi_unittest.cc +++ b/chrome/browser/sync/internal_api/syncapi_unittest.cc @@ -67,7 +67,6 @@ using browser_sync::Cryptographer; using browser_sync::HasArgsAsList; using browser_sync::HasDetailsAsDictionary; using browser_sync::KeyParams; -using browser_sync::kNigoriTag; using browser_sync::JsArgList; using browser_sync::JsBackend; using browser_sync::JsEventHandler; @@ -669,8 +668,7 @@ class SyncManagerObserverMock : public SyncManager::Observer { MOCK_METHOD2(OnPassphraseRequired, void(sync_api::PassphraseRequiredReason, const sync_pb::EncryptedData&)); // NOLINT - MOCK_METHOD0(OnPassphraseAccepted, void()); // NOLINT - MOCK_METHOD1(OnBootstrapTokenUpdated, void(const std::string&)); // NOLINT + MOCK_METHOD1(OnPassphraseAccepted, void(const std::string&)); // NOLINT MOCK_METHOD0(OnStopSyncingPermanently, void()); // NOLINT MOCK_METHOD1(OnUpdatedToken, void(const std::string&)); // NOLINT MOCK_METHOD0(OnClearServerDataFailed, void()); // NOLINT @@ -710,7 +708,6 @@ class SyncManagerTest : public testing::Test, }; enum EncryptionStatus { - UNINITIALIZED, DEFAULT_ENCRYPTION, FULL_ENCRYPTION }; @@ -838,12 +835,8 @@ class SyncManagerTest : public testing::Test, Cryptographer* cryptographer = trans.GetCryptographer(); if (!cryptographer) return false; - if (encryption_status != UNINITIALIZED) { - KeyParams params = {"localhost", "dummy", "foobar"}; - cryptographer->AddKey(params); - } else { - DCHECK_NE(nigori_status, WRITE_TO_NIGORI); - } + KeyParams params = {"localhost", "dummy", "foobar"}; + cryptographer->AddKey(params); if (encryption_status == FULL_ENCRYPTION) cryptographer->set_encrypt_everything(); if (nigori_status == WRITE_TO_NIGORI) { @@ -1457,10 +1450,9 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithData) { // Trigger's a ReEncryptEverything with new passphrase. testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)); EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", true, true); + sync_manager_.SetPassphrase("new_passphrase", true); EXPECT_TRUE(sync_manager_.EncryptEverythingEnabledForTest()); { ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); @@ -1486,76 +1478,15 @@ TEST_F(SyncManagerTest, EncryptDataTypesWithData) { // a reencryption and should just notify immediately. // TODO(zea): add logic to ensure nothing was written. testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)).Times(0); - EXPECT_CALL(observer_, OnPassphraseAccepted()).Times(0); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)).Times(0); EXPECT_CALL(observer_, OnEncryptionComplete()); sync_manager_.EnableEncryptEverything(); } -// Test that when there are no pending keys and the cryptographer is not -// initialized, we add a key based on the current GAIA password. -// (case 1 in SyncManager::SyncInternalSetPassphrase) -TEST_F(SyncManagerTest, SetInitialGaiaPass) { - EXPECT_FALSE(SetUpEncryption(DONT_WRITE_NIGORI, UNINITIALIZED)); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", false, false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - ReadNode node(&trans); - EXPECT_TRUE(node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori = node.GetNigoriSpecifics(); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - EXPECT_TRUE(cryptographer->CanDecrypt(nigori.encrypted())); - } -} - -// Test that when there are no pending keys and we have on the old GAIA -// password, we update and re-encrypt everything with the new GAIA password. -// (case 1 in SyncManager::SyncInternalSetPassphrase) -TEST_F(SyncManagerTest, UpdateGaiaPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer verifier; - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - verifier.Bootstrap(bootstrap_token); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", false, false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify the default key has changed. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_FALSE(verifier.CanDecrypt(encrypted)); - } -} - -// Sets a new explicit passphrase. This should update the bootstrap token -// and re-encrypt everything. -// (case 2 in SyncManager::SyncInternalSetPassphrase) TEST_F(SyncManagerTest, SetPassphraseWithPassword) { - Cryptographer verifier; EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); { WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - // Store the default (soon to be old) key. - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - verifier.Bootstrap(bootstrap_token); - ReadNode root_node(&trans); root_node.InitByRootLookup(); @@ -1566,20 +1497,12 @@ TEST_F(SyncManagerTest, SetPassphraseWithPassword) { data.set_password_value("secret"); password_node.SetPasswordSpecifics(data); } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)); EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", true, true); + sync_manager_.SetPassphrase("new_passphrase", true); EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); { ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify the default key has changed. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_FALSE(verifier.CanDecrypt(encrypted)); - ReadNode password_node(&trans); EXPECT_TRUE(password_node.InitByClientTagLookup(syncable::PASSWORDS, "foo")); @@ -1589,163 +1512,6 @@ TEST_F(SyncManagerTest, SetPassphraseWithPassword) { } } -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with a new (unprovided) GAIA password, then supply the -// password. -// (case 3 in SyncManager::SyncInternalSetPassphrase) -TEST_F(SyncManagerTest, SupplyPendingGAIAPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer; - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "passphrase2"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_TRUE(node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - cryptographer->Update(nigori); - EXPECT_TRUE(cryptographer->has_pending_keys()); - node.SetNigoriSpecifics(nigori); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("passphrase2", false, false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted)); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with an old (unprovided) GAIA password. Attempt to supply -// the current GAIA password and verify the bootstrap token is updated. Then -// supply the old GAIA password, and verify we re-encrypt all data with the -// new GAIA password. -// (case 4 in SyncManager::SyncInternalSetPassphrase) -TEST_F(SyncManagerTest, SupplyPendingOldGAIAPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer; - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "old_gaia"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_TRUE(node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - node.SetNigoriSpecifics(nigori); - cryptographer->Update(nigori); - - // other_cryptographer now contains all encryption keys, and is encrypting - // with the newest gaia. - KeyParams new_params = {"localhost", "dummy", "new_gaia"}; - other_cryptographer.AddKey(new_params); - } - // The bootstrap token should have been updated. Save it to ensure it's based - // on the new GAIA password. - std::string bootstrap_token; - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)) - .WillOnce(SaveArg<0>(&bootstrap_token)); - EXPECT_CALL(observer_, OnPassphraseRequired(_,_)); - sync_manager_.SetPassphrase("new_gaia", false, false); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - testing::Mock::VerifyAndClearExpectations(&observer_); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_initialized()); - EXPECT_FALSE(cryptographer->is_ready()); - // Verify we're encrypting with the new key, even though we have pending - // keys. - sync_pb::EncryptedData encrypted; - other_cryptographer.GetKeys(&encrypted); - EXPECT_TRUE(cryptographer->CanDecrypt(encrypted)); - } - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("old_gaia", false, true); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - other_cryptographer.GetKeys(&encrypted); - EXPECT_TRUE(cryptographer->CanDecrypt(encrypted)); - - // Verify the saved bootstrap token is based on the new gaia password. - Cryptographer temp_cryptographer; - temp_cryptographer.Bootstrap(bootstrap_token); - EXPECT_TRUE(temp_cryptographer.CanDecrypt(encrypted)); - } -} - -// Manually set the pending keys in the cryptographer/nigori to reflect the data -// being encrypted with an explicit (unprovided) passphrase, then supply the -// passphrase. -// (case 5 in SyncManager::SyncInternalSetPassphrase) -TEST_F(SyncManagerTest, SupplyPendingExplicitPass) { - EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); - Cryptographer other_cryptographer; - { - WriteTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - std::string bootstrap_token; - cryptographer->GetBootstrapToken(&bootstrap_token); - other_cryptographer.Bootstrap(bootstrap_token); - - // Now update the nigori to reflect the new keys, and update the - // cryptographer to have pending keys. - KeyParams params = {"localhost", "dummy", "explicit"}; - other_cryptographer.AddKey(params); - WriteNode node(&trans); - EXPECT_TRUE(node.InitByTagLookup(kNigoriTag)); - sync_pb::NigoriSpecifics nigori; - other_cryptographer.GetKeys(nigori.mutable_encrypted()); - cryptographer->Update(nigori); - EXPECT_TRUE(cryptographer->has_pending_keys()); - nigori.set_using_explicit_passphrase(true); - node.SetNigoriSpecifics(nigori); - } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); - EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("explicit", true, true); - EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); - { - ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); - Cryptographer* cryptographer = trans.GetCryptographer(); - EXPECT_TRUE(cryptographer->is_ready()); - // Verify we're encrypting with the new key. - sync_pb::EncryptedData encrypted; - cryptographer->GetKeys(&encrypted); - EXPECT_TRUE(other_cryptographer.CanDecrypt(encrypted)); - } -} - TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { EXPECT_TRUE(SetUpEncryption(WRITE_TO_NIGORI, DEFAULT_ENCRYPTION)); int64 node_id = 0; @@ -1760,10 +1526,9 @@ TEST_F(SyncManagerTest, SetPassphraseWithEmptyPasswordNode) { root_node, tag)); node_id = password_node.GetId(); } - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)); EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", true, true); + sync_manager_.SetPassphrase("new_passphrase", true); EXPECT_FALSE(sync_manager_.EncryptEverythingEnabledForTest()); { ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); @@ -1981,10 +1746,9 @@ TEST_F(SyncManagerTest, UpdateEntryWithEncryption) { // Set a new passphrase. Should set is_unsynced. testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)); EXPECT_CALL(observer_, OnEncryptionComplete()); - sync_manager_.SetPassphrase("new_passphrase", true, true); + sync_manager_.SetPassphrase("new_passphrase", true); { ReadTransaction trans(FROM_HERE, sync_manager_.GetUserShare()); ReadNode node(&trans); @@ -2169,8 +1933,7 @@ TEST_F(SyncManagerTest, UpdatePasswordNewPassphrase) { // Set a new passphrase. Should set is_unsynced. testing::Mock::VerifyAndClearExpectations(&observer_); - EXPECT_CALL(observer_, OnBootstrapTokenUpdated(_)); - EXPECT_CALL(observer_, OnPassphraseAccepted()); + EXPECT_CALL(observer_, OnPassphraseAccepted(_)); EXPECT_CALL(observer_, OnEncryptionComplete()); sync_manager_.SetPassphrase("new_passphrase", true); EXPECT_TRUE(ResetUnsyncedEntry(syncable::PASSWORDS, client_tag)); diff --git a/chrome/browser/sync/js/js_sync_manager_observer.cc b/chrome/browser/sync/js/js_sync_manager_observer.cc index 843ac1d..ecb4304 100644 --- a/chrome/browser/sync/js/js_sync_manager_observer.cc +++ b/chrome/browser/sync/js/js_sync_manager_observer.cc @@ -71,22 +71,14 @@ void JsSyncManagerObserver::OnPassphraseRequired( HandleJsEvent(FROM_HERE, "onPassphraseRequired", JsEventDetails(&details)); } -void JsSyncManagerObserver::OnPassphraseAccepted() { - if (!event_handler_.IsInitialized()) { - return; - } - DictionaryValue details; - HandleJsEvent(FROM_HERE, "onPassphraseAccepted", JsEventDetails(&details)); -} - -void JsSyncManagerObserver::OnBootstrapTokenUpdated( - const std::string& boostrap_token) { +void JsSyncManagerObserver::OnPassphraseAccepted( + const std::string& bootstrap_token) { if (!event_handler_.IsInitialized()) { return; } DictionaryValue details; details.SetString("bootstrapToken", "<redacted>"); - HandleJsEvent(FROM_HERE, "OnBootstrapTokenUpdated", JsEventDetails(&details)); + HandleJsEvent(FROM_HERE, "onPassphraseAccepted", JsEventDetails(&details)); } void JsSyncManagerObserver::OnEncryptedTypesChanged( diff --git a/chrome/browser/sync/js/js_sync_manager_observer.h b/chrome/browser/sync/js/js_sync_manager_observer.h index e3cddc7..44d2b5c 100644 --- a/chrome/browser/sync/js/js_sync_manager_observer.h +++ b/chrome/browser/sync/js/js_sync_manager_observer.h @@ -39,8 +39,7 @@ class JsSyncManagerObserver : public sync_api::SyncManager::Observer { virtual void OnPassphraseRequired( sync_api::PassphraseRequiredReason reason, const sync_pb::EncryptedData& pending_keys) OVERRIDE; - virtual void OnPassphraseAccepted() OVERRIDE; - virtual void OnBootstrapTokenUpdated( + virtual void OnPassphraseAccepted( const std::string& bootstrap_token) OVERRIDE; virtual void OnEncryptedTypesChanged( syncable::ModelTypeSet encrypted_types, diff --git a/chrome/browser/sync/js/js_sync_manager_observer_unittest.cc b/chrome/browser/sync/js/js_sync_manager_observer_unittest.cc index 1145458..be15219 100644 --- a/chrome/browser/sync/js/js_sync_manager_observer_unittest.cc +++ b/chrome/browser/sync/js/js_sync_manager_observer_unittest.cc @@ -191,11 +191,11 @@ TEST_F(JsSyncManagerObserverTest, SensitiveNotifiations) { HasDetailsAsDictionary(redacted_token_details))); EXPECT_CALL(mock_js_event_handler_, HandleJsEvent( - "OnBootstrapTokenUpdated", + "onPassphraseAccepted", HasDetailsAsDictionary(redacted_bootstrap_token_details))); js_sync_manager_observer_.OnUpdatedToken("sensitive_token"); - js_sync_manager_observer_.OnBootstrapTokenUpdated("sensitive_token"); + js_sync_manager_observer_.OnPassphraseAccepted("sensitive_token"); PumpLoop(); } diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc index 20d6572..111c72b 100644 --- a/chrome/browser/sync/profile_sync_service.cc +++ b/chrome/browser/sync/profile_sync_service.cc @@ -810,9 +810,7 @@ void ProfileSyncService::OnPassphraseRequired( cached_passphrases_.gaia_passphrase.clear(); DVLOG(1) << "Attempting gaia passphrase."; // SetPassphrase will re-cache this passphrase if the syncer isn't ready. - SetPassphrase(gaia_passphrase, IMPLICIT, - (cached_passphrases_.user_provided_gaia ? - USER_PROVIDED : INTERNAL)); + SetPassphrase(gaia_passphrase, false); return; } @@ -823,7 +821,7 @@ void ProfileSyncService::OnPassphraseRequired( cached_passphrases_.explicit_passphrase.clear(); DVLOG(1) << "Attempting explicit passphrase."; // SetPassphrase will re-cache this passphrase if the syncer isn't ready. - SetPassphrase(explicit_passphrase, EXPLICIT, USER_PROVIDED); + SetPassphrase(explicit_passphrase, true); return; } @@ -1290,27 +1288,15 @@ void ProfileSyncService::DeactivateDataType(syncable::ModelType type) { } void ProfileSyncService::SetPassphrase(const std::string& passphrase, - PassphraseType type, - PassphraseSource source) { - DCHECK(source == USER_PROVIDED || type == IMPLICIT); + bool is_explicit) { if (ShouldPushChanges() || IsPassphraseRequired()) { - DVLOG(1) << "Setting " << (type == EXPLICIT ? "explicit" : "implicit") - << " passphrase."; - backend_->SetPassphrase(passphrase, - type == EXPLICIT, - source == USER_PROVIDED); + DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit"); + backend_->SetPassphrase(passphrase, is_explicit); } else { - if (type == EXPLICIT) { - NOTREACHED() << "SetPassphrase should only be called after the backend " - << "is initialized."; + if (is_explicit) { cached_passphrases_.explicit_passphrase = passphrase; } else { cached_passphrases_.gaia_passphrase = passphrase; - cached_passphrases_.user_provided_gaia = (source == USER_PROVIDED); - DVLOG(1) << "Caching " - << (cached_passphrases_.user_provided_gaia ? "user provided" : - "internal") - << " gaia passphrase."; } } } @@ -1451,12 +1437,13 @@ void ProfileSyncService::Observe(int type, // want to suppress start up anymore. sync_prefs_.SetStartSuppressed(false); - // Because we specify IMPLICIT to SetPassphrase, we know it won't override - // an explicit one. Thus, we either update the implicit passphrase - // (idempotent if the passphrase didn't actually change), or the user has - // an explicit passphrase set so this becomes a no-op. + // We pass 'false' to SetPassphrase to denote that this is an implicit + // request and shouldn't override an explicit one. Thus, we either + // update the implicit passphrase (idempotent if the passphrase didn't + // actually change), or the user has an explicit passphrase set so this + // becomes a no-op. if (!successful->password.empty()) - SetPassphrase(successful->password, IMPLICIT, INTERNAL); + SetPassphrase(successful->password, false); break; } case chrome::NOTIFICATION_TOKEN_REQUEST_FAILED: { diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h index c05d70b..d9d8068 100644 --- a/chrome/browser/sync/profile_sync_service.h +++ b/chrome/browser/sync/profile_sync_service.h @@ -155,16 +155,6 @@ class ProfileSyncService : public browser_sync::SyncFrontend, MANUAL_START, }; - enum PassphraseType { - IMPLICIT, - EXPLICIT, - }; - - enum PassphraseSource { - INTERNAL, - USER_PROVIDED, - }; - // Default sync server URL. static const char* kSyncServerUrl; // Sync server URL for dev channel users @@ -458,19 +448,12 @@ class ProfileSyncService : public browser_sync::SyncFrontend, // This will check asynchronously whether the passphrase is valid and notify // ProfileSyncServiceObservers via the NotificationService when the outcome // is known. - // |type| == EXPLICIT if the call is in response to the user setting a - // custom explicit passphrase as opposed to implicitly (from the users' - // perspective) using their Google Account password. Once an explicit - // passphrase is set, it can never be overwritten (not even by another - // explicit passphrase). - // |source| == USER_PROVIDED corresponds to the user having manually provided - // this passphrase. It should only be INTERNAL for passphrases intercepted - // from the Google Sign-in Success notification. Note that if the data is - // encrypted with an old Google Account password, the user may still have to - // provide an "implicit" passphrase. + // |is_explicit| is true if the call is in response to the user explicitly + // setting a passphrase as opposed to implicitly (from the users' perspective) + // using their Google Account password. An implicit SetPassphrase will + // *not* override an explicit passphrase set previously. virtual void SetPassphrase(const std::string& passphrase, - PassphraseType type, - PassphraseSource source); + bool is_explicit); // Turns on encryption for all data. Callers must call OnUserChoseDatatypes() // after calling this to force the encryption to occur. @@ -689,9 +672,6 @@ class ProfileSyncService : public browser_sync::SyncFrontend, struct CachedPassphrases { std::string explicit_passphrase; std::string gaia_passphrase; - // This distinguishes from GAIA passphrases intercepted by the signin code - // (which will always be the most recent GAIA passphrase). - bool user_provided_gaia; }; CachedPassphrases cached_passphrases_; diff --git a/chrome/browser/sync/profile_sync_service_harness.cc b/chrome/browser/sync/profile_sync_service_harness.cc index 59c039a..7a999e7 100644 --- a/chrome/browser/sync/profile_sync_service_harness.cc +++ b/chrome/browser/sync/profile_sync_service_harness.cc @@ -193,9 +193,7 @@ bool ProfileSyncServiceHarness::SetupSync( } // Set our implicit passphrase. - service_->SetPassphrase(password_, - ProfileSyncService::IMPLICIT, - ProfileSyncService::USER_PROVIDED); + service_->SetPassphrase(password_, false); // Wait for initial sync cycle to be completed. DCHECK_EQ(wait_state_, WAITING_FOR_INITIAL_SYNC); diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc index 0b2bbf0..0ccfbba 100644 --- a/chrome/browser/sync/profile_sync_service_password_unittest.cc +++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc @@ -267,9 +267,7 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest { MessageLoop::current()->Run(); FlushLastDBTask(); - service_->SetPassphrase("foo", - ProfileSyncService::IMPLICIT, - ProfileSyncService::INTERNAL); + service_->SetPassphrase("foo", false); MessageLoop::current()->Run(); } } diff --git a/chrome/browser/sync/protocol/client_debug_info.proto b/chrome/browser/sync/protocol/client_debug_info.proto index 6d67b72..af97839 100644 --- a/chrome/browser/sync/protocol/client_debug_info.proto +++ b/chrome/browser/sync/protocol/client_debug_info.proto @@ -38,8 +38,6 @@ message DebugEventInfo { ENCRYPTED_TYPES_CHANGED = 9; // Set of encrypted types has changed. ENCRYPTION_COMPLETE = 7; // Client has finished encrypting all data. ACTIONABLE_ERROR = 8; // Client received an actionable error. - BOOTSTRAP_TOKEN_UPDATED = 9; // A new cryptographer bootstrap token was - // generated. } optional EventType type = 1; optional SyncCycleCompletedEventInfo sync_cycle_completed_event_info = 2; diff --git a/chrome/browser/sync/sync_setup_flow.cc b/chrome/browser/sync/sync_setup_flow.cc index c1abbee..3e2f1f2 100644 --- a/chrome/browser/sync/sync_setup_flow.cc +++ b/chrome/browser/sync/sync_setup_flow.cc @@ -453,9 +453,7 @@ void SyncSetupFlow::OnUserConfigured(const SyncConfiguration& configuration) { // Caller passed a gaia passphrase. This is illegal if we are currently // using a secondary passphrase. DCHECK(!service_->IsUsingSecondaryPassphrase()); - service_->SetPassphrase(configuration.gaia_passphrase, - ProfileSyncService::IMPLICIT, - ProfileSyncService::USER_PROVIDED); + service_->SetPassphrase(configuration.gaia_passphrase, false); // Since the user entered the passphrase manually, set this flag so we can // report an error if the passphrase setting failed. user_tried_setting_passphrase_ = true; @@ -466,9 +464,7 @@ void SyncSetupFlow::OnUserConfigured(const SyncConfiguration& configuration) { // as an attempt to encrypt the user's data using this new passphrase. if (configuration.set_secondary_passphrase && !configuration.secondary_passphrase.empty()) { - service_->SetPassphrase(configuration.secondary_passphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + service_->SetPassphrase(configuration.secondary_passphrase, true); if (service_->IsUsingSecondaryPassphrase()) { user_tried_setting_passphrase_ = true; set_new_decryption_passphrase = true; @@ -498,9 +494,7 @@ void SyncSetupFlow::OnUserConfigured(const SyncConfiguration& configuration) { void SyncSetupFlow::OnPassphraseEntry(const std::string& passphrase) { Advance(SyncSetupWizard::SETTING_UP); - service_->SetPassphrase(passphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + service_->SetPassphrase(passphrase, true); user_tried_setting_passphrase_ = true; } diff --git a/chrome/browser/sync/sync_setup_wizard_unittest.cc b/chrome/browser/sync/sync_setup_wizard_unittest.cc index 5f0f98f..46b7cb0 100644 --- a/chrome/browser/sync/sync_setup_wizard_unittest.cc +++ b/chrome/browser/sync/sync_setup_wizard_unittest.cc @@ -114,8 +114,7 @@ class ProfileSyncServiceForWizardTest : public ProfileSyncService { } virtual void SetPassphrase(const std::string& passphrase, - PassphraseType type, - PassphraseSource source) OVERRIDE { + bool is_explicit) OVERRIDE { passphrase_ = passphrase; } diff --git a/chrome/browser/sync/test/integration/passwords_helper.cc b/chrome/browser/sync/test/integration/passwords_helper.cc index f2cf8ab..947ac47 100644 --- a/chrome/browser/sync/test/integration/passwords_helper.cc +++ b/chrome/browser/sync/test/integration/passwords_helper.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -107,9 +107,7 @@ void RemoveLogins(PasswordStore* store) { void SetPassphrase(int index, const std::string& passphrase) { test()->GetProfile(index)->GetProfileSyncService()->SetPassphrase( - passphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + passphrase, true); } PasswordStore* GetPasswordStore(int index) { diff --git a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc index 808b1a2..450e6713 100644 --- a/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_bookmarks_sync_test.cc @@ -1804,10 +1804,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, // Set a passphrase and enable encryption on Client 0. Client 1 will not // understand the bookmark updates. - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(EnableEncryption(0, syncable::BOOKMARKS)); ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); @@ -1824,10 +1821,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientBookmarksSyncTest, EXPECT_FALSE(AllModelsMatch()); // Set the passphrase. Everything should resolve. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(1)->AwaitMutualSyncCycleCompletion(GetClient(0))); EXPECT_TRUE(AllModelsMatchVerifier()); diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc index e47084d..9b62e2f 100644 --- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc @@ -243,6 +243,22 @@ IN_PROC_BROWSER_TEST_F(TwoClientPasswordsSyncTest, ASSERT_EQ(browser_sync::GROUP_PASSWORD, routes[syncable::PASSWORDS]); } +IN_PROC_BROWSER_TEST_F(TwoClientPasswordsSyncTest, SetPassphraseTwice) { + ASSERT_TRUE(SetupSync()) << "SetupSync() failed."; + + SetPassphrase(0, kValidPassphrase); + ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); + ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); + + SetPassphrase(1, kValidPassphrase); + ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); + ASSERT_TRUE(GetClient(1)->AwaitFullSyncCompletion("Set passphrase.")); + + SetPassphrase(1, kValidPassphrase); + ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); + ASSERT_TRUE(GetClient(1)->AwaitFullSyncCompletion("Set passphrase again.")); +} + IN_PROC_BROWSER_TEST_F(TwoClientPasswordsSyncTest, SetDifferentPassphraseAndThenSetupSync) { ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; diff --git a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc index 0134830..d5c9a23 100644 --- a/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_sessions_sync_test.cc @@ -160,10 +160,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, client0_windows.GetMutable())); ASSERT_TRUE(EnableEncryption(0, syncable::SESSIONS)); - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired()); @@ -175,10 +172,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, GetClient(1)->GetLastSessionSnapshot()-> num_conflicting_updates); // The encrypted nodes. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(1)->WaitForTypeEncryption(syncable::SESSIONS)); @@ -210,10 +204,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, ASSERT_TRUE(CheckInitialState(1)); ASSERT_TRUE(EnableEncryption(0, syncable::SESSIONS)); - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired()); @@ -235,10 +226,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, GetClient(1)->GetLastSessionSnapshot()-> num_conflicting_updates); // The encrypted nodes. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(1)->WaitForTypeEncryption(syncable::SESSIONS)); @@ -262,10 +250,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, ASSERT_TRUE(CheckInitialState(1)); ASSERT_TRUE(EnableEncryption(0, syncable::SESSIONS)); - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired()); @@ -285,10 +270,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, // At this point we enter the passphrase, triggering a resync, in which the // local changes of client 1 get sent to client 0. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(1)->WaitForTypeEncryption(syncable::SESSIONS)); ASSERT_TRUE(GetClient(1)->AwaitMutualSyncCycleCompletion(GetClient(0))); @@ -327,10 +309,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, // Turn encryption on client 0. Client 1's foreign will be encrypted with the // new passphrase and synced back. It will be unable to decrypt it yet. ASSERT_TRUE(EnableEncryption(0, syncable::SESSIONS)); - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(AwaitQuiescence()); ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired()); @@ -344,10 +323,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, num_conflicting_updates); // The encrypted nodes. // At this point we enter the passphrase, triggering a resync. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(1)->WaitForTypeEncryption(syncable::SESSIONS)); @@ -378,10 +354,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, ASSERT_TRUE(CheckInitialState(0)); ASSERT_TRUE(CheckInitialState(1)); - GetClient(0)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(0)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(0)->AwaitPassphraseAccepted()); ASSERT_TRUE(GetClient(0)->AwaitMutualSyncCycleCompletion(GetClient(1))); ASSERT_TRUE(GetClient(1)->AwaitPassphraseRequired()); @@ -402,10 +375,7 @@ IN_PROC_BROWSER_TEST_F(TwoClientSessionsSyncTest, GetClient(1)->GetLastSessionSnapshot()-> num_conflicting_updates); // The encrypted nodes. - GetClient(1)->service()->SetPassphrase( - kValidPassphrase, - ProfileSyncService::EXPLICIT, - ProfileSyncService::USER_PROVIDED); + GetClient(1)->service()->SetPassphrase(kValidPassphrase, true); ASSERT_TRUE(GetClient(1)->AwaitPassphraseAccepted()); ASSERT_FALSE(GetClient(1)->service()->IsPassphraseRequired()); ASSERT_TRUE(GetClient(1)->WaitForTypeEncryption(syncable::SESSIONS)); diff --git a/chrome/browser/sync/util/cryptographer.cc b/chrome/browser/sync/util/cryptographer.cc index 26fbc55..de83652 100644 --- a/chrome/browser/sync/util/cryptographer.cc +++ b/chrome/browser/sync/util/cryptographer.cc @@ -131,6 +131,8 @@ bool Cryptographer::GetKeys(sync_pb::EncryptedData* encrypted) const { } bool Cryptographer::AddKey(const KeyParams& params) { + DCHECK(NULL == pending_keys_.get()); + // Create the new Nigori and make it the default encryptor. scoped_ptr<Nigori> nigori(new Nigori); if (!nigori->InitByDerivation(params.hostname, @@ -142,15 +144,6 @@ bool Cryptographer::AddKey(const KeyParams& params) { return AddKeyImpl(nigori.release()); } -bool Cryptographer::AddKeyFromBootstrapToken( - const std::string restored_bootstrap_token) { - // Create the new Nigori and make it the default encryptor. - scoped_ptr<Nigori> nigori(UnpackBootstrapToken(restored_bootstrap_token)); - if (!nigori.get()) - return false; - return AddKeyImpl(nigori.release()); -} - bool Cryptographer::AddKeyImpl(Nigori* initialized_nigori) { scoped_ptr<Nigori> nigori(initialized_nigori); std::string name; diff --git a/chrome/browser/sync/util/cryptographer.h b/chrome/browser/sync/util/cryptographer.h index d5e98f7..2c319ab 100644 --- a/chrome/browser/sync/util/cryptographer.h +++ b/chrome/browser/sync/util/cryptographer.h @@ -131,11 +131,6 @@ class Cryptographer { // Encrypt. bool AddKey(const KeyParams& params); - // Same as AddKey(..), but builds the new Nigori from a previously persisted - // bootstrap token. This can be useful when consuming a bootstrap token - // with a cryptographer that has already been initialized. - bool AddKeyFromBootstrapToken(const std::string restored_bootstrap_token); - // Decrypts |encrypted| and uses its contents to initialize Nigori instances. // Returns true unless decryption of |encrypted| fails. The caller is // responsible for checking that CanDecrypt(encrypted) == true. |