| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "components/sync/core_impl/sync_encryption_handler_impl.h" | |
| 6 | |
| 7 #include <stddef.h> | |
| 8 #include <stdint.h> | |
| 9 | |
| 10 #include <memory> | |
| 11 #include <queue> | |
| 12 | |
| 13 #include "base/base64.h" | |
| 14 #include "base/bind.h" | |
| 15 #include "base/json/json_string_value_serializer.h" | |
| 16 #include "base/location.h" | |
| 17 #include "base/metrics/histogram_macros.h" | |
| 18 #include "base/single_thread_task_runner.h" | |
| 19 #include "base/threading/thread_task_runner_handle.h" | |
| 20 #include "base/tracked_objects.h" | |
| 21 #include "components/sync/base/encryptor.h" | |
| 22 #include "components/sync/base/experiments.h" | |
| 23 #include "components/sync/base/passphrase_type.h" | |
| 24 #include "components/sync/base/time.h" | |
| 25 #include "components/sync/engine/sync_string_conversions.h" | |
| 26 #include "components/sync/protocol/encryption.pb.h" | |
| 27 #include "components/sync/protocol/nigori_specifics.pb.h" | |
| 28 #include "components/sync/protocol/sync.pb.h" | |
| 29 #include "components/sync/syncable/directory.h" | |
| 30 #include "components/sync/syncable/entry.h" | |
| 31 #include "components/sync/syncable/mutable_entry.h" | |
| 32 #include "components/sync/syncable/nigori_util.h" | |
| 33 #include "components/sync/syncable/read_node.h" | |
| 34 #include "components/sync/syncable/read_transaction.h" | |
| 35 #include "components/sync/syncable/syncable_base_transaction.h" | |
| 36 #include "components/sync/syncable/syncable_model_neutral_write_transaction.h" | |
| 37 #include "components/sync/syncable/syncable_write_transaction.h" | |
| 38 #include "components/sync/syncable/user_share.h" | |
| 39 #include "components/sync/syncable/write_node.h" | |
| 40 #include "components/sync/syncable/write_transaction.h" | |
| 41 | |
| 42 namespace syncer { | |
| 43 | |
| 44 namespace { | |
| 45 | |
| 46 // The maximum number of times we will automatically overwrite the nigori node | |
| 47 // because the encryption keys don't match (per chrome instantiation). | |
| 48 // We protect ourselves against nigori rollbacks, but it's possible two | |
| 49 // different clients might have contrasting view of what the nigori node state | |
| 50 // should be, in which case they might ping pong (see crbug.com/119207). | |
| 51 static const int kNigoriOverwriteLimit = 10; | |
| 52 | |
| 53 // Enumeration of nigori keystore migration results (for use in UMA stats). | |
| 54 enum NigoriMigrationResult { | |
| 55 FAILED_TO_SET_DEFAULT_KEYSTORE, | |
| 56 FAILED_TO_SET_NONDEFAULT_KEYSTORE, | |
| 57 FAILED_TO_EXTRACT_DECRYPTOR, | |
| 58 FAILED_TO_EXTRACT_KEYBAG, | |
| 59 MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT, | |
| 60 MIGRATION_SUCCESS_KEYSTORE_DEFAULT, | |
| 61 MIGRATION_SUCCESS_FROZEN_IMPLICIT, | |
| 62 MIGRATION_SUCCESS_CUSTOM, | |
| 63 MIGRATION_RESULT_SIZE, | |
| 64 }; | |
| 65 | |
| 66 enum NigoriMigrationState { | |
| 67 MIGRATED, | |
| 68 NOT_MIGRATED_CRYPTO_NOT_READY, | |
| 69 NOT_MIGRATED_NO_KEYSTORE_KEY, | |
| 70 NOT_MIGRATED_UNKNOWN_REASON, | |
| 71 MIGRATION_STATE_SIZE, | |
| 72 }; | |
| 73 | |
| 74 // The new passphrase state is sufficient to determine whether a nigori node | |
| 75 // is migrated to support keystore encryption. In addition though, we also | |
| 76 // want to verify the conditions for proper keystore encryption functionality. | |
| 77 // 1. Passphrase type is set. | |
| 78 // 2. Frozen keybag is true | |
| 79 // 3. If passphrase state is keystore, keystore_decryptor_token is set. | |
| 80 bool IsNigoriMigratedToKeystore(const sync_pb::NigoriSpecifics& nigori) { | |
| 81 if (!nigori.has_passphrase_type()) | |
| 82 return false; | |
| 83 if (!nigori.keybag_is_frozen()) | |
| 84 return false; | |
| 85 if (nigori.passphrase_type() == sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE) | |
| 86 return false; | |
| 87 if (nigori.passphrase_type() == | |
| 88 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE && | |
| 89 nigori.keystore_decryptor_token().blob().empty()) | |
| 90 return false; | |
| 91 return true; | |
| 92 } | |
| 93 | |
| 94 PassphraseType ProtoPassphraseTypeToEnum( | |
| 95 sync_pb::NigoriSpecifics::PassphraseType type) { | |
| 96 switch (type) { | |
| 97 case sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE: | |
| 98 return PassphraseType::IMPLICIT_PASSPHRASE; | |
| 99 case sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE: | |
| 100 return PassphraseType::KEYSTORE_PASSPHRASE; | |
| 101 case sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE: | |
| 102 return PassphraseType::CUSTOM_PASSPHRASE; | |
| 103 case sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE: | |
| 104 return PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; | |
| 105 default: | |
| 106 NOTREACHED(); | |
| 107 return PassphraseType::IMPLICIT_PASSPHRASE; | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 sync_pb::NigoriSpecifics::PassphraseType EnumPassphraseTypeToProto( | |
| 112 PassphraseType type) { | |
| 113 switch (type) { | |
| 114 case PassphraseType::IMPLICIT_PASSPHRASE: | |
| 115 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE; | |
| 116 case PassphraseType::KEYSTORE_PASSPHRASE: | |
| 117 return sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE; | |
| 118 case PassphraseType::CUSTOM_PASSPHRASE: | |
| 119 return sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE; | |
| 120 case PassphraseType::FROZEN_IMPLICIT_PASSPHRASE: | |
| 121 return sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE; | |
| 122 default: | |
| 123 NOTREACHED(); | |
| 124 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE; | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 // Keystore Bootstrap Token helper methods. | |
| 129 // The bootstrap is a base64 encoded, encrypted, ListValue of keystore key | |
| 130 // strings, with the current keystore key as the last value in the list. | |
| 131 std::string PackKeystoreBootstrapToken( | |
| 132 const std::vector<std::string>& old_keystore_keys, | |
| 133 const std::string& current_keystore_key, | |
| 134 Encryptor* encryptor) { | |
| 135 if (current_keystore_key.empty()) | |
| 136 return std::string(); | |
| 137 | |
| 138 base::ListValue keystore_key_values; | |
| 139 for (size_t i = 0; i < old_keystore_keys.size(); ++i) | |
| 140 keystore_key_values.AppendString(old_keystore_keys[i]); | |
| 141 keystore_key_values.AppendString(current_keystore_key); | |
| 142 | |
| 143 // Update the bootstrap token. | |
| 144 // The bootstrap is a base64 encoded, encrypted, ListValue of keystore key | |
| 145 // strings, with the current keystore key as the last value in the list. | |
| 146 std::string serialized_keystores; | |
| 147 JSONStringValueSerializer json(&serialized_keystores); | |
| 148 json.Serialize(keystore_key_values); | |
| 149 std::string encrypted_keystores; | |
| 150 encryptor->EncryptString(serialized_keystores, &encrypted_keystores); | |
| 151 std::string keystore_bootstrap; | |
| 152 base::Base64Encode(encrypted_keystores, &keystore_bootstrap); | |
| 153 return keystore_bootstrap; | |
| 154 } | |
| 155 | |
| 156 bool UnpackKeystoreBootstrapToken(const std::string& keystore_bootstrap_token, | |
| 157 Encryptor* encryptor, | |
| 158 std::vector<std::string>* old_keystore_keys, | |
| 159 std::string* current_keystore_key) { | |
| 160 if (keystore_bootstrap_token.empty()) | |
| 161 return false; | |
| 162 std::string base64_decoded_keystore_bootstrap; | |
| 163 if (!base::Base64Decode(keystore_bootstrap_token, | |
| 164 &base64_decoded_keystore_bootstrap)) { | |
| 165 return false; | |
| 166 } | |
| 167 std::string decrypted_keystore_bootstrap; | |
| 168 if (!encryptor->DecryptString(base64_decoded_keystore_bootstrap, | |
| 169 &decrypted_keystore_bootstrap)) { | |
| 170 return false; | |
| 171 } | |
| 172 | |
| 173 JSONStringValueDeserializer json(decrypted_keystore_bootstrap); | |
| 174 std::unique_ptr<base::Value> deserialized_keystore_keys( | |
| 175 json.Deserialize(NULL, NULL)); | |
| 176 if (!deserialized_keystore_keys) | |
| 177 return false; | |
| 178 base::ListValue* internal_list_value = NULL; | |
| 179 if (!deserialized_keystore_keys->GetAsList(&internal_list_value)) | |
| 180 return false; | |
| 181 int number_of_keystore_keys = internal_list_value->GetSize(); | |
| 182 if (!internal_list_value->GetString(number_of_keystore_keys - 1, | |
| 183 current_keystore_key)) { | |
| 184 return false; | |
| 185 } | |
| 186 old_keystore_keys->resize(number_of_keystore_keys - 1); | |
| 187 for (int i = 0; i < number_of_keystore_keys - 1; ++i) | |
| 188 internal_list_value->GetString(i, &(*old_keystore_keys)[i]); | |
| 189 return true; | |
| 190 } | |
| 191 | |
| 192 } // namespace | |
| 193 | |
| 194 SyncEncryptionHandlerImpl::Vault::Vault(Encryptor* encryptor, | |
| 195 ModelTypeSet encrypted_types, | |
| 196 PassphraseType passphrase_type) | |
| 197 : cryptographer(encryptor), | |
| 198 encrypted_types(encrypted_types), | |
| 199 passphrase_type(passphrase_type) {} | |
| 200 | |
| 201 SyncEncryptionHandlerImpl::Vault::~Vault() {} | |
| 202 | |
| 203 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( | |
| 204 UserShare* user_share, | |
| 205 Encryptor* encryptor, | |
| 206 const std::string& restored_key_for_bootstrapping, | |
| 207 const std::string& restored_keystore_key_for_bootstrapping) | |
| 208 : user_share_(user_share), | |
| 209 vault_unsafe_(encryptor, | |
| 210 SensitiveTypes(), | |
| 211 PassphraseType::IMPLICIT_PASSPHRASE), | |
| 212 encrypt_everything_(false), | |
| 213 nigori_overwrite_count_(0), | |
| 214 weak_ptr_factory_(this) { | |
| 215 // Restore the cryptographer's previous keys. Note that we don't add the | |
| 216 // keystore keys into the cryptographer here, in case a migration was pending. | |
| 217 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping); | |
| 218 | |
| 219 // If this fails, we won't have a valid keystore key, and will simply request | |
| 220 // new ones from the server on the next DownloadUpdates. | |
| 221 UnpackKeystoreBootstrapToken(restored_keystore_key_for_bootstrapping, | |
| 222 encryptor, &old_keystore_keys_, &keystore_key_); | |
| 223 } | |
| 224 | |
| 225 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} | |
| 226 | |
| 227 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { | |
| 228 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 229 DCHECK(!observers_.HasObserver(observer)); | |
| 230 observers_.AddObserver(observer); | |
| 231 } | |
| 232 | |
| 233 void SyncEncryptionHandlerImpl::RemoveObserver(Observer* observer) { | |
| 234 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 235 DCHECK(observers_.HasObserver(observer)); | |
| 236 observers_.RemoveObserver(observer); | |
| 237 } | |
| 238 | |
| 239 void SyncEncryptionHandlerImpl::Init() { | |
| 240 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 241 WriteTransaction trans(FROM_HERE, user_share_); | |
| 242 WriteNode node(&trans); | |
| 243 | |
| 244 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) | |
| 245 return; | |
| 246 if (!ApplyNigoriUpdateImpl(node.GetNigoriSpecifics(), | |
| 247 trans.GetWrappedTrans())) { | |
| 248 WriteEncryptionStateToNigori(&trans); | |
| 249 } | |
| 250 | |
| 251 UMA_HISTOGRAM_ENUMERATION( | |
| 252 "Sync.PassphraseType", | |
| 253 static_cast<unsigned>(GetPassphraseType(trans.GetWrappedTrans())), | |
| 254 static_cast<unsigned>(PassphraseType::PASSPHRASE_TYPE_SIZE)); | |
| 255 | |
| 256 bool has_pending_keys = | |
| 257 UnlockVault(trans.GetWrappedTrans()).cryptographer.has_pending_keys(); | |
| 258 bool is_ready = UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready(); | |
| 259 // Log the state of the cryptographer regardless of migration state. | |
| 260 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerReady", is_ready); | |
| 261 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerPendingKeys", has_pending_keys); | |
| 262 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) { | |
| 263 // This account has a nigori node that has been migrated to support | |
| 264 // keystore. | |
| 265 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", MIGRATED, | |
| 266 MIGRATION_STATE_SIZE); | |
| 267 if (has_pending_keys && | |
| 268 GetPassphraseType(trans.GetWrappedTrans()) == | |
| 269 PassphraseType::KEYSTORE_PASSPHRASE) { | |
| 270 // If this is happening, it means the keystore decryptor is either | |
| 271 // undecryptable with the available keystore keys or does not match the | |
| 272 // nigori keybag's encryption key. Otherwise we're simply missing the | |
| 273 // keystore key. | |
| 274 UMA_HISTOGRAM_BOOLEAN("Sync.KeystoreDecryptionFailed", | |
| 275 !keystore_key_.empty()); | |
| 276 } | |
| 277 } else if (!is_ready) { | |
| 278 // Migration cannot occur until the cryptographer is ready (initialized | |
| 279 // with GAIA password and any pending keys resolved). | |
| 280 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", | |
| 281 NOT_MIGRATED_CRYPTO_NOT_READY, | |
| 282 MIGRATION_STATE_SIZE); | |
| 283 } else if (keystore_key_.empty()) { | |
| 284 // The client has no keystore key, either because it is not yet enabled or | |
| 285 // the server is not sending a valid keystore key. | |
| 286 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", | |
| 287 NOT_MIGRATED_NO_KEYSTORE_KEY, | |
| 288 MIGRATION_STATE_SIZE); | |
| 289 } else { | |
| 290 // If the above conditions have been met and the nigori node is still not | |
| 291 // migrated, something failed in the migration process. | |
| 292 UMA_HISTOGRAM_ENUMERATION("Sync.NigoriMigrationState", | |
| 293 NOT_MIGRATED_UNKNOWN_REASON, | |
| 294 MIGRATION_STATE_SIZE); | |
| 295 } | |
| 296 | |
| 297 // Always trigger an encrypted types and cryptographer state change event at | |
| 298 // init time so observers get the initial values. | |
| 299 FOR_EACH_OBSERVER(Observer, observers_, | |
| 300 OnEncryptedTypesChanged( | |
| 301 UnlockVault(trans.GetWrappedTrans()).encrypted_types, | |
| 302 encrypt_everything_)); | |
| 303 FOR_EACH_OBSERVER( | |
| 304 SyncEncryptionHandler::Observer, observers_, | |
| 305 OnCryptographerStateChanged( | |
| 306 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer)); | |
| 307 | |
| 308 // If the cryptographer is not ready (either it has pending keys or we | |
| 309 // failed to initialize it), we don't want to try and re-encrypt the data. | |
| 310 // If we had encrypted types, the DataTypeManager will block, preventing | |
| 311 // sync from happening until the the passphrase is provided. | |
| 312 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) | |
| 313 ReEncryptEverything(&trans); | |
| 314 } | |
| 315 | |
| 316 void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( | |
| 317 const std::string& passphrase, | |
| 318 bool is_explicit) { | |
| 319 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 320 // We do not accept empty passphrases. | |
| 321 if (passphrase.empty()) { | |
| 322 NOTREACHED() << "Cannot encrypt with an empty passphrase."; | |
| 323 return; | |
| 324 } | |
| 325 | |
| 326 // All accesses to the cryptographer are protected by a transaction. | |
| 327 WriteTransaction trans(FROM_HERE, user_share_); | |
| 328 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 329 WriteNode node(&trans); | |
| 330 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) { | |
| 331 NOTREACHED(); | |
| 332 return; | |
| 333 } | |
| 334 | |
| 335 Cryptographer* cryptographer = | |
| 336 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; | |
| 337 | |
| 338 // Once we've migrated to keystore, the only way to set a passphrase for | |
| 339 // encryption is to set a custom passphrase. | |
| 340 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) { | |
| 341 if (!is_explicit) { | |
| 342 // The user is setting a new implicit passphrase. At this point we don't | |
| 343 // care, so drop it on the floor. This is safe because if we have a | |
| 344 // migrated nigori node, then we don't need to create an initial | |
| 345 // encryption key. | |
| 346 LOG(WARNING) << "Ignoring new implicit passphrase. Keystore migration " | |
| 347 << "already performed."; | |
| 348 return; | |
| 349 } | |
| 350 // Will fail if we already have an explicit passphrase or we have pending | |
| 351 // keys. | |
| 352 SetCustomPassphrase(passphrase, &trans, &node); | |
| 353 | |
| 354 // When keystore migration occurs, the "CustomEncryption" UMA stat must be | |
| 355 // logged as true. | |
| 356 UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", true); | |
| 357 return; | |
| 358 } | |
| 359 | |
| 360 std::string bootstrap_token; | |
| 361 sync_pb::EncryptedData pending_keys; | |
| 362 if (cryptographer->has_pending_keys()) | |
| 363 pending_keys = cryptographer->GetPendingKeys(); | |
| 364 bool success = false; | |
| 365 PassphraseType* passphrase_type = | |
| 366 &UnlockVaultMutable(trans.GetWrappedTrans())->passphrase_type; | |
| 367 // There are six cases to handle here: | |
| 368 // 1. The user has no pending keys and is setting their current GAIA password | |
| 369 // as the encryption passphrase. This happens either during first time sync | |
| 370 // with a clean profile, or after re-authenticating on a profile that was | |
| 371 // already signed in with the cryptographer ready. | |
| 372 // 2. The user has no pending keys, and is overwriting an (already provided) | |
| 373 // implicit passphrase with an explicit (custom) passphrase. | |
| 374 // 3. The user has pending keys for an explicit passphrase that is somehow set | |
| 375 // to their current GAIA passphrase. | |
| 376 // 4. The user has pending keys encrypted with their current GAIA passphrase | |
| 377 // and the caller passes in the current GAIA passphrase. | |
| 378 // 5. The user has pending keys encrypted with an older GAIA passphrase | |
| 379 // and the caller passes in the current GAIA passphrase. | |
| 380 // 6. The user has previously done encryption with an explicit passphrase. | |
| 381 // Furthermore, we enforce the fact that the bootstrap encryption token will | |
| 382 // always be derived from the newest GAIA password if the account is using | |
| 383 // an implicit passphrase (even if the data is encrypted with an old GAIA | |
| 384 // password). If the account is using an explicit (custom) passphrase, the | |
| 385 // bootstrap token will be derived from the most recently provided explicit | |
| 386 // passphrase (that was able to decrypt the data). | |
| 387 if (!IsExplicitPassphrase(*passphrase_type)) { | |
| 388 if (!cryptographer->has_pending_keys()) { | |
| 389 if (cryptographer->AddKey(key_params)) { | |
| 390 // Case 1 and 2. We set a new GAIA passphrase when there are no pending | |
| 391 // keys (1), or overwriting an implicit passphrase with a new explicit | |
| 392 // one (2) when there are no pending keys. | |
| 393 if (is_explicit) { | |
| 394 DVLOG(1) << "Setting explicit passphrase for encryption."; | |
| 395 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; | |
| 396 custom_passphrase_time_ = base::Time::Now(); | |
| 397 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 398 OnPassphraseTypeChanged( | |
| 399 *passphrase_type, | |
| 400 GetExplicitPassphraseTime(*passphrase_type))); | |
| 401 } else { | |
| 402 DVLOG(1) << "Setting implicit passphrase for encryption."; | |
| 403 } | |
| 404 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 405 | |
| 406 // With M26, sync accounts can be in only one of two encryption states: | |
| 407 // 1) Encrypt only passwords with an implicit passphrase. | |
| 408 // 2) Encrypt all sync datatypes with an explicit passphrase. | |
| 409 // We deprecate the "EncryptAllData" and "CustomPassphrase" histograms, | |
| 410 // and keep track of an account's encryption state via the | |
| 411 // "CustomEncryption" histogram. See http://crbug.com/131478. | |
| 412 UMA_HISTOGRAM_BOOLEAN("Sync.CustomEncryption", is_explicit); | |
| 413 | |
| 414 success = true; | |
| 415 } else { | |
| 416 NOTREACHED() << "Failed to add key to cryptographer."; | |
| 417 success = false; | |
| 418 } | |
| 419 } else { // cryptographer->has_pending_keys() == true | |
| 420 if (is_explicit) { | |
| 421 // This can only happen if the nigori node is updated with a new | |
| 422 // implicit passphrase while a client is attempting to set a new custom | |
| 423 // passphrase (race condition). | |
| 424 DVLOG(1) << "Failing because an implicit passphrase is already set."; | |
| 425 success = false; | |
| 426 } else { // is_explicit == false | |
| 427 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 428 // Case 4. We successfully decrypted with the implicit GAIA passphrase | |
| 429 // passed in. | |
| 430 DVLOG(1) << "Implicit internal passphrase accepted for decryption."; | |
| 431 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 432 success = true; | |
| 433 } else { | |
| 434 // Case 5. Encryption was done with an old GAIA password, but we were | |
| 435 // provided with the current GAIA password. We need to generate a new | |
| 436 // bootstrap token to preserve it. We build a temporary cryptographer | |
| 437 // to allow us to extract these params without polluting our current | |
| 438 // cryptographer. | |
| 439 DVLOG(1) << "Implicit internal passphrase failed to decrypt, adding " | |
| 440 << "anyways as default passphrase and persisting via " | |
| 441 << "bootstrap token."; | |
| 442 Cryptographer temp_cryptographer(cryptographer->encryptor()); | |
| 443 temp_cryptographer.AddKey(key_params); | |
| 444 temp_cryptographer.GetBootstrapToken(&bootstrap_token); | |
| 445 // We then set the new passphrase as the default passphrase of the | |
| 446 // real cryptographer, even though we have pending keys. This is safe, | |
| 447 // as although Cryptographer::is_initialized() will now be true, | |
| 448 // is_ready() will remain false due to having pending keys. | |
| 449 cryptographer->AddKey(key_params); | |
| 450 success = false; | |
| 451 } | |
| 452 } // is_explicit | |
| 453 } // cryptographer->has_pending_keys() | |
| 454 } else { // IsExplicitPassphrase(passphrase_type) == true. | |
| 455 // Case 6. We do not want to override a previously set explicit passphrase, | |
| 456 // so we return a failure. | |
| 457 DVLOG(1) << "Failing because an explicit passphrase is already set."; | |
| 458 success = false; | |
| 459 } | |
| 460 | |
| 461 DVLOG_IF(1, !success) | |
| 462 << "Failure in SetEncryptionPassphrase; notifying and returning."; | |
| 463 DVLOG_IF(1, success) | |
| 464 << "Successfully set encryption passphrase; updating nigori and " | |
| 465 "reencrypting."; | |
| 466 | |
| 467 FinishSetPassphrase(success, bootstrap_token, &trans, &node); | |
| 468 } | |
| 469 | |
| 470 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( | |
| 471 const std::string& passphrase) { | |
| 472 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 473 // We do not accept empty passphrases. | |
| 474 if (passphrase.empty()) { | |
| 475 NOTREACHED() << "Cannot decrypt with an empty passphrase."; | |
| 476 return; | |
| 477 } | |
| 478 | |
| 479 // All accesses to the cryptographer are protected by a transaction. | |
| 480 WriteTransaction trans(FROM_HERE, user_share_); | |
| 481 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 482 WriteNode node(&trans); | |
| 483 if (node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) { | |
| 484 NOTREACHED(); | |
| 485 return; | |
| 486 } | |
| 487 | |
| 488 // Once we've migrated to keystore, we're only ever decrypting keys derived | |
| 489 // from an explicit passphrase. But, for clients without a keystore key yet | |
| 490 // (either not on by default or failed to download one), we still support | |
| 491 // decrypting with a gaia passphrase, and therefore bypass the | |
| 492 // DecryptPendingKeysWithExplicitPassphrase logic. | |
| 493 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) && | |
| 494 IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) { | |
| 495 DecryptPendingKeysWithExplicitPassphrase(passphrase, &trans, &node); | |
| 496 return; | |
| 497 } | |
| 498 | |
| 499 Cryptographer* cryptographer = | |
| 500 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; | |
| 501 if (!cryptographer->has_pending_keys()) { | |
| 502 // Note that this *can* happen in a rare situation where data is | |
| 503 // re-encrypted on another client while a SetDecryptionPassphrase() call is | |
| 504 // in-flight on this client. It is rare enough that we choose to do nothing. | |
| 505 NOTREACHED() << "Attempt to set decryption passphrase failed because there " | |
| 506 << "were no pending keys."; | |
| 507 return; | |
| 508 } | |
| 509 | |
| 510 std::string bootstrap_token; | |
| 511 sync_pb::EncryptedData pending_keys; | |
| 512 pending_keys = cryptographer->GetPendingKeys(); | |
| 513 bool success = false; | |
| 514 | |
| 515 // There are three cases to handle here: | |
| 516 // 7. We're using the current GAIA password to decrypt the pending keys. This | |
| 517 // happens when signing in to an account with a previously set implicit | |
| 518 // passphrase, where the data is already encrypted with the newest GAIA | |
| 519 // password. | |
| 520 // 8. The user is providing an old GAIA password to decrypt the pending keys. | |
| 521 // In this case, the user is using an implicit passphrase, but has changed | |
| 522 // their password since they last encrypted their data, and therefore | |
| 523 // their current GAIA password was unable to decrypt the data. This will | |
| 524 // happen when the user is setting up a new profile with a previously | |
| 525 // encrypted account (after changing passwords). | |
| 526 // 9. The user is providing a previously set explicit passphrase to decrypt | |
| 527 // the pending keys. | |
| 528 if (!IsExplicitPassphrase(GetPassphraseType(trans.GetWrappedTrans()))) { | |
| 529 if (cryptographer->is_initialized()) { | |
| 530 // We only want to change the default encryption key to the pending | |
| 531 // one if the pending keybag already contains the current default. | |
| 532 // This covers the case where a different client re-encrypted | |
| 533 // everything with a newer gaia passphrase (and hence the keybag | |
| 534 // contains keys from all previously used gaia passphrases). | |
| 535 // Otherwise, we're in a situation where the pending keys are | |
| 536 // encrypted with an old gaia passphrase, while the default is the | |
| 537 // current gaia passphrase. In that case, we preserve the default. | |
| 538 Cryptographer temp_cryptographer(cryptographer->encryptor()); | |
| 539 temp_cryptographer.SetPendingKeys(cryptographer->GetPendingKeys()); | |
| 540 if (temp_cryptographer.DecryptPendingKeys(key_params)) { | |
| 541 // Check to see if the pending bag of keys contains the current | |
| 542 // default key. | |
| 543 sync_pb::EncryptedData encrypted; | |
| 544 cryptographer->GetKeys(&encrypted); | |
| 545 if (temp_cryptographer.CanDecrypt(encrypted)) { | |
| 546 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 547 << "decryption, overwriting default."; | |
| 548 // Case 7. The pending keybag contains the current default. Go ahead | |
| 549 // and update the cryptographer, letting the default change. | |
| 550 cryptographer->DecryptPendingKeys(key_params); | |
| 551 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 552 success = true; | |
| 553 } else { | |
| 554 // Case 8. The pending keybag does not contain the current default | |
| 555 // encryption key. We decrypt the pending keys here, and in | |
| 556 // FinishSetPassphrase, re-encrypt everything with the current GAIA | |
| 557 // passphrase instead of the passphrase just provided by the user. | |
| 558 DVLOG(1) << "Implicit user provided passphrase accepted for " | |
| 559 << "decryption, restoring implicit internal passphrase " | |
| 560 << "as default."; | |
| 561 std::string bootstrap_token_from_current_key; | |
| 562 cryptographer->GetBootstrapToken(&bootstrap_token_from_current_key); | |
| 563 cryptographer->DecryptPendingKeys(key_params); | |
| 564 // Overwrite the default from the pending keys. | |
| 565 cryptographer->AddKeyFromBootstrapToken( | |
| 566 bootstrap_token_from_current_key); | |
| 567 success = true; | |
| 568 } | |
| 569 } else { // !temp_cryptographer.DecryptPendingKeys(..) | |
| 570 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 571 success = false; | |
| 572 } // temp_cryptographer.DecryptPendingKeys(...) | |
| 573 } else { // cryptographer->is_initialized() == false | |
| 574 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 575 // This can happpen in two cases: | |
| 576 // - First time sync on android, where we'll never have a | |
| 577 // !user_provided passphrase. | |
| 578 // - This is a restart for a client that lost their bootstrap token. | |
| 579 // In both cases, we should go ahead and initialize the cryptographer | |
| 580 // and persist the new bootstrap token. | |
| 581 // | |
| 582 // Note: at this point, we cannot distinguish between cases 7 and 8 | |
| 583 // above. This user provided passphrase could be the current or the | |
| 584 // old. But, as long as we persist the token, there's nothing more | |
| 585 // we can do. | |
| 586 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 587 DVLOG(1) << "Implicit user provided passphrase accepted, initializing" | |
| 588 << " cryptographer."; | |
| 589 success = true; | |
| 590 } else { | |
| 591 DVLOG(1) << "Implicit user provided passphrase failed to decrypt."; | |
| 592 success = false; | |
| 593 } | |
| 594 } // cryptographer->is_initialized() | |
| 595 } else { // nigori_has_explicit_passphrase == true | |
| 596 // Case 9. Encryption was done with an explicit passphrase, and we decrypt | |
| 597 // with the passphrase provided by the user. | |
| 598 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 599 DVLOG(1) << "Explicit passphrase accepted for decryption."; | |
| 600 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 601 success = true; | |
| 602 } else { | |
| 603 DVLOG(1) << "Explicit passphrase failed to decrypt."; | |
| 604 success = false; | |
| 605 } | |
| 606 } // nigori_has_explicit_passphrase | |
| 607 | |
| 608 DVLOG_IF(1, !success) | |
| 609 << "Failure in SetDecryptionPassphrase; notifying and returning."; | |
| 610 DVLOG_IF(1, success) | |
| 611 << "Successfully set decryption passphrase; updating nigori and " | |
| 612 "reencrypting."; | |
| 613 | |
| 614 FinishSetPassphrase(success, bootstrap_token, &trans, &node); | |
| 615 } | |
| 616 | |
| 617 void SyncEncryptionHandlerImpl::EnableEncryptEverything() { | |
| 618 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 619 WriteTransaction trans(FROM_HERE, user_share_); | |
| 620 DVLOG(1) << "Enabling encrypt everything."; | |
| 621 if (encrypt_everything_) | |
| 622 return; | |
| 623 EnableEncryptEverythingImpl(trans.GetWrappedTrans()); | |
| 624 WriteEncryptionStateToNigori(&trans); | |
| 625 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) | |
| 626 ReEncryptEverything(&trans); | |
| 627 } | |
| 628 | |
| 629 bool SyncEncryptionHandlerImpl::IsEncryptEverythingEnabled() const { | |
| 630 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 631 return encrypt_everything_; | |
| 632 } | |
| 633 | |
| 634 // Note: this is called from within a syncable transaction, so we need to post | |
| 635 // tasks if we want to do any work that creates a new sync_api transaction. | |
| 636 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( | |
| 637 const sync_pb::NigoriSpecifics& nigori, | |
| 638 syncable::BaseTransaction* const trans) { | |
| 639 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 640 DCHECK(trans); | |
| 641 if (!ApplyNigoriUpdateImpl(nigori, trans)) { | |
| 642 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 643 FROM_HERE, base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, | |
| 644 weak_ptr_factory_.GetWeakPtr())); | |
| 645 } | |
| 646 | |
| 647 FOR_EACH_OBSERVER( | |
| 648 SyncEncryptionHandler::Observer, observers_, | |
| 649 OnCryptographerStateChanged(&UnlockVaultMutable(trans)->cryptographer)); | |
| 650 } | |
| 651 | |
| 652 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes( | |
| 653 sync_pb::NigoriSpecifics* nigori, | |
| 654 syncable::BaseTransaction* const trans) const { | |
| 655 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 656 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types, | |
| 657 encrypt_everything_, nigori); | |
| 658 } | |
| 659 | |
| 660 bool SyncEncryptionHandlerImpl::NeedKeystoreKey( | |
| 661 syncable::BaseTransaction* const trans) const { | |
| 662 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 663 return keystore_key_.empty(); | |
| 664 } | |
| 665 | |
| 666 bool SyncEncryptionHandlerImpl::SetKeystoreKeys( | |
| 667 const google::protobuf::RepeatedPtrField<google::protobuf::string>& keys, | |
| 668 syncable::BaseTransaction* const trans) { | |
| 669 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 670 if (keys.size() == 0) | |
| 671 return false; | |
| 672 // The last key in the vector is the current keystore key. The others are kept | |
| 673 // around for decryption only. | |
| 674 const std::string& raw_keystore_key = keys.Get(keys.size() - 1); | |
| 675 if (raw_keystore_key.empty()) | |
| 676 return false; | |
| 677 | |
| 678 // Note: in order to Pack the keys, they must all be base64 encoded (else | |
| 679 // JSON serialization fails). | |
| 680 base::Base64Encode(raw_keystore_key, &keystore_key_); | |
| 681 | |
| 682 // Go through and save the old keystore keys. We always persist all keystore | |
| 683 // keys the server sends us. | |
| 684 old_keystore_keys_.resize(keys.size() - 1); | |
| 685 for (int i = 0; i < keys.size() - 1; ++i) | |
| 686 base::Base64Encode(keys.Get(i), &old_keystore_keys_[i]); | |
| 687 | |
| 688 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; | |
| 689 | |
| 690 // Update the bootstrap token. If this fails, we persist an empty string, | |
| 691 // which will force us to download the keystore keys again on the next | |
| 692 // restart. | |
| 693 std::string keystore_bootstrap = PackKeystoreBootstrapToken( | |
| 694 old_keystore_keys_, keystore_key_, cryptographer->encryptor()); | |
| 695 | |
| 696 FOR_EACH_OBSERVER( | |
| 697 SyncEncryptionHandler::Observer, observers_, | |
| 698 OnBootstrapTokenUpdated(keystore_bootstrap, KEYSTORE_BOOTSTRAP_TOKEN)); | |
| 699 DVLOG(1) << "Keystore bootstrap token updated."; | |
| 700 | |
| 701 // If this is a first time sync, we get the encryption keys before we process | |
| 702 // the nigori node. Just return for now, ApplyNigoriUpdate will be invoked | |
| 703 // once we have the nigori node. | |
| 704 syncable::Entry entry(trans, syncable::GET_TYPE_ROOT, NIGORI); | |
| 705 if (!entry.good()) | |
| 706 return true; | |
| 707 | |
| 708 const sync_pb::NigoriSpecifics& nigori = entry.GetSpecifics().nigori(); | |
| 709 if (cryptographer->has_pending_keys() && IsNigoriMigratedToKeystore(nigori) && | |
| 710 !nigori.keystore_decryptor_token().blob().empty()) { | |
| 711 // If the nigori is already migrated and we have pending keys, we might | |
| 712 // be able to decrypt them using either the keystore decryptor token | |
| 713 // or the existing keystore keys. | |
| 714 DecryptPendingKeysWithKeystoreKey(nigori.keystore_decryptor_token(), | |
| 715 cryptographer); | |
| 716 } | |
| 717 | |
| 718 // Note that triggering migration will have no effect if we're already | |
| 719 // properly migrated with the newest keystore keys. | |
| 720 if (ShouldTriggerMigration(nigori, *cryptographer, | |
| 721 GetPassphraseType(trans))) { | |
| 722 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
| 723 FROM_HERE, base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, | |
| 724 weak_ptr_factory_.GetWeakPtr())); | |
| 725 } | |
| 726 | |
| 727 return true; | |
| 728 } | |
| 729 | |
| 730 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes( | |
| 731 syncable::BaseTransaction* const trans) const { | |
| 732 return UnlockVault(trans).encrypted_types; | |
| 733 } | |
| 734 | |
| 735 PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType( | |
| 736 syncable::BaseTransaction* const trans) const { | |
| 737 return UnlockVault(trans).passphrase_type; | |
| 738 } | |
| 739 | |
| 740 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { | |
| 741 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 742 return &vault_unsafe_.cryptographer; | |
| 743 } | |
| 744 | |
| 745 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() { | |
| 746 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 747 return vault_unsafe_.encrypted_types; | |
| 748 } | |
| 749 | |
| 750 bool SyncEncryptionHandlerImpl::MigratedToKeystore() { | |
| 751 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 752 ReadTransaction trans(FROM_HERE, user_share_); | |
| 753 ReadNode nigori_node(&trans); | |
| 754 if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) | |
| 755 return false; | |
| 756 return IsNigoriMigratedToKeystore(nigori_node.GetNigoriSpecifics()); | |
| 757 } | |
| 758 | |
| 759 base::Time SyncEncryptionHandlerImpl::migration_time() const { | |
| 760 return migration_time_; | |
| 761 } | |
| 762 | |
| 763 base::Time SyncEncryptionHandlerImpl::custom_passphrase_time() const { | |
| 764 return custom_passphrase_time_; | |
| 765 } | |
| 766 | |
| 767 void SyncEncryptionHandlerImpl::RestoreNigori( | |
| 768 const SyncEncryptionHandler::NigoriState& nigori_state) { | |
| 769 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 770 | |
| 771 WriteTransaction trans(FROM_HERE, user_share_); | |
| 772 | |
| 773 // Verify we don't already have a nigori node. | |
| 774 WriteNode nigori_node(&trans); | |
| 775 BaseNode::InitByLookupResult init_result = nigori_node.InitTypeRoot(NIGORI); | |
| 776 DCHECK(init_result == BaseNode::INIT_FAILED_ENTRY_NOT_GOOD); | |
| 777 | |
| 778 // Create one. | |
| 779 syncable::ModelNeutralMutableEntry model_neutral_mutable_entry( | |
| 780 trans.GetWrappedWriteTrans(), syncable::CREATE_NEW_TYPE_ROOT, NIGORI); | |
| 781 DCHECK(model_neutral_mutable_entry.good()); | |
| 782 model_neutral_mutable_entry.PutServerIsDir(true); | |
| 783 model_neutral_mutable_entry.PutUniqueServerTag(ModelTypeToRootTag(NIGORI)); | |
| 784 model_neutral_mutable_entry.PutIsUnsynced(true); | |
| 785 | |
| 786 // Update it with the saved nigori specifics. | |
| 787 syncable::MutableEntry mutable_entry(trans.GetWrappedWriteTrans(), | |
| 788 syncable::GET_TYPE_ROOT, NIGORI); | |
| 789 DCHECK(mutable_entry.good()); | |
| 790 sync_pb::EntitySpecifics specifics; | |
| 791 specifics.mutable_nigori()->CopyFrom(nigori_state.nigori_specifics); | |
| 792 mutable_entry.PutSpecifics(specifics); | |
| 793 | |
| 794 // Update our state based on the saved nigori node. | |
| 795 ApplyNigoriUpdate(nigori_state.nigori_specifics, trans.GetWrappedTrans()); | |
| 796 } | |
| 797 | |
| 798 // This function iterates over all encrypted types. There are many scenarios in | |
| 799 // which data for some or all types is not currently available. In that case, | |
| 800 // the lookup of the root node will fail and we will skip encryption for that | |
| 801 // type. | |
| 802 void SyncEncryptionHandlerImpl::ReEncryptEverything(WriteTransaction* trans) { | |
| 803 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 804 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready()); | |
| 805 for (ModelTypeSet::Iterator iter = | |
| 806 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First(); | |
| 807 iter.Good(); iter.Inc()) { | |
| 808 if (iter.Get() == PASSWORDS || IsControlType(iter.Get())) | |
| 809 continue; // These types handle encryption differently. | |
| 810 | |
| 811 ReadNode type_root(trans); | |
| 812 if (type_root.InitTypeRoot(iter.Get()) != BaseNode::INIT_OK) | |
| 813 continue; // Don't try to reencrypt if the type's data is unavailable. | |
| 814 | |
| 815 // Iterate through all children of this datatype. | |
| 816 std::queue<int64_t> to_visit; | |
| 817 int64_t child_id = type_root.GetFirstChildId(); | |
| 818 to_visit.push(child_id); | |
| 819 while (!to_visit.empty()) { | |
| 820 child_id = to_visit.front(); | |
| 821 to_visit.pop(); | |
| 822 if (child_id == kInvalidId) | |
| 823 continue; | |
| 824 | |
| 825 WriteNode child(trans); | |
| 826 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) | |
| 827 continue; // Possible for locally deleted items. | |
| 828 if (child.GetIsFolder()) { | |
| 829 to_visit.push(child.GetFirstChildId()); | |
| 830 } | |
| 831 if (!child.GetIsPermanentFolder()) { | |
| 832 // Rewrite the specifics of the node with encrypted data if necessary | |
| 833 // (only rewrite the non-unique folders). | |
| 834 child.ResetFromSpecifics(); | |
| 835 } | |
| 836 to_visit.push(child.GetSuccessorId()); | |
| 837 } | |
| 838 } | |
| 839 | |
| 840 // Passwords are encrypted with their own legacy scheme. Passwords are always | |
| 841 // encrypted so we don't need to check GetEncryptedTypes() here. | |
| 842 ReadNode passwords_root(trans); | |
| 843 if (passwords_root.InitTypeRoot(PASSWORDS) == BaseNode::INIT_OK) { | |
| 844 int64_t child_id = passwords_root.GetFirstChildId(); | |
| 845 while (child_id != kInvalidId) { | |
| 846 WriteNode child(trans); | |
| 847 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) | |
| 848 break; // Possible if we failed to decrypt the data for some reason. | |
| 849 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); | |
| 850 child_id = child.GetSuccessorId(); | |
| 851 } | |
| 852 } | |
| 853 | |
| 854 DVLOG(1) << "Re-encrypt everything complete."; | |
| 855 | |
| 856 // NOTE: We notify from within a transaction. | |
| 857 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 858 OnEncryptionComplete()); | |
| 859 } | |
| 860 | |
| 861 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( | |
| 862 const sync_pb::NigoriSpecifics& nigori, | |
| 863 syncable::BaseTransaction* const trans) { | |
| 864 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 865 DVLOG(1) << "Applying nigori node update."; | |
| 866 bool nigori_types_need_update = | |
| 867 !UpdateEncryptedTypesFromNigori(nigori, trans); | |
| 868 | |
| 869 if (nigori.custom_passphrase_time() != 0) { | |
| 870 custom_passphrase_time_ = ProtoTimeToTime(nigori.custom_passphrase_time()); | |
| 871 } | |
| 872 bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori); | |
| 873 PassphraseType* passphrase_type = &UnlockVaultMutable(trans)->passphrase_type; | |
| 874 if (is_nigori_migrated) { | |
| 875 migration_time_ = ProtoTimeToTime(nigori.keystore_migration_time()); | |
| 876 PassphraseType nigori_passphrase_type = | |
| 877 ProtoPassphraseTypeToEnum(nigori.passphrase_type()); | |
| 878 | |
| 879 // Only update the local passphrase state if it's a valid transition: | |
| 880 // - implicit -> keystore | |
| 881 // - implicit -> frozen implicit | |
| 882 // - implicit -> custom | |
| 883 // - keystore -> custom | |
| 884 // Note: frozen implicit -> custom is not technically a valid transition, | |
| 885 // but we let it through here as well in case future versions do add support | |
| 886 // for this transition. | |
| 887 if (*passphrase_type != nigori_passphrase_type && | |
| 888 nigori_passphrase_type != PassphraseType::IMPLICIT_PASSPHRASE && | |
| 889 (*passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE || | |
| 890 nigori_passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)) { | |
| 891 DVLOG(1) << "Changing passphrase state from " | |
| 892 << PassphraseTypeToString(*passphrase_type) << " to " | |
| 893 << PassphraseTypeToString(nigori_passphrase_type); | |
| 894 *passphrase_type = nigori_passphrase_type; | |
| 895 FOR_EACH_OBSERVER( | |
| 896 SyncEncryptionHandler::Observer, observers_, | |
| 897 OnPassphraseTypeChanged(*passphrase_type, | |
| 898 GetExplicitPassphraseTime(*passphrase_type))); | |
| 899 } | |
| 900 if (*passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE && | |
| 901 encrypt_everything_) { | |
| 902 // This is the case where another client that didn't support keystore | |
| 903 // encryption attempted to enable full encryption. We detect it | |
| 904 // and switch the passphrase type to frozen implicit passphrase instead | |
| 905 // due to full encryption not being compatible with keystore passphrase. | |
| 906 // Because the local passphrase type will not match the nigori passphrase | |
| 907 // type, we will trigger a rewrite and subsequently a re-migration. | |
| 908 DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE " | |
| 909 << "due to full encryption."; | |
| 910 *passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; | |
| 911 FOR_EACH_OBSERVER( | |
| 912 SyncEncryptionHandler::Observer, observers_, | |
| 913 OnPassphraseTypeChanged(*passphrase_type, | |
| 914 GetExplicitPassphraseTime(*passphrase_type))); | |
| 915 } | |
| 916 } else { | |
| 917 // It's possible that while we're waiting for migration a client that does | |
| 918 // not have keystore encryption enabled switches to a custom passphrase. | |
| 919 if (nigori.keybag_is_frozen() && | |
| 920 *passphrase_type != PassphraseType::CUSTOM_PASSPHRASE) { | |
| 921 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; | |
| 922 FOR_EACH_OBSERVER( | |
| 923 SyncEncryptionHandler::Observer, observers_, | |
| 924 OnPassphraseTypeChanged(*passphrase_type, | |
| 925 GetExplicitPassphraseTime(*passphrase_type))); | |
| 926 } | |
| 927 } | |
| 928 | |
| 929 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; | |
| 930 bool nigori_needs_new_keys = false; | |
| 931 if (!nigori.encryption_keybag().blob().empty()) { | |
| 932 // We only update the default key if this was a new explicit passphrase. | |
| 933 // Else, since it was decryptable, it must not have been a new key. | |
| 934 bool need_new_default_key = false; | |
| 935 if (is_nigori_migrated) { | |
| 936 need_new_default_key = IsExplicitPassphrase( | |
| 937 ProtoPassphraseTypeToEnum(nigori.passphrase_type())); | |
| 938 } else { | |
| 939 need_new_default_key = nigori.keybag_is_frozen(); | |
| 940 } | |
| 941 if (!AttemptToInstallKeybag(nigori.encryption_keybag(), | |
| 942 need_new_default_key, cryptographer)) { | |
| 943 // Check to see if we can decrypt the keybag using the keystore decryptor | |
| 944 // token. | |
| 945 cryptographer->SetPendingKeys(nigori.encryption_keybag()); | |
| 946 if (!nigori.keystore_decryptor_token().blob().empty() && | |
| 947 !keystore_key_.empty()) { | |
| 948 if (DecryptPendingKeysWithKeystoreKey(nigori.keystore_decryptor_token(), | |
| 949 cryptographer)) { | |
| 950 nigori_needs_new_keys = | |
| 951 cryptographer->KeybagIsStale(nigori.encryption_keybag()); | |
| 952 } else { | |
| 953 LOG(ERROR) << "Failed to decrypt pending keys using keystore " | |
| 954 << "bootstrap key."; | |
| 955 } | |
| 956 } | |
| 957 } else { | |
| 958 // Keybag was installed. We write back our local keybag into the nigori | |
| 959 // node if the nigori node's keybag either contains less keys or | |
| 960 // has a different default key. | |
| 961 nigori_needs_new_keys = | |
| 962 cryptographer->KeybagIsStale(nigori.encryption_keybag()); | |
| 963 } | |
| 964 } else { | |
| 965 // The nigori node has an empty encryption keybag. Attempt to write our | |
| 966 // local encryption keys into it. | |
| 967 LOG(WARNING) << "Nigori had empty encryption keybag."; | |
| 968 nigori_needs_new_keys = true; | |
| 969 } | |
| 970 | |
| 971 // If we've completed a sync cycle and the cryptographer isn't ready | |
| 972 // yet or has pending keys, prompt the user for a passphrase. | |
| 973 if (cryptographer->has_pending_keys()) { | |
| 974 DVLOG(1) << "OnPassphraseRequired Sent"; | |
| 975 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); | |
| 976 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 977 OnPassphraseRequired(REASON_DECRYPTION, pending_keys)); | |
| 978 } else if (!cryptographer->is_ready()) { | |
| 979 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " | |
| 980 << "ready"; | |
| 981 FOR_EACH_OBSERVER( | |
| 982 SyncEncryptionHandler::Observer, observers_, | |
| 983 OnPassphraseRequired(REASON_ENCRYPTION, sync_pb::EncryptedData())); | |
| 984 } | |
| 985 | |
| 986 // Check if the current local encryption state is stricter/newer than the | |
| 987 // nigori state. If so, we need to overwrite the nigori node with the local | |
| 988 // state. | |
| 989 bool passphrase_type_matches = true; | |
| 990 if (!is_nigori_migrated) { | |
| 991 DCHECK(*passphrase_type == PassphraseType::CUSTOM_PASSPHRASE || | |
| 992 *passphrase_type == PassphraseType::IMPLICIT_PASSPHRASE); | |
| 993 passphrase_type_matches = | |
| 994 nigori.keybag_is_frozen() == IsExplicitPassphrase(*passphrase_type); | |
| 995 } else { | |
| 996 passphrase_type_matches = | |
| 997 (ProtoPassphraseTypeToEnum(nigori.passphrase_type()) == | |
| 998 *passphrase_type); | |
| 999 } | |
| 1000 if (!passphrase_type_matches || | |
| 1001 nigori.encrypt_everything() != encrypt_everything_ || | |
| 1002 nigori_types_need_update || nigori_needs_new_keys) { | |
| 1003 DVLOG(1) << "Triggering nigori rewrite."; | |
| 1004 return false; | |
| 1005 } | |
| 1006 return true; | |
| 1007 } | |
| 1008 | |
| 1009 void SyncEncryptionHandlerImpl::RewriteNigori() { | |
| 1010 DVLOG(1) << "Writing local encryption state into nigori."; | |
| 1011 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1012 WriteTransaction trans(FROM_HERE, user_share_); | |
| 1013 WriteEncryptionStateToNigori(&trans); | |
| 1014 } | |
| 1015 | |
| 1016 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori( | |
| 1017 WriteTransaction* trans) { | |
| 1018 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1019 WriteNode nigori_node(trans); | |
| 1020 // This can happen in tests that don't have nigori nodes. | |
| 1021 if (nigori_node.InitTypeRoot(NIGORI) != BaseNode::INIT_OK) | |
| 1022 return; | |
| 1023 | |
| 1024 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics(); | |
| 1025 const Cryptographer& cryptographer = | |
| 1026 UnlockVault(trans->GetWrappedTrans()).cryptographer; | |
| 1027 | |
| 1028 // Will not do anything if we shouldn't or can't migrate. Otherwise | |
| 1029 // migrates, writing the full encryption state as it does. | |
| 1030 if (!AttemptToMigrateNigoriToKeystore(trans, &nigori_node)) { | |
| 1031 if (cryptographer.is_ready() && | |
| 1032 nigori_overwrite_count_ < kNigoriOverwriteLimit) { | |
| 1033 // Does not modify the encrypted blob if the unencrypted data already | |
| 1034 // matches what is about to be written. | |
| 1035 sync_pb::EncryptedData original_keys = nigori.encryption_keybag(); | |
| 1036 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag())) | |
| 1037 NOTREACHED(); | |
| 1038 | |
| 1039 if (nigori.encryption_keybag().SerializeAsString() != | |
| 1040 original_keys.SerializeAsString()) { | |
| 1041 // We've updated the nigori node's encryption keys. In order to prevent | |
| 1042 // a possible looping of two clients constantly overwriting each other, | |
| 1043 // we limit the absolute number of overwrites per client instantiation. | |
| 1044 nigori_overwrite_count_++; | |
| 1045 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", | |
| 1046 nigori_overwrite_count_); | |
| 1047 } | |
| 1048 | |
| 1049 // Note: we don't try to set keybag_is_frozen here since if that | |
| 1050 // is lost the user can always set it again (and we don't want to clobber | |
| 1051 // any migration state). The main goal at this point is to preserve | |
| 1052 // the encryption keys so all data remains decryptable. | |
| 1053 } | |
| 1054 syncable::UpdateNigoriFromEncryptedTypes( | |
| 1055 UnlockVault(trans->GetWrappedTrans()).encrypted_types, | |
| 1056 encrypt_everything_, &nigori); | |
| 1057 if (!custom_passphrase_time_.is_null()) { | |
| 1058 nigori.set_custom_passphrase_time( | |
| 1059 TimeToProtoTime(custom_passphrase_time_)); | |
| 1060 } | |
| 1061 | |
| 1062 // If nothing has changed, this is a no-op. | |
| 1063 nigori_node.SetNigoriSpecifics(nigori); | |
| 1064 } | |
| 1065 } | |
| 1066 | |
| 1067 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori( | |
| 1068 const sync_pb::NigoriSpecifics& nigori, | |
| 1069 syncable::BaseTransaction* const trans) { | |
| 1070 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1071 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; | |
| 1072 if (nigori.encrypt_everything()) { | |
| 1073 EnableEncryptEverythingImpl(trans); | |
| 1074 DCHECK(*encrypted_types == EncryptableUserTypes()); | |
| 1075 return true; | |
| 1076 } else if (encrypt_everything_) { | |
| 1077 DCHECK(*encrypted_types == EncryptableUserTypes()); | |
| 1078 return false; | |
| 1079 } | |
| 1080 | |
| 1081 ModelTypeSet nigori_encrypted_types; | |
| 1082 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori); | |
| 1083 nigori_encrypted_types.PutAll(SensitiveTypes()); | |
| 1084 | |
| 1085 // If anything more than the sensitive types were encrypted, and | |
| 1086 // encrypt_everything is not explicitly set to false, we assume it means | |
| 1087 // a client intended to enable encrypt everything. | |
| 1088 if (!nigori.has_encrypt_everything() && | |
| 1089 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) { | |
| 1090 if (!encrypt_everything_) { | |
| 1091 encrypt_everything_ = true; | |
| 1092 *encrypted_types = EncryptableUserTypes(); | |
| 1093 FOR_EACH_OBSERVER( | |
| 1094 Observer, observers_, | |
| 1095 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | |
| 1096 } | |
| 1097 DCHECK(*encrypted_types == EncryptableUserTypes()); | |
| 1098 return false; | |
| 1099 } | |
| 1100 | |
| 1101 MergeEncryptedTypes(nigori_encrypted_types, trans); | |
| 1102 return *encrypted_types == nigori_encrypted_types; | |
| 1103 } | |
| 1104 | |
| 1105 void SyncEncryptionHandlerImpl::SetCustomPassphrase( | |
| 1106 const std::string& passphrase, | |
| 1107 WriteTransaction* trans, | |
| 1108 WriteNode* nigori_node) { | |
| 1109 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1110 DCHECK(IsNigoriMigratedToKeystore(nigori_node->GetNigoriSpecifics())); | |
| 1111 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 1112 | |
| 1113 if (GetPassphraseType(trans->GetWrappedTrans()) != | |
| 1114 PassphraseType::KEYSTORE_PASSPHRASE) { | |
| 1115 DVLOG(1) << "Failing to set a custom passphrase because one has already " | |
| 1116 << "been set."; | |
| 1117 FinishSetPassphrase(false, std::string(), trans, nigori_node); | |
| 1118 return; | |
| 1119 } | |
| 1120 | |
| 1121 Cryptographer* cryptographer = | |
| 1122 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; | |
| 1123 if (cryptographer->has_pending_keys()) { | |
| 1124 // This theoretically shouldn't happen, because the only way to have pending | |
| 1125 // keys after migrating to keystore support is if a custom passphrase was | |
| 1126 // set, which should update passpshrase_state_ and should be caught by the | |
| 1127 // if statement above. For the sake of safety though, we check for it in | |
| 1128 // case a client is misbehaving. | |
| 1129 LOG(ERROR) << "Failing to set custom passphrase because of pending keys."; | |
| 1130 FinishSetPassphrase(false, std::string(), trans, nigori_node); | |
| 1131 return; | |
| 1132 } | |
| 1133 | |
| 1134 std::string bootstrap_token; | |
| 1135 if (!cryptographer->AddKey(key_params)) { | |
| 1136 NOTREACHED() << "Failed to add key to cryptographer."; | |
| 1137 return; | |
| 1138 } | |
| 1139 | |
| 1140 DVLOG(1) << "Setting custom passphrase."; | |
| 1141 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 1142 PassphraseType* passphrase_type = | |
| 1143 &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type; | |
| 1144 *passphrase_type = PassphraseType::CUSTOM_PASSPHRASE; | |
| 1145 custom_passphrase_time_ = base::Time::Now(); | |
| 1146 FOR_EACH_OBSERVER( | |
| 1147 SyncEncryptionHandler::Observer, observers_, | |
| 1148 OnPassphraseTypeChanged(*passphrase_type, | |
| 1149 GetExplicitPassphraseTime(*passphrase_type))); | |
| 1150 FinishSetPassphrase(true, bootstrap_token, trans, nigori_node); | |
| 1151 } | |
| 1152 | |
| 1153 void SyncEncryptionHandlerImpl::NotifyObserversOfLocalCustomPassphrase( | |
| 1154 WriteTransaction* trans) { | |
| 1155 WriteNode nigori_node(trans); | |
| 1156 BaseNode::InitByLookupResult init_result = nigori_node.InitTypeRoot(NIGORI); | |
| 1157 DCHECK_EQ(init_result, BaseNode::INIT_OK); | |
| 1158 NigoriState nigori_state; | |
| 1159 nigori_state.nigori_specifics = nigori_node.GetNigoriSpecifics(); | |
| 1160 DCHECK(nigori_state.nigori_specifics.passphrase_type() == | |
| 1161 sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE || | |
| 1162 nigori_state.nigori_specifics.passphrase_type() == | |
| 1163 sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE); | |
| 1164 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1165 OnLocalSetPassphraseEncryption(nigori_state)); | |
| 1166 } | |
| 1167 | |
| 1168 void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase( | |
| 1169 const std::string& passphrase, | |
| 1170 WriteTransaction* trans, | |
| 1171 WriteNode* nigori_node) { | |
| 1172 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1173 DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); | |
| 1174 KeyParams key_params = {"localhost", "dummy", passphrase}; | |
| 1175 | |
| 1176 Cryptographer* cryptographer = | |
| 1177 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; | |
| 1178 if (!cryptographer->has_pending_keys()) { | |
| 1179 // Note that this *can* happen in a rare situation where data is | |
| 1180 // re-encrypted on another client while a SetDecryptionPassphrase() call is | |
| 1181 // in-flight on this client. It is rare enough that we choose to do nothing. | |
| 1182 NOTREACHED() << "Attempt to set decryption passphrase failed because there " | |
| 1183 << "were no pending keys."; | |
| 1184 return; | |
| 1185 } | |
| 1186 | |
| 1187 DCHECK(IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); | |
| 1188 bool success = false; | |
| 1189 std::string bootstrap_token; | |
| 1190 if (cryptographer->DecryptPendingKeys(key_params)) { | |
| 1191 DVLOG(1) << "Explicit passphrase accepted for decryption."; | |
| 1192 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 1193 success = true; | |
| 1194 } else { | |
| 1195 DVLOG(1) << "Explicit passphrase failed to decrypt."; | |
| 1196 success = false; | |
| 1197 } | |
| 1198 if (success && !keystore_key_.empty()) { | |
| 1199 // Should already be part of the encryption keybag, but we add it just | |
| 1200 // in case. | |
| 1201 KeyParams key_params = {"localhost", "dummy", keystore_key_}; | |
| 1202 cryptographer->AddNonDefaultKey(key_params); | |
| 1203 } | |
| 1204 FinishSetPassphrase(success, bootstrap_token, trans, nigori_node); | |
| 1205 } | |
| 1206 | |
| 1207 void SyncEncryptionHandlerImpl::FinishSetPassphrase( | |
| 1208 bool success, | |
| 1209 const std::string& bootstrap_token, | |
| 1210 WriteTransaction* trans, | |
| 1211 WriteNode* nigori_node) { | |
| 1212 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1213 FOR_EACH_OBSERVER( | |
| 1214 SyncEncryptionHandler::Observer, observers_, | |
| 1215 OnCryptographerStateChanged( | |
| 1216 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); | |
| 1217 | |
| 1218 // It's possible we need to change the bootstrap token even if we failed to | |
| 1219 // set the passphrase (for example if we need to preserve the new GAIA | |
| 1220 // passphrase). | |
| 1221 if (!bootstrap_token.empty()) { | |
| 1222 DVLOG(1) << "Passphrase bootstrap token updated."; | |
| 1223 FOR_EACH_OBSERVER( | |
| 1224 SyncEncryptionHandler::Observer, observers_, | |
| 1225 OnBootstrapTokenUpdated(bootstrap_token, PASSPHRASE_BOOTSTRAP_TOKEN)); | |
| 1226 } | |
| 1227 | |
| 1228 const Cryptographer& cryptographer = | |
| 1229 UnlockVault(trans->GetWrappedTrans()).cryptographer; | |
| 1230 if (!success) { | |
| 1231 if (cryptographer.is_ready()) { | |
| 1232 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " | |
| 1233 << "was ready."; | |
| 1234 } else if (cryptographer.has_pending_keys()) { | |
| 1235 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1236 OnPassphraseRequired(REASON_DECRYPTION, | |
| 1237 cryptographer.GetPendingKeys())); | |
| 1238 } else { | |
| 1239 FOR_EACH_OBSERVER( | |
| 1240 SyncEncryptionHandler::Observer, observers_, | |
| 1241 OnPassphraseRequired(REASON_ENCRYPTION, sync_pb::EncryptedData())); | |
| 1242 } | |
| 1243 return; | |
| 1244 } | |
| 1245 DCHECK(success); | |
| 1246 DCHECK(cryptographer.is_ready()); | |
| 1247 | |
| 1248 // Will do nothing if we're already properly migrated or unable to migrate | |
| 1249 // (in otherwords, if ShouldTriggerMigration is false). | |
| 1250 // Otherwise will update the nigori node with the current migrated state, | |
| 1251 // writing all encryption state as it does. | |
| 1252 if (!AttemptToMigrateNigoriToKeystore(trans, nigori_node)) { | |
| 1253 sync_pb::NigoriSpecifics nigori(nigori_node->GetNigoriSpecifics()); | |
| 1254 // Does not modify nigori.encryption_keybag() if the original decrypted | |
| 1255 // data was the same. | |
| 1256 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag())) | |
| 1257 NOTREACHED(); | |
| 1258 if (IsNigoriMigratedToKeystore(nigori)) { | |
| 1259 DCHECK(keystore_key_.empty() || | |
| 1260 IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); | |
| 1261 DVLOG(1) << "Leaving nigori migration state untouched after setting" | |
| 1262 << " passphrase."; | |
| 1263 } else { | |
| 1264 nigori.set_keybag_is_frozen( | |
| 1265 IsExplicitPassphrase(GetPassphraseType(trans->GetWrappedTrans()))); | |
| 1266 } | |
| 1267 // If we set a new custom passphrase, store the timestamp. | |
| 1268 if (!custom_passphrase_time_.is_null()) { | |
| 1269 nigori.set_custom_passphrase_time( | |
| 1270 TimeToProtoTime(custom_passphrase_time_)); | |
| 1271 } | |
| 1272 nigori_node->SetNigoriSpecifics(nigori); | |
| 1273 } | |
| 1274 | |
| 1275 // Must do this after OnPassphraseTypeChanged, in order to ensure the PSS | |
| 1276 // checks the passphrase state after it has been set. | |
| 1277 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1278 OnPassphraseAccepted()); | |
| 1279 | |
| 1280 // Does nothing if everything is already encrypted. | |
| 1281 // TODO(zea): If we just migrated and enabled encryption, this will be | |
| 1282 // redundant. Figure out a way to not do this unnecessarily. | |
| 1283 ReEncryptEverything(trans); | |
| 1284 } | |
| 1285 | |
| 1286 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( | |
| 1287 ModelTypeSet new_encrypted_types, | |
| 1288 syncable::BaseTransaction* const trans) { | |
| 1289 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1290 | |
| 1291 // Only UserTypes may be encrypted. | |
| 1292 DCHECK(EncryptableUserTypes().HasAll(new_encrypted_types)); | |
| 1293 | |
| 1294 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; | |
| 1295 if (!encrypted_types->HasAll(new_encrypted_types)) { | |
| 1296 *encrypted_types = new_encrypted_types; | |
| 1297 FOR_EACH_OBSERVER( | |
| 1298 Observer, observers_, | |
| 1299 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | |
| 1300 } | |
| 1301 } | |
| 1302 | |
| 1303 SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable( | |
| 1304 syncable::BaseTransaction* const trans) { | |
| 1305 DCHECK_EQ(user_share_->directory.get(), trans->directory()); | |
| 1306 return &vault_unsafe_; | |
| 1307 } | |
| 1308 | |
| 1309 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( | |
| 1310 syncable::BaseTransaction* const trans) const { | |
| 1311 DCHECK_EQ(user_share_->directory.get(), trans->directory()); | |
| 1312 return vault_unsafe_; | |
| 1313 } | |
| 1314 | |
| 1315 bool SyncEncryptionHandlerImpl::ShouldTriggerMigration( | |
| 1316 const sync_pb::NigoriSpecifics& nigori, | |
| 1317 const Cryptographer& cryptographer, | |
| 1318 PassphraseType passphrase_type) const { | |
| 1319 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1320 // Don't migrate if there are pending encryption keys (because data | |
| 1321 // encrypted with the pending keys will not be decryptable). | |
| 1322 if (cryptographer.has_pending_keys()) | |
| 1323 return false; | |
| 1324 if (IsNigoriMigratedToKeystore(nigori)) { | |
| 1325 // If the nigori is already migrated but does not reflect the explicit | |
| 1326 // passphrase state, remigrate. Similarly, if the nigori has an explicit | |
| 1327 // passphrase but does not have full encryption, or the nigori has an | |
| 1328 // implicit passphrase but does have full encryption, re-migrate. | |
| 1329 // Note that this is to defend against other clients without keystore | |
| 1330 // encryption enabled transitioning to states that are no longer valid. | |
| 1331 if (passphrase_type != PassphraseType::KEYSTORE_PASSPHRASE && | |
| 1332 nigori.passphrase_type() == | |
| 1333 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { | |
| 1334 return true; | |
| 1335 } else if (IsExplicitPassphrase(passphrase_type) && !encrypt_everything_) { | |
| 1336 return true; | |
| 1337 } else if (passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE && | |
| 1338 encrypt_everything_) { | |
| 1339 return true; | |
| 1340 } else if (cryptographer.is_ready() && | |
| 1341 !cryptographer.CanDecryptUsingDefaultKey( | |
| 1342 nigori.encryption_keybag())) { | |
| 1343 // We need to overwrite the keybag. This might involve overwriting the | |
| 1344 // keystore decryptor too. | |
| 1345 return true; | |
| 1346 } else if (old_keystore_keys_.size() > 0 && !keystore_key_.empty()) { | |
| 1347 // Check to see if a server key rotation has happened, but the nigori | |
| 1348 // node's keys haven't been rotated yet, and hence we should re-migrate. | |
| 1349 // Note that once a key rotation has been performed, we no longer | |
| 1350 // preserve backwards compatibility, and the keybag will therefore be | |
| 1351 // encrypted with the current keystore key. | |
| 1352 Cryptographer temp_cryptographer(cryptographer.encryptor()); | |
| 1353 KeyParams keystore_params = {"localhost", "dummy", keystore_key_}; | |
| 1354 temp_cryptographer.AddKey(keystore_params); | |
| 1355 if (!temp_cryptographer.CanDecryptUsingDefaultKey( | |
| 1356 nigori.encryption_keybag())) { | |
| 1357 return true; | |
| 1358 } | |
| 1359 } | |
| 1360 return false; | |
| 1361 } else if (keystore_key_.empty()) { | |
| 1362 // If we haven't already migrated, we don't want to do anything unless | |
| 1363 // a keystore key is available (so that those clients without keystore | |
| 1364 // encryption enabled aren't forced into new states, e.g. frozen implicit | |
| 1365 // passphrase). | |
| 1366 return false; | |
| 1367 } | |
| 1368 return true; | |
| 1369 } | |
| 1370 | |
| 1371 bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore( | |
| 1372 WriteTransaction* trans, | |
| 1373 WriteNode* nigori_node) { | |
| 1374 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1375 const sync_pb::NigoriSpecifics& old_nigori = | |
| 1376 nigori_node->GetNigoriSpecifics(); | |
| 1377 Cryptographer* cryptographer = | |
| 1378 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; | |
| 1379 PassphraseType* passphrase_type = | |
| 1380 &UnlockVaultMutable(trans->GetWrappedTrans())->passphrase_type; | |
| 1381 if (!ShouldTriggerMigration(old_nigori, *cryptographer, *passphrase_type)) | |
| 1382 return false; | |
| 1383 | |
| 1384 DVLOG(1) << "Starting nigori migration to keystore support."; | |
| 1385 sync_pb::NigoriSpecifics migrated_nigori(old_nigori); | |
| 1386 | |
| 1387 PassphraseType new_passphrase_type = | |
| 1388 GetPassphraseType(trans->GetWrappedTrans()); | |
| 1389 bool new_encrypt_everything = encrypt_everything_; | |
| 1390 if (encrypt_everything_ && !IsExplicitPassphrase(*passphrase_type)) { | |
| 1391 DVLOG(1) << "Switching to frozen implicit passphrase due to already having " | |
| 1392 << "full encryption."; | |
| 1393 new_passphrase_type = PassphraseType::FROZEN_IMPLICIT_PASSPHRASE; | |
| 1394 migrated_nigori.clear_keystore_decryptor_token(); | |
| 1395 } else if (IsExplicitPassphrase(*passphrase_type)) { | |
| 1396 DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to " | |
| 1397 << "explicit passphrase"; | |
| 1398 new_encrypt_everything = true; | |
| 1399 migrated_nigori.clear_keystore_decryptor_token(); | |
| 1400 } else { | |
| 1401 DCHECK(!encrypt_everything_); | |
| 1402 new_passphrase_type = PassphraseType::KEYSTORE_PASSPHRASE; | |
| 1403 DVLOG(1) << "Switching to keystore passphrase state."; | |
| 1404 } | |
| 1405 migrated_nigori.set_encrypt_everything(new_encrypt_everything); | |
| 1406 migrated_nigori.set_passphrase_type( | |
| 1407 EnumPassphraseTypeToProto(new_passphrase_type)); | |
| 1408 migrated_nigori.set_keybag_is_frozen(true); | |
| 1409 | |
| 1410 if (!keystore_key_.empty()) { | |
| 1411 KeyParams key_params = {"localhost", "dummy", keystore_key_}; | |
| 1412 if ((old_keystore_keys_.size() > 0 && | |
| 1413 new_passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE) || | |
| 1414 !cryptographer->is_initialized()) { | |
| 1415 // Either at least one key rotation has been performed, so we no longer | |
| 1416 // care about backwards compatibility, or we're generating keystore-based | |
| 1417 // encryption keys without knowing the GAIA password (and therefore the | |
| 1418 // cryptographer is not initialized), so we can't support backwards | |
| 1419 // compatibility. Ensure the keystore key is the default key. | |
| 1420 DVLOG(1) << "Migrating keybag to keystore key."; | |
| 1421 bool cryptographer_was_ready = cryptographer->is_ready(); | |
| 1422 if (!cryptographer->AddKey(key_params)) { | |
| 1423 LOG(ERROR) << "Failed to add keystore key as default key"; | |
| 1424 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1425 FAILED_TO_SET_DEFAULT_KEYSTORE, | |
| 1426 MIGRATION_RESULT_SIZE); | |
| 1427 return false; | |
| 1428 } | |
| 1429 if (!cryptographer_was_ready && cryptographer->is_ready()) { | |
| 1430 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1431 OnPassphraseAccepted()); | |
| 1432 } | |
| 1433 } else { | |
| 1434 // We're in backwards compatible mode -- either the account has an | |
| 1435 // explicit passphrase, or we want to preserve the current GAIA-based key | |
| 1436 // as the default because we can (there have been no key rotations since | |
| 1437 // the migration). | |
| 1438 DVLOG(1) << "Migrating keybag while preserving old key"; | |
| 1439 if (!cryptographer->AddNonDefaultKey(key_params)) { | |
| 1440 LOG(ERROR) << "Failed to add keystore key as non-default key."; | |
| 1441 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1442 FAILED_TO_SET_NONDEFAULT_KEYSTORE, | |
| 1443 MIGRATION_RESULT_SIZE); | |
| 1444 return false; | |
| 1445 } | |
| 1446 } | |
| 1447 } | |
| 1448 if (!old_keystore_keys_.empty()) { | |
| 1449 // Go through and add all the old keystore keys as non default keys, so | |
| 1450 // they'll be preserved in the encryption_keybag when we next write the | |
| 1451 // nigori node. | |
| 1452 for (std::vector<std::string>::const_iterator iter = | |
| 1453 old_keystore_keys_.begin(); | |
| 1454 iter != old_keystore_keys_.end(); ++iter) { | |
| 1455 KeyParams key_params = {"localhost", "dummy", *iter}; | |
| 1456 cryptographer->AddNonDefaultKey(key_params); | |
| 1457 } | |
| 1458 } | |
| 1459 if (new_passphrase_type == PassphraseType::KEYSTORE_PASSPHRASE && | |
| 1460 !GetKeystoreDecryptor( | |
| 1461 *cryptographer, keystore_key_, | |
| 1462 migrated_nigori.mutable_keystore_decryptor_token())) { | |
| 1463 LOG(ERROR) << "Failed to extract keystore decryptor token."; | |
| 1464 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1465 FAILED_TO_EXTRACT_DECRYPTOR, | |
| 1466 MIGRATION_RESULT_SIZE); | |
| 1467 return false; | |
| 1468 } | |
| 1469 if (!cryptographer->GetKeys(migrated_nigori.mutable_encryption_keybag())) { | |
| 1470 LOG(ERROR) << "Failed to extract encryption keybag."; | |
| 1471 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1472 FAILED_TO_EXTRACT_KEYBAG, MIGRATION_RESULT_SIZE); | |
| 1473 return false; | |
| 1474 } | |
| 1475 | |
| 1476 if (migration_time_.is_null()) | |
| 1477 migration_time_ = base::Time::Now(); | |
| 1478 migrated_nigori.set_keystore_migration_time(TimeToProtoTime(migration_time_)); | |
| 1479 | |
| 1480 if (!custom_passphrase_time_.is_null()) { | |
| 1481 migrated_nigori.set_custom_passphrase_time( | |
| 1482 TimeToProtoTime(custom_passphrase_time_)); | |
| 1483 } | |
| 1484 | |
| 1485 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1486 OnCryptographerStateChanged(cryptographer)); | |
| 1487 if (*passphrase_type != new_passphrase_type) { | |
| 1488 *passphrase_type = new_passphrase_type; | |
| 1489 FOR_EACH_OBSERVER( | |
| 1490 SyncEncryptionHandler::Observer, observers_, | |
| 1491 OnPassphraseTypeChanged(*passphrase_type, | |
| 1492 GetExplicitPassphraseTime(*passphrase_type))); | |
| 1493 } | |
| 1494 | |
| 1495 if (new_encrypt_everything && !encrypt_everything_) { | |
| 1496 EnableEncryptEverythingImpl(trans->GetWrappedTrans()); | |
| 1497 ReEncryptEverything(trans); | |
| 1498 } else if (!cryptographer->CanDecryptUsingDefaultKey( | |
| 1499 old_nigori.encryption_keybag())) { | |
| 1500 DVLOG(1) << "Rencrypting everything due to key rotation."; | |
| 1501 ReEncryptEverything(trans); | |
| 1502 } | |
| 1503 | |
| 1504 DVLOG(1) << "Completing nigori migration to keystore support."; | |
| 1505 nigori_node->SetNigoriSpecifics(migrated_nigori); | |
| 1506 | |
| 1507 if (new_encrypt_everything && | |
| 1508 (new_passphrase_type == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE || | |
| 1509 new_passphrase_type == PassphraseType::CUSTOM_PASSPHRASE)) { | |
| 1510 NotifyObserversOfLocalCustomPassphrase(trans); | |
| 1511 } | |
| 1512 | |
| 1513 switch (new_passphrase_type) { | |
| 1514 case PassphraseType::KEYSTORE_PASSPHRASE: | |
| 1515 if (old_keystore_keys_.size() > 0) { | |
| 1516 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1517 MIGRATION_SUCCESS_KEYSTORE_NONDEFAULT, | |
| 1518 MIGRATION_RESULT_SIZE); | |
| 1519 } else { | |
| 1520 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1521 MIGRATION_SUCCESS_KEYSTORE_DEFAULT, | |
| 1522 MIGRATION_RESULT_SIZE); | |
| 1523 } | |
| 1524 break; | |
| 1525 case PassphraseType::FROZEN_IMPLICIT_PASSPHRASE: | |
| 1526 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1527 MIGRATION_SUCCESS_FROZEN_IMPLICIT, | |
| 1528 MIGRATION_RESULT_SIZE); | |
| 1529 break; | |
| 1530 case PassphraseType::CUSTOM_PASSPHRASE: | |
| 1531 UMA_HISTOGRAM_ENUMERATION("Sync.AttemptNigoriMigration", | |
| 1532 MIGRATION_SUCCESS_CUSTOM, | |
| 1533 MIGRATION_RESULT_SIZE); | |
| 1534 break; | |
| 1535 default: | |
| 1536 NOTREACHED(); | |
| 1537 break; | |
| 1538 } | |
| 1539 return true; | |
| 1540 } | |
| 1541 | |
| 1542 bool SyncEncryptionHandlerImpl::GetKeystoreDecryptor( | |
| 1543 const Cryptographer& cryptographer, | |
| 1544 const std::string& keystore_key, | |
| 1545 sync_pb::EncryptedData* encrypted_blob) { | |
| 1546 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1547 DCHECK(!keystore_key.empty()); | |
| 1548 DCHECK(cryptographer.is_ready()); | |
| 1549 std::string serialized_nigori; | |
| 1550 serialized_nigori = cryptographer.GetDefaultNigoriKeyData(); | |
| 1551 if (serialized_nigori.empty()) { | |
| 1552 LOG(ERROR) << "Failed to get cryptographer bootstrap token."; | |
| 1553 return false; | |
| 1554 } | |
| 1555 Cryptographer temp_cryptographer(cryptographer.encryptor()); | |
| 1556 KeyParams key_params = {"localhost", "dummy", keystore_key}; | |
| 1557 if (!temp_cryptographer.AddKey(key_params)) | |
| 1558 return false; | |
| 1559 if (!temp_cryptographer.EncryptString(serialized_nigori, encrypted_blob)) | |
| 1560 return false; | |
| 1561 return true; | |
| 1562 } | |
| 1563 | |
| 1564 bool SyncEncryptionHandlerImpl::AttemptToInstallKeybag( | |
| 1565 const sync_pb::EncryptedData& keybag, | |
| 1566 bool update_default, | |
| 1567 Cryptographer* cryptographer) { | |
| 1568 if (!cryptographer->CanDecrypt(keybag)) | |
| 1569 return false; | |
| 1570 cryptographer->InstallKeys(keybag); | |
| 1571 if (update_default) | |
| 1572 cryptographer->SetDefaultKey(keybag.key_name()); | |
| 1573 return true; | |
| 1574 } | |
| 1575 | |
| 1576 void SyncEncryptionHandlerImpl::EnableEncryptEverythingImpl( | |
| 1577 syncable::BaseTransaction* const trans) { | |
| 1578 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; | |
| 1579 if (encrypt_everything_) { | |
| 1580 DCHECK_EQ(EncryptableUserTypes(), *encrypted_types); | |
| 1581 return; | |
| 1582 } | |
| 1583 encrypt_everything_ = true; | |
| 1584 *encrypted_types = EncryptableUserTypes(); | |
| 1585 FOR_EACH_OBSERVER( | |
| 1586 Observer, observers_, | |
| 1587 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | |
| 1588 } | |
| 1589 | |
| 1590 bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey( | |
| 1591 const sync_pb::EncryptedData& keystore_decryptor_token, | |
| 1592 Cryptographer* cryptographer) { | |
| 1593 DCHECK(cryptographer->has_pending_keys()); | |
| 1594 if (keystore_decryptor_token.blob().empty()) | |
| 1595 return false; | |
| 1596 Cryptographer temp_cryptographer(cryptographer->encryptor()); | |
| 1597 | |
| 1598 // First, go through and all all the old keystore keys to the temporary | |
| 1599 // cryptographer. | |
| 1600 for (size_t i = 0; i < old_keystore_keys_.size(); ++i) { | |
| 1601 KeyParams old_key_params = {"localhost", "dummy", old_keystore_keys_[i]}; | |
| 1602 temp_cryptographer.AddKey(old_key_params); | |
| 1603 } | |
| 1604 | |
| 1605 // Then add the current keystore key as the default key and see if we can | |
| 1606 // decrypt. | |
| 1607 KeyParams keystore_params = {"localhost", "dummy", keystore_key_}; | |
| 1608 if (temp_cryptographer.AddKey(keystore_params) && | |
| 1609 temp_cryptographer.CanDecrypt(keystore_decryptor_token)) { | |
| 1610 // Someone else migrated the nigori for us! How generous! Go ahead and | |
| 1611 // install both the keystore key and the new default encryption key | |
| 1612 // (i.e. the one provided by the keystore decryptor token) into the | |
| 1613 // cryptographer. | |
| 1614 // The keystore decryptor token is a keystore key encrypted blob containing | |
| 1615 // the current serialized default encryption key (and as such should be | |
| 1616 // able to decrypt the nigori node's encryption keybag). | |
| 1617 // Note: it's possible a key rotation has happened since the migration, and | |
| 1618 // we're decrypting using an old keystore key. In that case we need to | |
| 1619 // ensure we re-encrypt using the newest key. | |
| 1620 DVLOG(1) << "Attempting to decrypt pending keys using " | |
| 1621 << "keystore decryptor token."; | |
| 1622 std::string serialized_nigori = | |
| 1623 temp_cryptographer.DecryptToString(keystore_decryptor_token); | |
| 1624 | |
| 1625 // This will decrypt the pending keys and add them if possible. The key | |
| 1626 // within |serialized_nigori| will be the default after. | |
| 1627 cryptographer->ImportNigoriKey(serialized_nigori); | |
| 1628 | |
| 1629 if (!temp_cryptographer.CanDecryptUsingDefaultKey( | |
| 1630 keystore_decryptor_token)) { | |
| 1631 // The keystore decryptor token was derived from an old keystore key. | |
| 1632 // A key rotation is necessary, so set the current keystore key as the | |
| 1633 // default key (which will trigger a re-migration). | |
| 1634 DVLOG(1) << "Pending keys based on old keystore key. Setting newest " | |
| 1635 << "keystore key as default."; | |
| 1636 cryptographer->AddKey(keystore_params); | |
| 1637 } else { | |
| 1638 // Theoretically the encryption keybag should already contain the keystore | |
| 1639 // key. We explicitly add it as a safety measure. | |
| 1640 DVLOG(1) << "Pending keys based on newest keystore key."; | |
| 1641 cryptographer->AddNonDefaultKey(keystore_params); | |
| 1642 } | |
| 1643 if (cryptographer->is_ready()) { | |
| 1644 std::string bootstrap_token; | |
| 1645 cryptographer->GetBootstrapToken(&bootstrap_token); | |
| 1646 DVLOG(1) << "Keystore decryptor token decrypted pending keys."; | |
| 1647 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1648 OnPassphraseAccepted()); | |
| 1649 FOR_EACH_OBSERVER( | |
| 1650 SyncEncryptionHandler::Observer, observers_, | |
| 1651 OnBootstrapTokenUpdated(bootstrap_token, PASSPHRASE_BOOTSTRAP_TOKEN)); | |
| 1652 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 1653 OnCryptographerStateChanged(cryptographer)); | |
| 1654 return true; | |
| 1655 } | |
| 1656 } | |
| 1657 return false; | |
| 1658 } | |
| 1659 | |
| 1660 base::Time SyncEncryptionHandlerImpl::GetExplicitPassphraseTime( | |
| 1661 PassphraseType passphrase_type) const { | |
| 1662 if (passphrase_type == PassphraseType::FROZEN_IMPLICIT_PASSPHRASE) | |
| 1663 return migration_time(); | |
| 1664 else if (passphrase_type == PassphraseType::CUSTOM_PASSPHRASE) | |
| 1665 return custom_passphrase_time(); | |
| 1666 return base::Time(); | |
| 1667 } | |
| 1668 | |
| 1669 } // namespace syncer | |
| OLD | NEW |