This source file includes following definitions.
- BuildEncryptionKeyProto
- SetUp
- TearDown
- SetUpEncryption
- CreateRootForType
- PumpLoop
- user_share
- encryption_handler
- observer
- GetCryptographer
- VerifyMigratedNigori
- VerifyMigratedNigoriWithTimestamp
- BuildMigratedNigori
- InitKeystoreMigratedNigori
- InitCustomPassMigratedNigori
- InitUnmigratedNigori
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "sync/internal_api/sync_encryption_handler_impl.h"
#include <string>
#include "base/base64.h"
#include "base/json/json_string_value_serializer.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/tracked_objects.h"
#include "sync/internal_api/public/base/model_type_test_util.h"
#include "sync/internal_api/public/read_node.h"
#include "sync/internal_api/public/read_transaction.h"
#include "sync/internal_api/public/test/test_user_share.h"
#include "sync/internal_api/public/write_node.h"
#include "sync/internal_api/public/write_transaction.h"
#include "sync/protocol/nigori_specifics.pb.h"
#include "sync/protocol/sync.pb.h"
#include "sync/syncable/entry.h"
#include "sync/syncable/mutable_entry.h"
#include "sync/syncable/syncable_write_transaction.h"
#include "sync/test/engine/test_id_factory.h"
#include "sync/test/fake_encryptor.h"
#include "sync/util/cryptographer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::AtLeast;
using ::testing::Mock;
using ::testing::SaveArg;
using ::testing::StrictMock;
static const char kRawKeystoreKey[] = "keystore_key";
static const char kKeystoreKey[] = "a2V5c3RvcmVfa2V5";
class SyncEncryptionHandlerObserverMock
: public SyncEncryptionHandler::Observer {
public:
MOCK_METHOD2(OnPassphraseRequired,
void(PassphraseRequiredReason,
const sync_pb::EncryptedData&));
MOCK_METHOD0(OnPassphraseAccepted, void());
MOCK_METHOD2(OnBootstrapTokenUpdated,
void(const std::string&, BootstrapTokenType type));
MOCK_METHOD2(OnEncryptedTypesChanged,
void(ModelTypeSet, bool));
MOCK_METHOD0(OnEncryptionComplete, void());
MOCK_METHOD1(OnCryptographerStateChanged, void(Cryptographer*));
MOCK_METHOD2(OnPassphraseTypeChanged, void(PassphraseType,
base::Time));
};
google::protobuf::RepeatedPtrField<google::protobuf::string>
BuildEncryptionKeyProto(std::string encryption_key) {
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(encryption_key);
return keys;
}
}
class SyncEncryptionHandlerImplTest : public ::testing::Test {
public:
SyncEncryptionHandlerImplTest() {}
virtual ~SyncEncryptionHandlerImplTest() {}
virtual void SetUp() {
test_user_share_.SetUp();
SetUpEncryption();
CreateRootForType(NIGORI);
}
virtual void TearDown() {
PumpLoop();
test_user_share_.TearDown();
}
protected:
void SetUpEncryption() {
encryption_handler_.reset(
new SyncEncryptionHandlerImpl(user_share(),
&encryptor_,
std::string(),
std::string() ));
encryption_handler_->AddObserver(&observer_);
}
void CreateRootForType(ModelType model_type) {
syncer::syncable::Directory* directory = user_share()->directory.get();
std::string tag_name = ModelTypeToRootTag(model_type);
syncable::WriteTransaction wtrans(FROM_HERE, syncable::UNITTEST, directory);
syncable::MutableEntry node(&wtrans,
syncable::CREATE,
model_type,
wtrans.root_id(),
tag_name);
node.PutUniqueServerTag(tag_name);
node.PutIsDir(true);
node.PutServerIsDir(false);
node.PutIsUnsynced(false);
node.PutIsUnappliedUpdate(false);
node.PutServerVersion(20);
node.PutBaseVersion(20);
node.PutIsDel(false);
node.PutId(ids_.MakeServer(tag_name));
sync_pb::EntitySpecifics specifics;
syncer::AddDefaultFieldValue(model_type, &specifics);
node.PutSpecifics(specifics);
}
void PumpLoop() {
message_loop_.RunUntilIdle();
}
UserShare* user_share() { return test_user_share_.user_share(); }
SyncEncryptionHandlerImpl* encryption_handler() {
return encryption_handler_.get();
}
SyncEncryptionHandlerObserverMock* observer() { return &observer_; }
Cryptographer* GetCryptographer() {
return encryption_handler_->GetCryptographerUnsafe();
}
void VerifyMigratedNigori(PassphraseType passphrase_type,
const std::string& passphrase) {
VerifyMigratedNigoriWithTimestamp(0, passphrase_type, passphrase);
}
void VerifyMigratedNigoriWithTimestamp(
int64 migration_time,
PassphraseType passphrase_type,
const std::string& passphrase) {
ReadTransaction trans(FROM_HERE, user_share());
ReadNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
const sync_pb::NigoriSpecifics& nigori = nigori_node.GetNigoriSpecifics();
if (migration_time > 0)
EXPECT_EQ(migration_time, nigori.keystore_migration_time());
else
EXPECT_TRUE(nigori.has_keystore_migration_time());
EXPECT_TRUE(nigori.keybag_is_frozen());
if (passphrase_type == CUSTOM_PASSPHRASE ||
passphrase_type == FROZEN_IMPLICIT_PASSPHRASE) {
EXPECT_TRUE(nigori.encrypt_everything());
EXPECT_TRUE(nigori.keystore_decryptor_token().blob().empty());
if (passphrase_type == CUSTOM_PASSPHRASE) {
EXPECT_EQ(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE,
nigori.passphrase_type());
if (!encryption_handler()->custom_passphrase_time().is_null()) {
EXPECT_EQ(nigori.custom_passphrase_time(),
TimeToProtoTime(
encryption_handler()->custom_passphrase_time()));
}
} else {
EXPECT_EQ(sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE,
nigori.passphrase_type());
}
} else {
EXPECT_FALSE(nigori.encrypt_everything());
EXPECT_FALSE(nigori.keystore_decryptor_token().blob().empty());
EXPECT_EQ(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE,
nigori.passphrase_type());
Cryptographer keystore_cryptographer(&encryptor_);
KeyParams params = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(params);
EXPECT_TRUE(keystore_cryptographer.CanDecryptUsingDefaultKey(
nigori.keystore_decryptor_token()));
}
Cryptographer temp_cryptographer(&encryptor_);
KeyParams params = {"localhost", "dummy", passphrase};
temp_cryptographer.AddKey(params);
EXPECT_TRUE(temp_cryptographer.CanDecryptUsingDefaultKey(
nigori.encryption_keybag()));
}
sync_pb::NigoriSpecifics BuildMigratedNigori(
PassphraseType passphrase_type,
int64 migration_time,
const std::string& default_passphrase,
const std::string& keystore_key) {
DCHECK_NE(passphrase_type, IMPLICIT_PASSPHRASE);
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
std::string default_key = default_passphrase;
if (default_key.empty()) {
default_key = keystore_key;
} else {
KeyParams keystore_params = {"localhost", "dummy", keystore_key};
other_cryptographer.AddKey(keystore_params);
}
KeyParams params = {"localhost", "dummy", default_key};
other_cryptographer.AddKey(params);
EXPECT_TRUE(other_cryptographer.is_ready());
sync_pb::NigoriSpecifics nigori;
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(migration_time);
if (passphrase_type == KEYSTORE_PASSPHRASE) {
sync_pb::EncryptedData keystore_decryptor_token;
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
keystore_key,
&keystore_decryptor_token));
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
} else {
nigori.set_encrypt_everything(true);
nigori.set_passphrase_type(
passphrase_type == CUSTOM_PASSPHRASE ?
sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE :
sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE);
}
return nigori;
}
void InitKeystoreMigratedNigori(int64 migration_time,
const std::string& default_passphrase,
const std::string& keystore_key) {
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori = BuildMigratedNigori(
KEYSTORE_PASSPHRASE,
migration_time,
default_passphrase,
keystore_key);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AtLeast(1));
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(AtLeast(1));
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
}
void InitCustomPassMigratedNigori(int64 migration_time,
const std::string& default_passphrase) {
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori = BuildMigratedNigori(
CUSTOM_PASSPHRASE,
migration_time,
default_passphrase,
kKeystoreKey);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AtLeast(1));
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true)).Times(AtLeast(1));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(AtLeast(1));
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
}
void InitUnmigratedNigori(const std::string& default_passphrase,
PassphraseType passphrase_type) {
DCHECK_NE(passphrase_type, FROZEN_IMPLICIT_PASSPHRASE);
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams default_key = {"localhost", "dummy", default_passphrase};
other_cryptographer.AddKey(default_key);
EXPECT_TRUE(other_cryptographer.is_ready());
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(passphrase_type == CUSTOM_PASSPHRASE);
nigori_node.SetNigoriSpecifics(nigori);
}
if (passphrase_type != IMPLICIT_PASSPHRASE) {
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(passphrase_type, _));
}
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AtLeast(1));
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
encryption_handler()->Init();
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), passphrase_type);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
}
protected:
TestUserShare test_user_share_;
FakeEncryptor encryptor_;
scoped_ptr<SyncEncryptionHandlerImpl> encryption_handler_;
StrictMock<SyncEncryptionHandlerObserverMock> observer_;
TestIdFactory ids_;
base::MessageLoop message_loop_;
};
TEST_F(SyncEncryptionHandlerImplTest, NigoriEncryptionTypes) {
sync_pb::NigoriSpecifics nigori;
StrictMock<SyncEncryptionHandlerObserverMock> observer2;
SyncEncryptionHandlerImpl handler2(user_share(),
&encryptor_,
std::string(),
std::string() );
handler2.AddObserver(&observer2);
ModelTypeSet encrypted_types(SyncEncryptionHandler::SensitiveTypes());
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->MergeEncryptedTypes(
encrypted_types,
trans.GetWrappedTrans());
encryption_handler()->UpdateNigoriFromEncryptedTypes(
&nigori,
trans.GetWrappedTrans());
handler2.UpdateEncryptedTypesFromNigori(nigori, trans.GetWrappedTrans());
}
EXPECT_TRUE(encrypted_types.Equals(
encryption_handler()->GetEncryptedTypesUnsafe()));
EXPECT_TRUE(encrypted_types.Equals(
handler2.GetEncryptedTypesUnsafe()));
Mock::VerifyAndClearExpectations(observer());
Mock::VerifyAndClearExpectations(&observer2);
ModelTypeSet encrypted_user_types = EncryptableUserTypes();
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(
HasModelTypes(encrypted_user_types), false));
EXPECT_CALL(observer2,
OnEncryptedTypesChanged(
HasModelTypes(encrypted_user_types), false));
encrypted_types = EncryptableUserTypes();
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->MergeEncryptedTypes(
encrypted_types,
trans.GetWrappedTrans());
encryption_handler()->UpdateNigoriFromEncryptedTypes(
&nigori,
trans.GetWrappedTrans());
handler2.UpdateEncryptedTypesFromNigori(nigori, trans.GetWrappedTrans());
}
EXPECT_TRUE(encrypted_types.Equals(
encryption_handler()->GetEncryptedTypesUnsafe()));
EXPECT_TRUE(encrypted_types.Equals(handler2.GetEncryptedTypesUnsafe()));
Mock::VerifyAndClearExpectations(observer());
Mock::VerifyAndClearExpectations(&observer2);
nigori = sync_pb::NigoriSpecifics();
{
WriteTransaction trans(FROM_HERE, user_share());
handler2.UpdateEncryptedTypesFromNigori(nigori, trans.GetWrappedTrans());
}
EXPECT_TRUE(encrypted_types.Equals(
encryption_handler()->GetEncryptedTypesUnsafe()));
}
TEST_F(SyncEncryptionHandlerImplTest, EncryptEverythingExplicit) {
sync_pb::NigoriSpecifics nigori;
nigori.set_encrypt_everything(true);
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(
HasModelTypes(EncryptableUserTypes()), true));
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
ModelTypeSet encrypted_types =
encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.Equals(ModelTypeSet(PASSWORDS)));
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->UpdateEncryptedTypesFromNigori(
nigori,
trans.GetWrappedTrans());
}
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
encrypted_types = encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.HasAll(EncryptableUserTypes()));
Mock::VerifyAndClearExpectations(observer());
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->UpdateEncryptedTypesFromNigori(
nigori,
trans.GetWrappedTrans());
}
}
TEST_F(SyncEncryptionHandlerImplTest, EncryptEverythingImplicit) {
sync_pb::NigoriSpecifics nigori;
nigori.set_encrypt_bookmarks(true);
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(
HasModelTypes(EncryptableUserTypes()), true));
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
ModelTypeSet encrypted_types =
encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.Equals(ModelTypeSet(PASSWORDS)));
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->UpdateEncryptedTypesFromNigori(
nigori,
trans.GetWrappedTrans());
}
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
encrypted_types = encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.HasAll(EncryptableUserTypes()));
Mock::VerifyAndClearExpectations(observer());
nigori.set_encrypt_everything(true);
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->UpdateEncryptedTypesFromNigori(
nigori,
trans.GetWrappedTrans());
}
}
TEST_F(SyncEncryptionHandlerImplTest, UnknownSensitiveTypes) {
sync_pb::NigoriSpecifics nigori;
nigori.set_encrypt_everything(false);
nigori.set_encrypt_bookmarks(true);
ModelTypeSet expected_encrypted_types =
SyncEncryptionHandler::SensitiveTypes();
expected_encrypted_types.Put(BOOKMARKS);
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(
HasModelTypes(expected_encrypted_types), false));
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
ModelTypeSet encrypted_types =
encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.Equals(ModelTypeSet(PASSWORDS)));
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->UpdateEncryptedTypesFromNigori(
nigori,
trans.GetWrappedTrans());
}
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
encrypted_types = encryption_handler()->GetEncryptedTypesUnsafe();
EXPECT_TRUE(encrypted_types.Equals(ModelTypeSet(BOOKMARKS, PASSWORDS)));
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveOldNigori) {
KeyParams old_key = {"localhost", "dummy", "old"};
KeyParams current_key = {"localhost", "dummy", "cur"};
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
other_cryptographer.AddKey(old_key);
sync_pb::EntitySpecifics other_encrypted_specifics;
other_encrypted_specifics.mutable_bookmark()->set_title("title");
other_cryptographer.Encrypt(
other_encrypted_specifics,
other_encrypted_specifics.mutable_encrypted());
sync_pb::EntitySpecifics our_encrypted_specifics;
our_encrypted_specifics.mutable_bookmark()->set_title("title2");
ModelTypeSet encrypted_types = EncryptableUserTypes();
sync_pb::NigoriSpecifics current_nigori_specifics;
GetCryptographer()->AddKey(old_key);
GetCryptographer()->AddKey(current_key);
GetCryptographer()->Encrypt(
our_encrypted_specifics,
our_encrypted_specifics.mutable_encrypted());
GetCryptographer()->GetKeys(
current_nigori_specifics.mutable_encryption_keybag());
current_nigori_specifics.set_encrypt_everything(true);
EXPECT_CALL(*observer(), OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptedTypesChanged(
HasModelTypes(EncryptableUserTypes()), true));
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->ApplyNigoriUpdate(
current_nigori_specifics,
trans.GetWrappedTrans());
}
Mock::VerifyAndClearExpectations(observer());
sync_pb::NigoriSpecifics old_nigori;
other_cryptographer.GetKeys(old_nigori.mutable_encryption_keybag());
EXPECT_CALL(*observer(), OnCryptographerStateChanged(_)).Times(AnyNumber());
{
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->ApplyNigoriUpdate(
old_nigori,
trans.GetWrappedTrans());
}
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_FALSE(GetCryptographer()->has_pending_keys());
PumpLoop();
{
ReadTransaction trans(FROM_HERE, user_share());
ReadNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
const sync_pb::NigoriSpecifics& nigori = nigori_node.GetNigoriSpecifics();
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(
our_encrypted_specifics.encrypted()));
EXPECT_TRUE(GetCryptographer()->CanDecrypt(
other_encrypted_specifics.encrypted()));
EXPECT_TRUE(GetCryptographer()->CanDecrypt(nigori.encryption_keybag()));
EXPECT_TRUE(nigori.encrypt_everything());
EXPECT_TRUE(
GetCryptographer()->CanDecryptUsingDefaultKey(
nigori.encryption_keybag()));
}
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
}
TEST_F(SyncEncryptionHandlerImplTest, SetKeystoreMigratesAndUpdatesBootstrap) {
EXPECT_CALL(*observer(), OnBootstrapTokenUpdated(_, _)).Times(0);
{
WriteTransaction trans(FROM_HERE, user_share());
EXPECT_FALSE(GetCryptographer()->is_initialized());
EXPECT_TRUE(encryption_handler()->NeedKeystoreKey(trans.GetWrappedTrans()));
EXPECT_FALSE(encryption_handler()->SetKeystoreKeys(
BuildEncryptionKeyProto(std::string()), trans.GetWrappedTrans()));
EXPECT_TRUE(encryption_handler()->NeedKeystoreKey(trans.GetWrappedTrans()));
}
Mock::VerifyAndClearExpectations(observer());
const char kRawOldKeystoreKey[] = "old_keystore_key";
std::string old_keystore_key;
base::Base64Encode(kRawOldKeystoreKey, &old_keystore_key);
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
std::string encoded_key;
std::string keystore_bootstrap;
EXPECT_CALL(*observer(), OnEncryptionComplete());
EXPECT_CALL(*observer(), OnCryptographerStateChanged(_));
EXPECT_CALL(*observer(), OnPassphraseAccepted());
EXPECT_CALL(*observer(), OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_,
KEYSTORE_BOOTSTRAP_TOKEN)).
WillOnce(SaveArg<0>(&keystore_bootstrap));
{
WriteTransaction trans(FROM_HERE, user_share());
EXPECT_TRUE(
encryption_handler()->SetKeystoreKeys(
keys,
trans.GetWrappedTrans()));
EXPECT_FALSE(
encryption_handler()->NeedKeystoreKey(trans.GetWrappedTrans()));
EXPECT_FALSE(GetCryptographer()->is_initialized());
}
PumpLoop();
EXPECT_TRUE(GetCryptographer()->is_initialized());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
std::string decoded_bootstrap;
ASSERT_TRUE(base::Base64Decode(keystore_bootstrap, &decoded_bootstrap));
std::string decrypted_bootstrap;
ASSERT_TRUE(
GetCryptographer()->encryptor()->DecryptString(decoded_bootstrap,
&decrypted_bootstrap));
JSONStringValueSerializer json(decrypted_bootstrap);
scoped_ptr<base::Value> deserialized_keystore_keys(
json.Deserialize(NULL, NULL));
ASSERT_TRUE(deserialized_keystore_keys.get());
base::ListValue* keystore_list = NULL;
deserialized_keystore_keys->GetAsList(&keystore_list);
ASSERT_TRUE(keystore_list);
ASSERT_EQ(2U, keystore_list->GetSize());
std::string test_string;
keystore_list->GetString(0, &test_string);
ASSERT_EQ(old_keystore_key, test_string);
keystore_list->GetString(1, &test_string);
ASSERT_EQ(kKeystoreKey, test_string);
SyncEncryptionHandlerImpl handler2(user_share(),
&encryptor_,
std::string(),
keystore_bootstrap);
{
WriteTransaction trans(FROM_HERE, user_share());
EXPECT_FALSE(handler2.NeedKeystoreKey(trans.GetWrappedTrans()));
}
}
TEST_F(SyncEncryptionHandlerImplTest, GetKeystoreDecryptor) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&encrypted));
std::string serialized = encrypted.SerializeAsString();
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&encrypted));
EXPECT_EQ(serialized, encrypted.SerializeAsString());
}
TEST_F(SyncEncryptionHandlerImplTest, MigrateOnDecryptImplicitPass) {
const char kOtherKey[] = "other";
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
Mock::VerifyAndClearExpectations(observer());
}
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams other_key = {"localhost", "dummy", kOtherKey};
other_cryptographer.AddKey(other_key);
sync_pb::NigoriSpecifics nigori;
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(false);
nigori.set_encrypt_everything(false);
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
encryption_handler()->SetDecryptionPassphrase(kOtherKey);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(KEYSTORE_PASSPHRASE, encryption_handler()->GetPassphraseType());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kOtherKey);
}
TEST_F(SyncEncryptionHandlerImplTest, MigrateOnDecryptCustomPass) {
const char kOtherKey[] = "other";
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
Mock::VerifyAndClearExpectations(observer());
}
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams other_key = {"localhost", "dummy", kOtherKey};
other_cryptographer.AddKey(other_key);
sync_pb::NigoriSpecifics nigori;
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_encrypt_everything(false);
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(2);
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
encryption_handler()->SetDecryptionPassphrase(kOtherKey);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(CUSTOM_PASSPHRASE, encryption_handler()->GetPassphraseType());
VerifyMigratedNigori(CUSTOM_PASSPHRASE, kOtherKey);
}
TEST_F(SyncEncryptionHandlerImplTest, MigrateOnKeystoreKeyAvailableImplicit) {
const char kCurKey[] = "cur";
KeyParams current_key = {"localhost", "dummy", kCurKey};
GetCryptographer()->AddKey(current_key);
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
Mock::VerifyAndClearExpectations(observer());
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(KEYSTORE_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest,
MigrateOnKeystoreKeyAvailableFrozenImplicit) {
const char kCurKey[] = "cur";
KeyParams current_key = {"localhost", "dummy", kCurKey};
GetCryptographer()->AddKey(current_key);
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->EnableEncryptEverything();
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(FROZEN_IMPLICIT_PASSPHRASE, _));
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(FROZEN_IMPLICIT_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(FROZEN_IMPLICIT_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest,
MigrateOnKeystoreKeyAvailableCustomWithEncryption) {
const char kCurKey[] = "cur";
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
encryption_handler()->Init();
encryption_handler()->SetEncryptionPassphrase(kCurKey, true);
EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->EnableEncryptEverything();
Mock::VerifyAndClearExpectations(observer());
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(CUSTOM_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(CUSTOM_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest,
MigrateOnKeystoreKeyAvailableCustomNoEncryption) {
const char kCurKey[] = "cur";
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
encryption_handler()->Init();
encryption_handler()->SetEncryptionPassphrase(kCurKey, true);
EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
Mock::VerifyAndClearExpectations(observer());
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(CUSTOM_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(CUSTOM_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveMigratedNigoriKeystorePass) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
EXPECT_FALSE(GetCryptographer()->is_ready());
EXPECT_NE(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
EXPECT_CALL(*observer(), OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, KEYSTORE_PASSPHRASE, kCurKey);
sync_pb::EncryptedData current_encrypted;
other_cryptographer.EncryptString("string", ¤t_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(current_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveMigratedNigoriFrozenImplicitPass) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(FROZEN_IMPLICIT_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.set_keybag_is_frozen(true);
nigori.set_passphrase_type(
sync_pb::NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE);
nigori.set_keystore_migration_time(1);
nigori.set_encrypt_everything(true);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(FROZEN_IMPLICIT_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
encryption_handler()->SetDecryptionPassphrase(kCurKey);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
VerifyMigratedNigoriWithTimestamp(1, FROZEN_IMPLICIT_PASSPHRASE, kCurKey);
sync_pb::EncryptedData current_encrypted;
other_cryptographer.EncryptString("string", ¤t_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(current_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveMigratedNigoriCustomPass) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
{
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.set_keybag_is_frozen(true);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
nigori.set_keystore_migration_time(1);
nigori.set_encrypt_everything(true);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(CUSTOM_PASSPHRASE, encryption_handler()->GetPassphraseType());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
encryption_handler()->SetDecryptionPassphrase(kCurKey);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCurKey);
sync_pb::EncryptedData current_encrypted;
other_cryptographer.EncryptString("string", ¤t_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(current_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveUnmigratedNigoriAfterMigration) {
const char kOldKey[] = "old";
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
KeyParams old_key = {"localhost", "dummy", kOldKey};
KeyParams cur_key = {"localhost", "dummy", kCurKey};
GetCryptographer()->AddKey(old_key);
GetCryptographer()->AddKey(cur_key);
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
GetCryptographer()->GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
nigori.set_encrypt_everything(true);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true)).Times(2);
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCurKey);
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptionComplete());
{
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
other_cryptographer.AddKey(old_key);
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(false);
nigori.set_encrypt_everything(false);
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest, ReceiveOldMigratedNigori) {
const char kOldKey[] = "old";
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
KeyParams old_key = {"localhost", "dummy", kOldKey};
KeyParams cur_key = {"localhost", "dummy", kCurKey};
GetCryptographer()->AddKey(old_key);
GetCryptographer()->AddKey(cur_key);
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
GetCryptographer()->GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
nigori.set_encrypt_everything(true);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true)).Times(2);
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCurKey);
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptionComplete());
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
other_cryptographer.AddKey(old_key);
encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
nigori.mutable_keystore_decryptor_token());
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_encrypt_everything(false);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori.set_keystore_migration_time(1);
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest, SetKeystoreAfterReceivingMigratedNigori) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
EXPECT_FALSE(GetCryptographer()->is_ready());
EXPECT_NE(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(), OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, KEYSTORE_PASSPHRASE, kCurKey);
sync_pb::EncryptedData current_encrypted;
other_cryptographer.EncryptString("string", ¤t_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(current_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest, SetCustomPassAfterMigration) {
const char kOldKey[] = "old";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kOldKey};
other_cryptographer.AddKey(cur_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori_node.SetNigoriSpecifics(nigori);
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_CALL(*observer(), OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
const char kNewKey[] = "new_key";
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(2);
encryption_handler()->SetEncryptionPassphrase(kNewKey, true);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kNewKey);
sync_pb::EncryptedData old_encrypted;
other_cryptographer.EncryptString("string", &old_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(old_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
KeyParams new_key = {"localhost", "dummy", kNewKey};
Cryptographer new_cryptographer(GetCryptographer()->encryptor());
new_cryptographer.AddKey(new_key);
sync_pb::EncryptedData new_encrypted;
new_cryptographer.EncryptString("string", &new_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(new_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest,
SetCustomPassAfterMigrationNoKeystoreKey) {
const char kOldKey[] = "old";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kOldKey};
other_cryptographer.AddKey(cur_key);
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
other_cryptographer.AddNonDefaultKey(keystore_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->SetDecryptionPassphrase(kOldKey);
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
const char kNewKey[] = "new_key";
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(CUSTOM_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(2);
encryption_handler()->SetEncryptionPassphrase(kNewKey, true);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), CUSTOM_PASSPHRASE);
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kNewKey);
sync_pb::EncryptedData old_encrypted;
other_cryptographer.EncryptString("string", &old_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(old_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
KeyParams new_key = {"localhost", "dummy", kNewKey};
Cryptographer new_cryptographer(GetCryptographer()->encryptor());
new_cryptographer.AddKey(new_key);
sync_pb::EncryptedData new_encrypted;
new_cryptographer.EncryptString("string", &new_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(new_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest,
SetImplicitPassAfterMigrationNoKeystoreKey) {
const char kOldKey[] = "old";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kOldKey};
other_cryptographer.AddKey(cur_key);
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
other_cryptographer.AddNonDefaultKey(keystore_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->SetDecryptionPassphrase(kOldKey);
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
const char kNewKey[] = "new_key";
encryption_handler()->SetEncryptionPassphrase(kNewKey, false);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, KEYSTORE_PASSPHRASE, kOldKey);
sync_pb::EncryptedData old_encrypted;
other_cryptographer.EncryptString("string", &old_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(old_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
KeyParams new_key = {"localhost", "dummy", kNewKey};
Cryptographer new_cryptographer(GetCryptographer()->encryptor());
new_cryptographer.AddKey(new_key);
sync_pb::EncryptedData new_encrypted;
new_cryptographer.EncryptString("string", &new_encrypted);
EXPECT_FALSE(GetCryptographer()->CanDecryptUsingDefaultKey(new_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest,
MigrateOnEncryptEverythingKeystorePassphrase) {
const char kCurKey[] = "cur";
sync_pb::EncryptedData keystore_decryptor_token;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
KeyParams cur_key = {"localhost", "dummy", kCurKey};
other_cryptographer.AddKey(cur_key);
KeyParams keystore_key = {"localhost", "dummy", kKeystoreKey};
other_cryptographer.AddNonDefaultKey(keystore_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_TRUE(encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
&keystore_decryptor_token));
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
nigori.mutable_keystore_decryptor_token()->CopyFrom(
keystore_decryptor_token);
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_keystore_migration_time(1);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori_node.SetNigoriSpecifics(nigori);
}
EXPECT_CALL(*observer(),
OnPassphraseRequired(_, _));
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
encryption_handler()->Init();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->has_pending_keys());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->SetDecryptionPassphrase(kCurKey);
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(FROZEN_IMPLICIT_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
encryption_handler()->EnableEncryptEverything();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(FROZEN_IMPLICIT_PASSPHRASE,
encryption_handler()->GetPassphraseType());
EXPECT_TRUE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigoriWithTimestamp(1, FROZEN_IMPLICIT_PASSPHRASE, kCurKey);
sync_pb::EncryptedData current_encrypted;
other_cryptographer.EncryptString("string", ¤t_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecryptUsingDefaultKey(current_encrypted));
Cryptographer keystore_cryptographer(GetCryptographer()->encryptor());
keystore_cryptographer.AddKey(keystore_key);
sync_pb::EncryptedData keystore_encrypted;
keystore_cryptographer.EncryptString("string", &keystore_encrypted);
EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted));
}
TEST_F(SyncEncryptionHandlerImplTest,
ReceiveMigratedNigoriWithOldPassphrase) {
const char kOldKey[] = "old";
const char kCurKey[] = "cur";
sync_pb::EncryptedData encrypted;
KeyParams old_key = {"localhost", "dummy", kOldKey};
KeyParams cur_key = {"localhost", "dummy", kCurKey};
GetCryptographer()->AddKey(old_key);
GetCryptographer()->AddKey(cur_key);
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
other_cryptographer.AddKey(old_key);
EXPECT_TRUE(other_cryptographer.is_ready());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, false));
EXPECT_CALL(*observer(),
OnEncryptionComplete());
encryption_handler()->Init();
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
{
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawKeystoreKey),
trans.GetWrappedTrans());
}
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kCurKey);
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptionComplete());
{
WriteTransaction trans(FROM_HERE, user_share());
WriteNode nigori_node(&trans);
ASSERT_EQ(nigori_node.InitByTagLookup(kNigoriTag), BaseNode::INIT_OK);
sync_pb::NigoriSpecifics nigori;
Cryptographer other_cryptographer(GetCryptographer()->encryptor());
other_cryptographer.AddKey(old_key);
encryption_handler()->GetKeystoreDecryptor(
other_cryptographer,
kKeystoreKey,
nigori.mutable_keystore_decryptor_token());
other_cryptographer.GetKeys(nigori.mutable_encryption_keybag());
nigori.set_keybag_is_frozen(true);
nigori.set_encrypt_everything(false);
nigori.set_passphrase_type(sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE);
nigori.set_keystore_migration_time(1);
encryption_handler()->ApplyNigoriUpdate(nigori, trans.GetWrappedTrans());
nigori_node.SetNigoriSpecifics(nigori);
}
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kCurKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysGaiaDefault) {
TearDown();
test_user_share_.SetUp();
SetUpEncryption();
const char kOldGaiaKey[] = "old_gaia_key";
const char kRawOldKeystoreKey[] = "old_keystore_key";
std::string old_keystore_key;
base::Base64Encode(kRawOldKeystoreKey, &old_keystore_key);
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawOldKeystoreKey),
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
CreateRootForType(NIGORI);
EXPECT_CALL(*observer(), OnPassphraseAccepted());
InitKeystoreMigratedNigori(1, kOldGaiaKey, old_keystore_key);
EXPECT_CALL(*observer(), OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptionComplete());
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysKeystoreDefault) {
TearDown();
test_user_share_.SetUp();
SetUpEncryption();
const char kRawOldKeystoreKey[] = "old_keystore_key";
std::string old_keystore_key;
base::Base64Encode(kRawOldKeystoreKey, &old_keystore_key);
{
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(BuildEncryptionKeyProto(
kRawOldKeystoreKey),
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
CreateRootForType(NIGORI);
EXPECT_CALL(*observer(), OnPassphraseAccepted());
InitKeystoreMigratedNigori(1, old_keystore_key, old_keystore_key);
EXPECT_CALL(*observer(), OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(), OnEncryptionComplete());
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysAfterPendingGaiaResolved) {
const char kOldGaiaKey[] = "old_gaia_key";
const char kRawOldKeystoreKey[] = "old_keystore_key";
EXPECT_CALL(*observer(), OnPassphraseRequired(_, _));
InitUnmigratedNigori(kOldGaiaKey, IMPLICIT_PASSPHRASE);
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(AtLeast(1));
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
encryption_handler()->SetDecryptionPassphrase(kOldGaiaKey);
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(KEYSTORE_PASSPHRASE, encryption_handler()->GetPassphraseType());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysGaiaDefaultOnInit) {
TearDown();
test_user_share_.SetUp();
SetUpEncryption();
const char kOldGaiaKey[] = "old_gaia_key";
const char kRawOldKeystoreKey[] = "old_keystore_key";
std::string old_keystore_key;
base::Base64Encode(kRawOldKeystoreKey, &old_keystore_key);
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
ReadTransaction trans(FROM_HERE, user_share());
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
CreateRootForType(NIGORI);
EXPECT_CALL(*observer(), OnPassphraseAccepted());
InitKeystoreMigratedNigori(1, kOldGaiaKey, old_keystore_key);
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_TRUE(GetCryptographer()->is_ready());
EXPECT_EQ(encryption_handler()->GetPassphraseType(), KEYSTORE_PASSPHRASE);
EXPECT_FALSE(encryption_handler()->EncryptEverythingEnabled());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysWhenMigratedNigoriArrives) {
const char kOldGaiaKey[] = "old_gaia_key";
const char kRawOldKeystoreKey[] = "old_keystore_key";
std::string old_keystore_key;
base::Base64Encode(kRawOldKeystoreKey, &old_keystore_key);
EXPECT_CALL(*observer(), OnPassphraseRequired(_, _));
InitUnmigratedNigori(kOldGaiaKey, IMPLICIT_PASSPHRASE);
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnPassphraseTypeChanged(KEYSTORE_PASSPHRASE, _));
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(AtLeast(1));
{
sync_pb::NigoriSpecifics nigori = BuildMigratedNigori(
KEYSTORE_PASSPHRASE,
1,
kOldGaiaKey,
old_keystore_key);
WriteTransaction trans(FROM_HERE, user_share());
encryption_handler()->ApplyNigoriUpdate(
nigori,
trans.GetWrappedTrans());
}
EXPECT_FALSE(encryption_handler()->MigratedToKeystore());
PumpLoop();
EXPECT_TRUE(encryption_handler()->MigratedToKeystore());
EXPECT_EQ(KEYSTORE_PASSPHRASE, encryption_handler()->GetPassphraseType());
VerifyMigratedNigori(KEYSTORE_PASSPHRASE, kKeystoreKey);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysUnmigratedCustomPassphrase) {
const char kCustomPass[] = "custom_passphrase";
const char kRawOldKeystoreKey[] = "old_keystore_key";
EXPECT_CALL(*observer(), OnPassphraseRequired(_, _));
InitUnmigratedNigori(kCustomPass, CUSTOM_PASSPHRASE);
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnPassphraseAccepted());
EXPECT_CALL(*observer(),
OnEncryptedTypesChanged(_, true));
EXPECT_CALL(*observer(),
OnEncryptionComplete()).Times(AnyNumber());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, PASSPHRASE_BOOTSTRAP_TOKEN));
encryption_handler()->SetDecryptionPassphrase(kCustomPass);
Mock::VerifyAndClearExpectations(observer());
VerifyMigratedNigori(CUSTOM_PASSPHRASE, kCustomPass);
}
TEST_F(SyncEncryptionHandlerImplTest, RotateKeysMigratedCustomPassphrase) {
const char kCustomPass[] = "custom_passphrase";
const char kRawOldKeystoreKey[] = "old_keystore_key";
KeyParams custom_key = {"localhost", "dummy", kCustomPass};
GetCryptographer()->AddKey(custom_key);
InitCustomPassMigratedNigori(1, kCustomPass);
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCustomPass);
{
google::protobuf::RepeatedPtrField<google::protobuf::string> keys;
keys.Add()->assign(kRawOldKeystoreKey);
keys.Add()->assign(kRawKeystoreKey);
ReadTransaction trans(FROM_HERE, user_share());
EXPECT_CALL(*observer(),
OnBootstrapTokenUpdated(_, KEYSTORE_BOOTSTRAP_TOKEN));
EXPECT_CALL(*observer(),
OnCryptographerStateChanged(_)).Times(AnyNumber());
encryption_handler()->SetKeystoreKeys(keys,
trans.GetWrappedTrans());
}
PumpLoop();
Mock::VerifyAndClearExpectations(observer());
VerifyMigratedNigoriWithTimestamp(1, CUSTOM_PASSPHRASE, kCustomPass);
}
}