File: kcer_factory_ash.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 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 (194 lines) | stat: -rw-r--r-- 8,260 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
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_ASH_KCER_KCER_FACTORY_ASH_H_
#define CHROME_BROWSER_ASH_KCER_KCER_FACTORY_ASH_H_

#include "ash/public/cpp/session/session_observer.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "chrome/browser/ash/kcer/nssdb_migration/kcer_rollback_helper.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h"
#include "chromeos/ash/components/kcer/chaps/session_chaps_client.h"
#include "chromeos/ash/components/kcer/kcer.h"
#include "chromeos/ash/components/kcer/kcer_token.h"
#include "chromeos/ash/components/tpm/tpm_token_info_getter.h"

class Profile;
class PrefService;

namespace net {
class NSSCertDatabase;
}
namespace kcer::internal {
class KcerImpl;
}  // namespace kcer::internal
namespace user_prefs {
class PrefRegistrySyncable;
}

namespace kcer {

// Feature flag to toggle between Kcer-over-NSS and Kcer-without-NSS. If
// disabled, Kcer will use the implementation that relies on NSS. If enabled,
// Kcer will talk directly with Chaps without using NSS.
BASE_DECLARE_FEATURE(kKcerWithoutNss);

class KcerFactoryAsh : public ProfileKeyedServiceFactory, ash::SessionObserver {
 public:
  // Public for the implementation of this class.
  using UniqueSlotId = std::pair<SECMODModuleID, CK_SLOT_ID>;
  using KcerTokenMapNss =
      base::flat_map<UniqueSlotId, std::unique_ptr<internal::KcerToken>>;
  using KcerTokenMapWithoutNss =
      base::flat_map<SessionChapsClient::SlotId,
                     std::unique_ptr<internal::KcerToken>>;
  using InitializeOnUIThreadCallback =
      base::OnceCallback<void(base::WeakPtr<internal::KcerToken>,
                              base::WeakPtr<internal::KcerToken>)>;

  // Returns a Kcer instance for the `profile`. The lifetime of the instance is
  // bound to the `profile`. If the pointer is cached, it needs to be checked
  // before it's used.
  static base::WeakPtr<Kcer> GetKcer(Profile* profile);

  static KcerFactoryAsh* GetInstance();

  // Public for Pkcs12Migrator unit tests.
  struct KcerService : public KeyedService {
    explicit KcerService(std::unique_ptr<internal::KcerImpl> kcer_instance);
    ~KcerService() override;

    std::unique_ptr<internal::KcerImpl> kcer;
  };

  // Returns whether HighLevelChapsClient was initialized. The method is mostly
  // needed just for testing.
  static bool IsHighLevelChapsClientInitialized();

  // Creates an entry in user preferences in Ash that a PKCS#12 file was
  // dual-written. This will be used in case a rollback for the related
  // experiment is needed.
  static void RecordPkcs12CertDualWritten();

  // Clears cached NSS state. Useful for unittests using Kcer with a test NSS
  // database, the test should clear the Kcer state when finished to avoid
  // leaking into the next test. This must be called on the IO thread.
  static void ClearNssTokenMapForTesting();

 private:
  friend base::NoDestructor<KcerFactoryAsh>;

  KcerFactoryAsh();
  ~KcerFactoryAsh() override;

  // BrowserContextKeyedServiceFactory:
  // The services need to be created immediately after the browser context
  // because the instance for the main profile will also be exposed as the
  // default one and it won't be able to be created on demand from there.
  bool ServiceIsCreatedWithBrowserContext() const override;
  // Creates a new service, which is not fully initialized yet, but can already
  // be used as if it's initialized. Posts a task to finish the initialization.
  std::unique_ptr<KeyedService> BuildServiceInstanceForBrowserContext(
      content::BrowserContext* context) const override;

  // Implements BrowserContextKeyedServiceFactory.
  void RegisterProfilePrefs(
      user_prefs::PrefRegistrySyncable* registry) override;

  // Returns whether the Kcer-without-NSS experiment is enabled.
  bool UseKcerWithoutNss() const;

  void Initialize();

  void StartInitializingKcerInstance(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      content::BrowserContext* context);

