1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/sync/nigori/nigori_sync_bridge_impl.h"
6
7 #include <utility>
8
9 #include "base/base64.h"
10 #include "base/bind.h"
11 #include "base/feature_list.h"
12 #include "base/json/json_string_value_serializer.h"
13 #include "base/location.h"
14 #include "base/metrics/histogram_macros.h"
15 #include "components/sync/base/encryptor.h"
16 #include "components/sync/base/passphrase_enums.h"
17 #include "components/sync/base/sync_base_switches.h"
18 #include "components/sync/base/time.h"
19 #include "components/sync/engine/sync_engine_switches.h"
20 #include "components/sync/model/entity_data.h"
21 #include "components/sync/nigori/keystore_keys_cryptographer.h"
22 #include "components/sync/nigori/nigori.h"
23 #include "components/sync/nigori/nigori_storage.h"
24 #include "components/sync/nigori/pending_local_nigori_commit.h"
25 #include "components/sync/protocol/encryption.pb.h"
26 #include "components/sync/protocol/nigori_local_data.pb.h"
27 #include "components/sync/protocol/nigori_specifics.pb.h"
28
29 namespace syncer {
30
31 namespace {
32
33 using sync_pb::NigoriSpecifics;
34
35 const char kNigoriNonUniqueName[] = "Nigori";
36
GetKeyDerivationMethodStateForMetrics(const base::Optional<KeyDerivationParams> & key_derivation_params)37 KeyDerivationMethodStateForMetrics GetKeyDerivationMethodStateForMetrics(
38 const base::Optional<KeyDerivationParams>& key_derivation_params) {
39 if (!key_derivation_params.has_value()) {
40 return KeyDerivationMethodStateForMetrics::NOT_SET;
41 }
42 switch (key_derivation_params.value().method()) {
43 case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
44 return KeyDerivationMethodStateForMetrics::PBKDF2_HMAC_SHA1_1003;
45 case KeyDerivationMethod::SCRYPT_8192_8_11:
46 return KeyDerivationMethodStateForMetrics::SCRYPT_8192_8_11;
47 case KeyDerivationMethod::UNSUPPORTED:
48 return KeyDerivationMethodStateForMetrics::UNSUPPORTED;
49 }
50
51 NOTREACHED();
52 return KeyDerivationMethodStateForMetrics::UNSUPPORTED;
53 }
54
GetKeyDerivationMethodFromSpecifics(const sync_pb::NigoriSpecifics & specifics)55 KeyDerivationMethod GetKeyDerivationMethodFromSpecifics(
56 const sync_pb::NigoriSpecifics& specifics) {
57 KeyDerivationMethod key_derivation_method = ProtoKeyDerivationMethodToEnum(
58 specifics.custom_passphrase_key_derivation_method());
59 if (key_derivation_method == KeyDerivationMethod::SCRYPT_8192_8_11 &&
60 base::FeatureList::IsEnabled(
61 switches::kSyncForceDisableScryptForCustomPassphrase)) {
62 // Because scrypt is explicitly disabled, just behave as if it is an
63 // unsupported method.
64 key_derivation_method = KeyDerivationMethod::UNSUPPORTED;
65 }
66
67 return key_derivation_method;
68 }
69
GetScryptSaltFromSpecifics(const sync_pb::NigoriSpecifics & specifics)70 std::string GetScryptSaltFromSpecifics(
71 const sync_pb::NigoriSpecifics& specifics) {
72 DCHECK_EQ(specifics.custom_passphrase_key_derivation_method(),
73 sync_pb::NigoriSpecifics::SCRYPT_8192_8_11);
74 std::string decoded_salt;
75 bool result = base::Base64Decode(
76 specifics.custom_passphrase_key_derivation_salt(), &decoded_salt);
77 DCHECK(result);
78 return decoded_salt;
79 }
80
GetKeyDerivationParamsFromSpecifics(const sync_pb::NigoriSpecifics & specifics)81 KeyDerivationParams GetKeyDerivationParamsFromSpecifics(
82 const sync_pb::NigoriSpecifics& specifics) {
83 KeyDerivationMethod method = GetKeyDerivationMethodFromSpecifics(specifics);
84 switch (method) {
85 case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
86 return KeyDerivationParams::CreateForPbkdf2();
87 case KeyDerivationMethod::SCRYPT_8192_8_11:
88 return KeyDerivationParams::CreateForScrypt(
89 GetScryptSaltFromSpecifics(specifics));
90 case KeyDerivationMethod::UNSUPPORTED:
91 break;
92 }
93
94 return KeyDerivationParams::CreateWithUnsupportedMethod();
95 }
96
97 // We need to apply base64 encoding before deriving Nigori keys because the
98 // underlying crypto libraries (in particular the Java counterparts in JDK's
99 // implementation for PBKDF2) assume the keys are utf8.
Base64EncodeKeys(const std::vector<std::vector<uint8_t>> & keys)100 std::vector<std::string> Base64EncodeKeys(
101 const std::vector<std::vector<uint8_t>>& keys) {
102 std::vector<std::string> encoded_keystore_keys;
103 for (const std::vector<uint8_t>& key : keys) {
104 encoded_keystore_keys.push_back(base::Base64Encode(key));
105 }
106 return encoded_keystore_keys;
107 }
108
SpecificsHasValidKeyDerivationParams(const NigoriSpecifics & specifics)109 bool SpecificsHasValidKeyDerivationParams(const NigoriSpecifics& specifics) {
110 switch (GetKeyDerivationMethodFromSpecifics(specifics)) {
111 case KeyDerivationMethod::UNSUPPORTED:
112 DLOG(ERROR) << "Unsupported key derivation method encountered: "
113 << specifics.custom_passphrase_key_derivation_method();
114 return false;
115 case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
116 return true;
117 case KeyDerivationMethod::SCRYPT_8192_8_11:
118 if (!specifics.has_custom_passphrase_key_derivation_salt()) {
119 DLOG(ERROR) << "Missed key derivation salt while key derivation "
120 << "method is SCRYPT_8192_8_11.";
121 return false;
122 }
123 std::string temp;
124 if (!base::Base64Decode(specifics.custom_passphrase_key_derivation_salt(),
125 &temp)) {
126 DLOG(ERROR) << "Key derivation salt is not a valid base64 encoded "
127 "string.";
128 return false;
129 }
130 return true;
131 }
132 }
133
134 // Validates given |specifics| assuming it's not specifics received from the
135 // server during first-time sync for current user (i.e. it's not a default
136 // specifics).
IsValidNigoriSpecifics(const NigoriSpecifics & specifics)137 bool IsValidNigoriSpecifics(const NigoriSpecifics& specifics) {
138 if (specifics.encryption_keybag().blob().empty()) {
139 DLOG(ERROR) << "Specifics contains empty encryption_keybag.";
140 return false;
141 }
142 switch (ProtoPassphraseInt32ToProtoEnum(specifics.passphrase_type())) {
143 case NigoriSpecifics::UNKNOWN:
144 DLOG(ERROR) << "Received unknown passphrase type with value: "
145 << specifics.passphrase_type();
146 return false;
147 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
148 return true;
149 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
150 if (specifics.keystore_decryptor_token().blob().empty()) {
151 DLOG(ERROR) << "Keystore Nigori should have filled "
152 << "keystore_decryptor_token.";
153 return false;
154 }
155 break;
156 case NigoriSpecifics::CUSTOM_PASSPHRASE:
157 if (!SpecificsHasValidKeyDerivationParams(specifics)) {
158 return false;
159 }
160 FALLTHROUGH;
161 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
162 if (!specifics.encrypt_everything()) {
163 DLOG(ERROR) << "Nigori with explicit passphrase type should have "
164 "enabled encrypt_everything.";
165 return false;
166 }
167 break;
168 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
169 return base::FeatureList::IsEnabled(
170 switches::kSyncSupportTrustedVaultPassphrase);
171 }
172 return true;
173 }
174
IsValidPassphraseTransition(NigoriSpecifics::PassphraseType old_passphrase_type,NigoriSpecifics::PassphraseType new_passphrase_type)175 bool IsValidPassphraseTransition(
176 NigoriSpecifics::PassphraseType old_passphrase_type,
177 NigoriSpecifics::PassphraseType new_passphrase_type) {
178 // We assume that |new_passphrase_type| is valid.
179 DCHECK_NE(new_passphrase_type, NigoriSpecifics::UNKNOWN);
180
181 if (old_passphrase_type == new_passphrase_type) {
182 return true;
183 }
184 switch (old_passphrase_type) {
185 case NigoriSpecifics::UNKNOWN:
186 // This can happen iff we have not synced local state yet or synced with
187 // default NigoriSpecifics, so we accept any valid passphrase type
188 // (invalid filtered before).
189 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
190 return true;
191 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
192 return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE ||
193 new_passphrase_type == NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE;
194 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
195 // There is no client side code which can cause such transition, but
196 // technically it's a valid one and can be implemented in the future.
197 return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE;
198 case NigoriSpecifics::CUSTOM_PASSPHRASE:
199 return false;
200 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
201 return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE ||
202 new_passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE;
203 }
204 NOTREACHED();
205 return false;
206 }
207
208 // Updates |*current_type| if needed. Returns true if its value was changed.
UpdatePassphraseType(NigoriSpecifics::PassphraseType new_type,NigoriSpecifics::PassphraseType * current_type)209 bool UpdatePassphraseType(NigoriSpecifics::PassphraseType new_type,
210 NigoriSpecifics::PassphraseType* current_type) {
211 DCHECK(current_type);
212 DCHECK(IsValidPassphraseTransition(*current_type, new_type));
213 if (*current_type == new_type) {
214 return false;
215 }
216 *current_type = new_type;
217 return true;
218 }
219
IsValidEncryptedTypesTransition(bool old_encrypt_everything,const NigoriSpecifics & specifics)220 bool IsValidEncryptedTypesTransition(bool old_encrypt_everything,
221 const NigoriSpecifics& specifics) {
222 // We don't support relaxing the encryption requirements.
223 // TODO(crbug.com/922900): more logic is to be added here, once we support
224 // enforced encryption for individual datatypes.
225 return specifics.encrypt_everything() || !old_encrypt_everything;
226 }
227
228 // Updates |*current_encrypt_everything| if needed. Returns true if its value
229 // was changed.
UpdateEncryptedTypes(const NigoriSpecifics & specifics,bool * current_encrypt_everything)230 bool UpdateEncryptedTypes(const NigoriSpecifics& specifics,
231 bool* current_encrypt_everything) {
232 DCHECK(current_encrypt_everything);
233 DCHECK(
234 IsValidEncryptedTypesTransition(*current_encrypt_everything, specifics));
235 // TODO(crbug.com/922900): more logic is to be added here, once we support
236 // enforced encryption for individual datatypes.
237 if (*current_encrypt_everything == specifics.encrypt_everything()) {
238 return false;
239 }
240 *current_encrypt_everything = specifics.encrypt_everything();
241 return true;
242 }
243
244 // Packs explicit passphrase key in order to persist it. Returns empty string in
245 // case of errors.
PackExplicitPassphraseKey(const Encryptor & encryptor,const CryptographerImpl & cryptographer)246 std::string PackExplicitPassphraseKey(const Encryptor& encryptor,
247 const CryptographerImpl& cryptographer) {
248 DCHECK(cryptographer.CanEncrypt());
249
250 // Explicit passphrase key should always be default one.
251 std::string serialized_key =
252 cryptographer.ExportDefaultKey().SerializeAsString();
253
254 if (serialized_key.empty()) {
255 DLOG(ERROR) << "Failed to serialize explicit passphrase key.";
256 return std::string();
257 }
258
259 std::string encrypted_key;
260 if (!encryptor.EncryptString(serialized_key, &encrypted_key)) {
261 DLOG(ERROR) << "Failed to encrypt explicit passphrase key.";
262 return std::string();
263 }
264
265 std::string encoded_key;
266 base::Base64Encode(encrypted_key, &encoded_key);
267 return encoded_key;
268 }
269
270 // Unpacks explicit passphrase keys. Returns a populated sync_pb::NigoriKey if
271 // successful, or an empty instance (i.e. default value) if |packed_key| is
272 // empty or decoding/decryption errors occur.
UnpackExplicitPassphraseKey(const Encryptor & encryptor,const std::string & packed_key)273 sync_pb::NigoriKey UnpackExplicitPassphraseKey(const Encryptor& encryptor,
274 const std::string& packed_key) {
275 if (packed_key.empty()) {
276 return sync_pb::NigoriKey();
277 }
278
279 std::string decoded_key;
280 if (!base::Base64Decode(packed_key, &decoded_key)) {
281 DLOG(ERROR) << "Failed to decode explicit passphrase key.";
282 return sync_pb::NigoriKey();
283 }
284
285 std::string decrypted_key;
286 if (!encryptor.DecryptString(decoded_key, &decrypted_key)) {
287 DLOG(ERROR) << "Failed to decrypt expliciti passphrase key.";
288 return sync_pb::NigoriKey();
289 }
290
291 sync_pb::NigoriKey key;
292 key.ParseFromString(decrypted_key);
293 return key;
294 }
295
296 // Returns Base64 encoded keystore keys or empty vector if errors occur.
UnpackKeystoreKeys(const std::string & packed_keystore_keys,const Encryptor & encryptor)297 std::vector<std::string> UnpackKeystoreKeys(
298 const std::string& packed_keystore_keys,
299 const Encryptor& encryptor) {
300 DCHECK(!packed_keystore_keys.empty());
301
302 std::string base64_decoded_packed_keys;
303 if (!base::Base64Decode(packed_keystore_keys, &base64_decoded_packed_keys)) {
304 return std::vector<std::string>();
305 }
306 std::string decrypted_packed_keys;
307 if (!encryptor.DecryptString(base64_decoded_packed_keys,
308 &decrypted_packed_keys)) {
309 return std::vector<std::string>();
310 }
311
312 JSONStringValueDeserializer json_deserializer(decrypted_packed_keys);
313 std::unique_ptr<base::Value> deserialized_keys(json_deserializer.Deserialize(
314 /*error_code=*/nullptr, /*error_message=*/nullptr));
315 if (!deserialized_keys) {
316 return std::vector<std::string>();
317 }
318 base::ListValue* list_value = nullptr;
319 if (!deserialized_keys->GetAsList(&list_value)) {
320 return std::vector<std::string>();
321 }
322
323 std::vector<std::string> keystore_keys(list_value->GetSize());
324 for (size_t i = 0; i < keystore_keys.size(); ++i) {
325 if (!list_value->GetString(i, &keystore_keys[i])) {
326 return std::vector<std::string>();
327 }
328 }
329 return keystore_keys;
330 }
331
GetEncryptedTypes(bool encrypt_everything)332 ModelTypeSet GetEncryptedTypes(bool encrypt_everything) {
333 if (encrypt_everything) {
334 return EncryptableUserTypes();
335 }
336 return AlwaysEncryptedUserTypes();
337 }
338
339 } // namespace
340
341 class NigoriSyncBridgeImpl::BroadcastingObserver
342 : public SyncEncryptionHandler::Observer {
343 public:
BroadcastingObserver(const base::RepeatingClosure & post_passphrase_accepted_cb)344 explicit BroadcastingObserver(
345 const base::RepeatingClosure& post_passphrase_accepted_cb)
346 : post_passphrase_accepted_cb_(post_passphrase_accepted_cb) {}
347
348 ~BroadcastingObserver() override = default;
349
AddObserver(SyncEncryptionHandler::Observer * observer)350 void AddObserver(SyncEncryptionHandler::Observer* observer) {
351 observers_.AddObserver(observer);
352 }
353
RemoveObserver(SyncEncryptionHandler::Observer * observer)354 void RemoveObserver(SyncEncryptionHandler::Observer* observer) {
355 observers_.RemoveObserver(observer);
356 }
357
358 // SyncEncryptionHandler::Observer implementation.
OnPassphraseRequired(const KeyDerivationParams & key_derivation_params,const sync_pb::EncryptedData & pending_keys)359 void OnPassphraseRequired(
360 const KeyDerivationParams& key_derivation_params,
361 const sync_pb::EncryptedData& pending_keys) override {
362 for (auto& observer : observers_) {
363 observer.OnPassphraseRequired(key_derivation_params, pending_keys);
364 }
365 }
366
OnPassphraseAccepted()367 void OnPassphraseAccepted() override {
368 for (auto& observer : observers_) {
369 observer.OnPassphraseAccepted();
370 }
371 post_passphrase_accepted_cb_.Run();
372 }
373
OnTrustedVaultKeyRequired()374 void OnTrustedVaultKeyRequired() override {
375 for (auto& observer : observers_) {
376 observer.OnTrustedVaultKeyRequired();
377 }
378 }
379
OnTrustedVaultKeyAccepted()380 void OnTrustedVaultKeyAccepted() override {
381 for (auto& observer : observers_) {
382 observer.OnTrustedVaultKeyAccepted();
383 }
384 }
385
OnBootstrapTokenUpdated(const std::string & bootstrap_token,BootstrapTokenType type)386 void OnBootstrapTokenUpdated(const std::string& bootstrap_token,
387 BootstrapTokenType type) override {
388 for (auto& observer : observers_) {
389 observer.OnBootstrapTokenUpdated(bootstrap_token, type);
390 }
391 }
392
OnEncryptedTypesChanged(ModelTypeSet encrypted_types,bool encrypt_everything)393 void OnEncryptedTypesChanged(ModelTypeSet encrypted_types,
394 bool encrypt_everything) override {
395 for (auto& observer : observers_) {
396 observer.OnEncryptedTypesChanged(encrypted_types, encrypt_everything);
397 }
398 }
399
OnCryptographerStateChanged(Cryptographer * cryptographer,bool has_pending_keys)400 void OnCryptographerStateChanged(Cryptographer* cryptographer,
401 bool has_pending_keys) override {
402 for (auto& observer : observers_) {
403 observer.OnCryptographerStateChanged(cryptographer, has_pending_keys);
404 }
405 }
406
OnPassphraseTypeChanged(PassphraseType type,base::Time passphrase_time)407 void OnPassphraseTypeChanged(PassphraseType type,
408 base::Time passphrase_time) override {
409 for (auto& observer : observers_) {
410 observer.OnPassphraseTypeChanged(type, passphrase_time);
411 }
412 }
413
414 private:
415 // TODO(crbug/922900): consider using checked ObserverList once
416 // SyncEncryptionHandlerImpl is no longer needed or consider refactoring old
417 // implementation to use checked ObserverList as well.
418 base::ObserverList<SyncEncryptionHandler::Observer>::Unchecked observers_;
419
420 const base::RepeatingClosure post_passphrase_accepted_cb_;
421
422 DISALLOW_COPY_AND_ASSIGN(BroadcastingObserver);
423 };
424
NigoriSyncBridgeImpl(std::unique_ptr<NigoriLocalChangeProcessor> processor,std::unique_ptr<NigoriStorage> storage,const Encryptor * encryptor,const base::RepeatingCallback<std::string ()> & random_salt_generator,const std::string & packed_explicit_passphrase_key,const std::string & packed_keystore_keys)425 NigoriSyncBridgeImpl::NigoriSyncBridgeImpl(
426 std::unique_ptr<NigoriLocalChangeProcessor> processor,
427 std::unique_ptr<NigoriStorage> storage,
428 const Encryptor* encryptor,
429 const base::RepeatingCallback<std::string()>& random_salt_generator,
430 const std::string& packed_explicit_passphrase_key,
431 const std::string& packed_keystore_keys)
432 : encryptor_(encryptor),
433 processor_(std::move(processor)),
434 storage_(std::move(storage)),
435 random_salt_generator_(random_salt_generator),
436 explicit_passphrase_key_(
437 UnpackExplicitPassphraseKey(*encryptor,
438 packed_explicit_passphrase_key)),
439 broadcasting_observer_(std::make_unique<BroadcastingObserver>(
440 // base::Unretained() legit because the observer gets destroyed
441 // together with |this|.
442 base::BindRepeating(
443 &NigoriSyncBridgeImpl::MaybeNotifyBootstrapTokenUpdated,
444 base::Unretained(this)))) {
445 DCHECK(encryptor);
446
447 // TODO(crbug.com/922900): we currently don't verify |deserialized_data|.
448 // It's quite unlikely we get a corrupted data, since it was successfully
449 // deserialized and decrypted. But we may want to consider some
450 // verifications, taking into account sensitivity of this data.
451 base::Optional<sync_pb::NigoriLocalData> deserialized_data =
452 storage_->RestoreData();
453 if (!deserialized_data ||
454 (deserialized_data->nigori_model().passphrase_type() ==
455 NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE &&
456 !base::FeatureList::IsEnabled(
457 switches::kSyncSupportTrustedVaultPassphrase))) {
458 // We either have no Nigori node stored locally or it was corrupted.
459 processor_->ModelReadyToSync(this, NigoriMetadataBatch());
460 // Keystore keys needs migration independently of having local Nigori node.
461 MaybeMigrateKeystoreKeys(packed_keystore_keys);
462 return;
463 }
464
465 // Restore data.
466 state_ = syncer::NigoriState::CreateFromLocalProto(
467 deserialized_data->nigori_model());
468
469 // Restore metadata.
470 NigoriMetadataBatch metadata_batch;
471 metadata_batch.model_type_state = deserialized_data->model_type_state();
472 metadata_batch.entity_metadata = deserialized_data->entity_metadata();
473 processor_->ModelReadyToSync(this, std::move(metadata_batch));
474
475 // Attempt migration of keystore keys after deserialization to not overwrite
476 // newer keys.
477 MaybeMigrateKeystoreKeys(packed_keystore_keys);
478
479 if (state_.passphrase_type == NigoriSpecifics::UNKNOWN) {
480 // Commit with keystore initialization wasn't successfully completed before
481 // the restart, so trigger it again here.
482 DCHECK(!state_.keystore_keys_cryptographer->IsEmpty());
483 QueuePendingLocalCommit(
484 PendingLocalNigoriCommit::ForKeystoreInitialization());
485 }
486
487 // Keystore key rotation might be not performed, but required.
488 MaybeTriggerKeystoreReencryption();
489
490 // Ensure that |cryptographer| contains all keystore keys (non-keystore
491 // passphrase types only).
492 MaybePopulateKeystoreKeysIntoCryptographer();
493 }
494
~NigoriSyncBridgeImpl()495 NigoriSyncBridgeImpl::~NigoriSyncBridgeImpl() {
496 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
497 }
498
AddObserver(Observer * observer)499 void NigoriSyncBridgeImpl::AddObserver(Observer* observer) {
500 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
501 broadcasting_observer_->AddObserver(observer);
502 }
503
RemoveObserver(Observer * observer)504 void NigoriSyncBridgeImpl::RemoveObserver(Observer* observer) {
505 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
506 broadcasting_observer_->RemoveObserver(observer);
507 }
508
Init()509 bool NigoriSyncBridgeImpl::Init() {
510 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
511 // We need to expose whole bridge state through notifications, because it
512 // can be different from default due to restoring from the file or
513 // completeness of first sync cycle (which happens before Init() call).
514 // TODO(crbug.com/922900): try to avoid double notification (second one can
515 // happen during UpdateLocalState() call).
516 broadcasting_observer_->OnEncryptedTypesChanged(
517 GetEncryptedTypes(state_.encrypt_everything), state_.encrypt_everything);
518 broadcasting_observer_->OnCryptographerStateChanged(
519 state_.cryptographer.get(), state_.pending_keys.has_value());
520
521 MaybeNotifyOfPendingKeys();
522
523 if (state_.passphrase_type != NigoriSpecifics::UNKNOWN) {
524 // if |passphrase_type| is unknown, it is not yet initialized and we
525 // shouldn't expose it.
526 PassphraseType enum_passphrase_type =
527 *ProtoPassphraseInt32ToEnum(state_.passphrase_type);
528 broadcasting_observer_->OnPassphraseTypeChanged(
529 enum_passphrase_type, GetExplicitPassphraseTime());
530 UMA_HISTOGRAM_ENUMERATION("Sync.PassphraseType", enum_passphrase_type);
531 }
532 if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
533 UMA_HISTOGRAM_ENUMERATION(
534 "Sync.Crypto.CustomPassphraseKeyDerivationMethodStateOnStartup",
535 GetKeyDerivationMethodStateForMetrics(
536 state_.custom_passphrase_key_derivation_params));
537 }
538 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerReady",
539 state_.cryptographer->CanEncrypt());
540 UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerPendingKeys",
541 state_.pending_keys.has_value());
542 if (state_.pending_keys.has_value() &&
543 state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
544 // If this is happening, it means the keystore decryptor is either
545 // undecryptable with the available keystore keys or does not match the
546 // nigori keybag's encryption key. Otherwise we're simply missing the
547 // keystore key.
548 UMA_HISTOGRAM_BOOLEAN("Sync.KeystoreDecryptionFailed",
549 !state_.keystore_keys_cryptographer->IsEmpty());
550 }
551 return true;
552 }
553
SetEncryptionPassphrase(const std::string & passphrase)554 void NigoriSyncBridgeImpl::SetEncryptionPassphrase(
555 const std::string& passphrase) {
556 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
557
558 UMA_HISTOGRAM_ENUMERATION(
559 "Sync.Crypto.CustomPassphraseKeyDerivationMethodOnNewPassphrase",
560 GetKeyDerivationMethodStateForMetrics(
561 CreateKeyDerivationParamsForCustomPassphrase(
562 random_salt_generator_)));
563
564 QueuePendingLocalCommit(PendingLocalNigoriCommit::ForSetCustomPassphrase(
565 passphrase, random_salt_generator_));
566 }
567
SetDecryptionPassphrase(const std::string & passphrase)568 void NigoriSyncBridgeImpl::SetDecryptionPassphrase(
569 const std::string& passphrase) {
570 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
571 // |passphrase| should be a valid one already (verified by SyncServiceCrypto,
572 // using pending keys exposed by OnPassphraseRequired()).
573 DCHECK(!passphrase.empty());
574 if (!state_.pending_keys) {
575 DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
576 return;
577 }
578
579 NigoriKeyBag tmp_key_bag = NigoriKeyBag::CreateEmpty();
580 const std::string new_key_name =
581 tmp_key_bag.AddKey(Nigori::CreateByDerivation(
582 GetKeyDerivationParamsForPendingKeys(), passphrase));
583
584 base::Optional<ModelError> error = TryDecryptPendingKeysWith(tmp_key_bag);
585 if (error.has_value()) {
586 processor_->ReportError(*error);
587 return;
588 }
589
590 if (state_.pending_keys.has_value()) {
591 // |pending_keys| could be changed in between of OnPassphraseRequired()
592 // and SetDecryptionPassphrase() calls (remote update with different
593 // keystore Nigori or with transition from keystore to custom passphrase
594 // Nigori).
595 MaybeNotifyOfPendingKeys();
596 return;
597 }
598
599 if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
600 DCHECK(state_.custom_passphrase_key_derivation_params.has_value());
601 UMA_HISTOGRAM_ENUMERATION(
602 "Sync.Crypto."
603 "CustomPassphraseKeyDerivationMethodOnSuccessfulDecryption",
604 GetKeyDerivationMethodStateForMetrics(
605 state_.custom_passphrase_key_derivation_params));
606 }
607
608 DCHECK_EQ(state_.cryptographer->GetDefaultEncryptionKeyName(), new_key_name);
609 storage_->StoreData(SerializeAsNigoriLocalData());
610 broadcasting_observer_->OnCryptographerStateChanged(
611 state_.cryptographer.get(), state_.pending_keys.has_value());
612 broadcasting_observer_->OnPassphraseAccepted();
613 }
614
AddTrustedVaultDecryptionKeys(const std::vector<std::vector<uint8_t>> & keys)615 void NigoriSyncBridgeImpl::AddTrustedVaultDecryptionKeys(
616 const std::vector<std::vector<uint8_t>>& keys) {
617 // This API gets plumbed and ultimately exposed to layers outside the sync
618 // codebase and even outside the browser, so there are no preconditions and
619 // instead we ignore invalid or partially invalid input.
620 if (state_.passphrase_type != NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE ||
621 !state_.pending_keys || keys.empty()) {
622 return;
623 }
624
625 const std::vector<std::string> encoded_keys = Base64EncodeKeys(keys);
626 NigoriKeyBag tmp_key_bag = NigoriKeyBag::CreateEmpty();
627 for (const std::string& encoded_key : encoded_keys) {
628 tmp_key_bag.AddKey(Nigori::CreateByDerivation(
629 GetKeyDerivationParamsForPendingKeys(), encoded_key));
630 }
631
632 base::Optional<ModelError> error = TryDecryptPendingKeysWith(tmp_key_bag);
633 if (error.has_value()) {
634 processor_->ReportError(*error);
635 return;
636 }
637
638 if (state_.pending_keys.has_value()) {
639 return;
640 }
641
642 state_.last_default_trusted_vault_key_name =
643 state_.cryptographer->GetDefaultEncryptionKeyName();
644
645 storage_->StoreData(SerializeAsNigoriLocalData());
646 broadcasting_observer_->OnCryptographerStateChanged(
647 state_.cryptographer.get(), state_.pending_keys.has_value());
648 broadcasting_observer_->OnTrustedVaultKeyAccepted();
649 MaybeNotifyBootstrapTokenUpdated();
650 }
651
GetKeystoreMigrationTime() const652 base::Time NigoriSyncBridgeImpl::GetKeystoreMigrationTime() const {
653 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
654 return state_.keystore_migration_time;
655 }
656
GetKeystoreKeysHandler()657 KeystoreKeysHandler* NigoriSyncBridgeImpl::GetKeystoreKeysHandler() {
658 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
659 return this;
660 }
661
NeedKeystoreKey() const662 bool NigoriSyncBridgeImpl::NeedKeystoreKey() const {
663 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
664 // Explicitly asks the server for keystore keys if it's first-time sync, i.e.
665 // if there is no keystore keys yet or remote keybag wasn't decryptable due
666 // to absence of some keystore key. In case of key rotation, it's a server
667 // responsibility to send updated keystore keys. |keystore_keys_| is expected
668 // to be non-empty before MergeSyncData() call, regardless of passphrase
669 // type.
670 return state_.keystore_keys_cryptographer->IsEmpty() ||
671 (state_.pending_keystore_decryptor_token.has_value() &&
672 state_.pending_keys.has_value());
673 }
674
SetKeystoreKeys(const std::vector<std::vector<uint8_t>> & keys)675 bool NigoriSyncBridgeImpl::SetKeystoreKeys(
676 const std::vector<std::vector<uint8_t>>& keys) {
677 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
678 if (keys.empty() || keys.back().empty()) {
679 return false;
680 }
681
682 state_.keystore_keys_cryptographer =
683 KeystoreKeysCryptographer::FromKeystoreKeys(Base64EncodeKeys(keys));
684 if (!state_.keystore_keys_cryptographer) {
685 state_.keystore_keys_cryptographer =
686 KeystoreKeysCryptographer::CreateEmpty();
687 return false;
688 }
689
690 // TODO(crbug.com/1042251): having |pending_keystore_decryptor_token| without
691 // |pending_keys| means that new |keystore_decryptor_token| could be build
692 // in order to replace the potentially corrupted remote
693 // |keystore_decryptor_token|.
694 if (state_.pending_keystore_decryptor_token.has_value() &&
695 state_.pending_keys.has_value()) {
696 // Newly arrived keystore keys could resolve pending encryption state in
697 // keystore mode.
698 DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
699 const base::Optional<sync_pb::NigoriKey> keystore_decryptor_key =
700 TryDecryptPendingKeystoreDecryptorToken(
701 sync_pb::EncryptedData(*state_.pending_keystore_decryptor_token));
702
703 base::Optional<ModelError> error = UpdateCryptographer(
704 sync_pb::EncryptedData(*state_.pending_keys),
705 BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key));
706 if (error.has_value()) {
707 processor_->ReportError(*error);
708 return false;
709 }
710
711 broadcasting_observer_->OnCryptographerStateChanged(
712 state_.cryptographer.get(), state_.pending_keys.has_value());
713 }
714 MaybeTriggerKeystoreReencryption();
715 // Note: we don't need to persist keystore keys here, because we will receive
716 // Nigori node right after this method and persist all the data during
717 // UpdateLocalState().
718 return true;
719 }
720
MergeSyncData(base::Optional<EntityData> data)721 base::Optional<ModelError> NigoriSyncBridgeImpl::MergeSyncData(
722 base::Optional<EntityData> data) {
723 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
724 if (!data) {
725 return ModelError(FROM_HERE,
726 "Received empty EntityData during initial "
727 "sync of Nigori.");
728 }
729 DCHECK(data->specifics.has_nigori());
730
731 const NigoriSpecifics& specifics = data->specifics.nigori();
732 if (specifics.passphrase_type() != NigoriSpecifics::IMPLICIT_PASSPHRASE ||
733 !specifics.encryption_keybag().blob().empty()) {
734 // We received regular Nigori.
735 return UpdateLocalState(data->specifics.nigori());
736 }
737 // Ensure we have |keystore_keys| during the initial download, requested to
738 // the server as per NeedKeystoreKey(), and required for initializing the
739 // default keystore Nigori.
740 DCHECK(state_.keystore_keys_cryptographer);
741 if (state_.keystore_keys_cryptographer->IsEmpty()) {
742 // TODO(crbug.com/922900): try to relax this requirement for Nigori
743 // initialization as well. Keystore keys might not arrive, for example, due
744 // to throttling.
745 return ModelError(FROM_HERE,
746 "Keystore keys are not set during first time sync.");
747 }
748 // We received uninitialized Nigori and need to initialize it as default
749 // keystore Nigori.
750 QueuePendingLocalCommit(
751 PendingLocalNigoriCommit::ForKeystoreInitialization());
752 return base::nullopt;
753 }
754
ApplySyncChanges(base::Optional<EntityData> data)755 base::Optional<ModelError> NigoriSyncBridgeImpl::ApplySyncChanges(
756 base::Optional<EntityData> data) {
757 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
758
759 if (data) {
760 DCHECK(data->specifics.has_nigori());
761 return UpdateLocalState(data->specifics.nigori());
762 }
763
764 if (!pending_local_commit_queue_.empty() && !processor_->IsEntityUnsynced()) {
765 // Successfully committed first element in queue.
766 bool success = pending_local_commit_queue_.front()->TryApply(&state_);
767 DCHECK(success);
768 pending_local_commit_queue_.front()->OnSuccess(
769 state_, broadcasting_observer_.get());
770 pending_local_commit_queue_.pop_front();
771
772 // Advance until the next applicable local change if any and call Put().
773 PutNextApplicablePendingLocalCommit();
774 }
775
776 // Receiving empty |data| means metadata-only change (e.g. no remote updates,
777 // or local commit completion), so we need to persist its state.
778 storage_->StoreData(SerializeAsNigoriLocalData());
779 return base::nullopt;
780 }
781
UpdateLocalState(const NigoriSpecifics & specifics)782 base::Optional<ModelError> NigoriSyncBridgeImpl::UpdateLocalState(
783 const NigoriSpecifics& specifics) {
784 if (!IsValidNigoriSpecifics(specifics)) {
785 return ModelError(FROM_HERE, "NigoriSpecifics is not valid.");
786 }
787
788 const sync_pb::NigoriSpecifics::PassphraseType new_passphrase_type =
789 ProtoPassphraseInt32ToProtoEnum(specifics.passphrase_type());
790 DCHECK_NE(new_passphrase_type, NigoriSpecifics::UNKNOWN);
791
792 if (!IsValidPassphraseTransition(
793 /*old_passphrase_type=*/state_.passphrase_type,
794 new_passphrase_type)) {
795 return ModelError(FROM_HERE, "Invalid passphrase type transition.");
796 }
797 if (!IsValidEncryptedTypesTransition(state_.encrypt_everything, specifics)) {
798 return ModelError(FROM_HERE, "Invalid encrypted types transition.");
799 }
800
801 const bool passphrase_type_changed =
802 UpdatePassphraseType(new_passphrase_type, &state_.passphrase_type);
803 DCHECK_NE(state_.passphrase_type, NigoriSpecifics::UNKNOWN);
804
805 const bool encrypted_types_changed =
806 UpdateEncryptedTypes(specifics, &state_.encrypt_everything);
807
808 if (specifics.has_custom_passphrase_time()) {
809 state_.custom_passphrase_time =
810 ProtoTimeToTime(specifics.custom_passphrase_time());
811 }
812 if (specifics.has_keystore_migration_time()) {
813 state_.keystore_migration_time =
814 ProtoTimeToTime(specifics.keystore_migration_time());
815 }
816
817 base::Optional<sync_pb::NigoriKey> keystore_decryptor_key;
818 if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
819 keystore_decryptor_key = TryDecryptPendingKeystoreDecryptorToken(
820 specifics.keystore_decryptor_token());
821 } else {
822 state_.pending_keystore_decryptor_token.reset();
823 }
824
825 if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
826 state_.custom_passphrase_key_derivation_params =
827 GetKeyDerivationParamsFromSpecifics(specifics);
828 }
829
830 base::Optional<ModelError> error = UpdateCryptographer(
831 specifics.encryption_keybag(),
832 BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key));
833 if (error) {
834 return error;
835 }
836
837 if (passphrase_type_changed) {
838 broadcasting_observer_->OnPassphraseTypeChanged(
839 *ProtoPassphraseInt32ToEnum(state_.passphrase_type),
840 GetExplicitPassphraseTime());
841 }
842 if (encrypted_types_changed) {
843 // Currently the only way to change encrypted types is to enable
844 // encrypt_everything.
845 DCHECK(state_.encrypt_everything);
846 broadcasting_observer_->OnEncryptedTypesChanged(EncryptableUserTypes(),
847 state_.encrypt_everything);
848 }
849 broadcasting_observer_->OnCryptographerStateChanged(
850 state_.cryptographer.get(), state_.pending_keys.has_value());
851
852 MaybeNotifyOfPendingKeys();
853
854 // There might be pending local commits, so make attempt to apply them on top
855 // of new |state_|.
856 PutNextApplicablePendingLocalCommit();
857
858 storage_->StoreData(SerializeAsNigoriLocalData());
859
860 return base::nullopt;
861 }
862
UpdateCryptographer(const sync_pb::EncryptedData & encryption_keybag,const NigoriKeyBag & decryption_key_bag)863 base::Optional<ModelError> NigoriSyncBridgeImpl::UpdateCryptographer(
864 const sync_pb::EncryptedData& encryption_keybag,
865 const NigoriKeyBag& decryption_key_bag) {
866 DCHECK(!encryption_keybag.blob().empty());
867
868 const bool had_pending_keys_before_update = state_.pending_keys.has_value();
869
870 state_.pending_keys = encryption_keybag;
871 state_.cryptographer->ClearDefaultEncryptionKey();
872
873 base::Optional<ModelError> error =
874 TryDecryptPendingKeysWith(decryption_key_bag);
875 if (error.has_value()) {
876 return error;
877 }
878
879 // TODO(crbug.com/1057655): issuing OnPassphraseAccepted() should be allowed
880 // for all passphrase types, but going out from |pending_keys| state might
881 // be disallowed for some circumstances (such as CUSTOM_PASSPHRASE ->
882 // CUSTOM_PASSPHRASE updates). Keep temporarily as is to avoid behavioral
883 // changes.
884 if (!state_.pending_keys.has_value() && had_pending_keys_before_update &&
885 state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
886 broadcasting_observer_->OnPassphraseAccepted();
887 }
888
889 return base::nullopt;
890 }
891
892 base::Optional<sync_pb::NigoriKey>
TryDecryptPendingKeystoreDecryptorToken(const sync_pb::EncryptedData & keystore_decryptor_token)893 NigoriSyncBridgeImpl::TryDecryptPendingKeystoreDecryptorToken(
894 const sync_pb::EncryptedData& keystore_decryptor_token) {
895 DCHECK(!keystore_decryptor_token.blob().empty());
896 sync_pb::NigoriKey keystore_decryptor_key;
897 if (state_.keystore_keys_cryptographer->DecryptKeystoreDecryptorToken(
898 keystore_decryptor_token, &keystore_decryptor_key)) {
899 state_.pending_keystore_decryptor_token.reset();
900 return keystore_decryptor_key;
901 }
902 state_.pending_keystore_decryptor_token = keystore_decryptor_token;
903 return base::nullopt;
904 }
905
BuildDecryptionKeyBagForRemoteKeybag(const base::Optional<sync_pb::NigoriKey> & keystore_decryptor_key) const906 NigoriKeyBag NigoriSyncBridgeImpl::BuildDecryptionKeyBagForRemoteKeybag(
907 const base::Optional<sync_pb::NigoriKey>& keystore_decryptor_key) const {
908 NigoriKeyBag decryption_key_bag = NigoriKeyBag::CreateEmpty();
909
910 if (keystore_decryptor_key.has_value()) {
911 DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
912 decryption_key_bag.AddKeyFromProto(*keystore_decryptor_key);
913 }
914
915 // TODO(crbug.com/1057655, crbug.com/1020084): This should be allowed for
916 // KEYSTORE_PASSPHRASE and disallowed for TRUSTED_VAULT_PASSPHRASE, keep
917 // temporarily as is to avoid behavioral changes.
918 if (state_.passphrase_type != NigoriSpecifics::KEYSTORE_PASSPHRASE) {
919 // Note: key derived from explicit passphrase was stored in prefs prior to
920 // USS, and using |explicit_passphrase_key_| here effectively does
921 // migration. If |explicit_passphrase_key_| is empty, following line is
922 // no-op.
923 decryption_key_bag.AddKeyFromProto(explicit_passphrase_key_);
924 }
925
926 // TODO(crbug.com/1057655): this should be allowed for KEYSTORE_PASSPHRASE,
927 // but should be disallowed if |passphrase_type| was changed in current
928 // update.
929 if (state_.passphrase_type != NigoriSpecifics::KEYSTORE_PASSPHRASE &&
930 state_.cryptographer->CanEncrypt()) {
931 decryption_key_bag.AddKeyFromProto(
932 state_.cryptographer->ExportDefaultKey());
933 }
934
935 return decryption_key_bag;
936 }
937
TryDecryptPendingKeysWith(const NigoriKeyBag & key_bag)938 base::Optional<ModelError> NigoriSyncBridgeImpl::TryDecryptPendingKeysWith(
939 const NigoriKeyBag& key_bag) {
940 DCHECK(state_.pending_keys.has_value());
941 DCHECK(state_.cryptographer->GetDefaultEncryptionKeyName().empty());
942
943 std::string decrypted_pending_keys_str;
944 if (!key_bag.Decrypt(*state_.pending_keys, &decrypted_pending_keys_str)) {
945 return base::nullopt;
946 }
947
948 sync_pb::NigoriKeyBag decrypted_pending_keys;
949 if (!decrypted_pending_keys.ParseFromString(decrypted_pending_keys_str)) {
950 return base::nullopt;
951 }
952
953 const std::string new_default_key_name = state_.pending_keys->key_name();
954 DCHECK(key_bag.HasKey(new_default_key_name));
955
956 NigoriKeyBag new_key_bag =
957 NigoriKeyBag::CreateFromProto(decrypted_pending_keys);
958
959 if (!new_key_bag.HasKey(new_default_key_name)) {
960 // Protocol violation.
961 return ModelError(FROM_HERE,
962 "Received keybag is missing the new default key.");
963 }
964
965 if (state_.last_default_trusted_vault_key_name.has_value() &&
966 !new_key_bag.HasKey(*state_.last_default_trusted_vault_key_name)) {
967 // Protocol violation.
968 return ModelError(FROM_HERE,
969 "Received keybag is missing the last trusted vault key.");
970 }
971
972 // Reset |last_default_trusted_vault_key_name| as |state_| might go out of
973 // TRUSTED_VAULT passphrase type. The callers are responsible to set it again
974 // if needed.
975 state_.last_default_trusted_vault_key_name = base::nullopt;
976 state_.cryptographer->EmplaceKeysFrom(new_key_bag);
977 state_.cryptographer->SelectDefaultEncryptionKey(new_default_key_name);
978 state_.pending_keys.reset();
979
980 return base::nullopt;
981 }
982
GetData()983 std::unique_ptr<EntityData> NigoriSyncBridgeImpl::GetData() {
984 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
985
986 NigoriSpecifics specifics;
987 if (!pending_local_commit_queue_.empty()) {
988 NigoriState changed_state = state_.Clone();
989 bool success =
990 pending_local_commit_queue_.front()->TryApply(&changed_state);
991 DCHECK(success);
992 specifics = changed_state.ToSpecificsProto();
993 } else {
994 specifics = state_.ToSpecificsProto();
995 }
996
997 if (specifics.passphrase_type() == NigoriSpecifics::UNKNOWN) {
998 // Bridge never received NigoriSpecifics from the server. This line should
999 // be reachable only from processor's GetAllNodesForDebugging().
1000 DCHECK(!state_.cryptographer->CanEncrypt());
1001 DCHECK(!state_.pending_keys.has_value());
1002 return nullptr;
1003 }
1004
1005 DCHECK(IsValidNigoriSpecifics(specifics));
1006
1007 auto entity_data = std::make_unique<EntityData>();
1008 *entity_data->specifics.mutable_nigori() = std::move(specifics);
1009 entity_data->name = kNigoriNonUniqueName;
1010 entity_data->is_folder = true;
1011 return entity_data;
1012 }
1013
ApplyDisableSyncChanges()1014 void NigoriSyncBridgeImpl::ApplyDisableSyncChanges() {
1015 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
1016 // The user intended to disable sync, so we need to clear all the data, except
1017 // |explicit_passphrase_key_| in memory, because this function can be called
1018 // due to BackendMigrator. It's safe even if this function called due to
1019 // actual disabling sync, since we remove the persisted key by clearing sync
1020 // prefs explicitly, and don't reuse current instance of the bridge after
1021 // that.
1022 // TODO(crbug.com/922900): idea with keeping
1023 // |explicit_passphrase_key_| will become not working, once we clean up
1024 // storing explicit passphrase key in prefs, we need to find better solution.
1025 storage_->ClearData();
1026 state_.keystore_keys_cryptographer = KeystoreKeysCryptographer::CreateEmpty();
1027 state_.cryptographer = CryptographerImpl::CreateEmpty();
1028 state_.pending_keys.reset();
1029 state_.pending_keystore_decryptor_token.reset();
1030 state_.passphrase_type = NigoriSpecifics::UNKNOWN;
1031 state_.encrypt_everything = false;
1032 state_.custom_passphrase_time = base::Time();
1033 state_.keystore_migration_time = base::Time();
1034 state_.custom_passphrase_key_derivation_params = base::nullopt;
1035 state_.last_default_trusted_vault_key_name = base::nullopt;
1036 broadcasting_observer_->OnCryptographerStateChanged(
1037 state_.cryptographer.get(),
1038 /*has_pending_keys=*/false);
1039 broadcasting_observer_->OnEncryptedTypesChanged(AlwaysEncryptedUserTypes(),
1040 false);
1041 }
1042
GetCryptographerForTesting() const1043 const CryptographerImpl& NigoriSyncBridgeImpl::GetCryptographerForTesting()
1044 const {
1045 return *state_.cryptographer;
1046 }
1047
1048 sync_pb::NigoriSpecifics::PassphraseType
GetPassphraseTypeForTesting() const1049 NigoriSyncBridgeImpl::GetPassphraseTypeForTesting() const {
1050 return state_.passphrase_type;
1051 }
1052
GetEncryptedTypesForTesting() const1053 ModelTypeSet NigoriSyncBridgeImpl::GetEncryptedTypesForTesting() const {
1054 return GetEncryptedTypes(state_.encrypt_everything);
1055 }
1056
HasPendingKeysForTesting() const1057 bool NigoriSyncBridgeImpl::HasPendingKeysForTesting() const {
1058 return state_.pending_keys.has_value();
1059 }
1060
1061 KeyDerivationParams
GetCustomPassphraseKeyDerivationParamsForTesting() const1062 NigoriSyncBridgeImpl::GetCustomPassphraseKeyDerivationParamsForTesting() const {
1063 if (!state_.custom_passphrase_key_derivation_params) {
1064 return KeyDerivationParams::CreateForPbkdf2();
1065 }
1066 return *state_.custom_passphrase_key_derivation_params;
1067 }
1068
PackExplicitPassphraseKeyForTesting(const Encryptor & encryptor,const CryptographerImpl & cryptographer)1069 std::string NigoriSyncBridgeImpl::PackExplicitPassphraseKeyForTesting(
1070 const Encryptor& encryptor,
1071 const CryptographerImpl& cryptographer) {
1072 return PackExplicitPassphraseKey(encryptor, cryptographer);
1073 }
1074
GetExplicitPassphraseTime() const1075 base::Time NigoriSyncBridgeImpl::GetExplicitPassphraseTime() const {
1076 switch (state_.passphrase_type) {
1077 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
1078 case NigoriSpecifics::UNKNOWN:
1079 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
1080 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
1081 return base::Time();
1082 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
1083 return state_.keystore_migration_time;
1084 case NigoriSpecifics::CUSTOM_PASSPHRASE:
1085 return state_.custom_passphrase_time;
1086 }
1087 NOTREACHED();
1088 return state_.custom_passphrase_time;
1089 }
1090
GetKeyDerivationParamsForPendingKeys() const1091 KeyDerivationParams NigoriSyncBridgeImpl::GetKeyDerivationParamsForPendingKeys()
1092 const {
1093 switch (state_.passphrase_type) {
1094 case NigoriSpecifics::UNKNOWN:
1095 NOTREACHED();
1096 return KeyDerivationParams::CreateWithUnsupportedMethod();
1097 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
1098 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
1099 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
1100 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
1101 return KeyDerivationParams::CreateForPbkdf2();
1102 case NigoriSpecifics::CUSTOM_PASSPHRASE:
1103 DCHECK(state_.custom_passphrase_key_derivation_params);
1104 return *state_.custom_passphrase_key_derivation_params;
1105 }
1106 }
1107
MaybeNotifyOfPendingKeys() const1108 void NigoriSyncBridgeImpl::MaybeNotifyOfPendingKeys() const {
1109 if (!state_.pending_keys.has_value()) {
1110 return;
1111 }
1112
1113 switch (state_.passphrase_type) {
1114 case NigoriSpecifics::UNKNOWN:
1115 return;
1116 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
1117 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
1118 case NigoriSpecifics::CUSTOM_PASSPHRASE:
1119 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
1120 broadcasting_observer_->OnPassphraseRequired(
1121 GetKeyDerivationParamsForPendingKeys(), *state_.pending_keys);
1122 break;
1123 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
1124 broadcasting_observer_->OnTrustedVaultKeyRequired();
1125 break;
1126 }
1127 }
1128
MaybeNotifyBootstrapTokenUpdated() const1129 void NigoriSyncBridgeImpl::MaybeNotifyBootstrapTokenUpdated() const {
1130 switch (state_.passphrase_type) {
1131 case NigoriSpecifics::UNKNOWN:
1132 NOTREACHED();
1133 return;
1134 case NigoriSpecifics::KEYSTORE_PASSPHRASE:
1135 // TODO(crbug.com/922900): notify about keystore bootstrap token updates
1136 // if decided to support keystore keys migration on transit to Directory
1137 // implementation.
1138 return;
1139 case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
1140 // This may be problematic for the MIGRATION_DONE case because the local
1141 // keybag will be cleared and it won't be automatically recovered from
1142 // prefs.
1143 NOTIMPLEMENTED();
1144 return;
1145 case NigoriSpecifics::IMPLICIT_PASSPHRASE:
1146 case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
1147 case NigoriSpecifics::CUSTOM_PASSPHRASE:
1148 // |packed_custom_passphrase_key| will be empty in case serialization or
1149 // encryption error occurs.
1150 std::string packed_custom_passphrase_key =
1151 PackExplicitPassphraseKey(*encryptor_, *state_.cryptographer);
1152 if (!packed_custom_passphrase_key.empty()) {
1153 broadcasting_observer_->OnBootstrapTokenUpdated(
1154 packed_custom_passphrase_key, PASSPHRASE_BOOTSTRAP_TOKEN);
1155 }
1156 }
1157 }
1158
SerializeAsNigoriLocalData() const1159 sync_pb::NigoriLocalData NigoriSyncBridgeImpl::SerializeAsNigoriLocalData()
1160 const {
1161 sync_pb::NigoriLocalData output;
1162
1163 // Serialize the metadata.
1164 const NigoriMetadataBatch metadata_batch = processor_->GetMetadata();
1165 *output.mutable_model_type_state() = metadata_batch.model_type_state;
1166 if (metadata_batch.entity_metadata) {
1167 *output.mutable_entity_metadata() = *metadata_batch.entity_metadata;
1168 }
1169
1170 // Serialize the data.
1171 *output.mutable_nigori_model() = state_.ToLocalProto();
1172
1173 return output;
1174 }
1175
MaybeTriggerKeystoreReencryption()1176 void NigoriSyncBridgeImpl::MaybeTriggerKeystoreReencryption() {
1177 if (state_.NeedsKeystoreReencryption()) {
1178 QueuePendingLocalCommit(
1179 PendingLocalNigoriCommit::ForKeystoreReencryption());
1180 }
1181 }
1182
MaybeMigrateKeystoreKeys(const std::string & packed_keystore_keys)1183 void NigoriSyncBridgeImpl::MaybeMigrateKeystoreKeys(
1184 const std::string& packed_keystore_keys) {
1185 if (!state_.keystore_keys_cryptographer->IsEmpty() ||
1186 packed_keystore_keys.empty()) {
1187 return;
1188 }
1189 std::vector<std::string> keystore_keys =
1190 UnpackKeystoreKeys(packed_keystore_keys, *encryptor_);
1191 if (keystore_keys.empty()) {
1192 // Error occurred during unpacking.
1193 return;
1194 }
1195
1196 state_.keystore_keys_cryptographer =
1197 KeystoreKeysCryptographer::FromKeystoreKeys(keystore_keys);
1198 if (!state_.keystore_keys_cryptographer) {
1199 // Crypto error occurred during cryptographer creation.
1200 state_.keystore_keys_cryptographer =
1201 KeystoreKeysCryptographer::CreateEmpty();
1202 }
1203 }
1204
QueuePendingLocalCommit(std::unique_ptr<PendingLocalNigoriCommit> local_commit)1205 void NigoriSyncBridgeImpl::QueuePendingLocalCommit(
1206 std::unique_ptr<PendingLocalNigoriCommit> local_commit) {
1207 DCHECK(processor_->IsTrackingMetadata());
1208
1209 pending_local_commit_queue_.push_back(std::move(local_commit));
1210
1211 if (pending_local_commit_queue_.size() == 1) {
1212 // Verify that the newly-introduced commit (if first in the queue) applies
1213 // and if so call Put(), or otherwise issue an immediate failure.
1214 PutNextApplicablePendingLocalCommit();
1215 }
1216 }
1217
PutNextApplicablePendingLocalCommit()1218 void NigoriSyncBridgeImpl::PutNextApplicablePendingLocalCommit() {
1219 while (!pending_local_commit_queue_.empty()) {
1220 NigoriState tmp_state = state_.Clone();
1221 bool success = pending_local_commit_queue_.front()->TryApply(&tmp_state);
1222 if (success) {
1223 // This particular commit applies cleanly.
1224 processor_->Put(GetData());
1225 break;
1226 }
1227
1228 // The local change failed to apply.
1229 pending_local_commit_queue_.front()->OnFailure(
1230 broadcasting_observer_.get());
1231 pending_local_commit_queue_.pop_front();
1232 }
1233 }
1234
MaybePopulateKeystoreKeysIntoCryptographer()1235 void NigoriSyncBridgeImpl::MaybePopulateKeystoreKeysIntoCryptographer() {
1236 DCHECK(!state_.keystore_keys_cryptographer->IsEmpty());
1237 if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
1238 // KEYSTORE_PASSPHRASE should be ignored, because otherwise keystore key
1239 // rotation logic would be broken.
1240 return;
1241 }
1242 // These keys should usually already be in the keybag, but there is evidence
1243 // that some users run into corrupt data with the keys missing in the keybag.
1244 for (const std::string& keystore_key :
1245 state_.keystore_keys_cryptographer->keystore_keys()) {
1246 state_.cryptographer->EmplaceKey(keystore_key,
1247 KeyDerivationParams::CreateForPbkdf2());
1248 }
1249 }
1250
1251 } // namespace syncer
1252