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" |
(...skipping 22 matching lines...) Expand all Loading... |
33 // because the encryption keys don't match (per chrome instantiation). | 33 // because the encryption keys don't match (per chrome instantiation). |
34 // We protect ourselves against nigori rollbacks, but it's possible two | 34 // We protect ourselves against nigori rollbacks, but it's possible two |
35 // 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 |
36 // 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). |
37 static const int kNigoriOverwriteLimit = 10; | 37 static const int kNigoriOverwriteLimit = 10; |
38 } | 38 } |
39 | 39 |
40 SyncEncryptionHandlerImpl::Vault::Vault( | 40 SyncEncryptionHandlerImpl::Vault::Vault( |
41 Encryptor* encryptor, | 41 Encryptor* encryptor, |
42 ModelTypeSet encrypted_types) | 42 ModelTypeSet encrypted_types) |
43 : cryptographer(encryptor), | 43 : cryptographer(encryptor), |
44 encrypted_types(encrypted_types) { | 44 encrypted_types(encrypted_types) { |
45 } | 45 } |
46 | 46 |
47 SyncEncryptionHandlerImpl::Vault::~Vault() { | 47 SyncEncryptionHandlerImpl::Vault::~Vault() { |
48 } | 48 } |
49 | 49 |
50 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( | 50 SyncEncryptionHandlerImpl::SyncEncryptionHandlerImpl( |
51 UserShare* user_share, | 51 UserShare* user_share, |
52 Encryptor* encryptor) | 52 Encryptor* encryptor) |
53 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 53 : weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
54 user_share_(user_share), | 54 user_share_(user_share), |
55 vault_unsafe_(encryptor, SensitiveTypes()), | 55 vault_unsafe_(encryptor, SensitiveTypes()), |
56 encrypt_everything_(false), | 56 encrypt_everything_(false), |
57 explicit_passphrase_(false), | 57 passphrase_state_(IMPLICIT_PASSPHRASE), |
58 nigori_overwrite_count_(0) { | 58 nigori_overwrite_count_(0) { |
59 } | 59 } |
60 | 60 |
61 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} | 61 SyncEncryptionHandlerImpl::~SyncEncryptionHandlerImpl() {} |
62 | 62 |
63 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { | 63 void SyncEncryptionHandlerImpl::AddObserver(Observer* observer) { |
64 DCHECK(thread_checker_.CalledOnValidThread()); | 64 DCHECK(thread_checker_.CalledOnValidThread()); |
65 DCHECK(!observers_.HasObserver(observer)); | 65 DCHECK(!observers_.HasObserver(observer)); |
66 observers_.AddObserver(observer); | 66 observers_.AddObserver(observer); |
67 } | 67 } |
(...skipping 315 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 WriteEncryptionStateToNigori(&trans); | 383 WriteEncryptionStateToNigori(&trans); |
384 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) | 384 if (UnlockVault(trans.GetWrappedTrans()).cryptographer.is_ready()) |
385 ReEncryptEverything(&trans); | 385 ReEncryptEverything(&trans); |
386 } | 386 } |
387 | 387 |
388 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { | 388 bool SyncEncryptionHandlerImpl::EncryptEverythingEnabled() const { |
389 DCHECK(thread_checker_.CalledOnValidThread()); | 389 DCHECK(thread_checker_.CalledOnValidThread()); |
390 return encrypt_everything_; | 390 return encrypt_everything_; |
391 } | 391 } |
392 | 392 |
393 bool SyncEncryptionHandlerImpl::IsUsingExplicitPassphrase() const { | 393 PassphraseState SyncEncryptionHandlerImpl::GetPassphraseState() const { |
394 // TODO(zea): this is called from the UI thread, so we have to have a | 394 DCHECK(thread_checker_.CalledOnValidThread()); |
395 // transaction while accessing it. Add an OnPassphraseTypeChanged observer | 395 return passphrase_state_; |
396 // and have the SBH cache the value on the UI thread. | |
397 ReadTransaction trans(FROM_HERE, user_share_); | |
398 return explicit_passphrase_; | |
399 } | 396 } |
400 | 397 |
401 // Note: this is called from within a syncable transaction, so we need to post | 398 // 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. | 399 // tasks if we want to do any work that creates a new sync_api transaction. |
403 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( | 400 void SyncEncryptionHandlerImpl::ApplyNigoriUpdate( |
404 const sync_pb::NigoriSpecifics& nigori, | 401 const sync_pb::NigoriSpecifics& nigori, |
405 syncable::BaseTransaction* const trans) { | 402 syncable::BaseTransaction* const trans) { |
406 DCHECK(thread_checker_.CalledOnValidThread()); | 403 DCHECK(thread_checker_.CalledOnValidThread()); |
407 DCHECK(trans); | 404 DCHECK(trans); |
408 if (!ApplyNigoriUpdateImpl(nigori, trans)) { | 405 if (!ApplyNigoriUpdateImpl(nigori, trans)) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
510 | 507 |
511 // NOTE: We notify from within a transaction. | 508 // NOTE: We notify from within a transaction. |
512 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 509 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
513 OnEncryptionComplete()); | 510 OnEncryptionComplete()); |
514 } | 511 } |
515 | 512 |
516 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( | 513 bool SyncEncryptionHandlerImpl::ApplyNigoriUpdateImpl( |
517 const sync_pb::NigoriSpecifics& nigori, | 514 const sync_pb::NigoriSpecifics& nigori, |
518 syncable::BaseTransaction* const trans) { | 515 syncable::BaseTransaction* const trans) { |
519 DCHECK(thread_checker_.CalledOnValidThread()); | 516 DCHECK(thread_checker_.CalledOnValidThread()); |
| 517 DVLOG(1) << "Applying nigori node update."; |
520 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori, | 518 bool nigori_types_need_update = !UpdateEncryptedTypesFromNigori(nigori, |
521 trans); | 519 trans); |
522 if (nigori.using_explicit_passphrase()) | 520 if (nigori.using_explicit_passphrase() && |
523 explicit_passphrase_ = true; | 521 passphrase_state_ != CUSTOM_PASSPHRASE) { |
| 522 passphrase_state_ = CUSTOM_PASSPHRASE; |
| 523 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 524 OnPassphraseStateChanged(passphrase_state_)); |
| 525 } |
524 | 526 |
525 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; | 527 Cryptographer* cryptographer = &UnlockVaultMutable(trans)->cryptographer; |
526 bool nigori_needs_new_keys = false; | 528 bool nigori_needs_new_keys = false; |
527 if (!nigori.encrypted().blob().empty()) { | 529 if (!nigori.encrypted().blob().empty()) { |
528 if (cryptographer->CanDecrypt(nigori.encrypted())) { | 530 if (cryptographer->CanDecrypt(nigori.encrypted())) { |
529 cryptographer->InstallKeys(nigori.encrypted()); | 531 cryptographer->InstallKeys(nigori.encrypted()); |
530 // We only update the default passphrase if this was a new explicit | 532 // We only update the default passphrase if this was a new explicit |
531 // passphrase. Else, since it was decryptable, it must not have been a new | 533 // passphrase. Else, since it was decryptable, it must not have been a new |
532 // key. | 534 // key. |
533 if (nigori.using_explicit_passphrase()) | 535 if (nigori.using_explicit_passphrase()) |
(...skipping 26 matching lines...) Expand all Loading... |
560 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " | 562 DVLOG(1) << "OnPassphraseRequired sent because cryptographer is not " |
561 << "ready"; | 563 << "ready"; |
562 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 564 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
563 OnPassphraseRequired(REASON_ENCRYPTION, | 565 OnPassphraseRequired(REASON_ENCRYPTION, |
564 sync_pb::EncryptedData())); | 566 sync_pb::EncryptedData())); |
565 } | 567 } |
566 | 568 |
567 // Check if the current local encryption state is stricter/newer than the | 569 // Check if the current local encryption state is stricter/newer than the |
568 // nigori state. If so, we need to overwrite the nigori node with the local | 570 // nigori state. If so, we need to overwrite the nigori node with the local |
569 // state. | 571 // state. |
570 if (nigori.using_explicit_passphrase() != explicit_passphrase_ || | 572 bool explicit_passphrase = passphrase_state_ == CUSTOM_PASSPHRASE; |
| 573 if (nigori.using_explicit_passphrase() != explicit_passphrase || |
571 nigori.encrypt_everything() != encrypt_everything_ || | 574 nigori.encrypt_everything() != encrypt_everything_ || |
572 nigori_types_need_update || | 575 nigori_types_need_update || |
573 nigori_needs_new_keys) { | 576 nigori_needs_new_keys) { |
574 return false; | 577 return false; |
575 } | 578 } |
576 return true; | 579 return true; |
577 } | 580 } |
578 | 581 |
579 void SyncEncryptionHandlerImpl::RewriteNigori() { | 582 void SyncEncryptionHandlerImpl::RewriteNigori() { |
580 DVLOG(1) << "Overwriting stale nigori node."; | 583 DVLOG(1) << "Overwriting stale nigori node."; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 FOR_EACH_OBSERVER( | 679 FOR_EACH_OBSERVER( |
677 SyncEncryptionHandler::Observer, | 680 SyncEncryptionHandler::Observer, |
678 observers_, | 681 observers_, |
679 OnCryptographerStateChanged( | 682 OnCryptographerStateChanged( |
680 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); | 683 &UnlockVaultMutable(trans->GetWrappedTrans())->cryptographer)); |
681 | 684 |
682 // It's possible we need to change the bootstrap token even if we failed to | 685 // It's possible we need to change the bootstrap token even if we failed to |
683 // set the passphrase (for example if we need to preserve the new GAIA | 686 // set the passphrase (for example if we need to preserve the new GAIA |
684 // passphrase). | 687 // passphrase). |
685 if (!bootstrap_token.empty()) { | 688 if (!bootstrap_token.empty()) { |
686 DVLOG(1) << "Bootstrap token updated."; | 689 DVLOG(1) << "Passphrase bootstrap token updated."; |
687 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 690 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
688 OnBootstrapTokenUpdated(bootstrap_token)); | 691 OnBootstrapTokenUpdated(bootstrap_token)); |
689 } | 692 } |
690 | 693 |
691 const Cryptographer& cryptographer = | 694 const Cryptographer& cryptographer = |
692 UnlockVault(trans->GetWrappedTrans()).cryptographer; | 695 UnlockVault(trans->GetWrappedTrans()).cryptographer; |
693 if (!success) { | 696 if (!success) { |
694 if (cryptographer.is_ready()) { | 697 if (cryptographer.is_ready()) { |
695 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " | 698 LOG(ERROR) << "Attempt to change passphrase failed while cryptographer " |
696 << "was ready."; | 699 << "was ready."; |
697 } else if (cryptographer.has_pending_keys()) { | 700 } else if (cryptographer.has_pending_keys()) { |
698 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 701 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
699 OnPassphraseRequired(REASON_DECRYPTION, | 702 OnPassphraseRequired(REASON_DECRYPTION, |
700 cryptographer.GetPendingKeys())); | 703 cryptographer.GetPendingKeys())); |
701 } else { | 704 } else { |
702 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | 705 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
703 OnPassphraseRequired(REASON_ENCRYPTION, | 706 OnPassphraseRequired(REASON_ENCRYPTION, |
704 sync_pb::EncryptedData())); | 707 sync_pb::EncryptedData())); |
705 } | 708 } |
706 return; | 709 return; |
707 } | 710 } |
708 | 711 |
709 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, | |
710 OnPassphraseAccepted()); | |
711 DCHECK(cryptographer.is_ready()); | 712 DCHECK(cryptographer.is_ready()); |
712 | 713 |
713 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); | 714 sync_pb::NigoriSpecifics specifics(nigori_node->GetNigoriSpecifics()); |
714 // Does not modify specifics.encrypted() if the original decrypted data was | 715 // Does not modify specifics.encrypted() if the original decrypted data was |
715 // the same. | 716 // the same. |
716 if (!cryptographer.GetKeys(specifics.mutable_encrypted())) | 717 if (!cryptographer.GetKeys(specifics.mutable_encrypted())) |
717 NOTREACHED(); | 718 NOTREACHED(); |
718 explicit_passphrase_ = is_explicit; | 719 if (is_explicit && passphrase_state_ != CUSTOM_PASSPHRASE) { |
| 720 passphrase_state_ = CUSTOM_PASSPHRASE; |
| 721 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 722 OnPassphraseStateChanged(passphrase_state_)); |
| 723 } |
719 specifics.set_using_explicit_passphrase(is_explicit); | 724 specifics.set_using_explicit_passphrase(is_explicit); |
720 nigori_node->SetNigoriSpecifics(specifics); | 725 nigori_node->SetNigoriSpecifics(specifics); |
721 | 726 |
| 727 // Must do this after OnPassphraseStateChanged, in order to ensure the PSS |
| 728 // checks the passphrase state after it has been set. |
| 729 FOR_EACH_OBSERVER(SyncEncryptionHandler::Observer, observers_, |
| 730 OnPassphraseAccepted()); |
| 731 |
722 // Does nothing if everything is already encrypted. | 732 // Does nothing if everything is already encrypted. |
723 ReEncryptEverything(trans); | 733 ReEncryptEverything(trans); |
724 } | 734 } |
725 | 735 |
726 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( | 736 void SyncEncryptionHandlerImpl::MergeEncryptedTypes( |
727 ModelTypeSet new_encrypted_types, | 737 ModelTypeSet new_encrypted_types, |
728 syncable::BaseTransaction* const trans) { | 738 syncable::BaseTransaction* const trans) { |
729 DCHECK(thread_checker_.CalledOnValidThread()); | 739 DCHECK(thread_checker_.CalledOnValidThread()); |
730 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; | 740 ModelTypeSet* encrypted_types = &UnlockVaultMutable(trans)->encrypted_types; |
731 if (!encrypted_types->HasAll(new_encrypted_types)) { | 741 if (!encrypted_types->HasAll(new_encrypted_types)) { |
(...skipping 10 matching lines...) Expand all Loading... |
742 return &vault_unsafe_; | 752 return &vault_unsafe_; |
743 } | 753 } |
744 | 754 |
745 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( | 755 const SyncEncryptionHandlerImpl::Vault& SyncEncryptionHandlerImpl::UnlockVault( |
746 syncable::BaseTransaction* const trans) const { | 756 syncable::BaseTransaction* const trans) const { |
747 DCHECK_EQ(user_share_->directory.get(), trans->directory()); | 757 DCHECK_EQ(user_share_->directory.get(), trans->directory()); |
748 return vault_unsafe_; | 758 return vault_unsafe_; |
749 } | 759 } |
750 | 760 |
751 } // namespace browser_sync | 761 } // namespace browser_sync |
OLD | NEW |