nigori_sync_bridge_impl.cc 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022
  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. #include "components/sync/nigori/nigori_sync_bridge_impl.h"
  5. #include <utility>
  6. #include "base/base64.h"
  7. #include "base/bind.h"
  8. #include "base/feature_list.h"
  9. #include "base/json/json_string_value_serializer.h"
  10. #include "base/location.h"
  11. #include "base/logging.h"
  12. #include "base/metrics/histogram_macros.h"
  13. #include "base/observer_list.h"
  14. #include "components/os_crypt/os_crypt.h"
  15. #include "components/sync/base/passphrase_enums.h"
  16. #include "components/sync/base/time.h"
  17. #include "components/sync/engine/nigori/nigori.h"
  18. #include "components/sync/nigori/keystore_keys_cryptographer.h"
  19. #include "components/sync/nigori/nigori_storage.h"
  20. #include "components/sync/nigori/pending_local_nigori_commit.h"
  21. #include "components/sync/protocol/encryption.pb.h"
  22. #include "components/sync/protocol/entity_data.h"
  23. #include "components/sync/protocol/nigori_local_data.pb.h"
  24. namespace syncer {
  25. namespace {
  26. using sync_pb::NigoriSpecifics;
  27. const char kNigoriNonUniqueName[] = "Nigori";
  28. // Enumeration of possible values for a key derivation method (including a
  29. // special value of "not set"). Used in UMA metrics. Do not re-order or delete
  30. // these entries; they are used in a UMA histogram. Please edit
  31. // SyncCustomPassphraseKeyDerivationMethodState in enums.xml if a value is
  32. // added.
  33. enum class KeyDerivationMethodStateForMetrics {
  34. NOT_SET = 0,
  35. UNSUPPORTED = 1,
  36. PBKDF2_HMAC_SHA1_1003 = 2,
  37. SCRYPT_8192_8_11 = 3,
  38. kMaxValue = SCRYPT_8192_8_11
  39. };
  40. KeyDerivationMethodStateForMetrics GetKeyDerivationMethodStateForMetrics(
  41. const absl::optional<KeyDerivationParams>& key_derivation_params) {
  42. if (!key_derivation_params.has_value()) {
  43. return KeyDerivationMethodStateForMetrics::NOT_SET;
  44. }
  45. switch (key_derivation_params.value().method()) {
  46. case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
  47. return KeyDerivationMethodStateForMetrics::PBKDF2_HMAC_SHA1_1003;
  48. case KeyDerivationMethod::SCRYPT_8192_8_11:
  49. return KeyDerivationMethodStateForMetrics::SCRYPT_8192_8_11;
  50. case KeyDerivationMethod::UNSUPPORTED:
  51. return KeyDerivationMethodStateForMetrics::UNSUPPORTED;
  52. }
  53. NOTREACHED();
  54. return KeyDerivationMethodStateForMetrics::UNSUPPORTED;
  55. }
  56. std::string GetScryptSaltFromSpecifics(
  57. const sync_pb::NigoriSpecifics& specifics) {
  58. DCHECK_EQ(specifics.custom_passphrase_key_derivation_method(),
  59. sync_pb::NigoriSpecifics::SCRYPT_8192_8_11);
  60. std::string decoded_salt;
  61. bool result = base::Base64Decode(
  62. specifics.custom_passphrase_key_derivation_salt(), &decoded_salt);
  63. DCHECK(result);
  64. return decoded_salt;
  65. }
  66. KeyDerivationParams GetKeyDerivationParamsFromSpecifics(
  67. const sync_pb::NigoriSpecifics& specifics) {
  68. switch (ProtoKeyDerivationMethodToEnum(
  69. specifics.custom_passphrase_key_derivation_method())) {
  70. case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
  71. return KeyDerivationParams::CreateForPbkdf2();
  72. case KeyDerivationMethod::SCRYPT_8192_8_11:
  73. return KeyDerivationParams::CreateForScrypt(
  74. GetScryptSaltFromSpecifics(specifics));
  75. case KeyDerivationMethod::UNSUPPORTED:
  76. break;
  77. }
  78. return KeyDerivationParams::CreateWithUnsupportedMethod();
  79. }
  80. // We need to apply base64 encoding before deriving Nigori keys because the
  81. // underlying crypto libraries (in particular the Java counterparts in JDK's
  82. // implementation for PBKDF2) assume the keys are utf8.
  83. std::vector<std::string> Base64EncodeKeys(
  84. const std::vector<std::vector<uint8_t>>& keys) {
  85. std::vector<std::string> encoded_keystore_keys;
  86. for (const std::vector<uint8_t>& key : keys) {
  87. encoded_keystore_keys.push_back(base::Base64Encode(key));
  88. }
  89. return encoded_keystore_keys;
  90. }
  91. bool SpecificsHasValidKeyDerivationParams(const NigoriSpecifics& specifics) {
  92. switch (ProtoKeyDerivationMethodToEnum(
  93. specifics.custom_passphrase_key_derivation_method())) {
  94. case KeyDerivationMethod::UNSUPPORTED:
  95. DLOG(ERROR) << "Unsupported key derivation method encountered: "
  96. << specifics.custom_passphrase_key_derivation_method();
  97. return false;
  98. case KeyDerivationMethod::PBKDF2_HMAC_SHA1_1003:
  99. return true;
  100. case KeyDerivationMethod::SCRYPT_8192_8_11:
  101. if (!specifics.has_custom_passphrase_key_derivation_salt()) {
  102. DLOG(ERROR) << "Missed key derivation salt while key derivation "
  103. << "method is SCRYPT_8192_8_11.";
  104. return false;
  105. }
  106. std::string temp;
  107. if (!base::Base64Decode(specifics.custom_passphrase_key_derivation_salt(),
  108. &temp)) {
  109. DLOG(ERROR) << "Key derivation salt is not a valid base64 encoded "
  110. "string.";
  111. return false;
  112. }
  113. return true;
  114. }
  115. }
  116. // Validates given |specifics| assuming it's not specifics received from the
  117. // server during first-time sync for current user (i.e. it's not a default
  118. // specifics).
  119. bool IsValidNigoriSpecifics(const NigoriSpecifics& specifics) {
  120. if (specifics.encryption_keybag().blob().empty()) {
  121. DLOG(ERROR) << "Specifics contains empty encryption_keybag.";
  122. return false;
  123. }
  124. switch (ProtoPassphraseInt32ToProtoEnum(specifics.passphrase_type())) {
  125. case NigoriSpecifics::UNKNOWN:
  126. DLOG(ERROR) << "Received unknown passphrase type with value: "
  127. << specifics.passphrase_type();
  128. return false;
  129. case NigoriSpecifics::IMPLICIT_PASSPHRASE:
  130. return true;
  131. case NigoriSpecifics::KEYSTORE_PASSPHRASE:
  132. if (specifics.keystore_decryptor_token().blob().empty()) {
  133. DLOG(ERROR) << "Keystore Nigori should have filled "
  134. << "keystore_decryptor_token.";
  135. return false;
  136. }
  137. break;
  138. case NigoriSpecifics::CUSTOM_PASSPHRASE:
  139. if (!SpecificsHasValidKeyDerivationParams(specifics)) {
  140. return false;
  141. }
  142. [[fallthrough]];
  143. case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
  144. if (!specifics.encrypt_everything()) {
  145. DLOG(ERROR) << "Nigori with explicit passphrase type should have "
  146. "enabled encrypt_everything.";
  147. return false;
  148. }
  149. break;
  150. case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
  151. return true;
  152. }
  153. return true;
  154. }
  155. bool IsValidPassphraseTransition(
  156. NigoriSpecifics::PassphraseType old_passphrase_type,
  157. NigoriSpecifics::PassphraseType new_passphrase_type) {
  158. // We assume that |new_passphrase_type| is valid.
  159. DCHECK_NE(new_passphrase_type, NigoriSpecifics::UNKNOWN);
  160. if (old_passphrase_type == new_passphrase_type) {
  161. return true;
  162. }
  163. switch (old_passphrase_type) {
  164. case NigoriSpecifics::UNKNOWN:
  165. // This can happen iff we have not synced local state yet or synced with
  166. // default NigoriSpecifics, so we accept any valid passphrase type
  167. // (invalid filtered before).
  168. case NigoriSpecifics::IMPLICIT_PASSPHRASE:
  169. return true;
  170. case NigoriSpecifics::KEYSTORE_PASSPHRASE:
  171. return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE ||
  172. new_passphrase_type == NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE;
  173. case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
  174. // There is no client side code which can cause such transition, but
  175. // technically it's a valid one and can be implemented in the future.
  176. return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE;
  177. case NigoriSpecifics::CUSTOM_PASSPHRASE:
  178. return false;
  179. case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
  180. return new_passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE ||
  181. new_passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE;
  182. }
  183. NOTREACHED();
  184. return false;
  185. }
  186. // Updates |*current_type| if needed. Returns true if its value was changed.
  187. bool UpdatePassphraseType(NigoriSpecifics::PassphraseType new_type,
  188. NigoriSpecifics::PassphraseType* current_type) {
  189. DCHECK(current_type);
  190. DCHECK(IsValidPassphraseTransition(*current_type, new_type));
  191. if (*current_type == new_type) {
  192. return false;
  193. }
  194. *current_type = new_type;
  195. return true;
  196. }
  197. bool IsValidEncryptedTypesTransition(bool old_encrypt_everything,
  198. const NigoriSpecifics& specifics) {
  199. // We don't support relaxing the encryption requirements.
  200. // TODO(crbug.com/922900): more logic is to be added here, once we support
  201. // enforced encryption for individual datatypes.
  202. return specifics.encrypt_everything() || !old_encrypt_everything;
  203. }
  204. } // namespace
  205. class NigoriSyncBridgeImpl::BroadcastingObserver
  206. : public SyncEncryptionHandler::Observer {
  207. public:
  208. BroadcastingObserver() = default;
  209. BroadcastingObserver(const BroadcastingObserver&) = delete;
  210. BroadcastingObserver& operator=(const BroadcastingObserver&) = delete;
  211. ~BroadcastingObserver() override = default;
  212. void AddObserver(SyncEncryptionHandler::Observer* observer) {
  213. observers_.AddObserver(observer);
  214. }
  215. void RemoveObserver(SyncEncryptionHandler::Observer* observer) {
  216. observers_.RemoveObserver(observer);
  217. }
  218. // SyncEncryptionHandler::Observer implementation.
  219. void OnPassphraseRequired(
  220. const KeyDerivationParams& key_derivation_params,
  221. const sync_pb::EncryptedData& pending_keys) override {
  222. for (Observer& observer : observers_) {
  223. observer.OnPassphraseRequired(key_derivation_params, pending_keys);
  224. }
  225. }
  226. void OnPassphraseAccepted() override {
  227. for (Observer& observer : observers_) {
  228. observer.OnPassphraseAccepted();
  229. }
  230. }
  231. void OnTrustedVaultKeyRequired() override {
  232. for (Observer& observer : observers_) {
  233. observer.OnTrustedVaultKeyRequired();
  234. }
  235. }
  236. void OnTrustedVaultKeyAccepted() override {
  237. for (Observer& observer : observers_) {
  238. observer.OnTrustedVaultKeyAccepted();
  239. }
  240. }
  241. void OnEncryptedTypesChanged(ModelTypeSet encrypted_types,
  242. bool encrypt_everything) override {
  243. for (Observer& observer : observers_) {
  244. observer.OnEncryptedTypesChanged(encrypted_types, encrypt_everything);
  245. }
  246. }
  247. void OnCryptographerStateChanged(Cryptographer* cryptographer,
  248. bool has_pending_keys) override {
  249. for (Observer& observer : observers_) {
  250. observer.OnCryptographerStateChanged(cryptographer, has_pending_keys);
  251. }
  252. }
  253. void OnPassphraseTypeChanged(PassphraseType type,
  254. base::Time passphrase_time) override {
  255. for (Observer& observer : observers_) {
  256. observer.OnPassphraseTypeChanged(type, passphrase_time);
  257. }
  258. }
  259. private:
  260. // TODO(crbug/922900): consider using checked ObserverList once
  261. // SyncEncryptionHandlerImpl is no longer needed or consider refactoring old
  262. // implementation to use checked ObserverList as well.
  263. base::ObserverList<SyncEncryptionHandler::Observer>::Unchecked observers_;
  264. };
  265. NigoriSyncBridgeImpl::NigoriSyncBridgeImpl(
  266. std::unique_ptr<NigoriLocalChangeProcessor> processor,
  267. std::unique_ptr<NigoriStorage> storage)
  268. : processor_(std::move(processor)),
  269. storage_(std::move(storage)),
  270. broadcasting_observer_(std::make_unique<BroadcastingObserver>()) {
  271. // TODO(crbug.com/922900): we currently don't verify |deserialized_data|.
  272. // It's quite unlikely we get a corrupted data, since it was successfully
  273. // deserialized and decrypted. But we may want to consider some
  274. // verifications, taking into account sensitivity of this data.
  275. absl::optional<sync_pb::NigoriLocalData> deserialized_data =
  276. storage_->RestoreData();
  277. if (!deserialized_data) {
  278. // We either have no Nigori node stored locally or it was corrupted.
  279. processor_->ModelReadyToSync(this, NigoriMetadataBatch());
  280. return;
  281. }
  282. // Restore data.
  283. state_ = syncer::NigoriState::CreateFromLocalProto(
  284. deserialized_data->nigori_model());
  285. // Restore metadata.
  286. NigoriMetadataBatch metadata_batch;
  287. metadata_batch.model_type_state = deserialized_data->model_type_state();
  288. metadata_batch.entity_metadata = deserialized_data->entity_metadata();
  289. processor_->ModelReadyToSync(this, std::move(metadata_batch));
  290. if (state_.passphrase_type == NigoriSpecifics::UNKNOWN) {
  291. // Commit with keystore initialization wasn't successfully completed before
  292. // the restart, so trigger it again here.
  293. DCHECK(!state_.keystore_keys_cryptographer->IsEmpty());
  294. QueuePendingLocalCommit(
  295. PendingLocalNigoriCommit::ForKeystoreInitialization());
  296. }
  297. // Keystore key rotation might be not performed, but required.
  298. MaybeTriggerKeystoreReencryption();
  299. // Ensure that |cryptographer| contains all keystore keys (non-keystore
  300. // passphrase types only).
  301. MaybePopulateKeystoreKeysIntoCryptographer();
  302. }
  303. NigoriSyncBridgeImpl::~NigoriSyncBridgeImpl() {
  304. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  305. }
  306. void NigoriSyncBridgeImpl::AddObserver(Observer* observer) {
  307. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  308. broadcasting_observer_->AddObserver(observer);
  309. }
  310. void NigoriSyncBridgeImpl::RemoveObserver(Observer* observer) {
  311. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  312. broadcasting_observer_->RemoveObserver(observer);
  313. }
  314. void NigoriSyncBridgeImpl::NotifyInitialStateToObservers() {
  315. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  316. // We need to expose whole bridge state through notifications, because it
  317. // can be different from default due to restoring from the file or
  318. // completeness of first sync cycle (which happens before Init() call).
  319. // TODO(crbug.com/922900): try to avoid double notification (second one can
  320. // happen during UpdateLocalState() call).
  321. broadcasting_observer_->OnEncryptedTypesChanged(state_.GetEncryptedTypes(),
  322. state_.encrypt_everything);
  323. broadcasting_observer_->OnCryptographerStateChanged(
  324. state_.cryptographer.get(), state_.pending_keys.has_value());
  325. MaybeNotifyOfPendingKeys();
  326. if (state_.passphrase_type != NigoriSpecifics::UNKNOWN) {
  327. // if |passphrase_type| is unknown, it is not yet initialized and we
  328. // shouldn't expose it.
  329. PassphraseType enum_passphrase_type =
  330. *ProtoPassphraseInt32ToEnum(state_.passphrase_type);
  331. broadcasting_observer_->OnPassphraseTypeChanged(
  332. enum_passphrase_type, GetExplicitPassphraseTime());
  333. UMA_HISTOGRAM_ENUMERATION("Sync.PassphraseType", enum_passphrase_type);
  334. }
  335. if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
  336. UMA_HISTOGRAM_ENUMERATION(
  337. "Sync.Crypto.CustomPassphraseKeyDerivationMethodStateOnStartup",
  338. GetKeyDerivationMethodStateForMetrics(
  339. state_.custom_passphrase_key_derivation_params));
  340. }
  341. UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerReady",
  342. state_.cryptographer->CanEncrypt());
  343. UMA_HISTOGRAM_BOOLEAN("Sync.CryptographerPendingKeys",
  344. state_.pending_keys.has_value());
  345. if (state_.pending_keys.has_value() &&
  346. state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
  347. // If this is happening, it means the keystore decryptor is either
  348. // undecryptable with the available keystore keys or does not match the
  349. // nigori keybag's encryption key. Otherwise we're simply missing the
  350. // keystore key.
  351. UMA_HISTOGRAM_BOOLEAN("Sync.KeystoreDecryptionFailed",
  352. !state_.keystore_keys_cryptographer->IsEmpty());
  353. }
  354. }
  355. ModelTypeSet NigoriSyncBridgeImpl::GetEncryptedTypes() {
  356. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  357. return state_.GetEncryptedTypes();
  358. }
  359. Cryptographer* NigoriSyncBridgeImpl::GetCryptographer() {
  360. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  361. DCHECK(state_.cryptographer);
  362. return state_.cryptographer.get();
  363. }
  364. PassphraseType NigoriSyncBridgeImpl::GetPassphraseType() {
  365. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  366. return ProtoPassphraseInt32ToEnum(state_.passphrase_type)
  367. .value_or(PassphraseType::kImplicitPassphrase);
  368. }
  369. void NigoriSyncBridgeImpl::SetEncryptionPassphrase(
  370. const std::string& passphrase,
  371. const KeyDerivationParams& key_derivation_params) {
  372. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  373. QueuePendingLocalCommit(PendingLocalNigoriCommit::ForSetCustomPassphrase(
  374. passphrase, key_derivation_params));
  375. }
  376. void NigoriSyncBridgeImpl::SetExplicitPassphraseDecryptionKey(
  377. std::unique_ptr<Nigori> key) {
  378. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  379. // |key| should be a valid one already (verified by SyncServiceCrypto,
  380. // using pending keys exposed by OnPassphraseRequired()).
  381. if (!state_.pending_keys) {
  382. DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
  383. return;
  384. }
  385. NigoriKeyBag tmp_key_bag = NigoriKeyBag::CreateEmpty();
  386. const std::string new_key_name = tmp_key_bag.AddKey(std::move(key));
  387. absl::optional<ModelError> error = TryDecryptPendingKeysWith(tmp_key_bag);
  388. if (error.has_value()) {
  389. processor_->ReportError(*error);
  390. return;
  391. }
  392. if (state_.pending_keys.has_value()) {
  393. // |pending_keys| could be changed in between of OnPassphraseRequired()
  394. // and SetExplicitPassphraseDecryptionKey() calls (remote update with
  395. // different keystore Nigori or with transition from keystore to custom
  396. // passphrase Nigori).
  397. MaybeNotifyOfPendingKeys();
  398. return;
  399. }
  400. if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
  401. DCHECK(state_.custom_passphrase_key_derivation_params.has_value());
  402. UMA_HISTOGRAM_ENUMERATION(
  403. "Sync.Crypto."
  404. "CustomPassphraseKeyDerivationMethodOnSuccessfulDecryption",
  405. GetKeyDerivationMethodStateForMetrics(
  406. state_.custom_passphrase_key_derivation_params));
  407. }
  408. DCHECK_EQ(state_.cryptographer->GetDefaultEncryptionKeyName(), new_key_name);
  409. storage_->StoreData(SerializeAsNigoriLocalData());
  410. broadcasting_observer_->OnCryptographerStateChanged(
  411. state_.cryptographer.get(), state_.pending_keys.has_value());
  412. broadcasting_observer_->OnPassphraseAccepted();
  413. }
  414. void NigoriSyncBridgeImpl::AddTrustedVaultDecryptionKeys(
  415. const std::vector<std::vector<uint8_t>>& keys) {
  416. // This API gets plumbed and ultimately exposed to layers outside the sync
  417. // codebase and even outside the browser, so there are no preconditions and
  418. // instead we ignore invalid or partially invalid input.
  419. if (state_.passphrase_type != NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE ||
  420. !state_.pending_keys || keys.empty()) {
  421. return;
  422. }
  423. const std::vector<std::string> encoded_keys = Base64EncodeKeys(keys);
  424. NigoriKeyBag tmp_key_bag = NigoriKeyBag::CreateEmpty();
  425. for (const std::string& encoded_key : encoded_keys) {
  426. tmp_key_bag.AddKey(Nigori::CreateByDerivation(
  427. GetKeyDerivationParamsForPendingKeys(), encoded_key));
  428. }
  429. absl::optional<ModelError> error = TryDecryptPendingKeysWith(tmp_key_bag);
  430. if (error.has_value()) {
  431. processor_->ReportError(*error);
  432. return;
  433. }
  434. if (state_.pending_keys.has_value()) {
  435. return;
  436. }
  437. state_.last_default_trusted_vault_key_name =
  438. state_.cryptographer->GetDefaultEncryptionKeyName();
  439. storage_->StoreData(SerializeAsNigoriLocalData());
  440. broadcasting_observer_->OnCryptographerStateChanged(
  441. state_.cryptographer.get(), state_.pending_keys.has_value());
  442. broadcasting_observer_->OnTrustedVaultKeyAccepted();
  443. }
  444. base::Time NigoriSyncBridgeImpl::GetKeystoreMigrationTime() {
  445. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  446. return state_.keystore_migration_time;
  447. }
  448. KeystoreKeysHandler* NigoriSyncBridgeImpl::GetKeystoreKeysHandler() {
  449. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  450. return this;
  451. }
  452. const sync_pb::NigoriSpecifics::TrustedVaultDebugInfo&
  453. NigoriSyncBridgeImpl::GetTrustedVaultDebugInfo() {
  454. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  455. return state_.trusted_vault_debug_info;
  456. }
  457. bool NigoriSyncBridgeImpl::NeedKeystoreKey() const {
  458. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  459. // Explicitly asks the server for keystore keys if it's first-time sync, i.e.
  460. // if there is no keystore keys yet or remote keybag wasn't decryptable due
  461. // to absence of some keystore key. In case of key rotation, it's a server
  462. // responsibility to send updated keystore keys. |keystore_keys_| is expected
  463. // to be non-empty before MergeSyncData() call, regardless of passphrase
  464. // type.
  465. return state_.keystore_keys_cryptographer->IsEmpty() ||
  466. (state_.pending_keystore_decryptor_token.has_value() &&
  467. state_.pending_keys.has_value());
  468. }
  469. bool NigoriSyncBridgeImpl::SetKeystoreKeys(
  470. const std::vector<std::vector<uint8_t>>& keys) {
  471. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  472. if (keys.empty() || keys.back().empty()) {
  473. return false;
  474. }
  475. state_.keystore_keys_cryptographer =
  476. KeystoreKeysCryptographer::FromKeystoreKeys(Base64EncodeKeys(keys));
  477. if (!state_.keystore_keys_cryptographer) {
  478. state_.keystore_keys_cryptographer =
  479. KeystoreKeysCryptographer::CreateEmpty();
  480. return false;
  481. }
  482. if (state_.pending_keystore_decryptor_token.has_value() &&
  483. state_.pending_keys.has_value()) {
  484. // Newly arrived keystore keys could resolve pending encryption state in
  485. // keystore mode.
  486. DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
  487. const absl::optional<sync_pb::NigoriKey> keystore_decryptor_key =
  488. TryDecryptPendingKeystoreDecryptorToken(
  489. sync_pb::EncryptedData(*state_.pending_keystore_decryptor_token));
  490. absl::optional<ModelError> error = TryDecryptPendingKeysWith(
  491. BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key));
  492. if (error.has_value()) {
  493. processor_->ReportError(*error);
  494. return false;
  495. }
  496. if (!state_.pending_keys.has_value()) {
  497. broadcasting_observer_->OnCryptographerStateChanged(
  498. state_.cryptographer.get(), state_.pending_keys.has_value());
  499. broadcasting_observer_->OnPassphraseAccepted();
  500. }
  501. }
  502. MaybeTriggerKeystoreReencryption();
  503. // Note: we don't need to persist keystore keys here, because we will receive
  504. // Nigori node right after this method and persist all the data during
  505. // UpdateLocalState().
  506. return true;
  507. }
  508. absl::optional<ModelError> NigoriSyncBridgeImpl::MergeSyncData(
  509. absl::optional<EntityData> data) {
  510. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  511. if (!data) {
  512. return ModelError(FROM_HERE,
  513. "Received empty EntityData during initial "
  514. "sync of Nigori.");
  515. }
  516. DCHECK(data->specifics.has_nigori());
  517. const NigoriSpecifics& specifics = data->specifics.nigori();
  518. if (specifics.passphrase_type() != NigoriSpecifics::IMPLICIT_PASSPHRASE ||
  519. !specifics.encryption_keybag().blob().empty()) {
  520. // We received regular Nigori.
  521. return UpdateLocalState(data->specifics.nigori());
  522. }
  523. // Ensure we have |keystore_keys| during the initial download, requested to
  524. // the server as per NeedKeystoreKey(), and required for initializing the
  525. // default keystore Nigori.
  526. DCHECK(state_.keystore_keys_cryptographer);
  527. if (state_.keystore_keys_cryptographer->IsEmpty()) {
  528. // TODO(crbug.com/922900): try to relax this requirement for Nigori
  529. // initialization as well. Keystore keys might not arrive, for example, due
  530. // to throttling.
  531. return ModelError(FROM_HERE,
  532. "Keystore keys are not set during first time sync.");
  533. }
  534. // We received uninitialized Nigori and need to initialize it as default
  535. // keystore Nigori.
  536. QueuePendingLocalCommit(
  537. PendingLocalNigoriCommit::ForKeystoreInitialization());
  538. return absl::nullopt;
  539. }
  540. absl::optional<ModelError> NigoriSyncBridgeImpl::ApplySyncChanges(
  541. absl::optional<EntityData> data) {
  542. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  543. if (data) {
  544. DCHECK(data->specifics.has_nigori());
  545. return UpdateLocalState(data->specifics.nigori());
  546. }
  547. if (!pending_local_commit_queue_.empty() && !processor_->IsEntityUnsynced()) {
  548. // Successfully committed first element in queue.
  549. bool success = pending_local_commit_queue_.front()->TryApply(&state_);
  550. DCHECK(success);
  551. pending_local_commit_queue_.front()->OnSuccess(
  552. state_, broadcasting_observer_.get());
  553. pending_local_commit_queue_.pop_front();
  554. // Advance until the next applicable local change if any and call Put().
  555. PutNextApplicablePendingLocalCommit();
  556. }
  557. // Receiving empty |data| means metadata-only change (e.g. no remote updates,
  558. // or local commit completion), so we need to persist its state.
  559. storage_->StoreData(SerializeAsNigoriLocalData());
  560. return absl::nullopt;
  561. }
  562. absl::optional<ModelError> NigoriSyncBridgeImpl::UpdateLocalState(
  563. const NigoriSpecifics& specifics) {
  564. if (!IsValidNigoriSpecifics(specifics)) {
  565. return ModelError(FROM_HERE, "NigoriSpecifics is not valid.");
  566. }
  567. const sync_pb::NigoriSpecifics::PassphraseType new_passphrase_type =
  568. ProtoPassphraseInt32ToProtoEnum(specifics.passphrase_type());
  569. DCHECK_NE(new_passphrase_type, NigoriSpecifics::UNKNOWN);
  570. if (!IsValidPassphraseTransition(
  571. /*old_passphrase_type=*/state_.passphrase_type,
  572. new_passphrase_type)) {
  573. return ModelError(FROM_HERE, "Invalid passphrase type transition.");
  574. }
  575. if (!IsValidEncryptedTypesTransition(state_.encrypt_everything, specifics)) {
  576. return ModelError(FROM_HERE, "Invalid encrypted types transition.");
  577. }
  578. const bool had_pending_keys_before_update = state_.pending_keys.has_value();
  579. const ModelTypeSet encrypted_types_before_update = state_.GetEncryptedTypes();
  580. state_.encrypt_everything = specifics.encrypt_everything();
  581. const bool passphrase_type_changed =
  582. UpdatePassphraseType(new_passphrase_type, &state_.passphrase_type);
  583. DCHECK_NE(state_.passphrase_type, NigoriSpecifics::UNKNOWN);
  584. if (specifics.has_custom_passphrase_time()) {
  585. state_.custom_passphrase_time =
  586. ProtoTimeToTime(specifics.custom_passphrase_time());
  587. }
  588. if (specifics.has_keystore_migration_time()) {
  589. state_.keystore_migration_time =
  590. ProtoTimeToTime(specifics.keystore_migration_time());
  591. }
  592. state_.trusted_vault_debug_info = specifics.trusted_vault_debug_info();
  593. absl::optional<sync_pb::NigoriKey> keystore_decryptor_key;
  594. if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
  595. keystore_decryptor_key = TryDecryptPendingKeystoreDecryptorToken(
  596. specifics.keystore_decryptor_token());
  597. } else {
  598. state_.pending_keystore_decryptor_token.reset();
  599. }
  600. const NigoriKeyBag decryption_key_bag_for_remote_update =
  601. BuildDecryptionKeyBagForRemoteKeybag(keystore_decryptor_key);
  602. if (state_.passphrase_type == NigoriSpecifics::CUSTOM_PASSPHRASE) {
  603. state_.custom_passphrase_key_derivation_params =
  604. GetKeyDerivationParamsFromSpecifics(specifics);
  605. }
  606. // Set incoming encrypted keys as pending, so they are processed in
  607. // TryDecryptPendingKeysWith(). If the keybag is not immediately decryptable,
  608. // it will be kept in |state_.pending_keys| until decryption is possible, e.g.
  609. // upon SetExplicitPassphraseDecryptionKey() or equivalent depending on the
  610. // passphrase type.
  611. state_.pending_keys = specifics.encryption_keybag();
  612. state_.cryptographer->ClearDefaultEncryptionKey();
  613. absl::optional<ModelError> error =
  614. TryDecryptPendingKeysWith(decryption_key_bag_for_remote_update);
  615. if (error.has_value()) {
  616. return error;
  617. }
  618. if (passphrase_type_changed) {
  619. broadcasting_observer_->OnPassphraseTypeChanged(
  620. *ProtoPassphraseInt32ToEnum(state_.passphrase_type),
  621. GetExplicitPassphraseTime());
  622. }
  623. if (encrypted_types_before_update != state_.GetEncryptedTypes()) {
  624. broadcasting_observer_->OnEncryptedTypesChanged(state_.GetEncryptedTypes(),
  625. state_.encrypt_everything);
  626. }
  627. broadcasting_observer_->OnCryptographerStateChanged(
  628. state_.cryptographer.get(), state_.pending_keys.has_value());
  629. // TODO(crbug.com/1057655): issuing OnPassphraseAccepted() should be allowed
  630. // for all passphrase types, but going out from |pending_keys| state might
  631. // be disallowed for some circumstances (such as CUSTOM_PASSPHRASE ->
  632. // CUSTOM_PASSPHRASE updates). Keep temporarily as is to avoid behavioral
  633. // changes.
  634. if (!state_.pending_keys.has_value() && had_pending_keys_before_update &&
  635. state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
  636. broadcasting_observer_->OnPassphraseAccepted();
  637. }
  638. MaybeNotifyOfPendingKeys();
  639. // There might be pending local commits, so make attempt to apply them on top
  640. // of new |state_|.
  641. PutNextApplicablePendingLocalCommit();
  642. storage_->StoreData(SerializeAsNigoriLocalData());
  643. return absl::nullopt;
  644. }
  645. absl::optional<sync_pb::NigoriKey>
  646. NigoriSyncBridgeImpl::TryDecryptPendingKeystoreDecryptorToken(
  647. const sync_pb::EncryptedData& keystore_decryptor_token) {
  648. DCHECK(!keystore_decryptor_token.blob().empty());
  649. sync_pb::NigoriKey keystore_decryptor_key;
  650. if (state_.keystore_keys_cryptographer->DecryptKeystoreDecryptorToken(
  651. keystore_decryptor_token, &keystore_decryptor_key)) {
  652. state_.pending_keystore_decryptor_token.reset();
  653. return keystore_decryptor_key;
  654. }
  655. state_.pending_keystore_decryptor_token = keystore_decryptor_token;
  656. return absl::nullopt;
  657. }
  658. NigoriKeyBag NigoriSyncBridgeImpl::BuildDecryptionKeyBagForRemoteKeybag(
  659. const absl::optional<sync_pb::NigoriKey>& keystore_decryptor_key) const {
  660. NigoriKeyBag decryption_key_bag = NigoriKeyBag::CreateEmpty();
  661. if (keystore_decryptor_key.has_value()) {
  662. DCHECK_EQ(state_.passphrase_type, NigoriSpecifics::KEYSTORE_PASSPHRASE);
  663. decryption_key_bag.AddKeyFromProto(*keystore_decryptor_key);
  664. }
  665. // TODO(crbug.com/1057655): this should be allowed for KEYSTORE_PASSPHRASE,
  666. // but should be disallowed if |passphrase_type| was changed in current
  667. // update.
  668. if (state_.passphrase_type != NigoriSpecifics::KEYSTORE_PASSPHRASE &&
  669. state_.cryptographer->CanEncrypt()) {
  670. decryption_key_bag.AddKeyFromProto(
  671. state_.cryptographer->ExportDefaultKey());
  672. }
  673. return decryption_key_bag;
  674. }
  675. absl::optional<ModelError> NigoriSyncBridgeImpl::TryDecryptPendingKeysWith(
  676. const NigoriKeyBag& key_bag) {
  677. DCHECK(state_.pending_keys.has_value());
  678. DCHECK(state_.cryptographer->GetDefaultEncryptionKeyName().empty());
  679. std::string decrypted_pending_keys_str;
  680. if (!key_bag.Decrypt(*state_.pending_keys, &decrypted_pending_keys_str)) {
  681. return absl::nullopt;
  682. }
  683. sync_pb::NigoriKeyBag decrypted_pending_keys;
  684. if (!decrypted_pending_keys.ParseFromString(decrypted_pending_keys_str)) {
  685. return absl::nullopt;
  686. }
  687. const std::string new_default_key_name = state_.pending_keys->key_name();
  688. DCHECK(key_bag.HasKey(new_default_key_name));
  689. NigoriKeyBag new_key_bag =
  690. NigoriKeyBag::CreateFromProto(decrypted_pending_keys);
  691. if (!new_key_bag.HasKey(new_default_key_name)) {
  692. // Protocol violation.
  693. return ModelError(FROM_HERE,
  694. "Received keybag is missing the new default key.");
  695. }
  696. if (state_.last_default_trusted_vault_key_name.has_value() &&
  697. !new_key_bag.HasKey(*state_.last_default_trusted_vault_key_name)) {
  698. // Protocol violation.
  699. return ModelError(FROM_HERE,
  700. "Received keybag is missing the last trusted vault key.");
  701. }
  702. // Reset |last_default_trusted_vault_key_name| as |state_| might go out of
  703. // TRUSTED_VAULT passphrase type. The callers are responsible to set it again
  704. // if needed.
  705. state_.last_default_trusted_vault_key_name = absl::nullopt;
  706. state_.cryptographer->EmplaceKeysFrom(new_key_bag);
  707. state_.cryptographer->SelectDefaultEncryptionKey(new_default_key_name);
  708. state_.pending_keys.reset();
  709. return absl::nullopt;
  710. }
  711. std::unique_ptr<EntityData> NigoriSyncBridgeImpl::GetData() {
  712. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  713. NigoriSpecifics specifics;
  714. if (!pending_local_commit_queue_.empty()) {
  715. NigoriState changed_state = state_.Clone();
  716. bool success =
  717. pending_local_commit_queue_.front()->TryApply(&changed_state);
  718. DCHECK(success);
  719. specifics = changed_state.ToSpecificsProto();
  720. } else {
  721. specifics = state_.ToSpecificsProto();
  722. }
  723. if (specifics.passphrase_type() == NigoriSpecifics::UNKNOWN) {
  724. // Bridge never received NigoriSpecifics from the server. This line should
  725. // be reachable only from processor's GetAllNodesForDebugging().
  726. DCHECK(!state_.cryptographer->CanEncrypt());
  727. DCHECK(!state_.pending_keys.has_value());
  728. return nullptr;
  729. }
  730. DCHECK(IsValidNigoriSpecifics(specifics));
  731. auto entity_data = std::make_unique<EntityData>();
  732. *entity_data->specifics.mutable_nigori() = std::move(specifics);
  733. entity_data->name = kNigoriNonUniqueName;
  734. return entity_data;
  735. }
  736. void NigoriSyncBridgeImpl::ApplyDisableSyncChanges() {
  737. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  738. storage_->ClearData();
  739. state_.keystore_keys_cryptographer = KeystoreKeysCryptographer::CreateEmpty();
  740. state_.cryptographer->ClearAllKeys();
  741. state_.pending_keys.reset();
  742. state_.pending_keystore_decryptor_token.reset();
  743. state_.passphrase_type = NigoriSpecifics::UNKNOWN;
  744. state_.encrypt_everything = false;
  745. state_.custom_passphrase_time = base::Time();
  746. state_.keystore_migration_time = base::Time();
  747. state_.custom_passphrase_key_derivation_params = absl::nullopt;
  748. state_.last_default_trusted_vault_key_name = absl::nullopt;
  749. state_.trusted_vault_debug_info =
  750. sync_pb::NigoriSpecifics::TrustedVaultDebugInfo();
  751. broadcasting_observer_->OnCryptographerStateChanged(
  752. state_.cryptographer.get(),
  753. /*has_pending_keys=*/false);
  754. broadcasting_observer_->OnEncryptedTypesChanged(state_.GetEncryptedTypes(),
  755. false);
  756. }
  757. const CryptographerImpl& NigoriSyncBridgeImpl::GetCryptographerImplForTesting()
  758. const {
  759. return *state_.cryptographer;
  760. }
  761. bool NigoriSyncBridgeImpl::HasPendingKeysForTesting() const {
  762. return state_.pending_keys.has_value();
  763. }
  764. KeyDerivationParams
  765. NigoriSyncBridgeImpl::GetCustomPassphraseKeyDerivationParamsForTesting() const {
  766. if (!state_.custom_passphrase_key_derivation_params) {
  767. return KeyDerivationParams::CreateForPbkdf2();
  768. }
  769. return *state_.custom_passphrase_key_derivation_params;
  770. }
  771. base::Time NigoriSyncBridgeImpl::GetExplicitPassphraseTime() const {
  772. switch (state_.passphrase_type) {
  773. case NigoriSpecifics::IMPLICIT_PASSPHRASE:
  774. case NigoriSpecifics::UNKNOWN:
  775. case NigoriSpecifics::KEYSTORE_PASSPHRASE:
  776. case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
  777. return base::Time();
  778. case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
  779. return state_.keystore_migration_time;
  780. case NigoriSpecifics::CUSTOM_PASSPHRASE:
  781. return state_.custom_passphrase_time;
  782. }
  783. NOTREACHED();
  784. return state_.custom_passphrase_time;
  785. }
  786. KeyDerivationParams NigoriSyncBridgeImpl::GetKeyDerivationParamsForPendingKeys()
  787. const {
  788. switch (state_.passphrase_type) {
  789. case NigoriSpecifics::UNKNOWN:
  790. NOTREACHED();
  791. return KeyDerivationParams::CreateWithUnsupportedMethod();
  792. case NigoriSpecifics::IMPLICIT_PASSPHRASE:
  793. case NigoriSpecifics::KEYSTORE_PASSPHRASE:
  794. case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
  795. case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
  796. return KeyDerivationParams::CreateForPbkdf2();
  797. case NigoriSpecifics::CUSTOM_PASSPHRASE:
  798. DCHECK(state_.custom_passphrase_key_derivation_params);
  799. return *state_.custom_passphrase_key_derivation_params;
  800. }
  801. }
  802. void NigoriSyncBridgeImpl::MaybeNotifyOfPendingKeys() const {
  803. if (!state_.pending_keys.has_value()) {
  804. return;
  805. }
  806. switch (state_.passphrase_type) {
  807. case NigoriSpecifics::UNKNOWN:
  808. return;
  809. case NigoriSpecifics::IMPLICIT_PASSPHRASE:
  810. case NigoriSpecifics::KEYSTORE_PASSPHRASE:
  811. case NigoriSpecifics::CUSTOM_PASSPHRASE:
  812. case NigoriSpecifics::FROZEN_IMPLICIT_PASSPHRASE:
  813. broadcasting_observer_->OnPassphraseRequired(
  814. GetKeyDerivationParamsForPendingKeys(), *state_.pending_keys);
  815. break;
  816. case NigoriSpecifics::TRUSTED_VAULT_PASSPHRASE:
  817. broadcasting_observer_->OnTrustedVaultKeyRequired();
  818. break;
  819. }
  820. }
  821. sync_pb::NigoriLocalData NigoriSyncBridgeImpl::SerializeAsNigoriLocalData()
  822. const {
  823. sync_pb::NigoriLocalData output;
  824. // Serialize the metadata.
  825. const NigoriMetadataBatch metadata_batch = processor_->GetMetadata();
  826. *output.mutable_model_type_state() = metadata_batch.model_type_state;
  827. if (metadata_batch.entity_metadata) {
  828. *output.mutable_entity_metadata() = *metadata_batch.entity_metadata;
  829. }
  830. // Serialize the data.
  831. *output.mutable_nigori_model() = state_.ToLocalProto();
  832. return output;
  833. }
  834. void NigoriSyncBridgeImpl::MaybeTriggerKeystoreReencryption() {
  835. if (state_.NeedsKeystoreReencryption()) {
  836. QueuePendingLocalCommit(
  837. PendingLocalNigoriCommit::ForKeystoreReencryption());
  838. }
  839. }
  840. void NigoriSyncBridgeImpl::QueuePendingLocalCommit(
  841. std::unique_ptr<PendingLocalNigoriCommit> local_commit) {
  842. DCHECK(processor_->IsTrackingMetadata());
  843. pending_local_commit_queue_.push_back(std::move(local_commit));
  844. if (pending_local_commit_queue_.size() == 1) {
  845. // Verify that the newly-introduced commit (if first in the queue) applies
  846. // and if so call Put(), or otherwise issue an immediate failure.
  847. PutNextApplicablePendingLocalCommit();
  848. }
  849. }
  850. void NigoriSyncBridgeImpl::PutNextApplicablePendingLocalCommit() {
  851. while (!pending_local_commit_queue_.empty()) {
  852. NigoriState tmp_state = state_.Clone();
  853. bool success = pending_local_commit_queue_.front()->TryApply(&tmp_state);
  854. if (success) {
  855. // This particular commit applies cleanly.
  856. processor_->Put(GetData());
  857. break;
  858. }
  859. // The local change failed to apply.
  860. pending_local_commit_queue_.front()->OnFailure(
  861. broadcasting_observer_.get());
  862. pending_local_commit_queue_.pop_front();
  863. }
  864. }
  865. void NigoriSyncBridgeImpl::MaybePopulateKeystoreKeysIntoCryptographer() {
  866. DCHECK(!state_.keystore_keys_cryptographer->IsEmpty());
  867. if (state_.passphrase_type == NigoriSpecifics::KEYSTORE_PASSPHRASE) {
  868. // KEYSTORE_PASSPHRASE should be ignored, because otherwise keystore key
  869. // rotation logic would be broken.
  870. return;
  871. }
  872. // These keys should usually already be in the keybag, but there is evidence
  873. // that some users run into corrupt data with the keys missing in the keybag.
  874. for (const std::string& keystore_key :
  875. state_.keystore_keys_cryptographer->keystore_keys()) {
  876. state_.cryptographer->EmplaceKey(keystore_key,
  877. KeyDerivationParams::CreateForPbkdf2());
  878. }
  879. }
  880. } // namespace syncer