| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "sync/internal_api/sync_encryption_handler_impl.h" | 5 #include "sync/internal_api/sync_encryption_handler_impl.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
| 12 #include "base/time.h" |
| 12 #include "base/tracked_objects.h" | 13 #include "base/tracked_objects.h" |
| 13 #include "base/metrics/histogram.h" | 14 #include "base/metrics/histogram.h" |
| 14 #include "sync/internal_api/public/read_node.h" | 15 #include "sync/internal_api/public/read_node.h" |
| 15 #include "sync/internal_api/public/read_transaction.h" | 16 #include "sync/internal_api/public/read_transaction.h" |
| 16 #include "sync/internal_api/public/user_share.h" | 17 #include "sync/internal_api/public/user_share.h" |
| 17 #include "sync/internal_api/public/util/experiments.h" | 18 #include "sync/internal_api/public/util/experiments.h" |
| 18 #include "sync/internal_api/public/write_node.h" | 19 #include "sync/internal_api/public/write_node.h" |
| 19 #include "sync/internal_api/public/write_transaction.h" | 20 #include "sync/internal_api/public/write_transaction.h" |
| 21 #include "sync/internal_api/public/util/sync_string_conversions.h" |
| 20 #include "sync/protocol/encryption.pb.h" | 22 #include "sync/protocol/encryption.pb.h" |
| 21 #include "sync/protocol/nigori_specifics.pb.h" | 23 #include "sync/protocol/nigori_specifics.pb.h" |
| 22 #include "sync/protocol/sync.pb.h" | 24 #include "sync/protocol/sync.pb.h" |
| 23 #include "sync/syncable/base_transaction.h" | 25 #include "sync/syncable/base_transaction.h" |
| 24 #include "sync/syncable/directory.h" | 26 #include "sync/syncable/directory.h" |
| 25 #include "sync/syncable/entry.h" | 27 #include "sync/syncable/entry.h" |
| 26 #include "sync/syncable/nigori_util.h" | 28 #include "sync/syncable/nigori_util.h" |
| 27 #include "sync/util/cryptographer.h" | 29 #include "sync/util/cryptographer.h" |
| 30 #include "sync/util/time.h" |
| 28 | 31 |
| 29 namespace syncer { | 32 namespace syncer { |
| 30 | 33 |
| 31 namespace { | 34 namespace { |
| 35 |
| 32 // The maximum number of times we will automatically overwrite the nigori node | 36 // The maximum number of times we will automatically overwrite the nigori node |
| 33 // because the encryption keys don't match (per chrome instantiation). | 37 // because the encryption keys don't match (per chrome instantiation). |
| 34 // We protect ourselves against nigori rollbacks, but it's possible two | 38 // We protect ourselves against nigori rollbacks, but it's possible two |
| 35 // different clients might have contrasting view of what the nigori node state | 39 // different clients might have contrasting view of what the nigori node state |
| 36 // should be, in which case they might ping pong (see crbug.com/119207). | 40 // should be, in which case they might ping pong (see crbug.com/119207). |
| 37 static const int kNigoriOverwriteLimit = 10; | 41 static const int kNigoriOverwriteLimit = 10; |
| 42 |
| 43 // The new passphrase state is sufficient to determine whether a nigori node |
| 44 // is migrated to support keystore encryption. In addition though, we also |
| 45 // want to verify the conditions for proper keystore encryption functionality. |
| 46 // 1. Passphrase state is set. |
| 47 // 2. Migration time is set. |
| 48 // 3. Frozen keybag is true |
| 49 // 4. If passphrase state is keystore, keystore_decryptor_token is set. |
| 50 bool IsNigoriMigratedToKeystore(const sync_pb::NigoriSpecifics& nigori) { |
| 51 if (!nigori.has_passphrase_type()) |
| 52 return false; |
| 53 if (!nigori.has_keystore_migration_time()) |
| 54 return false; |
| 55 if (!nigori.keybag_is_frozen()) |
| 56 return false; |
| 57 if (nigori.passphrase_type() == |
| 58 sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE) |
| 59 return false; |
| 60 if (nigori.passphrase_type() == |
| 61 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE && |
| 62 nigori.keystore_decryptor_token().blob().empty()) |
| 63 return false; |
| 64 if (!nigori.has_keystore_migration_time()) |
| 65 return false; |
| 66 return true; |
| 38 } | 67 } |
| 39 | 68 |
| 69 PassphraseType ProtoPassphraseTypeToEnum( |
| 70 sync_pb::NigoriSpecifics::PassphraseType type) { |
| 71 switch(type) { |
| 72 case sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE: |
| 73 return IMPLICIT_PASSPHRASE; |
| 74 case sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE: |
| 75 return KEYSTORE_PASSPHRASE; |
| 76 case sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE: |
| 77 return CUSTOM_PASSPHRASE; |
| 78 case sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE: |
| 79 return FROZEN_IMPLICIT_PASSPHRASE; |
| 80 default: |
| 81 NOTREACHED(); |
| 82 return IMPLICIT_PASSPHRASE; |
| 83 }; |
| 84 } |
| 85 |
| 86 sync_pb::NigoriSpecifics::PassphraseType |
| 87 EnumPassphraseTypeToProto(PassphraseType type) { |
| 88 switch(type) { |
| 89 case IMPLICIT_PASSPHRASE: |
| 90 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE; |
| 91 case KEYSTORE_PASSPHRASE: |
| 92 return sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE; |
| 93 case CUSTOM_PASSPHRASE: |
| 94 return sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE; |
| 95 case FROZEN_IMPLICIT_PASSPHRASE: |
| 96 return sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE; |
| 97 default: |
| 98 NOTREACHED(); |
| 99 return sync_pb::NigoriSpecifics::IMPLICIT_PASSPHRASE;; |
| 100 }; |
| 101 } |
| 102 |
| 103 bool IsExplicitPassphrase(PassphraseType type) { |
| 104 return type == CUSTOM_PASSPHRASE || type == FROZEN_IMPLICIT_PASSPHRASE; |
| 105 } |
| 106 |
| 107 } // namespace |
| 108 |
| 40 SyncEncryptionHandlerImpl::Vault::Vault( | 109 SyncEncryptionHandlerImpl::Vault::Vault( |
| 41 Encryptor* encryptor, | 110 Encryptor* encryptor, |
| 42 ModelTypeSet encrypted_types) | 111 ModelTypeSet encrypted_types) |
| 43 : cryptographer(encryptor), | 112 : cryptographer(encryptor), |
| 44 encrypted_types(encrypted_types) { | 113 encrypted_types(encrypted_types) { |
| 45 } | 114 } |
| 46 | 115 |
| 47 SyncEncryptionHandlerImpl::Vault::~Vault() { | 116 SyncEncryptionHandlerImpl::Vault::~Vault() { |
| 48 } | 117 } |
| 49 | 118 |
| 50 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( | 119 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( |
| 51 UserShare* user_share, | 120 UserShare* user_share, |
| 52 Encryptor* encryptor, | 121 Encryptor* encryptor, |
| 53 const std::string& restored_key_for_bootstrapping, | 122 const std::string& restored_key_for_bootstrapping, |
| 54 const std::string& restored_keystore_key_for_bootstrapping) | 123 const std::string& restored_keystore_key_for_bootstrapping) |
| 55 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 124 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 56 user_share_(user_share), | 125 user_share_(user_share), |
| 57 vault_unsafe_(encryptor, SensitiveTypes()), | 126 vault_unsafe_(encryptor, SensitiveTypes()), |
| 58 encrypt_everything_(false), | 127 encrypt_everything_(false), |
| 59 passphrase_state_(IMPLICIT_PASSPHRASE), | 128 passphrase_type_(IMPLICIT_PASSPHRASE), |
| 60 keystore_key_(restored_keystore_key_for_bootstrapping), | 129 keystore_key_(restored_keystore_key_for_bootstrapping), |
| 61 nigori_overwrite_count_(0) { | 130 nigori_overwrite_count_(0), |
| 131 migration_time_ms_(0) { |
| 62 // We only bootstrap the user provided passphrase. The keystore key is handled | 132 // We only bootstrap the user provided passphrase. The keystore key is handled |
| 63 // at Init time once we're sure the nigori is downloaded. | 133 // at Init time once we're sure the nigori is downloaded. |
| 64 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping); | 134 vault_unsafe_.cryptographer.Bootstrap(restored_key_for_bootstrapping); |
| 65 } | 135 } |
| 66 | 136 |
| 67 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} | 137 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} |
| 68 | 138 |
| 69 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { | 139 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { |
| 70 DCHECK(thread_checker_.CalledOnValidThread()); | 140 DCHECK(thread_checker_.CalledOnValidThread()); |
| 71 DCHECK(!observers_.HasObserver(observer)); | 141 DCHECK(!observers_.HasObserver(observer)); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 123 | 193 |
| 124 // All accesses to the cryptographer are protected by a transaction. | 194 // All accesses to the cryptographer are protected by a transaction. |
| 125 WriteTransaction trans(FROM_HERE, user_share_); | 195 WriteTransaction trans(FROM_HERE, user_share_); |
| 126 KeyParams key_params = {"localhost", "dummy", passphrase}; | 196 KeyParams key_params = {"localhost", "dummy", passphrase}; |
| 127 WriteNode node(&trans); | 197 WriteNode node(&trans); |
| 128 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | 198 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { |
| 129 NOTREACHED(); | 199 NOTREACHED(); |
| 130 return; | 200 return; |
| 131 } | 201 } |
| 132 | 202 |
| 133 bool nigori_has_explicit_passphrase = | 203 Cryptographer* cryptographer = |
| 134 node.GetNigoriSpecifics().using_explicit_passphrase(); | 204 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; |
| 205 |
| 206 // Once we've migrated to keystore, the only way to set a passphrase for |
| 207 // encryption is to set a custom passphrase. |
| 208 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics())) { |
| 209 if (!is_explicit) { |
| 210 DCHECK(cryptographer->is_ready()); |
| 211 // The user is setting a new implicit passphrase. At this point we don't |
| 212 // care, so drop it on the floor. This is safe because if we have a |
| 213 // migrated nigori node, then we don't need to create an initial |
| 214 // encryption key. |
| 215 LOG(WARNING) << "Ignoring new implicit passphrase. Keystore migration " |
| 216 << "already performed."; |
| 217 return; |
| 218 } |
| 219 // Will fail if we already have an explicit passphrase or we have pending |
| 220 // keys. |
| 221 SetCustomPassphrase(passphrase, &trans, &node); |
| 222 return; |
| 223 } |
| 224 |
| 135 std::string bootstrap_token; | 225 std::string bootstrap_token; |
| 136 sync_pb::EncryptedData pending_keys; | 226 sync_pb::EncryptedData pending_keys; |
| 137 Cryptographer* cryptographer = | |
| 138 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; | |
| 139 if (cryptographer->has_pending_keys()) | 227 if (cryptographer->has_pending_keys()) |
| 140 pending_keys = cryptographer->GetPendingKeys(); | 228 pending_keys = cryptographer->GetPendingKeys(); |
| 141 bool success = false; | 229 bool success = false; |
| 142 | 230 |
| 143 // There are six cases to handle here: | 231 // There are six cases to handle here: |
| 144 // 1. The user has no pending keys and is setting their current GAIA password | 232 // 1. The user has no pending keys and is setting their current GAIA password |
| 145 // as the encryption passphrase. This happens either during first time sync | 233 // as the encryption passphrase. This happens either during first time sync |
| 146 // with a clean profile, or after re-authenticating on a profile that was | 234 // with a clean profile, or after re-authenticating on a profile that was |
| 147 // already signed in with the cryptographer ready. | 235 // already signed in with the cryptographer ready. |
| 148 // 2. The user has no pending keys, and is overwriting an (already provided) | 236 // 2. The user has no pending keys, and is overwriting an (already provided) |
| 149 // implicit passphrase with an explicit (custom) passphrase. | 237 // implicit passphrase with an explicit (custom) passphrase. |
| 150 // 3. The user has pending keys for an explicit passphrase that is somehow set | 238 // 3. The user has pending keys for an explicit passphrase that is somehow set |
| 151 // to their current GAIA passphrase. | 239 // to their current GAIA passphrase. |
| 152 // 4. The user has pending keys encrypted with their current GAIA passphrase | 240 // 4. The user has pending keys encrypted with their current GAIA passphrase |
| 153 // and the caller passes in the current GAIA passphrase. | 241 // and the caller passes in the current GAIA passphrase. |
| 154 // 5. The user has pending keys encrypted with an older GAIA passphrase | 242 // 5. The user has pending keys encrypted with an older GAIA passphrase |
| 155 // and the caller passes in the current GAIA passphrase. | 243 // and the caller passes in the current GAIA passphrase. |
| 156 // 6. The user has previously done encryption with an explicit passphrase. | 244 // 6. The user has previously done encryption with an explicit passphrase. |
| 157 // Furthermore, we enforce the fact that the bootstrap encryption token will | 245 // Furthermore, we enforce the fact that the bootstrap encryption token will |
| 158 // always be derived from the newest GAIA password if the account is using | 246 // always be derived from the newest GAIA password if the account is using |
| 159 // an implicit passphrase (even if the data is encrypted with an old GAIA | 247 // an implicit passphrase (even if the data is encrypted with an old GAIA |
| 160 // password). If the account is using an explicit (custom) passphrase, the | 248 // password). If the account is using an explicit (custom) passphrase, the |
| 161 // bootstrap token will be derived from the most recently provided explicit | 249 // bootstrap token will be derived from the most recently provided explicit |
| 162 // passphrase (that was able to decrypt the data). | 250 // passphrase (that was able to decrypt the data). |
| 163 if (!nigori_has_explicit_passphrase) { | 251 if (!IsExplicitPassphrase(passphrase_type_)) { |
| 164 if (!cryptographer->has_pending_keys()) { | 252 if (!cryptographer->has_pending_keys()) { |
| 165 if (cryptographer->AddKey(key_params)) { | 253 if (cryptographer->AddKey(key_params)) { |
| 166 // Case 1 and 2. We set a new GAIA passphrase when there are no pending | 254 // Case 1 and 2. We set a new GAIA passphrase when there are no pending |
| 167 // keys (1), or overwriting an implicit passphrase with a new explicit | 255 // keys (1), or overwriting an implicit passphrase with a new explicit |
| 168 // one (2) when there are no pending keys. | 256 // one (2) when there are no pending keys. |
| 169 DVLOG(1) << "Setting " << (is_explicit ? "explicit" : "implicit" ) | 257 if (is_explicit) { |
| 170 << " passphrase for encryption."; | 258 DVLOG(1) << "Setting explicit passphrase for encryption."; |
| 259 passphrase_type_ = CUSTOM_PASSPHRASE; |
| 260 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 261 OnPassphraseTypeChanged(passphrase_type_)); |
| 262 } else { |
| 263 DVLOG(1) << "Setting implicit passphrase for encryption."; |
| 264 } |
| 171 cryptographer->GetBootstrapToken(&bootstrap_token); | 265 cryptographer->GetBootstrapToken(&bootstrap_token); |
| 172 success = true; | 266 success = true; |
| 173 } else { | 267 } else { |
| 174 NOTREACHED() << "Failed to add key to cryptographer."; | 268 NOTREACHED() << "Failed to add key to cryptographer."; |
| 175 success = false; | 269 success = false; |
| 176 } | 270 } |
| 177 } else { // cryptographer->has_pending_keys() == true | 271 } else { // cryptographer->has_pending_keys() == true |
| 178 if (is_explicit) { | 272 if (is_explicit) { |
| 179 // This can only happen if the nigori node is updated with a new | 273 // This can only happen if the nigori node is updated with a new |
| 180 // implicit passphrase while a client is attempting to set a new custom | 274 // implicit passphrase while a client is attempting to set a new custom |
| (...skipping 21 matching lines...) Expand all Loading... |
| 202 temp_cryptographer.GetBootstrapToken(&bootstrap_token); | 296 temp_cryptographer.GetBootstrapToken(&bootstrap_token); |
| 203 // We then set the new passphrase as the default passphrase of the | 297 // We then set the new passphrase as the default passphrase of the |
| 204 // real cryptographer, even though we have pending keys. This is safe, | 298 // real cryptographer, even though we have pending keys. This is safe, |
| 205 // as although Cryptographer::is_initialized() will now be true, | 299 // as although Cryptographer::is_initialized() will now be true, |
| 206 // is_ready() will remain false due to having pending keys. | 300 // is_ready() will remain false due to having pending keys. |
| 207 cryptographer->AddKey(key_params); | 301 cryptographer->AddKey(key_params); |
| 208 success = false; | 302 success = false; |
| 209 } | 303 } |
| 210 } // is_explicit | 304 } // is_explicit |
| 211 } // cryptographer->has_pending_keys() | 305 } // cryptographer->has_pending_keys() |
| 212 } else { // nigori_has_explicit_passphrase == true | 306 } else { // IsExplicitPassphrase(passphrase_type_) == true. |
| 213 // Case 6. We do not want to override a previously set explicit passphrase, | 307 // Case 6. We do not want to override a previously set explicit passphrase, |
| 214 // so we return a failure. | 308 // so we return a failure. |
| 215 DVLOG(1) << "Failing because an explicit passphrase is already set."; | 309 DVLOG(1) << "Failing because an explicit passphrase is already set."; |
| 216 success = false; | 310 success = false; |
| 217 } | 311 } |
| 218 | 312 |
| 219 DVLOG_IF(1, !success) | 313 DVLOG_IF(1, !success) |
| 220 << "Failure in SetEncryptionPassphrase; notifying and returning."; | 314 << "Failure in SetEncryptionPassphrase; notifying and returning."; |
| 221 DVLOG_IF(1, success) | 315 DVLOG_IF(1, success) |
| 222 << "Successfully set encryption passphrase; updating nigori and " | 316 << "Successfully set encryption passphrase; updating nigori and " |
| 223 "reencrypting."; | 317 "reencrypting."; |
| 224 | 318 |
| 225 FinishSetPassphrase( | 319 FinishSetPassphrase(success, bootstrap_token, &trans, &node); |
| 226 success, bootstrap_token, is_explicit, &trans, &node); | |
| 227 } | 320 } |
| 228 | 321 |
| 229 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( | 322 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( |
| 230 const std::string& passphrase) { | 323 const std::string& passphrase) { |
| 231 DCHECK(thread_checker_.CalledOnValidThread()); | 324 DCHECK(thread_checker_.CalledOnValidThread()); |
| 232 // We do not accept empty passphrases. | 325 // We do not accept empty passphrases. |
| 233 if (passphrase.empty()) { | 326 if (passphrase.empty()) { |
| 234 NOTREACHED() << "Cannot decrypt with an empty passphrase."; | 327 NOTREACHED() << "Cannot decrypt with an empty passphrase."; |
| 235 return; | 328 return; |
| 236 } | 329 } |
| 237 | 330 |
| 238 // All accesses to the cryptographer are protected by a transaction. | 331 // All accesses to the cryptographer are protected by a transaction. |
| 239 WriteTransaction trans(FROM_HERE, user_share_); | 332 WriteTransaction trans(FROM_HERE, user_share_); |
| 240 KeyParams key_params = {"localhost", "dummy", passphrase}; | 333 KeyParams key_params = {"localhost", "dummy", passphrase}; |
| 241 WriteNode node(&trans); | 334 WriteNode node(&trans); |
| 242 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { | 335 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { |
| 243 NOTREACHED(); | 336 NOTREACHED(); |
| 244 return; | 337 return; |
| 245 } | 338 } |
| 246 | 339 |
| 340 // Once we've migrated to keystore, we're only ever decrypting keys derived |
| 341 // from an explicit passphrase. But, for clients without a keystore key yet |
| 342 // (either not on by default or failed to download one), we still support |
| 343 // decrypting with a gaia passphrase, and therefore bypass the |
| 344 // DecryptPendingKeysWithExplicitPassphrase logic. |
| 345 if (IsNigoriMigratedToKeystore(node.GetNigoriSpecifics()) && |
| 346 IsExplicitPassphrase(passphrase_type_)) { |
| 347 DecryptPendingKeysWithExplicitPassphrase(passphrase, &trans, &node); |
| 348 return; |
| 349 } |
| 350 |
| 247 Cryptographer* cryptographer = | 351 Cryptographer* cryptographer = |
| 248 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; | 352 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer; |
| 249 if (!cryptographer->has_pending_keys()) { | 353 if (!cryptographer->has_pending_keys()) { |
| 250 // Note that this *can* happen in a rare situation where data is | 354 // Note that this *can* happen in a rare situation where data is |
| 251 // re-encrypted on another client while a SetDecryptionPassphrase() call is | 355 // re-encrypted on another client while a SetDecryptionPassphrase() call is |
| 252 // in-flight on this client. It is rare enough that we choose to do nothing. | 356 // in-flight on this client. It is rare enough that we choose to do nothing. |
| 253 NOTREACHED() << "Attempt to set decryption passphrase failed because there " | 357 NOTREACHED() << "Attempt to set decryption passphrase failed because there " |
| 254 << "were no pending keys."; | 358 << "were no pending keys."; |
| 255 return; | 359 return; |
| 256 } | 360 } |
| 257 | 361 |
| 258 bool nigori_has_explicit_passphrase = | |
| 259 node.GetNigoriSpecifics().using_explicit_passphrase(); | |
| 260 std::string bootstrap_token; | 362 std::string bootstrap_token; |
| 261 sync_pb::EncryptedData pending_keys; | 363 sync_pb::EncryptedData pending_keys; |
| 262 pending_keys = cryptographer->GetPendingKeys(); | 364 pending_keys = cryptographer->GetPendingKeys(); |
| 263 bool success = false; | 365 bool success = false; |
| 264 | 366 |
| 265 // There are three cases to handle here: | 367 // There are three cases to handle here: |
| 266 // 7. We're using the current GAIA password to decrypt the pending keys. This | 368 // 7. We're using the current GAIA password to decrypt the pending keys. This |
| 267 // happens when signing in to an account with a previously set implicit | 369 // happens when signing in to an account with a previously set implicit |
| 268 // passphrase, where the data is already encrypted with the newest GAIA | 370 // passphrase, where the data is already encrypted with the newest GAIA |
| 269 // password. | 371 // password. |
| 270 // 8. The user is providing an old GAIA password to decrypt the pending keys. | 372 // 8. The user is providing an old GAIA password to decrypt the pending keys. |
| 271 // In this case, the user is using an implicit passphrase, but has changed | 373 // In this case, the user is using an implicit passphrase, but has changed |
| 272 // their password since they last encrypted their data, and therefore | 374 // their password since they last encrypted their data, and therefore |
| 273 // their current GAIA password was unable to decrypt the data. This will | 375 // their current GAIA password was unable to decrypt the data. This will |
| 274 // happen when the user is setting up a new profile with a previously | 376 // happen when the user is setting up a new profile with a previously |
| 275 // encrypted account (after changing passwords). | 377 // encrypted account (after changing passwords). |
| 276 // 9. The user is providing a previously set explicit passphrase to decrypt | 378 // 9. The user is providing a previously set explicit passphrase to decrypt |
| 277 // the pending keys. | 379 // the pending keys. |
| 278 if (!nigori_has_explicit_passphrase) { | 380 if (!IsExplicitPassphrase(passphrase_type_)) { |
| 279 if (cryptographer->is_initialized()) { | 381 if (cryptographer->is_initialized()) { |
| 280 // We only want to change the default encryption key to the pending | 382 // We only want to change the default encryption key to the pending |
| 281 // one if the pending keybag already contains the current default. | 383 // one if the pending keybag already contains the current default. |
| 282 // This covers the case where a different client re-encrypted | 384 // This covers the case where a different client re-encrypted |
| 283 // everything with a newer gaia passphrase (and hence the keybag | 385 // everything with a newer gaia passphrase (and hence the keybag |
| 284 // contains keys from all previously used gaia passphrases). | 386 // contains keys from all previously used gaia passphrases). |
| 285 // Otherwise, we're in a situation where the pending keys are | 387 // Otherwise, we're in a situation where the pending keys are |
| 286 // encrypted with an old gaia passphrase, while the default is the | 388 // encrypted with an old gaia passphrase, while the default is the |
| 287 // current gaia passphrase. In that case, we preserve the default. | 389 // current gaia passphrase. In that case, we preserve the default. |
| 288 Cryptographer temp_cryptographer(cryptographer->encryptor()); | 390 Cryptographer temp_cryptographer(cryptographer->encryptor()); |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 355 success = false; | 457 success = false; |
| 356 } | 458 } |
| 357 } // nigori_has_explicit_passphrase | 459 } // nigori_has_explicit_passphrase |
| 358 | 460 |
| 359 DVLOG_IF(1, !success) | 461 DVLOG_IF(1, !success) |
| 360 << "Failure in SetDecryptionPassphrase; notifying and returning."; | 462 << "Failure in SetDecryptionPassphrase; notifying and returning."; |
| 361 DVLOG_IF(1, success) | 463 DVLOG_IF(1, success) |
| 362 << "Successfully set decryption passphrase; updating nigori and " | 464 << "Successfully set decryption passphrase; updating nigori and " |
| 363 "reencrypting."; | 465 "reencrypting."; |
| 364 | 466 |
| 365 FinishSetPassphrase(success, | 467 FinishSetPassphrase(success, bootstrap_token, &trans, &node); |
| 366 bootstrap_token, | |
| 367 nigori_has_explicit_passphrase, | |
| 368 &trans, | |
| 369 &node); | |
| 370 } | 468 } |
| 371 | 469 |
| 372 void SyncEncryptionHandlerImpl::EnableEncryptEverything() { | 470 void SyncEncryptionHandlerImpl::EnableEncryptEverything() { |
| 373 DCHECK(thread_checker_.CalledOnValidThread()); | 471 DCHECK(thread_checker_.CalledOnValidThread()); |
| 374 WriteTransaction trans(FROM_HERE, user_share_); | 472 WriteTransaction trans(FROM_HERE, user_share_); |
| 375 ModelTypeSet* encrypted_types = | 473 DVLOG(1) << "Enabling encrypt everything."; |
| 376 &UnlockVaultMutable(trans.GetWrappedTrans())->encrypted_types; | 474 if (encrypt_everything_) |
| 377 if (encrypt_everything_) { | |
| 378 DCHECK(encrypted_types->Equals(UserTypes())); | |
| 379 return; | 475 return; |
| 380 } | 476 EnableEncryptEverythingImpl(trans.GetWrappedTrans()); |
| 381 DVLOG(1) << "Enabling encrypt everything."; | |
| 382 encrypt_everything_ = true; | |
| 383 // Change |encrypted_types_| directly to avoid sending more than one | |
| 384 // notification. | |
| 385 *encrypted_types = UserTypes(); | |
| 386 FOR_EACH_OBSERVER( | |
| 387 Observer, observers_, | |
| 388 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | |
| 389 WriteEncryptionStateToNigori(&trans); | 477 WriteEncryptionStateToNigori(&trans); |
| 390 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) | 478 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) |
| 391 ReEncryptEverything(&trans); | 479 ReEncryptEverything(&trans); |
| 392 } | 480 } |
| 393 | 481 |
| 394 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { | 482 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { |
| 395 DCHECK(thread_checker_.CalledOnValidThread()); | 483 DCHECK(thread_checker_.CalledOnValidThread()); |
| 396 return encrypt_everything_; | 484 return encrypt_everything_; |
| 397 } | 485 } |
| 398 | 486 |
| 399 PassphraseState SyncEncryptionHandlerImpl::GetPassphraseState() const { | 487 PassphraseType SyncEncryptionHandlerImpl::GetPassphraseType() const { |
| 400 DCHECK(thread_checker_.CalledOnValidThread()); | 488 DCHECK(thread_checker_.CalledOnValidThread()); |
| 401 return passphrase_state_; | 489 return passphrase_type_; |
| 402 } | 490 } |
| 403 | 491 |
| 404 // Note: this is called from within a syncable transaction, so we need to post | 492 // Note: this is called from within a syncable transaction, so we need to post |
| 405 // tasks if we want to do any work that creates a new sync_api transaction. | 493 // tasks if we want to do any work that creates a new sync_api transaction. |
| 406 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( | 494 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( |
| 407 const sync_pb::NigoriSpecifics& nigori, | 495 const sync_pb::NigoriSpecifics& nigori, |
| 408 syncable::BaseTransaction* const trans) { | 496 syncable::BaseTransaction* const trans) { |
| 409 DCHECK(thread_checker_.CalledOnValidThread()); | 497 DCHECK(thread_checker_.CalledOnValidThread()); |
| 410 DCHECK(trans); | 498 DCHECK(trans); |
| 411 if (!ApplyNigoriUpdateImpl(nigori, trans)) { | 499 if (!ApplyNigoriUpdateImpl(nigori, trans)) { |
| 412 MessageLoop::current()->PostTask( | 500 MessageLoop::current()->PostTask( |
| 413 FROM_HERE, | 501 FROM_HERE, |
| 414 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, | 502 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, |
| 415 weak_ptr_factory_.GetWeakPtr())); | 503 weak_ptr_factory_.GetWeakPtr())); |
| 416 } | 504 } |
| 417 | 505 |
| 418 FOR_EACH_OBSERVER( | 506 FOR_EACH_OBSERVER( |
| 419 SyncEncryptionHandler::Observer, | 507 SyncEncryptionHandler::Observer, |
| 420 observers_, | 508 observers_, |
| 421 OnCryptographerStateChanged( | 509 OnCryptographerStateChanged( |
| 422 &UnlockVaultMutable(trans)->cryptographer)); | 510 &UnlockVaultMutable(trans)->cryptographer)); |
| 423 } | 511 } |
| 424 | 512 |
| 425 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes( | 513 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes( |
| 426 sync_pb::NigoriSpecifics* nigori, | 514 sync_pb::NigoriSpecifics* nigori, |
| 427 syncable::BaseTransaction* const trans) const { | 515 syncable::BaseTransaction* const trans) const { |
| 516 DCHECK(thread_checker_.CalledOnValidThread()); |
| 428 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types, | 517 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types, |
| 429 encrypt_everything_, | 518 encrypt_everything_, |
| 430 nigori); | 519 nigori); |
| 431 } | 520 } |
| 432 | 521 |
| 433 bool SyncEncryptionHandlerImpl::NeedKeystoreKey( | 522 bool SyncEncryptionHandlerImpl::NeedKeystoreKey( |
| 434 syncable::BaseTransaction* const trans) const { | 523 syncable::BaseTransaction* const trans) const { |
| 524 DCHECK(thread_checker_.CalledOnValidThread()); |
| 435 return keystore_key_.empty(); | 525 return keystore_key_.empty(); |
| 436 } | 526 } |
| 437 | 527 |
| 438 bool SyncEncryptionHandlerImpl::SetKeystoreKey( | 528 bool SyncEncryptionHandlerImpl::SetKeystoreKey( |
| 439 const std::string& key, | 529 const std::string& key, |
| 440 syncable::BaseTransaction* const trans) { | 530 syncable::BaseTransaction* const trans) { |
| 531 DCHECK(thread_checker_.CalledOnValidThread()); |
| 441 if (!keystore_key_.empty() || key.empty()) | 532 if (!keystore_key_.empty() || key.empty()) |
| 442 return false; | 533 return false; |
| 443 keystore_key_ = key; | 534 keystore_key_ = key; |
| 444 | 535 |
| 445 // TODO(zea): trigger migration if necessary. | |
| 446 | |
| 447 DVLOG(1) << "Keystore bootstrap token updated."; | 536 DVLOG(1) << "Keystore bootstrap token updated."; |
| 448 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 537 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 449 OnBootstrapTokenUpdated(key, | 538 OnBootstrapTokenUpdated(key, |
| 450 KEYSTORE_BOOTSTRAP_TOKEN)); | 539 KEYSTORE_BOOTSTRAP_TOKEN)); |
| 540 |
| 541 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; |
| 542 syncable::Entry entry(trans, syncable::GET_BY_SERVER_TAG, kNigoriTag); |
| 543 if (entry.good()) { |
| 544 const sync_pb::NigoriSpecifics& nigori = |
| 545 entry.Get(syncable::SPECIFICS).nigori(); |
| 546 if (cryptographer->has_pending_keys() && |
| 547 IsNigoriMigratedToKeystore(nigori) && |
| 548 !nigori.keystore_decryptor_token().blob().empty()) { |
| 549 // If the nigori is already migrated and we have pending keys, we might |
| 550 // be able to decrypt them using the keystore decryptor token. |
| 551 DecryptPendingKeysWithKeystoreKey(keystore_key_, |
| 552 nigori.keystore_decryptor_token(), |
| 553 cryptographer); |
| 554 } else if (ShouldTriggerMigration(nigori, *cryptographer)) { |
| 555 // We call rewrite nigori to attempt to trigger migration. |
| 556 // Need to post a task to open a new sync_api transaction. |
| 557 MessageLoop::current()->PostTask( |
| 558 FROM_HERE, |
| 559 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori, |
| 560 weak_ptr_factory_.GetWeakPtr())); |
| 561 } |
| 562 } |
| 563 |
| 451 return true; | 564 return true; |
| 452 } | 565 } |
| 453 | 566 |
| 454 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes( | 567 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes( |
| 455 syncable::BaseTransaction* const trans) const { | 568 syncable::BaseTransaction* const trans) const { |
| 456 return UnlockVault(trans).encrypted_types; | 569 return UnlockVault(trans).encrypted_types; |
| 457 } | 570 } |
| 458 | 571 |
| 459 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { | 572 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() { |
| 460 DCHECK(thread_checker_.CalledOnValidThread()); | 573 DCHECK(thread_checker_.CalledOnValidThread()); |
| 461 return &vault_unsafe_.cryptographer; | 574 return &vault_unsafe_.cryptographer; |
| 462 } | 575 } |
| 463 | 576 |
| 464 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() { | 577 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() { |
| 465 DCHECK(thread_checker_.CalledOnValidThread()); | 578 DCHECK(thread_checker_.CalledOnValidThread()); |
| 466 return vault_unsafe_.encrypted_types; | 579 return vault_unsafe_.encrypted_types; |
| 467 } | 580 } |
| 468 | 581 |
| 582 bool SyncEncryptionHandlerImpl::MigratedToKeystore() { |
| 583 DCHECK(thread_checker_.CalledOnValidThread()); |
| 584 ReadTransaction trans(FROM_HERE, user_share_); |
| 585 ReadNode nigori_node(&trans); |
| 586 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) |
| 587 return false; |
| 588 return IsNigoriMigratedToKeystore(nigori_node.GetNigoriSpecifics()); |
| 589 } |
| 590 |
| 469 // This function iterates over all encrypted types. There are many scenarios in | 591 // This function iterates over all encrypted types. There are many scenarios in |
| 470 // which data for some or all types is not currently available. In that case, | 592 // which data for some or all types is not currently available. In that case, |
| 471 // the lookup of the root node will fail and we will skip encryption for that | 593 // the lookup of the root node will fail and we will skip encryption for that |
| 472 // type. | 594 // type. |
| 473 void SyncEncryptionHandlerImpl::ReEncryptEverything( | 595 void SyncEncryptionHandlerImpl::ReEncryptEverything( |
| 474 WriteTransaction* trans) { | 596 WriteTransaction* trans) { |
| 475 DCHECK(thread_checker_.CalledOnValidThread()); | 597 DCHECK(thread_checker_.CalledOnValidThread()); |
| 476 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready()); | 598 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready()); |
| 477 for (ModelTypeSet::Iterator iter = | 599 for (ModelTypeSet::Iterator iter = |
| 478 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First(); | 600 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 OnEncryptionComplete()); | 659 OnEncryptionComplete()); |
| 538 } | 660 } |
| 539 | 661 |
| 540 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( | 662 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
| 541 const sync_pb::NigoriSpecifics& nigori, | 663 const sync_pb::NigoriSpecifics& nigori, |
| 542 syncable::BaseTransaction* const trans) { | 664 syncable::BaseTransaction* const trans) { |
| 543 DCHECK(thread_checker_.CalledOnValidThread()); | 665 DCHECK(thread_checker_.CalledOnValidThread()); |
| 544 DVLOG(1) << "Applying nigori node update."; | 666 DVLOG(1) << "Applying nigori node update."; |
| 545 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori, | 667 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori, |
| 546 trans); | 668 trans); |
| 547 if (nigori.using_explicit_passphrase() && | 669 bool is_nigori_migrated = IsNigoriMigratedToKeystore(nigori); |
| 548 passphrase_state_ != CUSTOM_PASSPHRASE) { | 670 if (is_nigori_migrated) { |
| 549 passphrase_state_ = CUSTOM_PASSPHRASE; | 671 migration_time_ms_ = nigori.keystore_migration_time(); |
| 550 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 672 PassphraseType nigori_passphrase_type = |
| 551 OnPassphraseStateChanged(passphrase_state_)); | 673 ProtoPassphraseTypeToEnum(nigori.passphrase_type()); |
| 674 |
| 675 // Only update the local passphrase state if it's a valid transition: |
| 676 // - implicit -> keystore |
| 677 // - implicit -> frozen implicit |
| 678 // - implicit -> custom |
| 679 // - keystore -> custom |
| 680 // Note: frozen implicit -> custom is not technically a valid transition, |
| 681 // but we let it through here as well in case future versions do add support |
| 682 // for this transition. |
| 683 if (passphrase_type_ != nigori_passphrase_type && |
| 684 nigori_passphrase_type != IMPLICIT_PASSPHRASE && |
| 685 (passphrase_type_ == IMPLICIT_PASSPHRASE || |
| 686 nigori_passphrase_type == CUSTOM_PASSPHRASE)) { |
| 687 DVLOG(1) << "Changing passphrase state from " |
| 688 << PassphraseTypeToString(passphrase_type_) |
| 689 << " to " |
| 690 << PassphraseTypeToString(nigori_passphrase_type); |
| 691 passphrase_type_ = nigori_passphrase_type; |
| 692 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 693 OnPassphraseTypeChanged(passphrase_type_)); |
| 694 } |
| 695 if (passphrase_type_ == KEYSTORE_PASSPHRASE && encrypt_everything_) { |
| 696 // This is the case where another client that didn't support keystore |
| 697 // encryption attempted to enable full encryption. We detect it |
| 698 // and switch the passphrase type to frozen implicit passphrase instead |
| 699 // due to full encryption not being compatible with keystore passphrase. |
| 700 // Because the local passphrase type will not match the nigori passphrase |
| 701 // type, we will trigger a rewrite and subsequently a re-migration. |
| 702 DVLOG(1) << "Changing passphrase state to FROZEN_IMPLICIT_PASSPHRASE " |
| 703 << "due to full encryption."; |
| 704 passphrase_type_ = FROZEN_IMPLICIT_PASSPHRASE; |
| 705 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 706 OnPassphraseTypeChanged(passphrase_type_)); |
| 707 } |
| 708 } else { |
| 709 // It's possible that while we're waiting for migration a client that does |
| 710 // not have keystore encryption enabled switches to a custom passphrase. |
| 711 if (nigori.keybag_is_frozen() && |
| 712 passphrase_type_ != CUSTOM_PASSPHRASE) { |
| 713 passphrase_type_ = CUSTOM_PASSPHRASE; |
| 714 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 715 OnPassphraseTypeChanged(passphrase_type_)); |
| 716 } |
| 552 } | 717 } |
| 553 | 718 |
| 554 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; | 719 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; |
| 555 bool nigori_needs_new_keys = false; | 720 bool nigori_needs_new_keys = false; |
| 556 if (!nigori.encrypted().blob().empty()) { | 721 if (!nigori.encryption_keybag().blob().empty()) { |
| 557 if (cryptographer->CanDecrypt(nigori.encrypted())) { | 722 // We only update the default key if this was a new explicit passphrase. |
| 558 cryptographer->InstallKeys(nigori.encrypted()); | 723 // Else, since it was decryptable, it must not have been a new key. |
| 559 // We only update the default passphrase if this was a new explicit | 724 bool need_new_default_key = false; |
| 560 // passphrase. Else, since it was decryptable, it must not have been a new | 725 if (is_nigori_migrated) { |
| 561 // key. | 726 need_new_default_key = IsExplicitPassphrase( |
| 562 if (nigori.using_explicit_passphrase()) | 727 ProtoPassphraseTypeToEnum(nigori.passphrase_type())); |
| 563 cryptographer->SetDefaultKey(nigori.encrypted().key_name()); | |
| 564 | |
| 565 // Check if the cryptographer's keybag is newer than the nigori's | |
| 566 // keybag. If so, we need to overwrite the nigori node. | |
| 567 sync_pb::EncryptedData new_keys = nigori.encrypted(); | |
| 568 if (!cryptographer->GetKeys(&new_keys)) | |
| 569 NOTREACHED(); | |
| 570 if (nigori.encrypted().SerializeAsString() != | |
| 571 new_keys.SerializeAsString()) | |
| 572 nigori_needs_new_keys = true; | |
| 573 } else { | 728 } else { |
| 574 cryptographer->SetPendingKeys(nigori.encrypted()); | 729 need_new_default_key = nigori.keybag_is_frozen(); |
| 730 } |
| 731 if (!AttemptToInstallKeybag(nigori.encryption_keybag(), |
| 732 need_new_default_key, |
| 733 cryptographer)) { |
| 734 // Check to see if we can decrypt the keybag using the keystore decryptor |
| 735 // token. |
| 736 cryptographer->SetPendingKeys(nigori.encryption_keybag()); |
| 737 if (!nigori.keystore_decryptor_token().blob().empty() && |
| 738 !keystore_key_.empty()) { |
| 739 if (DecryptPendingKeysWithKeystoreKey(keystore_key_, |
| 740 nigori.keystore_decryptor_token(), |
| 741 cryptographer)) { |
| 742 nigori_needs_new_keys = |
| 743 cryptographer->KeybagIsStale(nigori.encryption_keybag()); |
| 744 } else { |
| 745 LOG(ERROR) << "Failed to decrypt pending keys using keystore " |
| 746 << "bootstrap key."; |
| 747 } |
| 748 } |
| 749 } else { |
| 750 // Keybag was installed. We write back our local keybag into the nigori |
| 751 // node if the nigori node's keybag either contains less keys or |
| 752 // has a different default key. |
| 753 nigori_needs_new_keys = |
| 754 cryptographer->KeybagIsStale(nigori.encryption_keybag()); |
| 575 } | 755 } |
| 576 } else { | 756 } else { |
| 757 // The nigori node has an empty encryption keybag. Attempt to write our |
| 758 // local encryption keys into it. |
| 759 LOG(WARNING) << "Nigori had empty encryption keybag."; |
| 577 nigori_needs_new_keys = true; | 760 nigori_needs_new_keys = true; |
| 578 } | 761 } |
| 579 | 762 |
| 580 // If we've completed a sync cycle and the cryptographer isn't ready | 763 // If we've completed a sync cycle and the cryptographer isn't ready |
| 581 // yet or has pending keys, prompt the user for a passphrase. | 764 // yet or has pending keys, prompt the user for a passphrase. |
| 582 if (cryptographer->has_pending_keys()) { | 765 if (cryptographer->has_pending_keys()) { |
| 583 DVLOG(1) << "OnPassphraseRequired Sent"; | 766 DVLOG(1) << "OnPassphraseRequired Sent"; |
| 584 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); | 767 sync_pb::EncryptedData pending_keys = cryptographer->GetPendingKeys(); |
| 585 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 768 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 586 OnPassphraseRequired(REASON_DECRYPTION, | 769 OnPassphraseRequired(REASON_DECRYPTION, |
| 587 pending_keys)); | 770 pending_keys)); |
| 588 } else if (!cryptographer->is_ready()) { | 771 } else if (!cryptographer->is_ready()) { |
| 589 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " | 772 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " |
| 590 << "ready"; | 773 << "ready"; |
| 591 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 774 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 592 OnPassphraseRequired(REASON_ENCRYPTION, | 775 OnPassphraseRequired(REASON_ENCRYPTION, |
| 593 sync_pb::EncryptedData())); | 776 sync_pb::EncryptedData())); |
| 594 } | 777 } |
| 595 | 778 |
| 596 // Check if the current local encryption state is stricter/newer than the | 779 // Check if the current local encryption state is stricter/newer than the |
| 597 // nigori state. If so, we need to overwrite the nigori node with the local | 780 // nigori state. If so, we need to overwrite the nigori node with the local |
| 598 // state. | 781 // state. |
| 599 bool explicit_passphrase = passphrase_state_ == CUSTOM_PASSPHRASE; | 782 bool passphrase_type_matches = true; |
| 600 if (nigori.using_explicit_passphrase() != explicit_passphrase || | 783 if (!is_nigori_migrated) { |
| 784 DCHECK(passphrase_type_ == CUSTOM_PASSPHRASE || |
| 785 passphrase_type_ == IMPLICIT_PASSPHRASE); |
| 786 passphrase_type_matches = |
| 787 nigori.keybag_is_frozen() == IsExplicitPassphrase(passphrase_type_); |
| 788 } else { |
| 789 passphrase_type_matches = |
| 790 (ProtoPassphraseTypeToEnum(nigori.passphrase_type()) == |
| 791 passphrase_type_); |
| 792 } |
| 793 if (!passphrase_type_matches || |
| 601 nigori.encrypt_everything() != encrypt_everything_ || | 794 nigori.encrypt_everything() != encrypt_everything_ || |
| 602 nigori_types_need_update || | 795 nigori_types_need_update || |
| 603 nigori_needs_new_keys) { | 796 nigori_needs_new_keys) { |
| 797 DVLOG(1) << "Triggering nigori rewrite."; |
| 604 return false; | 798 return false; |
| 605 } | 799 } |
| 606 return true; | 800 return true; |
| 607 } | 801 } |
| 608 | 802 |
| 609 void SyncEncryptionHandlerImpl::RewriteNigori() { | 803 void SyncEncryptionHandlerImpl::RewriteNigori() { |
| 610 DVLOG(1) << "Overwriting stale nigori node."; | 804 DVLOG(1) << "Writing local encryption state into nigori."; |
| 611 DCHECK(thread_checker_.CalledOnValidThread()); | 805 DCHECK(thread_checker_.CalledOnValidThread()); |
| 612 WriteTransaction trans(FROM_HERE, user_share_); | 806 WriteTransaction trans(FROM_HERE, user_share_); |
| 613 WriteEncryptionStateToNigori(&trans); | 807 WriteEncryptionStateToNigori(&trans); |
| 614 } | 808 } |
| 615 | 809 |
| 616 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori( | 810 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori( |
| 617 WriteTransaction* trans) { | 811 WriteTransaction* trans) { |
| 618 DCHECK(thread_checker_.CalledOnValidThread()); | 812 DCHECK(thread_checker_.CalledOnValidThread()); |
| 619 WriteNode nigori_node(trans); | 813 WriteNode nigori_node(trans); |
| 620 // This can happen in tests that don't have nigori nodes. | 814 // This can happen in tests that don't have nigori nodes. |
| 621 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) | 815 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) |
| 622 return; | 816 return; |
| 817 |
| 623 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics(); | 818 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics(); |
| 624 const Cryptographer& cryptographer = | 819 const Cryptographer& cryptographer = |
| 625 UnlockVault(trans->GetWrappedTrans()).cryptographer; | 820 UnlockVault(trans->GetWrappedTrans()).cryptographer; |
| 626 if (cryptographer.is_ready() && | |
| 627 nigori_overwrite_count_ < kNigoriOverwriteLimit) { | |
| 628 // Does not modify the encrypted blob if the unencrypted data already | |
| 629 // matches what is about to be written. | |
| 630 sync_pb::EncryptedData original_keys = nigori.encrypted(); | |
| 631 if (!cryptographer.GetKeys(nigori.mutable_encrypted())) | |
| 632 NOTREACHED(); | |
| 633 | 821 |
| 634 if (nigori.encrypted().SerializeAsString() != | 822 // Will not do anything if we shouldn't or can't migrate. Otherwise |
| 635 original_keys.SerializeAsString()) { | 823 // migrates, writing the full encryption state as it does. |
| 636 // We've updated the nigori node's encryption keys. In order to prevent | 824 if (!AttemptToMigrateNigoriToKeystore(trans, &nigori_node)) { |
| 637 // a possible looping of two clients constantly overwriting each other, | 825 if (cryptographer.is_ready() && |
| 638 // we limit the absolute number of overwrites per client instantiation. | 826 nigori_overwrite_count_ < kNigoriOverwriteLimit) { |
| 639 nigori_overwrite_count_++; | 827 // Does not modify the encrypted blob if the unencrypted data already |
| 640 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", | 828 // matches what is about to be written. |
| 641 nigori_overwrite_count_); | 829 sync_pb::EncryptedData original_keys = nigori.encryption_keybag(); |
| 830 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag())) |
| 831 NOTREACHED(); |
| 832 |
| 833 if (nigori.encryption_keybag().SerializeAsString() != |
| 834 original_keys.SerializeAsString()) { |
| 835 // We've updated the nigori node's encryption keys. In order to prevent |
| 836 // a possible looping of two clients constantly overwriting each other, |
| 837 // we limit the absolute number of overwrites per client instantiation. |
| 838 nigori_overwrite_count_++; |
| 839 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", |
| 840 nigori_overwrite_count_); |
| 841 } |
| 842 |
| 843 // Note: we don't try to set keybag_is_frozen here since if that |
| 844 // is lost the user can always set it again (and we don't want to clobber |
| 845 // any migration state). The main goal at this point is to preserve |
| 846 // the encryption keys so all data remains decryptable. |
| 642 } | 847 } |
| 848 syncable::UpdateNigoriFromEncryptedTypes( |
| 849 UnlockVault(trans->GetWrappedTrans()).encrypted_types, |
| 850 encrypt_everything_, |
| 851 &nigori); |
| 643 | 852 |
| 644 // Note: we don't try to set using_explicit_passphrase here since if that | 853 // If nothing has changed, this is a no-op. |
| 645 // is lost the user can always set it again. The main point is to preserve | 854 nigori_node.SetNigoriSpecifics(nigori); |
| 646 // the encryption keys so all data remains decryptable. | |
| 647 } | 855 } |
| 648 syncable::UpdateNigoriFromEncryptedTypes( | |
| 649 UnlockVault(trans->GetWrappedTrans()).encrypted_types, | |
| 650 encrypt_everything_, | |
| 651 &nigori); | |
| 652 | |
| 653 // If nothing has changed, this is a no-op. | |
| 654 nigori_node.SetNigoriSpecifics(nigori); | |
| 655 } | 856 } |
| 656 | 857 |
| 657 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori( | 858 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori( |
| 658 const sync_pb::NigoriSpecifics& nigori, | 859 const sync_pb::NigoriSpecifics& nigori, |
| 659 syncable::BaseTransaction* const trans) { | 860 syncable::BaseTransaction* const trans) { |
| 660 DCHECK(thread_checker_.CalledOnValidThread()); | 861 DCHECK(thread_checker_.CalledOnValidThread()); |
| 661 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; | 862 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; |
| 662 if (nigori.encrypt_everything()) { | 863 if (nigori.encrypt_everything()) { |
| 663 if (!encrypt_everything_) { | 864 EnableEncryptEverythingImpl(trans); |
| 664 encrypt_everything_ = true; | |
| 665 *encrypted_types = UserTypes(); | |
| 666 DVLOG(1) << "Enabling encrypt everything via nigori node update"; | |
| 667 FOR_EACH_OBSERVER( | |
| 668 Observer, observers_, | |
| 669 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | |
| 670 } | |
| 671 DCHECK(encrypted_types->Equals(UserTypes())); | 865 DCHECK(encrypted_types->Equals(UserTypes())); |
| 672 return true; | 866 return true; |
| 867 } else if (encrypt_everything_) { |
| 868 DCHECK(encrypted_types->Equals(UserTypes())); |
| 869 return false; |
| 673 } | 870 } |
| 674 | 871 |
| 675 ModelTypeSet nigori_encrypted_types; | 872 ModelTypeSet nigori_encrypted_types; |
| 676 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori); | 873 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori); |
| 677 nigori_encrypted_types.PutAll(SensitiveTypes()); | 874 nigori_encrypted_types.PutAll(SensitiveTypes()); |
| 678 | 875 |
| 679 // If anything more than the sensitive types were encrypted, and | 876 // If anything more than the sensitive types were encrypted, and |
| 680 // encrypt_everything is not explicitly set to false, we assume it means | 877 // encrypt_everything is not explicitly set to false, we assume it means |
| 681 // a client intended to enable encrypt everything. | 878 // a client intended to enable encrypt everything. |
| 682 if (!nigori.has_encrypt_everything() && | 879 if (!nigori.has_encrypt_everything() && |
| 683 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) { | 880 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) { |
| 684 if (!encrypt_everything_) { | 881 if (!encrypt_everything_) { |
| 685 encrypt_everything_ = true; | 882 encrypt_everything_ = true; |
| 686 *encrypted_types = UserTypes(); | 883 *encrypted_types = UserTypes(); |
| 687 FOR_EACH_OBSERVER( | 884 FOR_EACH_OBSERVER( |
| 688 Observer, observers_, | 885 Observer, observers_, |
| 689 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); | 886 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); |
| 690 } | 887 } |
| 691 DCHECK(encrypted_types->Equals(UserTypes())); | 888 DCHECK(encrypted_types->Equals(UserTypes())); |
| 692 return false; | 889 return false; |
| 693 } | 890 } |
| 694 | 891 |
| 695 MergeEncryptedTypes(nigori_encrypted_types, trans); | 892 MergeEncryptedTypes(nigori_encrypted_types, trans); |
| 696 return encrypted_types->Equals(nigori_encrypted_types); | 893 return encrypted_types->Equals(nigori_encrypted_types); |
| 697 } | 894 } |
| 698 | 895 |
| 896 void SyncEncryptionHandlerImpl::SetCustomPassphrase( |
| 897 const std::string& passphrase, |
| 898 WriteTransaction* trans, |
| 899 WriteNode* nigori_node) { |
| 900 DCHECK(thread_checker_.CalledOnValidThread()); |
| 901 DCHECK(IsNigoriMigratedToKeystore(nigori_node->GetNigoriSpecifics())); |
| 902 KeyParams key_params = {"localhost", "dummy", passphrase}; |
| 903 |
| 904 if (passphrase_type_ != KEYSTORE_PASSPHRASE) { |
| 905 DVLOG(1) << "Failing to set a custom passphrase because one has already " |
| 906 << "been set."; |
| 907 FinishSetPassphrase(false, "", trans, nigori_node); |
| 908 return; |
| 909 } |
| 910 |
| 911 Cryptographer* cryptographer = |
| 912 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; |
| 913 if (cryptographer->has_pending_keys()) { |
| 914 // This theoretically shouldn't happen, because the only way to have pending |
| 915 // keys after migrating to keystore support is if a custom passphrase was |
| 916 // set, which should update passpshrase_state_ and should be caught by the |
| 917 // if statement above. For the sake of safety though, we check for it in |
| 918 // case a client is misbehaving. |
| 919 LOG(ERROR) << "Failing to set custom passphrase because of pending keys."; |
| 920 FinishSetPassphrase(false, "", trans, nigori_node); |
| 921 return; |
| 922 } |
| 923 |
| 924 std::string bootstrap_token; |
| 925 if (cryptographer->AddKey(key_params)) { |
| 926 DVLOG(1) << "Setting custom passphrase."; |
| 927 cryptographer->GetBootstrapToken(&bootstrap_token); |
| 928 passphrase_type_ = CUSTOM_PASSPHRASE; |
| 929 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 930 OnPassphraseTypeChanged(passphrase_type_)); |
| 931 } else { |
| 932 NOTREACHED() << "Failed to add key to cryptographer."; |
| 933 return; |
| 934 } |
| 935 FinishSetPassphrase(true, bootstrap_token, trans, nigori_node); |
| 936 } |
| 937 |
| 938 void SyncEncryptionHandlerImpl::DecryptPendingKeysWithExplicitPassphrase( |
| 939 const std::string& passphrase, |
| 940 WriteTransaction* trans, |
| 941 WriteNode* nigori_node) { |
| 942 DCHECK(thread_checker_.CalledOnValidThread()); |
| 943 DCHECK(IsExplicitPassphrase(passphrase_type_)); |
| 944 KeyParams key_params = {"localhost", "dummy", passphrase}; |
| 945 |
| 946 Cryptographer* cryptographer = |
| 947 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; |
| 948 if (!cryptographer->has_pending_keys()) { |
| 949 // Note that this *can* happen in a rare situation where data is |
| 950 // re-encrypted on another client while a SetDecryptionPassphrase() call is |
| 951 // in-flight on this client. It is rare enough that we choose to do nothing. |
| 952 NOTREACHED() << "Attempt to set decryption passphrase failed because there " |
| 953 << "were no pending keys."; |
| 954 return; |
| 955 } |
| 956 |
| 957 DCHECK(IsExplicitPassphrase(passphrase_type_)); |
| 958 bool success = false; |
| 959 std::string bootstrap_token; |
| 960 if (cryptographer->DecryptPendingKeys(key_params)) { |
| 961 DVLOG(1) << "Explicit passphrase accepted for decryption."; |
| 962 cryptographer->GetBootstrapToken(&bootstrap_token); |
| 963 success = true; |
| 964 } else { |
| 965 DVLOG(1) << "Explicit passphrase failed to decrypt."; |
| 966 success = false; |
| 967 } |
| 968 if (success && !keystore_key_.empty()) { |
| 969 // Should already be part of the encryption keybag, but we add it just |
| 970 // in case. |
| 971 KeyParams key_params = {"localhost", "dummy", keystore_key_}; |
| 972 cryptographer->AddNonDefaultKey(key_params); |
| 973 } |
| 974 FinishSetPassphrase(success, bootstrap_token, trans, nigori_node); |
| 975 } |
| 976 |
| 699 void SyncEncryptionHandlerImpl::FinishSetPassphrase( | 977 void SyncEncryptionHandlerImpl::FinishSetPassphrase( |
| 700 bool success, | 978 bool success, |
| 701 const std::string& bootstrap_token, | 979 const std::string& bootstrap_token, |
| 702 bool is_explicit, | |
| 703 WriteTransaction* trans, | 980 WriteTransaction* trans, |
| 704 WriteNode* nigori_node) { | 981 WriteNode* nigori_node) { |
| 705 DCHECK(thread_checker_.CalledOnValidThread()); | 982 DCHECK(thread_checker_.CalledOnValidThread()); |
| 706 FOR_EACH_OBSERVER( | 983 FOR_EACH_OBSERVER( |
| 707 SyncEncryptionHandler::Observer, | 984 SyncEncryptionHandler::Observer, |
| 708 observers_, | 985 observers_, |
| 709 OnCryptographerStateChanged( | 986 OnCryptographerStateChanged( |
| 710 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); | 987 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); |
| 711 | 988 |
| 712 // It's possible we need to change the bootstrap token even if we failed to | 989 // It's possible we need to change the bootstrap token even if we failed to |
| (...skipping 16 matching lines...) Expand all Loading... |
| 729 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 1006 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 730 OnPassphraseRequired(REASON_DECRYPTION, | 1007 OnPassphraseRequired(REASON_DECRYPTION, |
| 731 cryptographer.GetPendingKeys())); | 1008 cryptographer.GetPendingKeys())); |
| 732 } else { | 1009 } else { |
| 733 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 1010 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 734 OnPassphraseRequired(REASON_ENCRYPTION, | 1011 OnPassphraseRequired(REASON_ENCRYPTION, |
| 735 sync_pb::EncryptedData())); | 1012 sync_pb::EncryptedData())); |
| 736 } | 1013 } |
| 737 return; | 1014 return; |
| 738 } | 1015 } |
| 739 | 1016 DCHECK(success); |
| 740 DCHECK(cryptographer.is_ready()); | 1017 DCHECK(cryptographer.is_ready()); |
| 741 | 1018 |
| 742 // TODO(zea): trigger migration if necessary. | 1019 // Will do nothing if we're already properly migrated or unable to migrate |
| 1020 // (in otherwords, if ShouldTriggerMigration is false). |
| 1021 // Otherwise will update the nigori node with the current migrated state, |
| 1022 // writing all encryption state as it does. |
| 1023 if (!AttemptToMigrateNigoriToKeystore(trans, nigori_node)) { |
| 1024 sync_pb::NigoriSpecifics nigori(nigori_node->GetNigoriSpecifics()); |
| 1025 // Does not modify nigori.encryption_keybag() if the original decrypted |
| 1026 // data was the same. |
| 1027 if (!cryptographer.GetKeys(nigori.mutable_encryption_keybag())) |
| 1028 NOTREACHED(); |
| 1029 if (IsNigoriMigratedToKeystore(nigori)) { |
| 1030 DCHECK(keystore_key_.empty() || IsExplicitPassphrase(passphrase_type_)); |
| 1031 DVLOG(1) << "Leaving nigori migration state untouched after setting" |
| 1032 << " passphrase."; |
| 1033 } else { |
| 1034 nigori.set_keybag_is_frozen( |
| 1035 IsExplicitPassphrase(passphrase_type_)); |
| 1036 } |
| 1037 nigori_node->SetNigoriSpecifics(nigori); |
| 1038 } |
| 743 | 1039 |
| 744 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); | 1040 // Must do this after OnPassphraseTypeChanged, in order to ensure the PSS |
| 745 // Does not modify specifics.encrypted() if the original decrypted data was | |
| 746 // the same. | |
| 747 if (!cryptographer.GetKeys(specifics.mutable_encrypted())) | |
| 748 NOTREACHED(); | |
| 749 if (is_explicit && passphrase_state_ != CUSTOM_PASSPHRASE) { | |
| 750 passphrase_state_ = CUSTOM_PASSPHRASE; | |
| 751 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
| 752 OnPassphraseStateChanged(passphrase_state_)); | |
| 753 } | |
| 754 specifics.set_using_explicit_passphrase(is_explicit); | |
| 755 nigori_node->SetNigoriSpecifics(specifics); | |
| 756 | |
| 757 // Must do this after OnPassphraseStateChanged, in order to ensure the PSS | |
| 758 // checks the passphrase state after it has been set. | 1041 // checks the passphrase state after it has been set. |
| 759 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 1042 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 760 OnPassphraseAccepted()); | 1043 OnPassphraseAccepted()); |
| 761 | 1044 |
| 762 // Does nothing if everything is already encrypted. | 1045 // Does nothing if everything is already encrypted. |
| 1046 // TODO(zea): If we just migrated and enabled encryption, this will be |
| 1047 // redundant. Figure out a way to not do this unnecessarily. |
| 763 ReEncryptEverything(trans); | 1048 ReEncryptEverything(trans); |
| 764 } | 1049 } |
| 765 | 1050 |
| 766 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( | 1051 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( |
| 767 ModelTypeSet new_encrypted_types, | 1052 ModelTypeSet new_encrypted_types, |
| 768 syncable::BaseTransaction* const trans) { | 1053 syncable::BaseTransaction* const trans) { |
| 769 DCHECK(thread_checker_.CalledOnValidThread()); | 1054 DCHECK(thread_checker_.CalledOnValidThread()); |
| 770 | 1055 |
| 771 // Only UserTypes may be encrypted. | 1056 // Only UserTypes may be encrypted. |
| 772 DCHECK(UserTypes().HasAll(new_encrypted_types)); | 1057 DCHECK(UserTypes().HasAll(new_encrypted_types)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 785 DCHECK_EQ(user_share_->directory.get(), trans->directory()); | 1070 DCHECK_EQ(user_share_->directory.get(), trans->directory()); |
| 786 return &vault_unsafe_; | 1071 return &vault_unsafe_; |
| 787 } | 1072 } |
| 788 | 1073 |
| 789 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( | 1074 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( |
| 790 syncable::BaseTransaction* const trans) const { | 1075 syncable::BaseTransaction* const trans) const { |
| 791 DCHECK_EQ(user_share_->directory.get(), trans->directory()); | 1076 DCHECK_EQ(user_share_->directory.get(), trans->directory()); |
| 792 return vault_unsafe_; | 1077 return vault_unsafe_; |
| 793 } | 1078 } |
| 794 | 1079 |
| 1080 bool SyncEncryptionHandlerImpl::ShouldTriggerMigration( |
| 1081 const sync_pb::NigoriSpecifics& nigori, |
| 1082 const Cryptographer& cryptographer) const { |
| 1083 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1084 // TODO(zea): once we're willing to have the keystore key be the only |
| 1085 // encryption key, change this to !has_pending_keys(). For now, we need the |
| 1086 // cryptographer to be initialized with the current GAIA pass so that older |
| 1087 // clients (that don't have keystore support) can decrypt the keybag. |
| 1088 if (!cryptographer.is_ready()) |
| 1089 return false; |
| 1090 if (IsNigoriMigratedToKeystore(nigori)) { |
| 1091 // If the nigori is already migrated but does not reflect the explicit |
| 1092 // passphrase state, remigrate. Similarly, if the nigori has an explicit |
| 1093 // passphrase but does not have full encryption, or the nigori has an |
| 1094 // implicit passphrase but does have full encryption, re-migrate. |
| 1095 // Note that this is to defend against other clients without keystore |
| 1096 // encryption enabled transitioning to states that are no longer valid. |
| 1097 if (passphrase_type_ != KEYSTORE_PASSPHRASE && |
| 1098 nigori.passphrase_type() == |
| 1099 sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) { |
| 1100 return true; |
| 1101 } else if (IsExplicitPassphrase(passphrase_type_) && |
| 1102 !encrypt_everything_) { |
| 1103 return true; |
| 1104 } else if (passphrase_type_ == KEYSTORE_PASSPHRASE && |
| 1105 encrypt_everything_) { |
| 1106 return true; |
| 1107 } else { |
| 1108 return false; |
| 1109 } |
| 1110 } else if (keystore_key_.empty()) { |
| 1111 // If we haven't already migrated, we don't want to do anything unless |
| 1112 // a keystore key is available (so that those clients without keystore |
| 1113 // encryption enabled aren't forced into new states, e.g. frozen implicit |
| 1114 // passphrase). |
| 1115 return false; |
| 1116 } |
| 1117 return true; |
| 1118 } |
| 1119 |
| 1120 bool SyncEncryptionHandlerImpl::AttemptToMigrateNigoriToKeystore( |
| 1121 WriteTransaction* trans, |
| 1122 WriteNode* nigori_node) { |
| 1123 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1124 const sync_pb::NigoriSpecifics& old_nigori = |
| 1125 nigori_node->GetNigoriSpecifics(); |
| 1126 Cryptographer* cryptographer = |
| 1127 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer; |
| 1128 |
| 1129 if (!ShouldTriggerMigration(old_nigori, *cryptographer)) |
| 1130 return false; |
| 1131 |
| 1132 DVLOG(1) << "Starting nigori migration to keystore support."; |
| 1133 if (migration_time_ms_ == 0) |
| 1134 migration_time_ms_ = TimeToProtoTime(base::Time::Now()); |
| 1135 sync_pb::NigoriSpecifics migrated_nigori(old_nigori); |
| 1136 migrated_nigori.set_keystore_migration_time(migration_time_ms_); |
| 1137 |
| 1138 PassphraseType new_passphrase_type = passphrase_type_; |
| 1139 bool new_encrypt_everything = encrypt_everything_; |
| 1140 if (encrypt_everything_ && !IsExplicitPassphrase(passphrase_type_)) { |
| 1141 DVLOG(1) << "Switching to frozen implicit passphrase due to already having " |
| 1142 << "full encryption."; |
| 1143 new_passphrase_type = FROZEN_IMPLICIT_PASSPHRASE; |
| 1144 migrated_nigori.clear_keystore_decryptor_token(); |
| 1145 } else if (IsExplicitPassphrase(passphrase_type_)) { |
| 1146 DVLOG_IF(1, !encrypt_everything_) << "Enabling encrypt everything due to " |
| 1147 << "explicit passphrase"; |
| 1148 new_encrypt_everything = true; |
| 1149 migrated_nigori.clear_keystore_decryptor_token(); |
| 1150 } else { |
| 1151 DCHECK_EQ(passphrase_type_, IMPLICIT_PASSPHRASE); |
| 1152 DCHECK(!encrypt_everything_); |
| 1153 new_passphrase_type = KEYSTORE_PASSPHRASE; |
| 1154 DVLOG(1) << "Switching to keystore passphrase state."; |
| 1155 } |
| 1156 migrated_nigori.set_encrypt_everything(new_encrypt_everything); |
| 1157 migrated_nigori.set_passphrase_type( |
| 1158 EnumPassphraseTypeToProto(new_passphrase_type)); |
| 1159 migrated_nigori.set_keybag_is_frozen(true); |
| 1160 |
| 1161 if (!keystore_key_.empty()) { |
| 1162 KeyParams key_params = {"localhost", "dummy", keystore_key_}; |
| 1163 if (!cryptographer->AddNonDefaultKey(key_params)) { |
| 1164 LOG(ERROR) << "Failed to add keystore key as non-default key."; |
| 1165 return false; |
| 1166 } |
| 1167 } |
| 1168 if (new_passphrase_type == KEYSTORE_PASSPHRASE && |
| 1169 !GetKeystoreDecryptor( |
| 1170 *cryptographer, |
| 1171 keystore_key_, |
| 1172 migrated_nigori.mutable_keystore_decryptor_token())) { |
| 1173 LOG(ERROR) << "Failed to extract keystore decryptor token."; |
| 1174 return false; |
| 1175 } |
| 1176 if (!cryptographer->GetKeys(migrated_nigori.mutable_encryption_keybag())) { |
| 1177 LOG(ERROR) << "Failed to extract encryption keybag."; |
| 1178 return false; |
| 1179 } |
| 1180 |
| 1181 DVLOG(1) << "Completing nigori migration to keystore support."; |
| 1182 nigori_node->SetNigoriSpecifics(migrated_nigori); |
| 1183 if (passphrase_type_ != new_passphrase_type) { |
| 1184 passphrase_type_ = new_passphrase_type; |
| 1185 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 1186 OnPassphraseTypeChanged(passphrase_type_)); |
| 1187 } |
| 1188 if (new_encrypt_everything && !encrypt_everything_) { |
| 1189 EnableEncryptEverythingImpl(trans->GetWrappedTrans()); |
| 1190 ReEncryptEverything(trans); |
| 1191 } |
| 1192 return true; |
| 1193 } |
| 1194 |
| 1195 bool SyncEncryptionHandlerImpl::GetKeystoreDecryptor( |
| 1196 const Cryptographer& cryptographer, |
| 1197 const std::string& keystore_key, |
| 1198 sync_pb::EncryptedData* encrypted_blob) { |
| 1199 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1200 DCHECK(!keystore_key.empty()); |
| 1201 DCHECK(cryptographer.is_ready()); |
| 1202 std::string serialized_nigori; |
| 1203 serialized_nigori = cryptographer.GetDefaultNigoriKey(); |
| 1204 if (serialized_nigori.empty()) { |
| 1205 LOG(ERROR) << "Failed to get cryptographer bootstrap token."; |
| 1206 return false; |
| 1207 } |
| 1208 Cryptographer temp_cryptographer(cryptographer.encryptor()); |
| 1209 KeyParams key_params = {"localhost", "dummy", keystore_key}; |
| 1210 if (!temp_cryptographer.AddKey(key_params)) |
| 1211 return false; |
| 1212 if (!temp_cryptographer.EncryptString(serialized_nigori, encrypted_blob)) |
| 1213 return false; |
| 1214 return true; |
| 1215 } |
| 1216 |
| 1217 bool SyncEncryptionHandlerImpl::AttemptToInstallKeybag( |
| 1218 const sync_pb::EncryptedData& keybag, |
| 1219 bool update_default, |
| 1220 Cryptographer* cryptographer) { |
| 1221 if (!cryptographer->CanDecrypt(keybag)) |
| 1222 return false; |
| 1223 cryptographer->InstallKeys(keybag); |
| 1224 if (update_default) |
| 1225 cryptographer->SetDefaultKey(keybag.key_name()); |
| 1226 return true; |
| 1227 } |
| 1228 |
| 1229 void SyncEncryptionHandlerImpl::EnableEncryptEverythingImpl( |
| 1230 syncable::BaseTransaction* const trans) { |
| 1231 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; |
| 1232 if (encrypt_everything_) { |
| 1233 DCHECK(encrypted_types->Equals(UserTypes())); |
| 1234 return; |
| 1235 } |
| 1236 encrypt_everything_ = true; |
| 1237 *encrypted_types = UserTypes(); |
| 1238 FOR_EACH_OBSERVER( |
| 1239 Observer, observers_, |
| 1240 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_)); |
| 1241 } |
| 1242 |
| 1243 bool SyncEncryptionHandlerImpl::DecryptPendingKeysWithKeystoreKey( |
| 1244 const std::string& keystore_key, |
| 1245 const sync_pb::EncryptedData& keystore_decryptor_token, |
| 1246 Cryptographer* cryptographer) { |
| 1247 DCHECK(cryptographer->has_pending_keys()); |
| 1248 if (keystore_decryptor_token.blob().empty()) |
| 1249 return false; |
| 1250 Cryptographer temp_cryptographer(cryptographer->encryptor()); |
| 1251 KeyParams keystore_params = {"localhost", "dummy", keystore_key_}; |
| 1252 if (temp_cryptographer.AddKey(keystore_params) && |
| 1253 temp_cryptographer.CanDecrypt(keystore_decryptor_token)) { |
| 1254 // Someone else migrated the nigori for us! How generous! Go ahead and |
| 1255 // install both the keystore key and the new default encryption key |
| 1256 // (i.e. the one provided by the keystore decryptor token) into the |
| 1257 // cryptographer. |
| 1258 // The keystore decryptor token is a keystore key encrypted blob containing |
| 1259 // the current serialized default encryption key (and as such should be |
| 1260 // able to decrypt the nigori node's encryption keybag). |
| 1261 DVLOG(1) << "Attempting to decrypt pending keys using " |
| 1262 << "keystore decryptor token."; |
| 1263 std::string serialized_nigori = |
| 1264 temp_cryptographer.DecryptToString(keystore_decryptor_token); |
| 1265 // This will decrypt the pending keys and add them if possible. The key |
| 1266 // within |serialized_nigori| will be the default after. |
| 1267 cryptographer->ImportNigoriKey(serialized_nigori); |
| 1268 // Theoretically the encryption keybag should already contain the keystore |
| 1269 // key. We explicitly add it as a safety measure. |
| 1270 cryptographer->AddNonDefaultKey(keystore_params); |
| 1271 if (cryptographer->is_ready()) { |
| 1272 std::string bootstrap_token; |
| 1273 cryptographer->GetBootstrapToken(&bootstrap_token); |
| 1274 DVLOG(1) << "Keystore decryptor token decrypted pending keys."; |
| 1275 FOR_EACH_OBSERVER( |
| 1276 SyncEncryptionHandler::Observer, |
| 1277 observers_, |
| 1278 OnBootstrapTokenUpdated(bootstrap_token, |
| 1279 PASSPHRASE_BOOTSTRAP_TOKEN)); |
| 1280 FOR_EACH_OBSERVER( |
| 1281 SyncEncryptionHandler::Observer, |
| 1282 observers_, |
| 1283 OnCryptographerStateChanged(cryptographer)); |
| 1284 return true; |
| 1285 } |
| 1286 } |
| 1287 return false; |
| 1288 } |
| 1289 |
| 795 } // namespace browser_sync | 1290 } // namespace browser_sync |
| OLD | NEW |