Commit f97d24ac authored by Mikel Astiz's avatar Mikel Astiz Committed by Commit Bot

Move Nigori specifics conversion to NigoriState

This removes complexity from the bridge to a struct with much simpler
semantics, and allows future patches to compute specifics from
NigoriState instances other than the authoritative copy owned by the
bridge.

Bug: 922900
Change-Id: I0dd60f316145700502e22a1dbc1460b3e1bcf703
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1862457
Commit-Queue: Mikel Astiz <mastiz@chromium.org>
Reviewed-by: default avatarMaksim Moskvitin <mmoskvitin@google.com>
Cr-Commit-Position: refs/heads/master@{#706084}
parent 60dc9c93
......@@ -649,6 +649,7 @@ source_set("unit_tests") {
"nigori/cryptographer_impl_unittest.cc",
"nigori/nigori_key_bag_unittest.cc",
"nigori/nigori_model_type_processor_unittest.cc",
"nigori/nigori_state_unittest.cc",
"nigori/nigori_storage_impl_unittest.cc",
"nigori/nigori_sync_bridge_impl_unittest.cc",
"nigori/nigori_unittest.cc",
......
......@@ -4,6 +4,7 @@
#include "components/sync/nigori/nigori_state.h"
#include "base/base64.h"
#include "components/sync/base/model_type.h"
#include "components/sync/base/time.h"
#include "components/sync/engine/sync_encryption_handler.h"
......@@ -48,10 +49,123 @@ KeyDerivationParams CustomPassphraseKeyDerivationParamsFromProto(
return KeyDerivationParams::CreateWithUnsupportedMethod();
}
// |encrypted| must not be null.
bool EncryptKeyBag(const CryptographerImpl& cryptographer,
sync_pb::EncryptedData* encrypted) {
DCHECK(encrypted);
DCHECK(cryptographer.CanEncrypt());
sync_pb::CryptographerData proto = cryptographer.ToProto();
DCHECK(!proto.key_bag().key().empty());
// Encrypt the bag with the default Nigori.
return cryptographer.Encrypt(proto.key_bag(), encrypted);
}
// Updates |specifics|'s individual datatypes encryption state based on
// |encrypted_types|.
void UpdateNigoriSpecificsFromEncryptedTypes(
ModelTypeSet encrypted_types,
sync_pb::NigoriSpecifics* specifics) {
static_assert(39 == ModelType::NUM_ENTRIES,
"If adding an encryptable type, update handling below.");
specifics->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS));
specifics->set_encrypt_preferences(encrypted_types.Has(PREFERENCES));
specifics->set_encrypt_autofill_profile(
encrypted_types.Has(AUTOFILL_PROFILE));
specifics->set_encrypt_autofill(encrypted_types.Has(AUTOFILL));
specifics->set_encrypt_autofill_wallet_metadata(
encrypted_types.Has(AUTOFILL_WALLET_METADATA));
specifics->set_encrypt_themes(encrypted_types.Has(THEMES));
specifics->set_encrypt_typed_urls(encrypted_types.Has(TYPED_URLS));
specifics->set_encrypt_extensions(encrypted_types.Has(EXTENSIONS));
specifics->set_encrypt_search_engines(encrypted_types.Has(SEARCH_ENGINES));
specifics->set_encrypt_sessions(encrypted_types.Has(SESSIONS));
specifics->set_encrypt_apps(encrypted_types.Has(APPS));
specifics->set_encrypt_app_settings(encrypted_types.Has(APP_SETTINGS));
specifics->set_encrypt_extension_settings(
encrypted_types.Has(EXTENSION_SETTINGS));
specifics->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY));
specifics->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES));
specifics->set_encrypt_favicon_tracking(
encrypted_types.Has(FAVICON_TRACKING));
specifics->set_encrypt_app_list(encrypted_types.Has(APP_LIST));
specifics->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE));
specifics->set_encrypt_printers(encrypted_types.Has(PRINTERS));
specifics->set_encrypt_reading_list(encrypted_types.Has(READING_LIST));
specifics->set_encrypt_mountain_shares(encrypted_types.Has(MOUNTAIN_SHARES));
specifics->set_encrypt_send_tab_to_self(
encrypted_types.Has(SEND_TAB_TO_SELF));
specifics->set_encrypt_web_apps(encrypted_types.Has(WEB_APPS));
}
void UpdateSpecificsFromKeyDerivationParams(
const KeyDerivationParams& params,
sync_pb::NigoriSpecifics* specifics) {
DCHECK_EQ(specifics->passphrase_type(),
sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
DCHECK_NE(params.method(), KeyDerivationMethod::UNSUPPORTED);
specifics->set_custom_passphrase_key_derivation_method(
EnumKeyDerivationMethodToProto(params.method()));
if (params.method() == KeyDerivationMethod::SCRYPT_8192_8_11) {
// Persist the salt used for key derivation in Nigori if we're using scrypt.
std::string encoded_salt;
base::Base64Encode(params.scrypt_salt(), &encoded_salt);
specifics->set_custom_passphrase_key_derivation_salt(encoded_salt);
}
}
bool EncryptKeystoreDecryptorToken(
const CryptographerImpl& cryptographer,
sync_pb::EncryptedData* keystore_decryptor_token,
const std::vector<std::string>& keystore_keys) {
DCHECK(keystore_decryptor_token);
const sync_pb::NigoriKey default_key = cryptographer.ExportDefaultKey();
std::unique_ptr<Cryptographer> keystore_cryptographer =
CreateCryptographerFromKeystoreKeys(keystore_keys);
if (!keystore_cryptographer) {
return false;
}
return keystore_cryptographer->EncryptString(default_key.SerializeAsString(),
keystore_decryptor_token);
}
} // namespace
std::unique_ptr<CryptographerImpl> CreateCryptographerFromKeystoreKeys(
const std::vector<std::string>& keystore_keys) {
std::unique_ptr<CryptographerImpl> cryptographer =
CryptographerImpl::CreateEmpty();
if (keystore_keys.empty()) {
return cryptographer;
}
std::string last_key_name;
for (const std::string& key : keystore_keys) {
last_key_name =
cryptographer->EmplaceKey(key, KeyDerivationParams::CreateForPbkdf2());
// TODO(crbug.com/922900): possible behavioral change. Old implementation
// fails only if we failed to add current keystore key. Failing to add any
// of these keys doesn't seem valid. This line seems to be a good candidate
// for UMA, as it's not a normal situation, if we fail to add any key.
if (last_key_name.empty()) {
return nullptr;
}
}
DCHECK(!last_key_name.empty());
cryptographer->SelectDefaultEncryptionKey(last_key_name);
return cryptographer;
}
// static
NigoriState NigoriState::CreateFromProto(const sync_pb::NigoriModel& proto) {
NigoriState NigoriState::CreateFromLocalProto(
const sync_pb::NigoriModel& proto) {
NigoriState state;
state.cryptographer =
......@@ -93,7 +207,7 @@ NigoriState::~NigoriState() = default;
NigoriState& NigoriState::operator=(NigoriState&& other) = default;
sync_pb::NigoriModel NigoriState::ToProto() const {
sync_pb::NigoriModel NigoriState::ToLocalProto() const {
sync_pb::NigoriModel proto;
*proto.mutable_cryptographer_data() = cryptographer->ToProto();
if (pending_keys.has_value()) {
......@@ -138,4 +252,54 @@ sync_pb::NigoriModel NigoriState::ToProto() const {
return proto;
}
sync_pb::NigoriSpecifics NigoriState::ToSpecificsProto() const {
sync_pb::NigoriSpecifics specifics;
if (cryptographer->CanEncrypt()) {
EncryptKeyBag(*cryptographer, specifics.mutable_encryption_keybag());
} else {
DCHECK(pending_keys.has_value());
// This case is reachable only from processor's GetAllNodesForDebugging(),
// since currently commit is never issued while bridge has |pending_keys_|.
// Note: with complete support of TRUSTED_VAULT mode, commit might be
// issued in this case as well.
*specifics.mutable_encryption_keybag() = *pending_keys;
}
specifics.set_keybag_is_frozen(true);
specifics.set_encrypt_everything(encrypt_everything);
if (encrypt_everything) {
UpdateNigoriSpecificsFromEncryptedTypes(EncryptableUserTypes(), &specifics);
}
specifics.set_passphrase_type(passphrase_type);
if (passphrase_type == sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE) {
DCHECK(custom_passphrase_key_derivation_params);
UpdateSpecificsFromKeyDerivationParams(
*custom_passphrase_key_derivation_params, &specifics);
}
if (passphrase_type == sync_pb::NigoriSpecifics::KEYSTORE_PASSPHRASE) {
// TODO(crbug.com/922900): it seems possible to have corrupted
// |pending_keystore_decryptor_token| and an ability to recover it in case
// |pending_keys| isn't set and |keystore_keys| contains some keys.
if (pending_keystore_decryptor_token.has_value()) {
*specifics.mutable_keystore_decryptor_token() =
*pending_keystore_decryptor_token;
} else {
DCHECK(!keystore_keys.empty());
EncryptKeystoreDecryptorToken(
*cryptographer, specifics.mutable_keystore_decryptor_token(),
keystore_keys);
}
}
if (!keystore_migration_time.is_null()) {
specifics.set_keystore_migration_time(
TimeToProtoTime(keystore_migration_time));
}
if (!custom_passphrase_time.is_null()) {
specifics.set_custom_passphrase_time(
TimeToProtoTime(custom_passphrase_time));
}
// TODO(crbug.com/922900): add other fields support.
NOTIMPLEMENTED();
return specifics;
}
} // namespace syncer
......@@ -24,6 +24,13 @@ namespace syncer {
class CryptographerImpl;
// Creates a cryptographer that can decrypt all |keystore_keys| and uses the
// last one as default encryption key. May return null in case of error.
// TODO(crbug.com/922900): consider maintaining cached version of this
// cryptographer in NigoriState to avoid repeated creations.
std::unique_ptr<CryptographerImpl> CreateCryptographerFromKeystoreKeys(
const std::vector<std::string>& keystore_keys);
struct NigoriState {
static constexpr sync_pb::NigoriSpecifics::PassphraseType
kInitialPassphraseType = sync_pb::NigoriSpecifics::UNKNOWN;
......@@ -31,7 +38,7 @@ struct NigoriState {
static constexpr bool kInitialEncryptEverything = false;
// Deserialization from proto.
static NigoriState CreateFromProto(const sync_pb::NigoriModel& proto);
static NigoriState CreateFromLocalProto(const sync_pb::NigoriModel& proto);
NigoriState();
NigoriState(NigoriState&& other);
......@@ -39,8 +46,11 @@ struct NigoriState {
NigoriState& operator=(NigoriState&& other);
// Serialization to proto.
sync_pb::NigoriModel ToProto() const;
// Serialization to proto as persisted on local disk.
sync_pb::NigoriModel ToLocalProto() const;
// Serialization to proto as sent to the sync server.
sync_pb::NigoriSpecifics ToSpecificsProto() const;
std::unique_ptr<CryptographerImpl> cryptographer;
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync/nigori/nigori_state.h"
#include "components/sync/base/time.h"
#include "components/sync/nigori/cryptographer_impl.h"
#include "components/sync/nigori/nigori.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
namespace {
using sync_pb::NigoriSpecifics;
using testing::Eq;
using testing::Ne;
TEST(NigoriStateTest, ShouldConvertCustomPassphraseStateToSpecifics) {
const base::Time now = base::Time::Now();
const std::string kKey = "key1";
NigoriState state;
state.passphrase_type = NigoriSpecifics::CUSTOM_PASSPHRASE;
state.encrypt_everything = true;
state.custom_passphrase_time = now;
state.custom_passphrase_key_derivation_params =
KeyDerivationParams::CreateForPbkdf2();
const std::string key_name = state.cryptographer->EmplaceKey(
kKey, KeyDerivationParams::CreateForPbkdf2());
ASSERT_THAT(key_name, Ne(""));
state.cryptographer->SelectDefaultEncryptionKey(key_name);
NigoriSpecifics specifics = state.ToSpecificsProto();
EXPECT_THAT(specifics.passphrase_type(),
Eq(NigoriSpecifics::CUSTOM_PASSPHRASE));
EXPECT_TRUE(specifics.keybag_is_frozen());
EXPECT_THAT(specifics.encryption_keybag().key_name(), Eq(key_name));
EXPECT_THAT(specifics.custom_passphrase_key_derivation_method(),
Eq(NigoriSpecifics::PBKDF2_HMAC_SHA1_1003));
EXPECT_FALSE(specifics.has_keystore_decryptor_token());
EXPECT_FALSE(specifics.has_keystore_migration_time());
EXPECT_THAT(specifics.custom_passphrase_time(), Eq(TimeToProtoTime(now)));
}
TEST(NigoriStateTest, ShouldConvertKeystoreStateToSpecifics) {
// Note that in practice having a NigoriState with two keystore keys and yet
// a default encryption key that is neither of them is not realistic. However,
// it serves this test well to verify that a) which key is used to encrypt the
// keybag and b) which key is used to encrypt the keystore decryptor token.
const base::Time now = base::Time::Now();
const std::string kKeystoreKey1 = "keystorekey1";
const std::string kKeystoreKey2 = "keystorekey2";
const std::string kDefaultEncryptionKey = "defaultkey";
NigoriState state;
state.keystore_keys = {kKeystoreKey1, kKeystoreKey2};
state.passphrase_type = NigoriSpecifics::KEYSTORE_PASSPHRASE;
state.keystore_migration_time = now;
state.cryptographer = CryptographerImpl::CreateEmpty();
state.cryptographer->EmplaceKey(kKeystoreKey1,
KeyDerivationParams::CreateForPbkdf2());
const std::string last_keystore_key_name = state.cryptographer->EmplaceKey(
kKeystoreKey2, KeyDerivationParams::CreateForPbkdf2());
const std::string default_encryption_key_name =
state.cryptographer->EmplaceKey(kDefaultEncryptionKey,
KeyDerivationParams::CreateForPbkdf2());
state.cryptographer->SelectDefaultEncryptionKey(default_encryption_key_name);
ASSERT_THAT(last_keystore_key_name, Ne(""));
ASSERT_THAT(default_encryption_key_name, Ne(""));
ASSERT_THAT(default_encryption_key_name, Ne(last_keystore_key_name));
NigoriSpecifics specifics = state.ToSpecificsProto();
EXPECT_THAT(specifics.passphrase_type(),
NigoriSpecifics::KEYSTORE_PASSPHRASE);
EXPECT_TRUE(specifics.keybag_is_frozen());
EXPECT_THAT(specifics.encryption_keybag().key_name(),
Eq(default_encryption_key_name));
EXPECT_TRUE(specifics.has_keystore_decryptor_token());
EXPECT_THAT(specifics.keystore_decryptor_token().key_name(),
Eq(last_keystore_key_name));
EXPECT_FALSE(specifics.has_custom_passphrase_time());
EXPECT_FALSE(specifics.has_custom_passphrase_key_derivation_method());
EXPECT_THAT(specifics.keystore_migration_time(), Eq(TimeToProtoTime(now)));
}
} // namespace
} // namespace syncer
......@@ -29,68 +29,8 @@ using sync_pb::NigoriSpecifics;
const char kNigoriNonUniqueName[] = "Nigori";
std::unique_ptr<CryptographerImpl> CreateCryptographerFromKeystoreKeys(
const std::vector<std::string>& keystore_keys) {
std::unique_ptr<CryptographerImpl> cryptographer =
CryptographerImpl::CreateEmpty();
if (keystore_keys.empty()) {
return cryptographer;
}
std::string last_key_name;
for (const std::string& key : keystore_keys) {
last_key_name =
cryptographer->EmplaceKey(key, KeyDerivationParams::CreateForPbkdf2());
// TODO(crbug.com/922900): possible behavioral change. Old implementation
// fails only if we failed to add current keystore key. Failing to add any
// of these keys doesn't seem valid. This line seems to be a good candidate
// for UMA, as it's not a normal situation, if we fail to add any key.
if (last_key_name.empty()) {
return nullptr;
}
}
DCHECK(!last_key_name.empty());
cryptographer->SelectDefaultEncryptionKey(last_key_name);
return cryptographer;
}
// |encrypted| must not be null.
bool EncryptKeyBag(const CryptographerImpl& cryptographer,
sync_pb::EncryptedData* encrypted) {
DCHECK(encrypted);
DCHECK(cryptographer.CanEncrypt());
sync_pb::CryptographerData proto = cryptographer.ToProto();
DCHECK(!proto.key_bag().key().empty());
// Encrypt the bag with the default Nigori.
return cryptographer.Encrypt(proto.key_bag(), encrypted);
}
bool EncryptKeystoreDecryptorToken(
const CryptographerImpl& cryptographer,
sync_pb::EncryptedData* keystore_decryptor_token,
const std::vector<std::string>& keystore_keys) {
DCHECK(keystore_decryptor_token);
const sync_pb::NigoriKey default_key = cryptographer.ExportDefaultKey();
// TODO(crbug.com/922900): consider maintaining cached version of this
// |keystore_cryptographer| to avoid its creation here and inside
// DecryptKestoreDecryptorToken().
std::unique_ptr<CryptographerImpl> keystore_cryptographer =
CreateCryptographerFromKeystoreKeys(keystore_keys);
return keystore_cryptographer->EncryptString(default_key.SerializeAsString(),
keystore_decryptor_token);
}
// Creates keystore Nigori specifics given |keystore_keys|.
// Returns new NigoriSpecifics if successful and base::nullopt otherwise. If
// successful the result will contain:
// Returns NigoriSpecifics that contain:
// 1. passphrase_type = KEYSTORE_PASSPHRASE.
// 2. encryption_keybag contains all |keystore_keys| and encrypted with the
// latest keystore key.
......@@ -99,32 +39,17 @@ bool EncryptKeystoreDecryptorToken(
// 4. keybag_is_frozen = true.
// 5. keystore_migration_time is current time.
// 6. Other fields are default.
base::Optional<NigoriSpecifics> MakeDefaultKeystoreNigori(
NigoriSpecifics MakeDefaultKeystoreNigori(
const std::vector<std::string>& keystore_keys) {
DCHECK(!keystore_keys.empty());
std::unique_ptr<CryptographerImpl> cryptographer =
CreateCryptographerFromKeystoreKeys(keystore_keys);
if (!cryptographer) {
return base::nullopt;
}
NigoriState state;
state.keystore_keys = keystore_keys;
state.passphrase_type = NigoriSpecifics::KEYSTORE_PASSPHRASE;
state.keystore_migration_time = base::Time::Now();
state.cryptographer = CreateCryptographerFromKeystoreKeys(keystore_keys);
NigoriSpecifics specifics;
if (!EncryptKeystoreDecryptorToken(
*cryptographer, specifics.mutable_keystore_decryptor_token(),
keystore_keys)) {
DLOG(ERROR) << "Failed to encrypt default key as keystore_decryptor_token.";
return base::nullopt;
}
if (!EncryptKeyBag(*cryptographer, specifics.mutable_encryption_keybag())) {
DLOG(ERROR) << "Failed to encrypt keystore keys into encryption_keybag.";
return base::nullopt;
}
specifics.set_passphrase_type(NigoriSpecifics::KEYSTORE_PASSPHRASE);
// Let non-USS client know, that Nigori doesn't need migration.
specifics.set_keybag_is_frozen(true);
specifics.set_keystore_migration_time(TimeToProtoTime(base::Time::Now()));
return specifics;
return state.ToSpecificsProto();
}
// Returns the key derivation method to be used when a user sets a new
......@@ -199,22 +124,6 @@ KeyDerivationParams GetKeyDerivationParamsFromSpecifics(
return KeyDerivationParams::CreateWithUnsupportedMethod();
}
void UpdateSpecificsFromKeyDerivationParams(
const KeyDerivationParams& params,
sync_pb::NigoriSpecifics* specifics) {
DCHECK_EQ(specifics->passphrase_type(),
sync_pb::NigoriSpecifics::CUSTOM_PASSPHRASE);
DCHECK_NE(params.method(), KeyDerivationMethod::UNSUPPORTED);
specifics->set_custom_passphrase_key_derivation_method(
EnumKeyDerivationMethodToProto(params.method()));
if (params.method() == KeyDerivationMethod::SCRYPT_8192_8_11) {
// Persist the salt used for key derivation in Nigori if we're using scrypt.
std::string encoded_salt;
base::Base64Encode(params.scrypt_salt(), &encoded_salt);
specifics->set_custom_passphrase_key_derivation_salt(encoded_salt);
}
}
bool SpecificsHasValidKeyDerivationParams(const NigoriSpecifics& specifics) {
switch (GetKeyDerivationMethodFromSpecifics(specifics)) {
case KeyDerivationMethod::UNSUPPORTED:
......@@ -371,43 +280,6 @@ bool UpdateEncryptedTypes(const NigoriSpecifics& specifics,
return true;
}
// Updates |specifics|'s individual datatypes encryption state based on
// |encrypted_types|.
void UpdateNigoriSpecificsFromEncryptedTypes(
ModelTypeSet encrypted_types,
sync_pb::NigoriSpecifics* specifics) {
static_assert(39 == ModelType::NUM_ENTRIES,
"If adding an encryptable type, update handling below.");
specifics->set_encrypt_bookmarks(encrypted_types.Has(BOOKMARKS));
specifics->set_encrypt_preferences(encrypted_types.Has(PREFERENCES));
specifics->set_encrypt_autofill_profile(
encrypted_types.Has(AUTOFILL_PROFILE));
specifics->set_encrypt_autofill(encrypted_types.Has(AUTOFILL));
specifics->set_encrypt_autofill_wallet_metadata(
encrypted_types.Has(AUTOFILL_WALLET_METADATA));
specifics->set_encrypt_themes(encrypted_types.Has(THEMES));
specifics->set_encrypt_typed_urls(encrypted_types.Has(TYPED_URLS));
specifics->set_encrypt_extensions(encrypted_types.Has(EXTENSIONS));
specifics->set_encrypt_search_engines(encrypted_types.Has(SEARCH_ENGINES));
specifics->set_encrypt_sessions(encrypted_types.Has(SESSIONS));
specifics->set_encrypt_apps(encrypted_types.Has(APPS));
specifics->set_encrypt_app_settings(encrypted_types.Has(APP_SETTINGS));
specifics->set_encrypt_extension_settings(
encrypted_types.Has(EXTENSION_SETTINGS));
specifics->set_encrypt_dictionary(encrypted_types.Has(DICTIONARY));
specifics->set_encrypt_favicon_images(encrypted_types.Has(FAVICON_IMAGES));
specifics->set_encrypt_favicon_tracking(
encrypted_types.Has(FAVICON_TRACKING));
specifics->set_encrypt_app_list(encrypted_types.Has(APP_LIST));
specifics->set_encrypt_arc_package(encrypted_types.Has(ARC_PACKAGE));
specifics->set_encrypt_printers(encrypted_types.Has(PRINTERS));
specifics->set_encrypt_reading_list(encrypted_types.Has(READING_LIST));
specifics->set_encrypt_mountain_shares(encrypted_types.Has(MOUNTAIN_SHARES));
specifics->set_encrypt_send_tab_to_self(
encrypted_types.Has(SEND_TAB_TO_SELF));
specifics->set_encrypt_web_apps(encrypted_types.Has(WEB_APPS));
}
// Packs explicit passphrase key in order to persist it. Should be aligned with
// Directory implementation (Cryptographer::GetBootstrapToken()) unless it is
// removed. Returns empty string in case of errors.
......@@ -504,8 +376,8 @@ NigoriSyncBridgeImpl::NigoriSyncBridgeImpl(
}
// Restore data.
state_ =
syncer::NigoriState::CreateFromProto(deserialized_data->nigori_model());
state_ = syncer::NigoriState::CreateFromLocalProto(
deserialized_data->nigori_model());
// Restore metadata.
NigoriMetadataBatch metadata_batch;
......@@ -844,14 +716,15 @@ base::Optional<ModelError> NigoriSyncBridgeImpl::MergeSyncData(
}
// We received uninitialized Nigori and need to initialize it as default
// keystore Nigori.
base::Optional<NigoriSpecifics> initialized_specifics =
NigoriSpecifics initialized_specifics =
MakeDefaultKeystoreNigori(state_.keystore_keys);
if (!initialized_specifics) {
// In rare cases the crypto operations may fail.
if (!IsValidNigoriSpecifics(initialized_specifics)) {
return ModelError(FROM_HERE, "Failed to initialize keystore Nigori.");
}
*data->specifics.mutable_nigori() = *initialized_specifics;
*data->specifics.mutable_nigori() = initialized_specifics;
processor_->Put(std::make_unique<EntityData>(std::move(*data)));
return UpdateLocalState(*initialized_specifics);
return UpdateLocalState(initialized_specifics);
}
base::Optional<ModelError> NigoriSyncBridgeImpl::ApplySyncChanges(
......@@ -1078,52 +951,7 @@ std::unique_ptr<EntityData> NigoriSyncBridgeImpl::GetData() {
return nullptr;
}
NigoriSpecifics specifics;
if (state_.cryptographer->CanEncrypt()) {
EncryptKeyBag(*state_.cryptographer, specifics.mutable_encryption_keybag());
} else {
DCHECK(state_.pending_keys.has_value());
// This case is reachable only from processor's GetAllNodesForDebugging(),
// since currently commit is never issued while bridge has |pending_keys_|.
// Note: with complete support of TRUSTED_VAULT mode, commit might be
// issued in this case as well.
*specifics.mutable_encryption_keybag() = *state_.pending_keys;
}
specifics.set_keybag_is_frozen(true);
specifics.set_encrypt_everything(state_.encrypt_everything);
if (state_.encrypt_everything) {
UpdateNigoriSpecificsFromEncryptedTypes(EncryptableUserTypes(), &specifics);
}
specifics.set_passphrase_type(state_.passphrase_type);
if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
DCHECK(state_.custom_passphrase_key_derivation_params);
UpdateSpecificsFromKeyDerivationParams(
*state_.custom_passphrase_key_derivation_params, &specifics);
}
if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
// TODO(crbug.com/922900): it seems possible to have corrupted
// |pending_keystore_decryptor_token| and an ability to recover it in case
// |pending_keys| isn't set and |keystore_keys| contains some keys.
if (state_.pending_keystore_decryptor_token.has_value()) {
*specifics.mutable_keystore_decryptor_token() =
*state_.pending_keystore_decryptor_token;
} else {
DCHECK(!state_.keystore_keys.empty());
EncryptKeystoreDecryptorToken(
*state_.cryptographer, specifics.mutable_keystore_decryptor_token(),
state_.keystore_keys);
}
}
if (!state_.keystore_migration_time.is_null()) {
specifics.set_keystore_migration_time(
TimeToProtoTime(state_.keystore_migration_time));
}
if (!state_.custom_passphrase_time.is_null()) {
specifics.set_custom_passphrase_time(
TimeToProtoTime(state_.custom_passphrase_time));
}
// TODO(crbug.com/922900): add other fields support.
NOTIMPLEMENTED();
const sync_pb::NigoriSpecifics specifics = state_.ToSpecificsProto();
DCHECK(IsValidNigoriSpecifics(specifics));
auto entity_data = std::make_unique<EntityData>();
......@@ -1300,7 +1128,7 @@ sync_pb::NigoriLocalData NigoriSyncBridgeImpl::SerializeAsNigoriLocalData()
}
// Serialize the data.
*output.mutable_nigori_model() = state_.ToProto();
*output.mutable_nigori_model() = state_.ToLocalProto();
return output;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment