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