File: sync_service_crypto.h

package info (click to toggle)
chromium 139.0.7258.127-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,122,156 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (235 lines) | stat: -rw-r--r-- 10,020 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_SYNC_SERVICE_SYNC_SERVICE_CRYPTO_H_
#define COMPONENTS_SYNC_SERVICE_SYNC_SERVICE_CRYPTO_H_

#include <memory>
#include <string>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/sync/base/data_type.h"
#include "components/sync/engine/nigori/key_derivation_params.h"
#include "components/sync/engine/sync_encryption_handler.h"
#include "components/sync/engine/sync_engine.h"
#include "components/sync/protocol/encryption.pb.h"
#include "components/sync/service/data_type_encryption_handler.h"
#include "components/trusted_vault/trusted_vault_client.h"

namespace syncer {

// This class functions as mostly independent component of SyncService that
// handles things related to encryption, including holding lots of state and
// encryption communications with the sync thread.
class SyncServiceCrypto : public SyncEncryptionHandler::Observer,
                          public DataTypeEncryptionHandler,
                          public trusted_vault::TrustedVaultClient::Observer {
 public:
  class Delegate {
   public:
    virtual ~Delegate() = default;
    virtual void CryptoStateChanged() = 0;
    virtual void CryptoRequiredUserActionChanged() = 0;
    virtual void ReconfigureDataTypesDueToCrypto() = 0;
    virtual void PassphraseTypeChanged(PassphraseType passphrase_type) = 0;
    virtual std::optional<PassphraseType> GetPassphraseType() const = 0;
    virtual void SetEncryptionBootstrapToken(
        const std::string& bootstrap_token) = 0;
    virtual std::string GetEncryptionBootstrapToken() const = 0;
  };

  // `delegate` and `trusted_vault_client` must not be null and must outlive
  // this object.
  SyncServiceCrypto(Delegate* delegate,
                    trusted_vault::TrustedVaultClient* trusted_vault_client);

  SyncServiceCrypto(const SyncServiceCrypto&) = delete;
  SyncServiceCrypto& operator=(const SyncServiceCrypto&) = delete;

  ~SyncServiceCrypto() override;

  void Reset();
  void StopObservingTrustedVaultClient();

  // See the SyncUserSettings header.
  base::Time GetExplicitPassphraseTime() const;
  bool IsPassphraseRequired() const;
  bool IsTrustedVaultKeyRequired() const;
  bool IsTrustedVaultRecoverabilityDegraded() const;
  bool IsEncryptEverythingEnabled() const;
  void SetEncryptionPassphrase(const std::string& passphrase);
  bool SetDecryptionPassphrase(const std::string& passphrase);
  void SetExplicitPassphraseDecryptionNigoriKey(std::unique_ptr<Nigori> nigori);
  std::unique_ptr<Nigori> GetExplicitPassphraseDecryptionNigoriKey() const;

  // Returns whether it's already possible to determine whether trusted vault
  // key required (e.g. engine didn't start yet or silent fetch attempt is in
  // progress).
  bool IsTrustedVaultKeyRequiredStateKnown() const;

  // Returns the actual passphrase type being used for encryption.
  std::optional<PassphraseType> GetPassphraseType() const;

  // Used to provide the engine when it is initialized, `engine` must not be
  // null and must outlive the `this` or the Reset() call. Should not be called
  // second time, unless Reset() is called first.
  void SetSyncEngine(const CoreAccountInfo& account_info, SyncEngine* engine);

  // Creates a proxy observer object that will post calls to this thread.
  std::unique_ptr<SyncEncryptionHandler::Observer> GetEncryptionObserverProxy();

  // SyncEncryptionHandler::Observer implementation.
  void OnPassphraseRequired(
      const KeyDerivationParams& key_derivation_params,
      const sync_pb::EncryptedData& pending_keys) override;
  void OnPassphraseAccepted() override;
  void OnTrustedVaultKeyRequired() override;
  void OnTrustedVaultKeyAccepted() override;
  void OnEncryptedTypesChanged(DataTypeSet encrypted_types,
                               bool encrypt_everything) override;
  void OnCryptographerStateChanged(Cryptographer* cryptographer,
                                   bool has_pending_keys) override;
  void OnPassphraseTypeChanged(PassphraseType type,
                               base::Time passphrase_time) override;

  // DataTypeEncryptionHandler implementation.
  bool HasCryptoError() const override;
  DataTypeSet GetAllEncryptedDataTypes() const override;

  // TrustedVaultClient::Observer implementation.
  void OnTrustedVaultKeysChanged() override;
  void OnTrustedVaultRecoverabilityChanged() override;

 private:
  enum class RequiredUserAction {
    kUnknownDuringInitialization,
    kNone,
    kPassphraseRequired,
    // Trusted vault keys are required but a silent attempt to fetch keys is in
    // progress before prompting the user.
    kFetchingTrustedVaultKeys,
    // Silent attempt is completed and user action is definitely required to
    // retrieve trusted vault keys.
    kTrustedVaultKeyRequired,
    // The need for user action has already been surfaced to upper layers (UI)
    // via IsTrustedVaultKeyRequired() but there's an ongoing fetch that may
    // resolve the issue.
    kTrustedVaultKeyRequiredButFetching,
    // No keys are required locally but user action is recommended to improve
    // recoverability.
    kTrustedVaultRecoverabilityDegraded,
  };

  // Reads trusted vault keys from the client and feeds them to the sync engine.
  void FetchTrustedVaultKeys(bool is_second_fetch_attempt);

  // Called at various stages of asynchronously fetching and processing trusted
  // vault encryption keys. `is_second_fetch_attempt` is useful for the case
  // where multiple passes (up to two) are needed to fetch the keys from the
  // client.
  void TrustedVaultKeysFetchedFromClient(
      bool is_second_fetch_attempt,
      const std::vector<std::vector<uint8_t>>& keys);
  void TrustedVaultKeysAdded(bool is_second_fetch_attempt);
  void TrustedVaultKeysMarkedAsStale(bool is_second_fetch_attempt, bool result);
  void FetchTrustedVaultKeysCompletedButInsufficient();

  // Updates required user action and notifies observers via
  // `notify_required_user_action_changed_`.
  void UpdateRequiredUserActionAndNotify(
      RequiredUserAction new_required_user_action);

  // Invokes TrustedVaultClient::GetIsRecoverabilityDegraded() if needed.
  void RefreshIsRecoverabilityDegraded();

  // Completion callback function for
  // TrustedVaultClient::GetIsRecoverabilityDegraded().
  void GetIsRecoverabilityDegradedCompleted(bool is_recoverability_degraded);

  // Attempts decryption of `cached_pending_keys` with a `nigori` and, if
  // successful, resolves the kPassphraseRequired state and populates the
  // `nigori` to engine. Should never be called when there is no cached pending
  // keys. Returns true if successful. Doesn't update bootstrap token.
  bool SetDecryptionKeyWithoutUpdatingBootstrapToken(
      std::unique_ptr<Nigori> nigori);

  // Similar to SetDecryptionPassphrase(), but uses bootstrap token instead of
  // user provided passphrase. Resolves the kPassphraseRequired state on
  // successful attempt.
  void MaybeSetDecryptionKeyFromBootstrapToken();

  const raw_ptr<Delegate> delegate_;

  // Never null and guaranteed to outlive us.
  const raw_ptr<trusted_vault::TrustedVaultClient> trusted_vault_client_;

  // All the mutable state is wrapped in a struct so that it can be easily
  // reset to its default values.
  struct State {
    State();
    ~State();

    State& operator=(State&& other) = default;

    // Not-null when the engine is initialized.
    raw_ptr<SyncEngine> engine = nullptr;

    // Populated when the engine is initialized.
    CoreAccountInfo account_info;

    // This field must be updated via UpdateRequiredUserAction() to ensure
    // observers are notified.
    RequiredUserAction required_user_action =
        RequiredUserAction::kUnknownDuringInitialization;

    // The current set of encrypted types. Always a superset of
    // AlwaysEncryptedUserTypes().
    DataTypeSet encrypted_types = AlwaysEncryptedUserTypes();

    // Whether we want to encrypt everything.
    bool encrypt_everything = false;

    // We cache the cryptographer's pending keys whenever
    // NotifyPassphraseRequired is called. This way, before the UI calls
    // SetDecryptionPassphrase on the syncer, it can avoid the overhead of an
    // asynchronous decryption call and give the user immediate feedback about
    // the passphrase entered by first trying to decrypt the cached pending keys
    // on the UI thread. Note that SetDecryptionPassphrase can still fail after
    // the cached pending keys are successfully decrypted if the pending keys
    // have changed since the time they were cached.
    sync_pb::EncryptedData cached_pending_keys;

    // The key derivation params for the passphrase. We save them when we
    // receive a passphrase required event, as they are a necessary piece of
    // information to be able to properly perform a decryption attempt, and we
    // want to be able to synchronously do that from the UI thread. For
    // passphrase types other than CUSTOM_PASSPHRASE, their key derivation
    // method will always be PBKDF2.
    KeyDerivationParams passphrase_key_derivation_params =
        KeyDerivationParams::CreateForPbkdf2();

    // If an explicit passphrase is in use, the time at which the passphrase was
    // first set (if available).
    base::Time cached_explicit_passphrase_time;

    // Set to true when FetchKeys() should be issued again once an ongoing
    // fetch-and-add procedure completes.
    bool deferred_trusted_vault_fetch_keys_pending = false;
  } state_;

  SEQUENCE_CHECKER(sequence_checker_);

  bool initial_trusted_vault_recoverability_logged_to_uma_ = false;

  base::WeakPtrFactory<SyncServiceCrypto> weak_factory_{this};
};

}  // namespace syncer

#endif  // COMPONENTS_SYNC_SERVICE_SYNC_SERVICE_CRYPTO_H_