Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(607)

Side by Side Diff: sync/internal_api/sync_encryption_handler_impl.cc

Issue 10844005: [Sync] Refactor GetEncryptedTypes usage. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase + add dcheck Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/tracked_objects.h" 12 #include "base/tracked_objects.h"
13 #include "base/metrics/histogram.h" 13 #include "base/metrics/histogram.h"
14 #include "sync/internal_api/public/read_node.h" 14 #include "sync/internal_api/public/read_node.h"
15 #include "sync/internal_api/public/read_transaction.h" 15 #include "sync/internal_api/public/read_transaction.h"
16 #include "sync/internal_api/public/user_share.h" 16 #include "sync/internal_api/public/user_share.h"
17 #include "sync/internal_api/public/util/experiments.h" 17 #include "sync/internal_api/public/util/experiments.h"
18 #include "sync/internal_api/public/write_node.h" 18 #include "sync/internal_api/public/write_node.h"
19 #include "sync/internal_api/public/write_transaction.h" 19 #include "sync/internal_api/public/write_transaction.h"
20 #include "sync/protocol/encryption.pb.h" 20 #include "sync/protocol/encryption.pb.h"
21 #include "sync/protocol/nigori_specifics.pb.h" 21 #include "sync/protocol/nigori_specifics.pb.h"
22 #include "sync/protocol/sync.pb.h"
22 #include "sync/syncable/base_transaction.h" 23 #include "sync/syncable/base_transaction.h"
23 #include "sync/syncable/directory.h" 24 #include "sync/syncable/directory.h"
24 #include "sync/syncable/entry.h" 25 #include "sync/syncable/entry.h"
25 #include "sync/syncable/nigori_util.h" 26 #include "sync/syncable/nigori_util.h"
26 #include "sync/util/cryptographer.h" 27 #include "sync/util/cryptographer.h"
27 28
28 namespace syncer { 29 namespace syncer {
29 30
30 namespace { 31 namespace {
31 // The maximum number of times we will automatically overwrite the nigori node 32 // The maximum number of times we will automatically overwrite the nigori node
32 // because the encryption keys don't match (per chrome instantiation). 33 // because the encryption keys don't match (per chrome instantiation).
33 // We protect ourselves against nigori rollbacks, but it's possible two 34 // We protect ourselves against nigori rollbacks, but it's possible two
34 // different clients might have contrasting view of what the nigori node state 35 // different clients might have contrasting view of what the nigori node state
35 // should be, in which case they might ping pong (see crbug.com/119207). 36 // should be, in which case they might ping pong (see crbug.com/119207).
36 static const int kNigoriOverwriteLimit = 10; 37 static const int kNigoriOverwriteLimit = 10;
37 } 38 }
38 39
40 SyncEncryptionHandlerImpl::Vault::Vault(
41 Encryptor* encryptor,
42 ModelTypeSet encrypted_types)
43 : cryptographer(encryptor),
44 encrypted_types(encrypted_types) {
45 }
46
47 SyncEncryptionHandlerImpl::Vault::~Vault() {
48 }
49
39 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( 50 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl(
40 UserShare* user_share, 51 UserShare* user_share,
41 Cryptographer* cryptographer) 52 Encryptor* encryptor)
42 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), 53 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)),
43 user_share_(user_share), 54 user_share_(user_share),
44 cryptographer_(cryptographer), 55 vault_unsafe_(encryptor, SensitiveTypes()),
45 encrypted_types_(SensitiveTypes()),
46 encrypt_everything_(false), 56 encrypt_everything_(false),
47 explicit_passphrase_(false), 57 explicit_passphrase_(false),
48 nigori_overwrite_count_(0) { 58 nigori_overwrite_count_(0) {
49 } 59 }
50 60
51 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} 61 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {}
52 62
53 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { 63 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) {
64 DCHECK(thread_checker_.CalledOnValidThread());
54 DCHECK(!observers_.HasObserver(observer)); 65 DCHECK(!observers_.HasObserver(observer));
55 observers_.AddObserver(observer); 66 observers_.AddObserver(observer);
56 } 67 }
57 68
58 void SyncEncryptionHandlerImpl::RemoveObserver(Observer* observer) { 69 void SyncEncryptionHandlerImpl::RemoveObserver(Observer* observer) {
70 DCHECK(thread_checker_.CalledOnValidThread());
59 DCHECK(observers_.HasObserver(observer)); 71 DCHECK(observers_.HasObserver(observer));
60 observers_.RemoveObserver(observer); 72 observers_.RemoveObserver(observer);
61 } 73 }
62 74
63 void SyncEncryptionHandlerImpl::Init() { 75 void SyncEncryptionHandlerImpl::Init() {
76 DCHECK(thread_checker_.CalledOnValidThread());
64 WriteTransaction trans(FROM_HERE, user_share_); 77 WriteTransaction trans(FROM_HERE, user_share_);
65 WriteNode node(&trans); 78 WriteNode node(&trans);
66 Cryptographer* cryptographer = trans.GetCryptographer();
67 cryptographer_ = cryptographer;
68 79
69 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) 80 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK)
70 return; 81 return;
71 if (!ApplyNigoriUpdateImpl(node.GetNigoriSpecifics(), 82 if (!ApplyNigoriUpdateImpl(node.GetNigoriSpecifics(),
72 trans.GetWrappedTrans())) { 83 trans.GetWrappedTrans())) {
73 WriteEncryptionStateToNigori(&trans); 84 WriteEncryptionStateToNigori(&trans);
74 } 85 }
75 86
76 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 87 // Always trigger an encrypted types and cryptographer state change event at
77 OnCryptographerStateChanged(cryptographer)); 88 // init time so observers get the initial values.
89 FOR_EACH_OBSERVER(
90 Observer, observers_,
91 OnEncryptedTypesChanged(
92 UnlockVault(trans.GetWrappedTrans()).encrypted_types,
93 encrypt_everything_));
94 FOR_EACH_OBSERVER(
95 SyncEncryptionHandler::Observer,
96 observers_,
97 OnCryptographerStateChanged(
98 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer));
78 99
79 // If the cryptographer is not ready (either it has pending keys or we 100 // If the cryptographer is not ready (either it has pending keys or we
80 // failed to initialize it), we don't want to try and re-encrypt the data. 101 // failed to initialize it), we don't want to try and re-encrypt the data.
81 // If we had encrypted types, the DataTypeManager will block, preventing 102 // If we had encrypted types, the DataTypeManager will block, preventing
82 // sync from happening until the the passphrase is provided. 103 // sync from happening until the the passphrase is provided.
83 if (cryptographer->is_ready()) 104 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
84 ReEncryptEverything(&trans); 105 ReEncryptEverything(&trans);
85 } 106 }
86 107
87 // Note: this is called from within a syncable transaction, so we need to post
88 // tasks if we want to do any work that creates a new sync_api transaction.
89 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate(
90 const sync_pb::NigoriSpecifics& nigori,
91 syncable::BaseTransaction* const trans) {
92 DCHECK(trans);
93 if (!ApplyNigoriUpdateImpl(nigori, trans)) {
94 MessageLoop::current()->PostTask(
95 FROM_HERE,
96 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
97 weak_ptr_factory_.GetWeakPtr()));
98 }
99
100 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
101 OnCryptographerStateChanged(cryptographer_));
102 }
103
104 // Note: this is always called via the Cryptographer interface right now,
105 // so a transaction is already held. Once we remove that interface, we'll
106 // need to enforce holding a transaction when calling this method.
107 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes() const {
108 return encrypted_types_;
109 }
110
111 void SyncEncryptionHandlerImpl::SetEncryptionPassphrase( 108 void SyncEncryptionHandlerImpl::SetEncryptionPassphrase(
112 const std::string& passphrase, 109 const std::string& passphrase,
113 bool is_explicit) { 110 bool is_explicit) {
111 DCHECK(thread_checker_.CalledOnValidThread());
114 // We do not accept empty passphrases. 112 // We do not accept empty passphrases.
115 if (passphrase.empty()) { 113 if (passphrase.empty()) {
116 NOTREACHED() << "Cannot encrypt with an empty passphrase."; 114 NOTREACHED() << "Cannot encrypt with an empty passphrase.";
117 return; 115 return;
118 } 116 }
119 117
120 // All accesses to the cryptographer are protected by a transaction. 118 // All accesses to the cryptographer are protected by a transaction.
121 WriteTransaction trans(FROM_HERE, user_share_); 119 WriteTransaction trans(FROM_HERE, user_share_);
122 Cryptographer* cryptographer = trans.GetCryptographer();
123 KeyParams key_params = {"localhost", "dummy", passphrase}; 120 KeyParams key_params = {"localhost", "dummy", passphrase};
124 WriteNode node(&trans); 121 WriteNode node(&trans);
125 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { 122 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) {
126 NOTREACHED(); 123 NOTREACHED();
127 return; 124 return;
128 } 125 }
129 126
130 bool nigori_has_explicit_passphrase = 127 bool nigori_has_explicit_passphrase =
131 node.GetNigoriSpecifics().using_explicit_passphrase(); 128 node.GetNigoriSpecifics().using_explicit_passphrase();
132 std::string bootstrap_token; 129 std::string bootstrap_token;
133 sync_pb::EncryptedData pending_keys; 130 sync_pb::EncryptedData pending_keys;
131 Cryptographer* cryptographer =
132 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
134 if (cryptographer->has_pending_keys()) 133 if (cryptographer->has_pending_keys())
135 pending_keys = cryptographer->GetPendingKeys(); 134 pending_keys = cryptographer->GetPendingKeys();
136 bool success = false; 135 bool success = false;
137 136
138
139 // There are six cases to handle here: 137 // There are six cases to handle here:
140 // 1. The user has no pending keys and is setting their current GAIA password 138 // 1. The user has no pending keys and is setting their current GAIA password
141 // as the encryption passphrase. This happens either during first time sync 139 // as the encryption passphrase. This happens either during first time sync
142 // with a clean profile, or after re-authenticating on a profile that was 140 // with a clean profile, or after re-authenticating on a profile that was
143 // already signed in with the cryptographer ready. 141 // already signed in with the cryptographer ready.
144 // 2. The user has no pending keys, and is overwriting an (already provided) 142 // 2. The user has no pending keys, and is overwriting an (already provided)
145 // implicit passphrase with an explicit (custom) passphrase. 143 // implicit passphrase with an explicit (custom) passphrase.
146 // 3. The user has pending keys for an explicit passphrase that is somehow set 144 // 3. The user has pending keys for an explicit passphrase that is somehow set
147 // to their current GAIA passphrase. 145 // to their current GAIA passphrase.
148 // 4. The user has pending keys encrypted with their current GAIA passphrase 146 // 4. The user has pending keys encrypted with their current GAIA passphrase
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
217 DVLOG_IF(1, success) 215 DVLOG_IF(1, success)
218 << "Successfully set encryption passphrase; updating nigori and " 216 << "Successfully set encryption passphrase; updating nigori and "
219 "reencrypting."; 217 "reencrypting.";
220 218
221 FinishSetPassphrase( 219 FinishSetPassphrase(
222 success, bootstrap_token, is_explicit, &trans, &node); 220 success, bootstrap_token, is_explicit, &trans, &node);
223 } 221 }
224 222
225 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase( 223 void SyncEncryptionHandlerImpl::SetDecryptionPassphrase(
226 const std::string& passphrase) { 224 const std::string& passphrase) {
225 DCHECK(thread_checker_.CalledOnValidThread());
227 // We do not accept empty passphrases. 226 // We do not accept empty passphrases.
228 if (passphrase.empty()) { 227 if (passphrase.empty()) {
229 NOTREACHED() << "Cannot decrypt with an empty passphrase."; 228 NOTREACHED() << "Cannot decrypt with an empty passphrase.";
230 return; 229 return;
231 } 230 }
232 231
233 // All accesses to the cryptographer are protected by a transaction. 232 // All accesses to the cryptographer are protected by a transaction.
234 WriteTransaction trans(FROM_HERE, user_share_); 233 WriteTransaction trans(FROM_HERE, user_share_);
235 Cryptographer* cryptographer = trans.GetCryptographer();
236 KeyParams key_params = {"localhost", "dummy", passphrase}; 234 KeyParams key_params = {"localhost", "dummy", passphrase};
237 WriteNode node(&trans); 235 WriteNode node(&trans);
238 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) { 236 if (node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK) {
239 NOTREACHED(); 237 NOTREACHED();
240 return; 238 return;
241 } 239 }
242 240
241 Cryptographer* cryptographer =
242 &UnlockVaultMutable(trans.GetWrappedTrans())->cryptographer;
243 if (!cryptographer->has_pending_keys()) { 243 if (!cryptographer->has_pending_keys()) {
244 // Note that this *can* happen in a rare situation where data is 244 // Note that this *can* happen in a rare situation where data is
245 // re-encrypted on another client while a SetDecryptionPassphrase() call is 245 // re-encrypted on another client while a SetDecryptionPassphrase() call is
246 // in-flight on this client. It is rare enough that we choose to do nothing. 246 // in-flight on this client. It is rare enough that we choose to do nothing.
247 NOTREACHED() << "Attempt to set decryption passphrase failed because there " 247 NOTREACHED() << "Attempt to set decryption passphrase failed because there "
248 << "were no pending keys."; 248 << "were no pending keys.";
249 return; 249 return;
250 } 250 }
251 251
252 bool nigori_has_explicit_passphrase = 252 bool nigori_has_explicit_passphrase =
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 "reencrypting."; 357 "reencrypting.";
358 358
359 FinishSetPassphrase(success, 359 FinishSetPassphrase(success,
360 bootstrap_token, 360 bootstrap_token,
361 nigori_has_explicit_passphrase, 361 nigori_has_explicit_passphrase,
362 &trans, 362 &trans,
363 &node); 363 &node);
364 } 364 }
365 365
366 void SyncEncryptionHandlerImpl::EnableEncryptEverything() { 366 void SyncEncryptionHandlerImpl::EnableEncryptEverything() {
367 DCHECK(thread_checker_.CalledOnValidThread());
368 WriteTransaction trans(FROM_HERE, user_share_);
369 ModelTypeSet* encrypted_types =
370 &UnlockVaultMutable(trans.GetWrappedTrans())->encrypted_types;
367 if (encrypt_everything_) { 371 if (encrypt_everything_) {
368 DCHECK(encrypted_types_.Equals(ModelTypeSet::All())); 372 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
369 return; 373 return;
370 } 374 }
371 WriteTransaction trans(FROM_HERE, user_share_); 375 DVLOG(1) << "Enabling encrypt everything.";
372 encrypt_everything_ = true; 376 encrypt_everything_ = true;
373 // Change |encrypted_types_| directly to avoid sending more than one 377 // Change |encrypted_types_| directly to avoid sending more than one
374 // notification. 378 // notification.
375 encrypted_types_ = ModelTypeSet::All(); 379 *encrypted_types = ModelTypeSet::All();
376 FOR_EACH_OBSERVER( 380 FOR_EACH_OBSERVER(
377 Observer, observers_, 381 Observer, observers_,
378 OnEncryptedTypesChanged(encrypted_types_, encrypt_everything_)); 382 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
379 WriteEncryptionStateToNigori(&trans); 383 WriteEncryptionStateToNigori(&trans);
380 ReEncryptEverything(&trans); 384 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready())
385 ReEncryptEverything(&trans);
381 } 386 }
382 387
383 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { 388 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const {
384 ReadTransaction trans(FROM_HERE, user_share_); 389 DCHECK(thread_checker_.CalledOnValidThread());
385 return encrypt_everything_; 390 return encrypt_everything_;
386 } 391 }
387 392
388 bool SyncEncryptionHandlerImpl::IsUsingExplicitPassphrase() const { 393 bool SyncEncryptionHandlerImpl::IsUsingExplicitPassphrase() const {
394 // TODO(zea): this is called from the UI thread, so we have to have a
395 // transaction while accessing it. Add an OnPassphraseTypeChanged observer
396 // and have the SBH cache the value on the UI thread.
389 ReadTransaction trans(FROM_HERE, user_share_); 397 ReadTransaction trans(FROM_HERE, user_share_);
390 return explicit_passphrase_; 398 return explicit_passphrase_;
391 } 399 }
392 400
401 // Note: this is called from within a syncable transaction, so we need to post
402 // tasks if we want to do any work that creates a new sync_api transaction.
403 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate(
404 const sync_pb::NigoriSpecifics& nigori,
405 syncable::BaseTransaction* const trans) {
406 DCHECK(thread_checker_.CalledOnValidThread());
407 DCHECK(trans);
408 if (!ApplyNigoriUpdateImpl(nigori, trans)) {
409 MessageLoop::current()->PostTask(
410 FROM_HERE,
411 base::Bind(&SyncEncryptionHandlerImpl::RewriteNigori,
412 weak_ptr_factory_.GetWeakPtr()));
413 }
414
415 FOR_EACH_OBSERVER(
416 SyncEncryptionHandler::Observer,
417 observers_,
418 OnCryptographerStateChanged(
419 &UnlockVaultMutable(trans)->cryptographer));
420 }
421
422 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes(
423 sync_pb::NigoriSpecifics* nigori,
424 syncable::BaseTransaction* const trans) const {
425 syncable::UpdateNigoriFromEncryptedTypes(UnlockVault(trans).encrypted_types,
426 encrypt_everything_,
427 nigori);
428 }
429
430 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypes(
431 syncable::BaseTransaction* const trans) const {
432 return UnlockVault(trans).encrypted_types;
433 }
434
435 Cryptographer* SyncEncryptionHandlerImpl::GetCryptographerUnsafe() {
436 DCHECK(thread_checker_.CalledOnValidThread());
437 return &vault_unsafe_.cryptographer;
438 }
439
440 ModelTypeSet SyncEncryptionHandlerImpl::GetEncryptedTypesUnsafe() {
441 DCHECK(thread_checker_.CalledOnValidThread());
442 return vault_unsafe_.encrypted_types;
443 }
444
393 // This function iterates over all encrypted types. There are many scenarios in 445 // This function iterates over all encrypted types. There are many scenarios in
394 // which data for some or all types is not currently available. In that case, 446 // which data for some or all types is not currently available. In that case,
395 // the lookup of the root node will fail and we will skip encryption for that 447 // the lookup of the root node will fail and we will skip encryption for that
396 // type. 448 // type.
397 void SyncEncryptionHandlerImpl::ReEncryptEverything( 449 void SyncEncryptionHandlerImpl::ReEncryptEverything(
398 WriteTransaction* trans) { 450 WriteTransaction* trans) {
399 Cryptographer* cryptographer = trans->GetCryptographer(); 451 DCHECK(thread_checker_.CalledOnValidThread());
400 if (!cryptographer->is_ready()) 452 DCHECK(UnlockVault(trans->GetWrappedTrans()).cryptographer.is_ready());
401 return; 453 for (ModelTypeSet::Iterator iter =
402 ModelTypeSet encrypted_types = GetEncryptedTypes(); 454 UnlockVault(trans->GetWrappedTrans()).encrypted_types.First();
403 for (ModelTypeSet::Iterator iter = encrypted_types.First();
404 iter.Good(); iter.Inc()) { 455 iter.Good(); iter.Inc()) {
405 if (iter.Get() == PASSWORDS || iter.Get() == NIGORI) 456 if (iter.Get() == PASSWORDS || iter.Get() == NIGORI)
406 continue; // These types handle encryption differently. 457 continue; // These types handle encryption differently.
407 458
408 ReadNode type_root(trans); 459 ReadNode type_root(trans);
409 std::string tag = ModelTypeToRootTag(iter.Get()); 460 std::string tag = ModelTypeToRootTag(iter.Get());
410 if (type_root.InitByTagLookup(tag) != BaseNode::INIT_OK) 461 if (type_root.InitByTagLookup(tag) != BaseNode::INIT_OK)
411 continue; // Don't try to reencrypt if the type's data is unavailable. 462 continue; // Don't try to reencrypt if the type's data is unavailable.
412 463
413 // Iterate through all children of this datatype. 464 // Iterate through all children of this datatype.
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
448 WriteNode child(trans); 499 WriteNode child(trans);
449 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) { 500 if (child.InitByIdLookup(child_id) != BaseNode::INIT_OK) {
450 NOTREACHED(); 501 NOTREACHED();
451 return; 502 return;
452 } 503 }
453 child.SetPasswordSpecifics(child.GetPasswordSpecifics()); 504 child.SetPasswordSpecifics(child.GetPasswordSpecifics());
454 child_id = child.GetSuccessorId(); 505 child_id = child.GetSuccessorId();
455 } 506 }
456 } 507 }
457 508
509 DVLOG(1) << "Re-encrypt everything complete.";
510
458 // NOTE: We notify from within a transaction. 511 // NOTE: We notify from within a transaction.
459 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 512 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
460 OnEncryptionComplete()); 513 OnEncryptionComplete());
461 } 514 }
462 515
463 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( 516 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl(
464 const sync_pb::NigoriSpecifics& nigori, 517 const sync_pb::NigoriSpecifics& nigori,
465 syncable::BaseTransaction* const trans) { 518 syncable::BaseTransaction* const trans) {
466 Cryptographer* cryptographer = trans->directory()->GetCryptographer(trans); 519 DCHECK(thread_checker_.CalledOnValidThread());
467 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori); 520 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori,
521 trans);
468 if (nigori.using_explicit_passphrase()) 522 if (nigori.using_explicit_passphrase())
469 explicit_passphrase_ = true; 523 explicit_passphrase_ = true;
470 524
525 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer;
471 bool nigori_needs_new_keys = false; 526 bool nigori_needs_new_keys = false;
472 if (!nigori.encrypted().blob().empty()) { 527 if (!nigori.encrypted().blob().empty()) {
473 if (cryptographer->CanDecrypt(nigori.encrypted())) { 528 if (cryptographer->CanDecrypt(nigori.encrypted())) {
474 cryptographer->InstallKeys(nigori.encrypted()); 529 cryptographer->InstallKeys(nigori.encrypted());
475 // We only update the default passphrase if this was a new explicit 530 // We only update the default passphrase if this was a new explicit
476 // passphrase. Else, since it was decryptable, it must not have been a new 531 // passphrase. Else, since it was decryptable, it must not have been a new
477 // key. 532 // key.
478 if (nigori.using_explicit_passphrase()) 533 if (nigori.using_explicit_passphrase())
479 cryptographer->SetDefaultKey(nigori.encrypted().key_name()); 534 cryptographer->SetDefaultKey(nigori.encrypted().key_name());
480 535
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 if (nigori.using_explicit_passphrase() != explicit_passphrase_ || 570 if (nigori.using_explicit_passphrase() != explicit_passphrase_ ||
516 nigori.encrypt_everything() != encrypt_everything_ || 571 nigori.encrypt_everything() != encrypt_everything_ ||
517 nigori_types_need_update || 572 nigori_types_need_update ||
518 nigori_needs_new_keys) { 573 nigori_needs_new_keys) {
519 return false; 574 return false;
520 } 575 }
521 return true; 576 return true;
522 } 577 }
523 578
524 void SyncEncryptionHandlerImpl::RewriteNigori() { 579 void SyncEncryptionHandlerImpl::RewriteNigori() {
580 DVLOG(1) << "Overwriting stale nigori node.";
581 DCHECK(thread_checker_.CalledOnValidThread());
525 WriteTransaction trans(FROM_HERE, user_share_); 582 WriteTransaction trans(FROM_HERE, user_share_);
526 WriteEncryptionStateToNigori(&trans); 583 WriteEncryptionStateToNigori(&trans);
527 } 584 }
528 585
529 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori( 586 void SyncEncryptionHandlerImpl::WriteEncryptionStateToNigori(
530 WriteTransaction* trans) { 587 WriteTransaction* trans) {
588 DCHECK(thread_checker_.CalledOnValidThread());
531 WriteNode nigori_node(trans); 589 WriteNode nigori_node(trans);
532 // This can happen in tests that don't have nigori nodes. 590 // This can happen in tests that don't have nigori nodes.
533 if (!nigori_node.InitByTagLookup(kNigoriTag) == BaseNode::INIT_OK) 591 if (nigori_node.InitByTagLookup(kNigoriTag) != BaseNode::INIT_OK)
534 return; 592 return;
535 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics(); 593 sync_pb::NigoriSpecifics nigori = nigori_node.GetNigoriSpecifics();
536 Cryptographer* cryptographer = trans->GetCryptographer(); 594 const Cryptographer& cryptographer =
537 if (cryptographer->is_ready() && 595 UnlockVault(trans->GetWrappedTrans()).cryptographer;
596 if (cryptographer.is_ready() &&
538 nigori_overwrite_count_ < kNigoriOverwriteLimit) { 597 nigori_overwrite_count_ < kNigoriOverwriteLimit) {
539 // Does not modify the encrypted blob if the unencrypted data already 598 // Does not modify the encrypted blob if the unencrypted data already
540 // matches what is about to be written. 599 // matches what is about to be written.
541 sync_pb::EncryptedData original_keys = nigori.encrypted(); 600 sync_pb::EncryptedData original_keys = nigori.encrypted();
542 if (!cryptographer->GetKeys(nigori.mutable_encrypted())) 601 if (!cryptographer.GetKeys(nigori.mutable_encrypted()))
543 NOTREACHED(); 602 NOTREACHED();
544 603
545 if (nigori.encrypted().SerializeAsString() != 604 if (nigori.encrypted().SerializeAsString() !=
546 original_keys.SerializeAsString()) { 605 original_keys.SerializeAsString()) {
547 // We've updated the nigori node's encryption keys. In order to prevent 606 // We've updated the nigori node's encryption keys. In order to prevent
548 // a possible looping of two clients constantly overwriting each other, 607 // a possible looping of two clients constantly overwriting each other,
549 // we limit the absolute number of overwrites per client instantiation. 608 // we limit the absolute number of overwrites per client instantiation.
550 nigori_overwrite_count_++; 609 nigori_overwrite_count_++;
551 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites", 610 UMA_HISTOGRAM_COUNTS("Sync.AutoNigoriOverwrites",
552 nigori_overwrite_count_); 611 nigori_overwrite_count_);
553 } 612 }
554 613
555 // Note: we don't try to set using_explicit_passphrase here since if that 614 // Note: we don't try to set using_explicit_passphrase here since if that
556 // is lost the user can always set it again. The main point is to preserve 615 // is lost the user can always set it again. The main point is to preserve
557 // the encryption keys so all data remains decryptable. 616 // the encryption keys so all data remains decryptable.
558 } 617 }
559 syncable::UpdateNigoriFromEncryptedTypes(encrypted_types_, 618 syncable::UpdateNigoriFromEncryptedTypes(
560 encrypt_everything_, 619 UnlockVault(trans->GetWrappedTrans()).encrypted_types,
561 &nigori); 620 encrypt_everything_,
621 &nigori);
562 622
563 // If nothing has changed, this is a no-op. 623 // If nothing has changed, this is a no-op.
564 nigori_node.SetNigoriSpecifics(nigori); 624 nigori_node.SetNigoriSpecifics(nigori);
565 } 625 }
566 626
567 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori( 627 bool SyncEncryptionHandlerImpl::UpdateEncryptedTypesFromNigori(
568 const sync_pb::NigoriSpecifics& nigori) { 628 const sync_pb::NigoriSpecifics& nigori,
629 syncable::BaseTransaction* const trans) {
630 DCHECK(thread_checker_.CalledOnValidThread());
631 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
569 if (nigori.encrypt_everything()) { 632 if (nigori.encrypt_everything()) {
570 if (!encrypt_everything_) { 633 if (!encrypt_everything_) {
571 encrypt_everything_ = true; 634 encrypt_everything_ = true;
572 encrypted_types_ = ModelTypeSet::All(); 635 *encrypted_types = ModelTypeSet::All();
636 DVLOG(1) << "Enabling encrypt everything via nigori node update";
573 FOR_EACH_OBSERVER( 637 FOR_EACH_OBSERVER(
574 Observer, observers_, 638 Observer, observers_,
575 OnEncryptedTypesChanged(encrypted_types_, encrypt_everything_)); 639 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
576 } 640 }
577 DCHECK(encrypted_types_.Equals(ModelTypeSet::All())); 641 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
578 return true; 642 return true;
579 } 643 }
580 644
581 ModelTypeSet encrypted_types; 645 ModelTypeSet nigori_encrypted_types;
582 encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori); 646 nigori_encrypted_types = syncable::GetEncryptedTypesFromNigori(nigori);
583 encrypted_types.PutAll(SensitiveTypes()); 647 nigori_encrypted_types.PutAll(SensitiveTypes());
584 648
585 // If anything more than the sensitive types were encrypted, and 649 // If anything more than the sensitive types were encrypted, and
586 // encrypt_everything is not explicitly set to false, we assume it means 650 // encrypt_everything is not explicitly set to false, we assume it means
587 // a client intended to enable encrypt everything. 651 // a client intended to enable encrypt everything.
588 if (!nigori.has_encrypt_everything() && 652 if (!nigori.has_encrypt_everything() &&
589 !Difference(encrypted_types, SensitiveTypes()).Empty()) { 653 !Difference(nigori_encrypted_types, SensitiveTypes()).Empty()) {
590 if (!encrypt_everything_) { 654 if (!encrypt_everything_) {
591 encrypt_everything_ = true; 655 encrypt_everything_ = true;
592 encrypted_types_ = ModelTypeSet::All(); 656 *encrypted_types = ModelTypeSet::All();
593 FOR_EACH_OBSERVER( 657 FOR_EACH_OBSERVER(
594 Observer, observers_, 658 Observer, observers_,
595 OnEncryptedTypesChanged(encrypted_types_, encrypt_everything_)); 659 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
596 } 660 }
597 DCHECK(encrypted_types_.Equals(ModelTypeSet::All())); 661 DCHECK(encrypted_types->Equals(ModelTypeSet::All()));
598 return false; 662 return false;
599 } 663 }
600 664
601 MergeEncryptedTypes(encrypted_types); 665 MergeEncryptedTypes(nigori_encrypted_types, trans);
602 return encrypted_types_.Equals(encrypted_types); 666 return encrypted_types->Equals(nigori_encrypted_types);
603 }
604
605 void SyncEncryptionHandlerImpl::UpdateNigoriFromEncryptedTypes(
606 sync_pb::NigoriSpecifics* nigori,
607 syncable::BaseTransaction* const trans) const {
608 syncable::UpdateNigoriFromEncryptedTypes(encrypted_types_,
609 encrypt_everything_,
610 nigori);
611 } 667 }
612 668
613 void SyncEncryptionHandlerImpl::FinishSetPassphrase( 669 void SyncEncryptionHandlerImpl::FinishSetPassphrase(
614 bool success, 670 bool success,
615 const std::string& bootstrap_token, 671 const std::string& bootstrap_token,
616 bool is_explicit, 672 bool is_explicit,
617 WriteTransaction* trans, 673 WriteTransaction* trans,
618 WriteNode* nigori_node) { 674 WriteNode* nigori_node) {
619 Cryptographer* cryptographer = trans->GetCryptographer(); 675 DCHECK(thread_checker_.CalledOnValidThread());
620 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 676 FOR_EACH_OBSERVER(
621 OnCryptographerStateChanged(cryptographer)); 677 SyncEncryptionHandler::Observer,
678 observers_,
679 OnCryptographerStateChanged(
680 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer));
622 681
623 // It's possible we need to change the bootstrap token even if we failed to 682 // It's possible we need to change the bootstrap token even if we failed to
624 // set the passphrase (for example if we need to preserve the new GAIA 683 // set the passphrase (for example if we need to preserve the new GAIA
625 // passphrase). 684 // passphrase).
626 if (!bootstrap_token.empty()) { 685 if (!bootstrap_token.empty()) {
627 DVLOG(1) << "Bootstrap token updated."; 686 DVLOG(1) << "Bootstrap token updated.";
628 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 687 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
629 OnBootstrapTokenUpdated(bootstrap_token)); 688 OnBootstrapTokenUpdated(bootstrap_token));
630 } 689 }
631 690
691 const Cryptographer& cryptographer =
692 UnlockVault(trans->GetWrappedTrans()).cryptographer;
632 if (!success) { 693 if (!success) {
633 if (cryptographer->is_ready()) { 694 if (cryptographer.is_ready()) {
634 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " 695 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer "
635 << "was ready."; 696 << "was ready.";
636 } else if (cryptographer->has_pending_keys()) { 697 } else if (cryptographer.has_pending_keys()) {
637 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 698 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
638 OnPassphraseRequired(REASON_DECRYPTION, 699 OnPassphraseRequired(REASON_DECRYPTION,
639 cryptographer->GetPendingKeys())); 700 cryptographer.GetPendingKeys()));
640 } else { 701 } else {
641 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 702 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
642 OnPassphraseRequired(REASON_ENCRYPTION, 703 OnPassphraseRequired(REASON_ENCRYPTION,
643 sync_pb::EncryptedData())); 704 sync_pb::EncryptedData()));
644 } 705 }
645 return; 706 return;
646 } 707 }
647 708
648 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, 709 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_,
649 OnPassphraseAccepted()); 710 OnPassphraseAccepted());
650 DCHECK(cryptographer->is_ready()); 711 DCHECK(cryptographer.is_ready());
651 712
652 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); 713 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics());
653 // Does not modify specifics.encrypted() if the original decrypted data was 714 // Does not modify specifics.encrypted() if the original decrypted data was
654 // the same. 715 // the same.
655 if (!cryptographer->GetKeys(specifics.mutable_encrypted())) { 716 if (!cryptographer.GetKeys(specifics.mutable_encrypted()))
656 NOTREACHED(); 717 NOTREACHED();
657 return;
658 }
659 explicit_passphrase_ = is_explicit; 718 explicit_passphrase_ = is_explicit;
660 specifics.set_using_explicit_passphrase(is_explicit); 719 specifics.set_using_explicit_passphrase(is_explicit);
661 nigori_node->SetNigoriSpecifics(specifics); 720 nigori_node->SetNigoriSpecifics(specifics);
662 721
663 // Does nothing if everything is already encrypted or the cryptographer has 722 // Does nothing if everything is already encrypted.
664 // pending keys.
665 ReEncryptEverything(trans); 723 ReEncryptEverything(trans);
666 } 724 }
667 725
668 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( 726 void SyncEncryptionHandlerImpl::MergeEncryptedTypes(
669 ModelTypeSet encrypted_types) { 727 ModelTypeSet new_encrypted_types,
670 if (!encrypted_types_.HasAll(encrypted_types)) { 728 syncable::BaseTransaction* const trans) {
671 encrypted_types_ = encrypted_types; 729 DCHECK(thread_checker_.CalledOnValidThread());
730 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types;
731 if (!encrypted_types->HasAll(new_encrypted_types)) {
732 *encrypted_types = new_encrypted_types;
672 FOR_EACH_OBSERVER( 733 FOR_EACH_OBSERVER(
673 Observer, observers_, 734 Observer, observers_,
674 OnEncryptedTypesChanged(encrypted_types_, encrypt_everything_)); 735 OnEncryptedTypesChanged(*encrypted_types, encrypt_everything_));
675 } 736 }
676 } 737 }
677 738
739 SyncEncryptionHandlerImpl::Vault* SyncEncryptionHandlerImpl::UnlockVaultMutable(
740 syncable::BaseTransaction* const trans) {
741 DCHECK_EQ(user_share_->directory.get(), trans->directory());
742 return &vault_unsafe_;
743 }
744
745 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault(
746 syncable::BaseTransaction* const trans) const {
747 DCHECK_EQ(user_share_->directory.get(), trans->directory());
748 return vault_unsafe_;
749 }
750
678 } // namespace browser_sync 751 } // namespace browser_sync
OLDNEW
« no previous file with comments | « sync/internal_api/sync_encryption_handler_impl.h ('k') | sync/internal_api/sync_encryption_handler_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698