Index: components/sync/core_impl/sync_encryption_handler_impl.cc |
diff --git a/components/sync/core_impl/sync_encryption_handler_impl.cc b/components/sync/core_impl/sync_encryption_handler_impl.cc |
index 67b46a86d5aa372e64c62cb28ed0233df986f055..795cc0cd1a448401c614953b4c98da1a00fd4bbc 100644 |
--- a/components/sync/core_impl/sync_encryption_handler_impl.cc |
+++ b/components/sync/core_impl/sync_encryption_handler_impl.cc |
@@ -196,8 +196,11 @@ bool UnpackKeystoreBootstrapToken(const std::string& keystore_bootstrap_token, |
} // namespace |
SyncEncryptionHandlerImpl::Vault::Vault(Encryptor* encryptor, |
- ModelTypeSet encrypted_types) |
- : cryptographer(encryptor), encrypted_types(encrypted_types) {} |
+ ModelTypeSet encrypted_types, |
+ PassphraseType passphrase_type) |
+ : cryptographer(encryptor), |
+ encrypted_types(encrypted_types), |
+ passphrase_type(passphrase_type) {} |
SyncEncryptionHandlerImpl::Vault::~Vault() {} |
@@ -207,9 +210,10 @@ SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( |
const std::string& restored_key_for_bootstrapping, |
const std::string& restored_keystore_key_for_bootstrapping) |
: user_share_(user_share), |
- vault_unsafe_(encryptor, SensitiveTypes()), |
+ vault_unsafe_(encryptor, |
+ SensitiveTypes(), |
+ PassphraseType::IMPLICIT_PASSPHRASE), |
encrypt_everything_(false), |
- passphrase_type_(PassphraseType::IMPLICIT_PASSPHRASE), |
nigori_overwrite_count_(0), |
weak_ptr_factory_(this) { |
// Restore the cryptographer's previous keys. Note that we don't add the |
@@ -249,7 +253,8 @@ void SyncEncryptionHandlerImpl::Init() { |
} |
UMA_HISTOGRAM_ENUMERATION( |
- "Sync.PassphraseType", static_cast<unsigned>(GetPassphraseType()), |
+ "Sync.PassphraseType", |
+ static_cast<unsigned>(GetPassphraseType(trans.GetWrappedTrans())), |
static_cast<unsigned>(PassphraseType::PASSPHRASE_TYPE_SIZE)); |
bool has_pending_keys = |
@@ -264,7 +269,8 @@ void SyncEncryptionHandlerImpl::Init() { |
UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", MIGRATED, |
MIGRATION_STATE_SIZE); |
if (has_pending_keys && |
- passphrase_type_ == PassphraseType::KEYSTORE_PASSPHRASE) { |
+ GetPassphraseType(trans.GetWrappedTrans()) == |
+ PassphraseType::KEYSTORE_PASSPHRASE) { |
// If this is happening, it means the keystore decryptor is either |
// undecryptable with the available keystore keys or does not match the |
// nigori keybag's encryption key. Otherwise we're simply missing the |
@@ -360,7 +366,8 @@ void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( |
if (cryptographer->has_pending_keys()) |
pending_keys = cryptographer->GetPendingKeys(); |
bool success = false; |
- |
+ PassphraseType* passphrase_type = |
+ &UnlockVaultMutable(trans.GetWrappedTrans())->passphrase_type; |
// There are six 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 |
@@ -381,7 +388,7 @@ void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( |
// 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). |
- if (!IsExplicitPassphrase(passphrase_type_)) { |
+ if (!IsExplicitPassphrase(*passphrase_type)) { |
if (!cryptographer->has_pending_keys()) { |
if (cryptographer->AddKey(key_params)) { |
// Case 1 and 2. We set a new GAIA passphrase when there are no pending |
@@ -389,11 +396,12 @@ void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( |
// one (2) when there are no pending keys. |
if (is_explicit) { |
DVLOG(1) << "Setting explicit passphrase for encryption."; |
- passphrase_type_ = PassphraseType::CUSTOM_PASSPHRASE; |
+ *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; |
custom_passphrase_time_ = base::Time::Now(); |
FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
OnPassphraseTypeChanged( |
- passphrase_type_, GetExplicitPassphraseTime())); |
+ *passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
} else { |
DVLOG(1) << "Setting implicit passphrase for encryption."; |
} |
@@ -447,7 +455,7 @@ void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( |
} |
} // is_explicit |
} // cryptographer->has_pending_keys() |
- } else { // IsExplicitPassphrase(passphrase_type_) == true. |
+ } else { // IsExplicitPassphrase(passphrase_type) == true. |
// Case 6. We do not want to override a previously set explicit passphrase, |
// so we return a failure. |
DVLOG(1) << "Failing because an explicit passphrase is already set."; |
@@ -487,7 +495,7 @@ void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( |
// decrypting with a gaia passphrase, and therefore bypass the |
// DecryptPendingKeysWithExplicitPassphrase logic. |
if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) && |
- IsExplicitPassphrase(passphrase_type_)) { |
+ IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) { |
DecryptPendingKeysWithExplicitPassphrase(passphrase, &trans, &node); |
return; |
} |
@@ -521,7 +529,7 @@ void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( |
// encrypted account (after changing passwords). |
// 9. The user is providing a previously set explicit passphrase to decrypt |
// the pending keys. |
- if (!IsExplicitPassphrase(passphrase_type_)) { |
+ if (!IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) { |
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. |
@@ -627,11 +635,6 @@ bool SyncEncryptionHandlerImpl::IsEncryptEverythingEnabled() const { |
return encrypt_everything_; |
} |
-PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType() const { |
- DCHECK(thread_checker_.CalledOnValidThread()); |
- return passphrase_type_; |
-} |
- |
// Note: this is called from within a syncable transaction, so we need to post |
// tasks if we want to do any work that creates a new sync_api transaction. |
void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( |
@@ -716,9 +719,10 @@ bool SyncEncryptionHandlerImpl::SetKeystoreKeys( |
keystore_key_, nigori.keystore_decryptor_token(), cryptographer); |
} |
+ PassphraseType* passphrase_type = &UnlockVaultMutable(trans)->passphrase_type; |
// Note that triggering migration will have no effect if we're already |
// properly migrated with the newest keystore keys. |
- if (ShouldTriggerMigration(nigori, *cryptographer)) { |
+ if (ShouldTriggerMigration(nigori, *cryptographer, passphrase_type)) { |
base::ThreadTaskRunnerHandle::Get()->PostTask( |
FROM_HERE, base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, |
weak_ptr_factory_.GetWeakPtr())); |
@@ -732,6 +736,11 @@ ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes( |
return UnlockVault(trans).encrypted_types; |
} |
+PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType( |
+ syncable::BaseTransaction* const trans) const { |
+ return UnlockVault(trans).passphrase_type; |
+} |
+ |
Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { |
DCHECK(thread_checker_.CalledOnValidThread()); |
return &vault_unsafe_.cryptographer; |
@@ -865,6 +874,7 @@ bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
custom_passphrase_time_ = ProtoTimeToTime(nigori.custom_passphrase_time()); |
} |
bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori); |
+ PassphraseType* passphrase_type = &UnlockVaultMutable(trans)->passphrase_type; |
if (is_nigori_migrated) { |
migration_time_ = ProtoTimeToTime(nigori.keystore_migration_time()); |
PassphraseType nigori_passphrase_type = |
@@ -878,19 +888,20 @@ bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
// Note: frozen implicit -> custom is not technically a valid transition, |
// but we let it through here as well in case future versions do add support |
// for this transition. |
- if (passphrase_type_ != nigori_passphrase_type && |
+ if (*passphrase_type != nigori_passphrase_type && |
nigori_passphrase_type != PassphraseType::IMPLICIT_PASSPHRASE && |
- (passphrase_type_ == PassphraseType::IMPLICIT_PASSPHRASE || |
+ (*passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE || |
nigori_passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)) { |
DVLOG(1) << "Changing passphrase state from " |
- << PassphraseTypeToString(passphrase_type_) << " to " |
+ << PassphraseTypeToString(*passphrase_type) << " to " |
<< PassphraseTypeToString(nigori_passphrase_type); |
- passphrase_type_ = nigori_passphrase_type; |
- FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
- OnPassphraseTypeChanged(passphrase_type_, |
- GetExplicitPassphraseTime())); |
+ *passphrase_type = nigori_passphrase_type; |
+ FOR_EACH_OBSERVER( |
+ SyncEncryptionHandler::Observer, observers_, |
+ OnPassphraseTypeChanged(*passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
} |
- if (passphrase_type_ == PassphraseType::KEYSTORE_PASSPHRASE && |
+ if (*passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE && |
encrypt_everything_) { |
// This is the case where another client that didn't support keystore |
// encryption attempted to enable full encryption. We detect it |
@@ -900,20 +911,22 @@ bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
// type, we will trigger a rewrite and subsequently a re-migration. |
DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE " |
<< "due to full encryption."; |
- passphrase_type_ = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; |
- FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
- OnPassphraseTypeChanged(passphrase_type_, |
- GetExplicitPassphraseTime())); |
+ *passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; |
+ FOR_EACH_OBSERVER( |
+ SyncEncryptionHandler::Observer, observers_, |
+ OnPassphraseTypeChanged(*passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
} |
} else { |
// It's possible that while we're waiting for migration a client that does |
// not have keystore encryption enabled switches to a custom passphrase. |
if (nigori.keybag_is_frozen() && |
- passphrase_type_ != PassphraseType::CUSTOM_PASSPHRASE) { |
- passphrase_type_ = PassphraseType::CUSTOM_PASSPHRASE; |
- FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
- OnPassphraseTypeChanged(passphrase_type_, |
- GetExplicitPassphraseTime())); |
+ *passphrase_type != PassphraseType::CUSTOM_PASSPHRASE) { |
+ *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; |
+ FOR_EACH_OBSERVER( |
+ SyncEncryptionHandler::Observer, observers_, |
+ OnPassphraseTypeChanged(*passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
} |
} |
@@ -978,18 +991,18 @@ bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
// Check if the current local encryption state is stricter/newer than the |
// nigori state. If so, we need to overwrite the nigori node with the local |
// state. |
- bool passphrase_type_matches = true; |
+ bool passphrase_typematches = true; |
if (!is_nigori_migrated) { |
- DCHECK(passphrase_type_ == PassphraseType::CUSTOM_PASSPHRASE || |
- passphrase_type_ == PassphraseType::IMPLICIT_PASSPHRASE); |
- passphrase_type_matches = |
- nigori.keybag_is_frozen() == IsExplicitPassphrase(passphrase_type_); |
+ DCHECK(*passphrase_type == PassphraseType::CUSTOM_PASSPHRASE || |
+ *passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE); |
+ passphrase_typematches = |
+ nigori.keybag_is_frozen() == IsExplicitPassphrase(*passphrase_type); |
} else { |
- passphrase_type_matches = |
+ passphrase_typematches = |
(ProtoPassphraseTypeToEnum(nigori.passphrase_type()) == |
- passphrase_type_); |
+ *passphrase_type); |
} |
- if (!passphrase_type_matches || |
+ if (!passphrase_typematches || |
nigori.encrypt_everything() != encrypt_everything_ || |
nigori_types_need_update || nigori_needs_new_keys) { |
DVLOG(1) << "Triggering nigori rewrite."; |
@@ -1102,7 +1115,8 @@ void SyncEncryptionHandlerImpl::SetCustomPassphrase( |
DCHECK(IsNigoriMigratedToKeystore(nigori_node->GetNigoriSpecifics())); |
KeyParams key_params = {"localhost", "dummy", passphrase}; |
- if (passphrase_type_ != PassphraseType::KEYSTORE_PASSPHRASE) { |
+ if (GetPassphraseType(trans->GetWrappedTrans()) != |
+ PassphraseType::KEYSTORE_PASSPHRASE) { |
DVLOG(1) << "Failing to set a custom passphrase because one has already " |
<< "been set."; |
FinishSetPassphrase(false, std::string(), trans, nigori_node); |
@@ -1130,11 +1144,14 @@ void SyncEncryptionHandlerImpl::SetCustomPassphrase( |
DVLOG(1) << "Setting custom passphrase."; |
cryptographer->GetBootstrapToken(&bootstrap_token); |
- passphrase_type_ = PassphraseType::CUSTOM_PASSPHRASE; |
+ PassphraseType* passphrase_type = |
+ &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type; |
+ *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; |
custom_passphrase_time_ = base::Time::Now(); |
FOR_EACH_OBSERVER( |
SyncEncryptionHandler::Observer, observers_, |
- OnPassphraseTypeChanged(passphrase_type_, GetExplicitPassphraseTime())); |
+ OnPassphraseTypeChanged(*passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
FinishSetPassphrase(true, bootstrap_token, trans, nigori_node); |
} |
@@ -1158,7 +1175,7 @@ void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase( |
WriteTransaction* trans, |
WriteNode* nigori_node) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
- DCHECK(IsExplicitPassphrase(passphrase_type_)); |
+ DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); |
KeyParams key_params = {"localhost", "dummy", passphrase}; |
Cryptographer* cryptographer = |
@@ -1172,7 +1189,7 @@ void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase( |
return; |
} |
- DCHECK(IsExplicitPassphrase(passphrase_type_)); |
+ DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); |
bool success = false; |
std::string bootstrap_token; |
if (cryptographer->DecryptPendingKeys(key_params)) { |
@@ -1244,11 +1261,13 @@ void SyncEncryptionHandlerImpl::FinishSetPassphrase( |
if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag())) |
NOTREACHED(); |
if (IsNigoriMigratedToKeystore(nigori)) { |
- DCHECK(keystore_key_.empty() || IsExplicitPassphrase(passphrase_type_)); |
+ DCHECK(keystore_key_.empty() || |
+ IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); |
DVLOG(1) << "Leaving nigori migration state untouched after setting" |
<< " passphrase."; |
} else { |
- nigori.set_keybag_is_frozen(IsExplicitPassphrase(passphrase_type_)); |
+ nigori.set_keybag_is_frozen( |
+ IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); |
} |
// If we set a new custom passphrase, store the timestamp. |
if (!custom_passphrase_time_.is_null()) { |
@@ -1300,7 +1319,8 @@ const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( |
bool SyncEncryptionHandlerImpl::ShouldTriggerMigration( |
const sync_pb::NigoriSpecifics& nigori, |
- const Cryptographer& cryptographer) const { |
+ const Cryptographer& cryptographer, |
+ PassphraseType* passphrase_type) const { |
DCHECK(thread_checker_.CalledOnValidThread()); |
// Don't migrate if there are pending encryption keys (because data |
// encrypted with the pending keys will not be decryptable). |
@@ -1313,13 +1333,13 @@ bool SyncEncryptionHandlerImpl::ShouldTriggerMigration( |
// implicit passphrase but does have full encryption, re-migrate. |
// Note that this is to defend against other clients without keystore |
// encryption enabled transitioning to states that are no longer valid. |
- if (passphrase_type_ != PassphraseType::KEYSTORE_PASSPHRASE && |
+ if (*passphrase_type != PassphraseType::KEYSTORE_PASSPHRASE && |
nigori.passphrase_type() == |
sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { |
return true; |
- } else if (IsExplicitPassphrase(passphrase_type_) && !encrypt_everything_) { |
+ } else if (IsExplicitPassphrase(*passphrase_type) && !encrypt_everything_) { |
return true; |
- } else if (passphrase_type_ == PassphraseType::KEYSTORE_PASSPHRASE && |
+ } else if (*passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE && |
encrypt_everything_) { |
return true; |
} else if (cryptographer.is_ready() && |
@@ -1361,21 +1381,23 @@ bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore( |
nigori_node->GetNigoriSpecifics(); |
Cryptographer* cryptographer = |
&UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; |
- |
- if (!ShouldTriggerMigration(old_nigori, *cryptographer)) |
+ PassphraseType* passphrase_type = |
+ &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type; |
+ if (!ShouldTriggerMigration(old_nigori, *cryptographer, passphrase_type)) |
return false; |
DVLOG(1) << "Starting nigori migration to keystore support."; |
sync_pb::NigoriSpecifics migrated_nigori(old_nigori); |
- PassphraseType new_passphrase_type = passphrase_type_; |
+ PassphraseType new_passphrase_type = |
+ GetPassphraseType(trans->GetWrappedTrans()); |
bool new_encrypt_everything = encrypt_everything_; |
- if (encrypt_everything_ && !IsExplicitPassphrase(passphrase_type_)) { |
+ if (encrypt_everything_ && !IsExplicitPassphrase(*passphrase_type)) { |
DVLOG(1) << "Switching to frozen implicit passphrase due to already having " |
<< "full encryption."; |
new_passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; |
migrated_nigori.clear_keystore_decryptor_token(); |
- } else if (IsExplicitPassphrase(passphrase_type_)) { |
+ } else if (IsExplicitPassphrase(*passphrase_type)) { |
DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to " |
<< "explicit passphrase"; |
new_encrypt_everything = true; |
@@ -1467,11 +1489,12 @@ bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore( |
FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
OnCryptographerStateChanged(cryptographer)); |
- if (passphrase_type_ != new_passphrase_type) { |
- passphrase_type_ = new_passphrase_type; |
+ if (*passphrase_type != new_passphrase_type) { |
+ *passphrase_type = new_passphrase_type; |
FOR_EACH_OBSERVER( |
SyncEncryptionHandler::Observer, observers_, |
- OnPassphraseTypeChanged(passphrase_type_, GetExplicitPassphraseTime())); |
+ OnPassphraseTypeChanged(*passphrase_type, |
+ GetExplicitPassphraseTime(*passphrase_type))); |
} |
if (new_encrypt_everything && !encrypt_everything_) { |
@@ -1640,10 +1663,11 @@ bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey( |
return false; |
} |
-base::Time SyncEncryptionHandlerImpl::GetExplicitPassphraseTime() const { |
- if (passphrase_type_ == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE) |
+base::Time SyncEncryptionHandlerImpl::GetExplicitPassphraseTime( |
+ PassphraseType passphrase_type) const { |
+ if (passphrase_type == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE) |
return migration_time(); |
- else if (passphrase_type_ == PassphraseType::CUSTOM_PASSPHRASE) |
+ else if (passphrase_type == PassphraseType::CUSTOM_PASSPHRASE) |
return custom_passphrase_time(); |
return base::Time(); |
} |