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 #ifndef COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_
6 #define COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_
7 
8 #include <list>
9 #include <memory>
10 #include <string>
11 #include <vector>
12 
13 #include "base/callback.h"
14 #include "base/macros.h"
15 #include "base/observer_list.h"
16 #include "base/optional.h"
17 #include "base/sequence_checker.h"
18 #include "base/time/time.h"
19 #include "components/sync/engine/sync_encryption_handler.h"
20 #include "components/sync/model/conflict_resolution.h"
21 #include "components/sync/model/model_error.h"
22 #include "components/sync/nigori/cryptographer_impl.h"
23 #include "components/sync/nigori/keystore_keys_handler.h"
24 #include "components/sync/nigori/nigori_local_change_processor.h"
25 #include "components/sync/nigori/nigori_state.h"
26 #include "components/sync/nigori/nigori_sync_bridge.h"
27 
28 namespace sync_pb {
29 class NigoriLocalData;
30 }  // namespace sync_pb
31 
32 namespace syncer {
33 
34 class Encryptor;
35 class KeyDerivationParams;
36 class NigoriStorage;
37 class PendingLocalNigoriCommit;
38 
39 // USS implementation of SyncEncryptionHandler.
40 // This class holds the current Nigori state and processes incoming changes and
41 // queries:
42 // 1. Serves observers of SyncEncryptionHandler interface.
43 // 2. Allows the passphrase manipulations (via SyncEncryptionHandler).
44 // 3. Communicates local and remote changes with a processor (via
45 // NigoriSyncBridge).
46 // 4. Handles keystore keys from a sync server (via KeystoreKeysHandler).
47 class NigoriSyncBridgeImpl : public KeystoreKeysHandler,
48                              public NigoriSyncBridge,
49                              public SyncEncryptionHandler {
50  public:
51   // |encryptor| must be not null and must outlive this object.
52   NigoriSyncBridgeImpl(
53       std::unique_ptr<NigoriLocalChangeProcessor> processor,
54       std::unique_ptr<NigoriStorage> storage,
55       const Encryptor* encryptor,
56       const base::RepeatingCallback<std::string()>& random_salt_generator,
57       const std::string& packed_explicit_passphrase_key,
58       const std::string& packed_keystore_keys);
59   ~NigoriSyncBridgeImpl() override;
60 
61   // SyncEncryptionHandler implementation.
62   void AddObserver(Observer* observer) override;
63   void RemoveObserver(Observer* observer) override;
64   bool Init() override;
65   void SetEncryptionPassphrase(const std::string& passphrase) override;
66   void SetDecryptionPassphrase(const std::string& passphrase) override;
67   void AddTrustedVaultDecryptionKeys(
68       const std::vector<std::vector<uint8_t>>& keys) override;
69   base::Time GetKeystoreMigrationTime() const override;
70   KeystoreKeysHandler* GetKeystoreKeysHandler() override;
71 
72   // KeystoreKeysHandler implementation.
73   bool NeedKeystoreKey() const override;
74   bool SetKeystoreKeys(const std::vector<std::vector<uint8_t>>& keys) override;
75 
76   // NigoriSyncBridge implementation.
77   base::Optional<ModelError> MergeSyncData(
78       base::Optional<EntityData> data) override;
79   base::Optional<ModelError> ApplySyncChanges(
80       base::Optional<EntityData> data) override;
81   std::unique_ptr<EntityData> GetData() override;
82   void ApplyDisableSyncChanges() override;
83 
84   // TODO(crbug.com/922900): investigate whether we need this getter outside of
85   // tests and decide whether this method should be a part of
86   // SyncEncryptionHandler interface.
87   const CryptographerImpl& GetCryptographerForTesting() const;
88   sync_pb::NigoriSpecifics::PassphraseType GetPassphraseTypeForTesting() const;
89   ModelTypeSet GetEncryptedTypesForTesting() const;
90   bool HasPendingKeysForTesting() const;
91   KeyDerivationParams GetCustomPassphraseKeyDerivationParamsForTesting() const;
92 
93   static std::string PackExplicitPassphraseKeyForTesting(
94       const Encryptor& encryptor,
95       const CryptographerImpl& cryptographer);
96 
97  private:
98   base::Optional<ModelError> UpdateLocalState(
99       const sync_pb::NigoriSpecifics& specifics);
100 
101   base::Optional<ModelError> UpdateCryptographer(
102       const sync_pb::EncryptedData& encryption_keybag,
103       const NigoriKeyBag& decryption_key_bag);
104 
105   base::Optional<sync_pb::NigoriKey> TryDecryptPendingKeystoreDecryptorToken(
106       const sync_pb::EncryptedData& keystore_decryptor_token);
107 
108   // Builds NigoriKeyBag, which contains keys acceptable for decryption of
109   // |encryption_keybag| from remote NigoriSpecifics. Its content depends on
110   // current passphrase type and available keys: for KEYSTORE_PASSPHRASE it
111   // contains only |keystore_decryptor_key|, for all other passphrase types
112   // it contains deserialized |explicit_passphrase_key_| and current default
113   // encryption key.
114   NigoriKeyBag BuildDecryptionKeyBagForRemoteKeybag(
115       const base::Optional<sync_pb::NigoriKey>& keystore_decryptor_key) const;
116 
117   // Uses |key_bag| to try to decrypt pending keys as represented in
118   // |state_.pending_keys| (which must be set).
119   //
120   // If decryption is possible, the newly decrypted keys are put in the
121   // |state_.cryptographer|'s keybag and the default key is updated. In that
122   // case pending keys are cleared.
123   //
124   // If |key_bag| is not capable of decrypting pending keys,
125   // |state_.pending_keys| stays set. Such outcome is not itself considered
126   // and error and returns base::nullopt.
127   //
128   // Errors may be returned, in rare cases, for fatal protocol violations.
129   base::Optional<ModelError> TryDecryptPendingKeysWith(
130       const NigoriKeyBag& key_bag);
131 
132   base::Time GetExplicitPassphraseTime() const;
133 
134   // Returns key derivation params based on |passphrase_type_| and
135   // |custom_passphrase_key_derivation_params_|. Should be called only if
136   // |passphrase_type_| is an explicit passphrase.
137   KeyDerivationParams GetKeyDerivationParamsForPendingKeys() const;
138 
139   // If there are pending keys and depending on the passphrase type, it invokes
140   // the appropriate observer methods (if any).
141   void MaybeNotifyOfPendingKeys() const;
142 
143   // Persists Nigori derived from explicit passphrase into preferences, in case
144   // error occurs during serialization/encryption, corresponding preference
145   // just won't be updated.
146   void MaybeNotifyBootstrapTokenUpdated() const;
147 
148   // Queues keystore rotation or full keystore migration if current state
149   // assumes it should happen.
150   void MaybeTriggerKeystoreReencryption();
151 
152   // Prior to USS keystore keys were stored in preferences. To avoid redundant
153   // requests to the server and make USS implementation more robust against
154   // failing such requests, the value restored from preferences should be
155   // populated to current |state_|. Performs unpacking of
156   // |packed_keystore_keys| and populates them to
157   // |keystore_keys_cryptographer|. Has no effect if |packed_keystore_keys| is
158   // empty, errors occur during deserealization or
159   // |keystore_keys_cryptographer| already has keys.
160   void MaybeMigrateKeystoreKeys(const std::string& packed_keystore_keys);
161 
162   // Serializes state of the bridge and sync metadata into the proto.
163   sync_pb::NigoriLocalData SerializeAsNigoriLocalData() const;
164 
165   // Appends |local_commit| to |pending_local_commit_queue_| and if appropriate
166   // calls Put() to trigger the commit.
167   void QueuePendingLocalCommit(
168       std::unique_ptr<PendingLocalNigoriCommit> local_commit);
169 
170   // Processes |pending_local_commit_queue_| FIFO such that all non-applicable
171   // pending commits issue a failure, until the first one that is applicable is
172   // found (if any). If such applicable commit is found, the corresponding Put()
173   // call is issued.
174   void PutNextApplicablePendingLocalCommit();
175 
176   // Populates keystore keys into |cryptographer| in case it doesn't contain
177   // them already and |passphrase_type| isn't KEYSTORE_PASSPHRASE. This
178   // function only updates local state and doesn't trigger a commit.
179   void MaybePopulateKeystoreKeysIntoCryptographer();
180 
181   const Encryptor* const encryptor_;
182 
183   const std::unique_ptr<NigoriLocalChangeProcessor> processor_;
184   const std::unique_ptr<NigoriStorage> storage_;
185 
186   // Used for generation of random salt for deriving keys from custom
187   // passphrase if SCRYPT is enabled.
188   const base::RepeatingCallback<std::string()> random_salt_generator_;
189 
190   // Stores a key derived from explicit passphrase and loaded from the prefs.
191   // Empty (i.e. default value) if prefs doesn't contain this key or in case of
192   // decryption/decoding errors.
193   const sync_pb::NigoriKey explicit_passphrase_key_;
194 
195   syncer::NigoriState state_;
196 
197   std::list<std::unique_ptr<PendingLocalNigoriCommit>>
198       pending_local_commit_queue_;
199 
200   // Observer that owns the list of actual observers, and broadcasts
201   // notifications to all observers in the list.
202   class BroadcastingObserver;
203   const std::unique_ptr<BroadcastingObserver> broadcasting_observer_;
204 
205   SEQUENCE_CHECKER(sequence_checker_);
206 
207   DISALLOW_COPY_AND_ASSIGN(NigoriSyncBridgeImpl);
208 };
209 
210 }  // namespace syncer
211 
212 #endif  // COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_
213