  void StartInitializingKcerWithoutNss(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      content::BrowserContext* context);
  void GetDeviceTokenInfo(base::WeakPtr<internal::KcerImpl> kcer_service,
                          AccountId account_id);
  void GetUserTokenInfo(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      AccountId account_id,
      std::unique_ptr<ash::TPMTokenInfoGetter> scoped_device_token_info_getter,
      std::optional<user_data_auth::TpmTokenInfo> device_token_info);
  void GotAllTokenInfos(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      std::optional<user_data_auth::TpmTokenInfo> device_token_info,
      std::unique_ptr<ash::TPMTokenInfoGetter> scoped_user_token_info_getter,
      std::optional<user_data_auth::TpmTokenInfo> user_token_info);
  base::WeakPtr<internal::KcerToken> GetTokenWithoutNss(
      std::optional<SessionChapsClient::SlotId> token_id,
      Token token_type);
  bool EnsureHighLevelChapsClientInitialized();
  void InitializeKcerInstanceWithoutNss(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      std::optional<SessionChapsClient::SlotId> user_token_id,
      std::optional<SessionChapsClient::SlotId> device_token_id);

  void StartInitializingKcerForNss(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      content::BrowserContext* context);
  // Returns a functor that will create KcerTokens for each slot from `nss_db`
  // (if necessary) and return weak pointers to them to the provided `callback`.
  // The functor should be run on the IO thread, the callback will be run on the
  // UI thread.
  base::OnceCallback<void(InitializeOnUIThreadCallback callback,
                          net::NSSCertDatabase* nss_db)>
  GetPrepareTokensForNssOnIOThreadFunctor();
  void InitializeKcerInstanceForNss(
      base::WeakPtr<internal::KcerImpl> kcer_service,
      base::WeakPtr<internal::KcerToken> user_token,
      base::WeakPtr<internal::KcerToken> device_token);

  void StartInitializingDeviceKcerWithoutNss();
  void InitializeDeviceKcerWithoutNss(
      std::unique_ptr<ash::TPMTokenInfoGetter> scoped_device_token_info_getter,
      std::optional<user_data_auth::TpmTokenInfo> device_token_info);

  void StartInitializingDeviceKcerForNss();
  void InitializeDeviceKcerForNss(
      base::WeakPtr<internal::KcerToken> /*user_token*/,
      base::WeakPtr<internal::KcerToken> device_token);

  base::WeakPtr<Kcer> GetKcerImpl(Profile* profile);
  void RecordPkcs12CertDualWrittenImpl();
  void ClearNssTokenMapForTestingImpl();

  // Implements ash::SessionObserver.
  void OnActiveUserPrefServiceChanged(PrefService* pref_service) override;
  // Might schedule a rollback of certs that were double-written into Chaps and
  // NSS (i.e. the deletion of related certs in Chaps).
  void MaybeScheduleRollbackForCertDoubleWrite(PrefService* pref_service);

  // Used by `high_level_chaps_client_` and must outlive it.
  std::unique_ptr<SessionChapsClient> session_chaps_client_;
  // Used by tokens in `chaps_tokens_ui_` (to communicate with Chaps) and must
  // outlive them.
  std::unique_ptr<HighLevelChapsClient> high_level_chaps_client_;

  std::unique_ptr<internal::KcerRollbackHelper> rollback_helper_;

  // Stores the mapping between NSS slots and KcerToken-s. Each private or
  // system slot is mapped into a KcerToken, so a Kcer instance equivalent to a
  // given NSSCertDatabase can be created. Public slots are ignored because
  // there should be no keys or client certificates there by the time Kcer is
  // launched.
  // The map is created on the UI thread, only used on the IO thread and is
  // never destroyed (as a part of NoDestructor<> factory).
  KcerTokenMapNss nss_tokens_io_;
  // Stores the mapping between Chaps tokens and KcerToken-s. The map is created
  // on the UI thread, only used on the UI thread and is never destroyed (as a
  // part of NoDestructor<> factory).
  // Only one token map is used for each Chromium launch, which is controlled by
  // an experiment.
  KcerTokenMapWithoutNss chaps_tokens_ui_;
};

}  // namespace kcer

#endif  // CHROME_BROWSER_ASH_KCER_KCER_FACTORY_ASH_H_