File: standalone_trusted_vault_backend.h

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (341 lines) | stat: -rw-r--r-- 14,718 bytes parent folder | download | duplicates (3)
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// Copyright 2020 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_TRUSTED_VAULT_STANDALONE_TRUSTED_VAULT_BACKEND_H_
#define COMPONENTS_TRUSTED_VAULT_STANDALONE_TRUSTED_VAULT_BACKEND_H_

#include <cstdint>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/trusted_vault/local_recovery_factor.h"
#include "components/trusted_vault/proto/local_trusted_vault.pb.h"
#include "components/trusted_vault/standalone_trusted_vault_storage.h"
#include "components/trusted_vault/trusted_vault_degraded_recoverability_handler.h"
#include "components/trusted_vault/trusted_vault_histograms.h"
#include "components/trusted_vault/trusted_vault_server_constants.h"
#include "components/trusted_vault/trusted_vault_throttling_connection.h"
#include "google_apis/gaia/gaia_id.h"
#include "google_apis/gaia/google_service_auth_error.h"

namespace signin {
class AccountsInCookieJarInfo;
}  // namespace signin

namespace trusted_vault {

// Provides interfaces to store/remove keys to/from file storage.
// This class performs expensive operations and expected to be run from
// dedicated sequence (using thread pool). Can be constructed on any thread/
// sequence.
class StandaloneTrustedVaultBackend
    : public base::RefCountedThreadSafe<StandaloneTrustedVaultBackend>,
      public TrustedVaultDegradedRecoverabilityHandler::Delegate {
 public:
  using FetchKeysCallback = base::OnceCallback<void(
      const std::vector<std::vector<uint8_t>>& vault_keys)>;

  class Delegate {
   public:
    Delegate() = default;
    Delegate(const Delegate&) = delete;
    virtual ~Delegate() = default;

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

    virtual void NotifyRecoverabilityDegradedChanged() = 0;
  };

  class LocalRecoveryFactorsFactory {
   public:
    LocalRecoveryFactorsFactory() = default;
    LocalRecoveryFactorsFactory(const LocalRecoveryFactorsFactory&) = delete;
    virtual ~LocalRecoveryFactorsFactory() = default;

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

    // Creates LocalRecoveryFactor's for |primary_account|.
    // Note that the returned LocalRecoveryFactor's will keep a reference to
    // |storage| and |connection|.
    virtual std::vector<std::unique_ptr<LocalRecoveryFactor>>
    CreateLocalRecoveryFactors(SecurityDomainId security_domain_id,
                               StandaloneTrustedVaultStorage* storage,
                               TrustedVaultThrottlingConnection* connection,
                               const CoreAccountInfo& primary_account) = 0;
  };

  enum class RefreshTokenErrorState {
    // State can not be identified (e.g. refresh token is not loaded yet).
    kUnknown,
    // Refresh token is in persistent auth error state.
    kPersistentAuthError,
    // There are no persistent auth errors (note, that transient errors are
    // still possible).
    kNoPersistentAuthErrors,
  };

  // |connection| can be null, in this case functionality that involves
  // interaction with vault service (such as recovery factor registration, keys
  // downloading, etc.) will be disabled.
  StandaloneTrustedVaultBackend(
#if BUILDFLAG(IS_MAC)
      const std::string& icloud_keychain_access_group_prefix,
#endif
      SecurityDomainId security_domain_id,
      std::unique_ptr<StandaloneTrustedVaultStorage> storage,
      std::unique_ptr<Delegate> delegate,
      std::unique_ptr<TrustedVaultConnection> connection);
  StandaloneTrustedVaultBackend(const StandaloneTrustedVaultBackend& other) =
      delete;
  StandaloneTrustedVaultBackend& operator=(
      const StandaloneTrustedVaultBackend& other) = delete;

  // TrustedVaultDegradedRecoverabilityHandler::Delegate implementation.
  void WriteDegradedRecoverabilityState(
      const trusted_vault_pb::LocalTrustedVaultDegradedRecoverabilityState&
          degraded_recoverability_state) override;
  void OnDegradedRecoverabilityChanged() override;

  // Restores state saved on disk, should be called before using the object.
  void ReadDataFromDisk();

  // Populates vault keys corresponding to |account_info| into |callback|. If
  // recent keys are locally available, |callback| will be called immediately.
  // Otherwise, attempts to download new keys from the server. In case of
  // failure or if current state isn't sufficient it will populate locally
  // available keys regardless of their freshness.
  void FetchKeys(const CoreAccountInfo& account_info,
                 FetchKeysCallback callback);

  // Replaces keys for given |gaia_id| both in memory and on disk.
  void StoreKeys(const GaiaId& gaia_id,
                 const std::vector<std::vector<uint8_t>>& keys,
                 int last_key_version);

  // Marks vault keys as stale.  Afterwards, the next FetchKeys() call for this
  // |account_info| will trigger a key download attempt.
  bool MarkLocalKeysAsStale(const CoreAccountInfo& account_info);

  // Sets/resets |primary_account_|.
  void SetPrimaryAccount(const std::optional<CoreAccountInfo>& primary_account,
                         RefreshTokenErrorState refresh_token_error_state);

  // Handles changes of accounts in cookie jar and removes keys for some
  // accounts:
  // 1. Non-primary account keys are removed if account isn't in cookie jar.
  // 2. Primary account keys marked for deferred deletion if account isn't in
  // cookie jar.
  void UpdateAccountsInCookieJarInfo(
      const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info);

  // Returns whether recoverability of the keys is degraded and user action is
  // required to add a new method.
  void GetIsRecoverabilityDegraded(const CoreAccountInfo& account_info,
                                   base::OnceCallback<void(bool)> cb);

  // Registers a new trusted recovery method that can be used to retrieve keys.
  void AddTrustedRecoveryMethod(const GaiaId& gaia_id,
                                const std::vector<uint8_t>& public_key,
                                int method_type_hint,
                                base::OnceClosure cb);

  void ClearLocalDataForAccount(const CoreAccountInfo& account_info);

  std::optional<CoreAccountInfo> GetPrimaryAccountForTesting() const;

  trusted_vault_pb::LocalDeviceRegistrationInfo
  GetDeviceRegistrationInfoForTesting(const GaiaId& gaia_id);

  std::vector<uint8_t> GetLastAddedRecoveryMethodPublicKeyForTesting() const;
  int GetLastKeyVersionForTesting(const GaiaId& gaia_id);

  bool HasPendingTrustedRecoveryMethodForTesting() const;

  static scoped_refptr<StandaloneTrustedVaultBackend> CreateForTesting(
      SecurityDomainId security_domain_id,
      std::unique_ptr<StandaloneTrustedVaultStorage> storage,
      std::unique_ptr<Delegate> delegate,
      std::unique_ptr<TrustedVaultThrottlingConnection> connection,
      std::unique_ptr<LocalRecoveryFactorsFactory>
          local_recovery_factors_factory);

 private:
  friend class base::RefCountedThreadSafe<StandaloneTrustedVaultBackend>;

  // Constructor which allows specifying a TrustedVaultThrottlingConnection and
  // a LocalRecoveryFactorsFactory.
  // Only used in tests.
  StandaloneTrustedVaultBackend(
      SecurityDomainId security_domain_id,
      std::unique_ptr<StandaloneTrustedVaultStorage> storage,
      std::unique_ptr<Delegate> delegate,
      std::unique_ptr<TrustedVaultThrottlingConnection> connection,
      std::unique_ptr<LocalRecoveryFactorsFactory>
          local_recovery_factors_factory);

  static TrustedVaultDownloadKeysStatusForUMA
  GetDownloadKeysStatusForUMAFromResponse(
      TrustedVaultDownloadKeysStatus response_status);

  ~StandaloneTrustedVaultBackend() override;

  // Attempts to register local recovery factors in case they're not yet
  // registered and currently available local data is sufficient to do it. Also
  // records registration related metrics.
  void MaybeRegisterLocalRecoveryFactors();

  // Attempts to honor the pending operation stored in
  // |pending_trusted_recovery_method_|.
  void MaybeProcessPendingTrustedRecoveryMethod();

  // Called when registration of a local recovery factor for |gaia_id| is
  // completed (either successfully or not). |storage_| must contain
  // LocalTrustedVaultPerUser for given |gaia_id|.
  void OnRecoveryFactorRegistered(
      LocalRecoveryFactorType local_recovery_factor_type,
      TrustedVaultRegistrationStatus status,
      int key_version,
      bool had_local_keys);

  void AttemptRecoveryFactor(size_t local_recovery_factor);
  void OnKeysRecovered(size_t current_local_recovery_factor,
                       LocalRecoveryFactor::RecoveryStatus status,
                       const std::vector<std::vector<uint8_t>>& new_vault_keys,
                       int last_vault_key_version);

  void OnTrustedRecoveryMethodAdded(base::OnceClosure cb);

  // Invokes |callback| with currently available keys for |gaia_id|.
  void FulfillFetchKeys(
      const GaiaId& gaia_id,
      FetchKeysCallback callback,
      std::optional<TrustedVaultRecoverKeysOutcomeForUMA> status_for_uma);

  // Same as above, but takes parameters from |ongoing_fetch_keys|, used when
  // keys are fetched asynchronously, after keys downloading attempt.
  void FulfillOngoingFetchKeys(
      std::optional<TrustedVaultRecoverKeysOutcomeForUMA> status_for_uma);

  // Removes all data for non-primary accounts if they were previously marked
  // for deletion due to accounts in cookie jar changes.
  void RemoveNonPrimaryAccountKeysIfMarkedForDeletion();

  const SecurityDomainId security_domain_id_;

  const std::unique_ptr<StandaloneTrustedVaultStorage> storage_;

  const std::unique_ptr<Delegate> delegate_;

  // Used for communication with trusted vault server. Can be null, in this case
  // functionality that involves interaction with vault service (such as
  // recovery factor registration, keys downloading, etc.) will be disabled.
  // Note: |connection_| depends on |storage_|, so it needs to be destroyed
  // first. Thus, the field order matters.
  // TODO(crbug.com/40143544): |connection_| can be null if URL passed as
  // kTrustedVaultServiceURLSwitch is not valid, consider making it non-nullable
  // even in this case and clean up related logic.
  const std::unique_ptr<TrustedVaultThrottlingConnection> connection_;

  // Only current |primary_account_| can be used for communication with trusted
  // vault server.
  std::optional<CoreAccountInfo> primary_account_;

  // Factory to create |local_recovery_factors_|. Can be overwritten in tests.
  const std::unique_ptr<LocalRecoveryFactorsFactory>
      local_recovery_factors_factory_;
  // All known local recovery factors that can be used to attempt key recovery.
  // Note: |local_recovery_factors_| depends on |storage_|, thus it must be
  // destroyed before |storage_| (i.e. the order of the fields matters).
  std::vector<std::unique_ptr<LocalRecoveryFactor>> local_recovery_factors_;

  // Error state of refresh token for |primary_account_|.
  RefreshTokenErrorState refresh_token_error_state_ =
      StandaloneTrustedVaultBackend::RefreshTokenErrorState::kUnknown;

  // If AddTrustedRecoveryMethod() gets invoked before SetPrimaryAccount(), the
  // execution gets deferred until SetPrimaryAccount() is invoked.
  struct PendingTrustedRecoveryMethod {
    PendingTrustedRecoveryMethod();
    PendingTrustedRecoveryMethod(PendingTrustedRecoveryMethod&) = delete;
    PendingTrustedRecoveryMethod& operator=(PendingTrustedRecoveryMethod&) =
        delete;
    PendingTrustedRecoveryMethod(PendingTrustedRecoveryMethod&&);
    PendingTrustedRecoveryMethod& operator=(PendingTrustedRecoveryMethod&&);
    ~PendingTrustedRecoveryMethod();

    GaiaId gaia_id;
    std::vector<uint8_t> public_key;
    int method_type_hint;
    base::OnceClosure completion_callback;
  };
  std::optional<PendingTrustedRecoveryMethod> pending_trusted_recovery_method_;

  // Keys fetching is asynchronous when it involves sending request to the
  // server, this structure encapsulates the data needed to process the response
  // and allow concurrent key fetches for the same user. Destroying this will
  // cancel the ongoing request.
  // Note, that |gaia_id| should match |primary_account_|. It is used only for
  // verification.
  struct OngoingFetchKeys {
    OngoingFetchKeys();
    OngoingFetchKeys(OngoingFetchKeys&) = delete;
    OngoingFetchKeys& operator=(OngoingFetchKeys&) = delete;
    OngoingFetchKeys(OngoingFetchKeys&&);
    OngoingFetchKeys& operator=(OngoingFetchKeys&&);
    ~OngoingFetchKeys();

    GaiaId gaia_id;
    std::vector<FetchKeysCallback> callbacks;
  };
  std::optional<OngoingFetchKeys> ongoing_fetch_keys_;

  // Same as above, but specifically used for recoverability-related requests.
  // TODO(crbug.com/40178774): Move elsewhere.
  std::unique_ptr<TrustedVaultConnection::Request>
      ongoing_add_recovery_method_request_;

  // Used to take care of polling the degraded recoverability state from the
  // server for the |primary_account|. Instance changes whenever
  // |primary_account| changes.
  std::unique_ptr<TrustedVaultDegradedRecoverabilityHandler>
      degraded_recoverability_handler_;

  std::vector<uint8_t> last_added_recovery_method_public_key_for_testing_;

  bool recovery_factor_registration_state_recorded_to_uma_ = false;

  // If GetIsRecoverabilityDegraded() gets invoked before
  // SetPrimaryAccount(), the execution gets deferred until
  // SetPrimaryAccount() is invoked. This is possible because
  // SetPrimaryAccount() is called only once refresh token are loaded and
  // GetIsRecoverabilityDegraded() could be invoked before that.
  struct PendingGetIsRecoverabilityDegraded {
    PendingGetIsRecoverabilityDegraded();
    PendingGetIsRecoverabilityDegraded(PendingGetIsRecoverabilityDegraded&) =
        delete;
    PendingGetIsRecoverabilityDegraded& operator=(
        PendingGetIsRecoverabilityDegraded&) = delete;
    PendingGetIsRecoverabilityDegraded(PendingGetIsRecoverabilityDegraded&&);
    PendingGetIsRecoverabilityDegraded& operator=(
        PendingGetIsRecoverabilityDegraded&&);
    ~PendingGetIsRecoverabilityDegraded();

    CoreAccountInfo account_info;
    base::OnceCallback<void(bool)> completion_callback;
  };
  std::optional<PendingGetIsRecoverabilityDegraded>
      pending_get_is_recoverability_degraded_;
};

}  // namespace trusted_vault

#endif  // COMPONENTS_TRUSTED_VAULT_STANDALONE_TRUSTED_VAULT_BACKEND_H_