File: cert_provisioning_common.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 (318 lines) | stat: -rw-r--r-- 12,952 bytes parent folder | download | duplicates (5)
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
// 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 CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_COMMON_H_
#define CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_COMMON_H_

#include <stdint.h>

#include <optional>
#include <string>

#include "base/containers/enum_set.h"
#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "chromeos/ash/components/dbus/constants/attestation_constants.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "net/cert/x509_certificate.h"

class PrefRegistrySimple;
class Profile;

namespace attestation {
enum VerifiedAccessFlow : int;
}  // namespace attestation

namespace ash {

namespace platform_keys {
class KeyPermissionsManager;
class PlatformKeysService;
}  // namespace platform_keys

namespace cert_provisioning {

// A feature to prevent Certificate Provisioning workers from attempting to
// continue the provisioning process on timeout (without receiving an
// invalidation). It is intended to be used for testing only to verify that new
// invalidations actually work. Also see `ShouldOnlyUseInvalidations`.
// TODO(b/336989561): Remove this after the migration to new invalidations is
// done.
BASE_DECLARE_FEATURE(kCertProvisioningUseOnlyInvalidationsForTesting);

BASE_DECLARE_FEATURE(
    kDeviceCertProvisioningInvalidationWithDirectMessagesEnabled);
BASE_DECLARE_FEATURE(
    kUserCertProvisioningInvalidationWithDirectMessagesEnabled);

// Used for both DeleteVaKey and DeleteVaKeysByPrefix
using DeleteVaKeyCallback = base::OnceCallback<void(bool)>;

inline constexpr char kKeyNamePrefix[] = "cert-provis-";

// The type for variables containing an error from DM Server response.
using CertProvisioningResponseErrorType =
    enterprise_management::ClientCertificateProvisioningResponse::Error;
// The namespace that contains convenient aliases for error values, e.g.
// UNDEFINED, TIMED_OUT, IDENTITY_VERIFICATION_ERROR, CA_ERROR.
using CertProvisioningResponseError =
    enterprise_management::ClientCertificateProvisioningResponse;

// Numeric values are used in serialization and should not be remapped.
enum class CertScope { kUser = 0, kDevice = 1, kMaxValue = kDevice };

// These values are used in serialization and should be changed carefully. Also
// enums.xml should be updated.
enum class CertProvisioningWorkerState {
  kInitState = 0,
  kKeypairGenerated = 1,
  kStartCsrResponseReceived = 2,  // Unused in "dynamic" flow.
  kVaChallengeFinished = 3,
  kKeyRegistered = 4,
  kKeypairMarked = 5,
  kSignCsrFinished = 6,
  kFinishCsrResponseReceived = 7,  // Unused in "dynamic" flow.
  kSucceeded = 8,
  kInconsistentDataError = 9,
  kFailed = 10,
  kCanceled = 11,

  // The following states are only used in the "dynamic" flow.
  // The worker is ready for next server-provided operation.
  kReadyForNextOperation = 12,
  // The worker has received an "Authorize" instruction.
  kAuthorizeInstructionReceived = 13,
  // The worker has received a "Proof of Possession" instruction.
  kProofOfPossessionInstructionReceived = 14,
  // The worker has received an "Import Certificate" instruction.
  kImportCertificateInstructionReceived = 15,

  kMaxValue = kImportCertificateInstructionReceived,
};

// All states that are allowed in a "static" flow.
inline constexpr base::EnumSet<CertProvisioningWorkerState,
                               CertProvisioningWorkerState::kInitState,
                               CertProvisioningWorkerState::kMaxValue>
    kStaticWorkerStates = {
        CertProvisioningWorkerState::kInitState,
        CertProvisioningWorkerState::kKeypairGenerated,
        CertProvisioningWorkerState::kStartCsrResponseReceived,
        CertProvisioningWorkerState::kVaChallengeFinished,
        CertProvisioningWorkerState::kKeyRegistered,
        CertProvisioningWorkerState::kKeypairMarked,
        CertProvisioningWorkerState::kSignCsrFinished,
        CertProvisioningWorkerState::kFinishCsrResponseReceived,
        CertProvisioningWorkerState::kSucceeded,
        CertProvisioningWorkerState::kInconsistentDataError,
        CertProvisioningWorkerState::kFailed,
        CertProvisioningWorkerState::kCanceled};

// All states that are allowed in a "dynamic" flow.
inline constexpr base::EnumSet<CertProvisioningWorkerState,
                               CertProvisioningWorkerState::kInitState,
                               CertProvisioningWorkerState::kMaxValue>
    kDynamicWorkerStates = {
        CertProvisioningWorkerState::kInitState,
        CertProvisioningWorkerState::kKeypairGenerated,
        CertProvisioningWorkerState::kVaChallengeFinished,
        CertProvisioningWorkerState::kKeyRegistered,
        CertProvisioningWorkerState::kKeypairMarked,
        CertProvisioningWorkerState::kSignCsrFinished,
        CertProvisioningWorkerState::kSucceeded,
        CertProvisioningWorkerState::kInconsistentDataError,
        CertProvisioningWorkerState::kFailed,
        CertProvisioningWorkerState::kCanceled,
        CertProvisioningWorkerState::kReadyForNextOperation,
        CertProvisioningWorkerState::kAuthorizeInstructionReceived,
        CertProvisioningWorkerState::kProofOfPossessionInstructionReceived,
        CertProvisioningWorkerState::kImportCertificateInstructionReceived};

// Location where a generated key has been persisted by a "dynamic" flow worker.
// These values are used in serialization and should be changed carefully.
enum class KeyLocation {
  kNone = 0,
  kVaDatabase = 1,
  kPkcs11Token = 2,
  kMaxValue = kPkcs11Token
};

// Types of the requests sent from the certificate provisioning client to the
// device management server.
enum class DeviceManagementServerRequestType {
  kStartCsr = 0,
  kFinishCsr = 1,
  kDownloadCert = 2,
};

// Converts the worker |state| to a string. This is mainly for logging purposes.
std::string CertificateProvisioningWorkerStateToString(
    CertProvisioningWorkerState state);

// Returns true if the |state| is one of final states, i. e. worker should
// finish its task in one of them.
bool IsFinalState(CertProvisioningWorkerState state);

using CertProfileId = std::string;

// Names of CertProfile fields in a base::Value representation. Must be in sync
// with policy schema definitions in RequiredClientCertificateForDevice.yaml and
// RequiredClientCertificateForUser.yaml.
inline constexpr char kCertProfileIdKey[] = "cert_profile_id";
inline constexpr char kCertProfileNameKey[] = "name";
inline constexpr char kCertProfileRenewalPeroidSec[] = "renewal_period_seconds";
inline constexpr char kCertProfilePolicyVersionKey[] = "policy_version";
inline constexpr char kCertProfileProtocolVersion[] = "protocol_version";
inline constexpr char kCertProfileIsVaEnabledKey[] =
    "enable_remote_attestation_check";
inline constexpr char kCertProfileKeyType[] = "key_algorithm";

// The version of the certificate provisioning protocol between ChromeOS client
// and device management server.
// The values must match the description in
// RequiredClientCertificateForDevice.yaml and
// RequiredClientCertificateForUser.yaml.
// They are also used in serialization so they should not be renumbered.
enum class ProtocolVersion {
  // Original "static" protocol.
  kStatic = 1,
  // "Dynamic" protocol.
  kDynamic = 2,
};

// The type of key the device should generate.
// The values must match the description in
// RequiredClientCertificateForDevice.yaml and
// RequiredClientCertificateForUser.yaml.
// They are also used in serialization so they should not be renumbered.
enum class KeyType {
  // 2048-bit RSA keys.
  kRsa = 1,
  // Elliptic-curve keys using the P-256 curve.
  kEc = 2,
  kMaxValue = KeyType::kEc
};

struct CertProfile {
  static std::optional<CertProfile> MakeFromValue(
      const base::Value::Dict& value);

  CertProfile();
  // For tests.
  CertProfile(CertProfileId profile_id,
              std::string name,
              std::string policy_version,
              KeyType key_type,
              bool is_va_enabled,
              base::TimeDelta renewal_period,
              ProtocolVersion protocol_version);
  CertProfile(const CertProfile& other);
  CertProfile& operator=(const CertProfile&);
  CertProfile(CertProfile&& source);
  CertProfile& operator=(CertProfile&&);
  ~CertProfile();

  CertProfileId profile_id;
  // Human-readable name (UTF-8).
  std::string name;
  std::string policy_version;
  KeyType key_type;
  bool is_va_enabled = true;
  // Default renewal period 0 means that a certificate will be renewed only
  // after the previous one has expired (0 seconds before it is expires).
  base::TimeDelta renewal_period = base::Seconds(0);
  ProtocolVersion protocol_version = ProtocolVersion::kStatic;

  // IMPORTANT:
  // Increment this when you add/change any member in CertProfile (and update
  // all functions that fail to compile because of it).
  static constexpr int kVersion = 7;

  friend bool operator==(const CertProfile&, const CertProfile&) = default;
};

struct CertProfileComparator {
  bool operator()(const CertProfile& a, const CertProfile& b) const;
};

// Parses `protocol_version_value` as ProtocolVersion enum.
std::optional<ProtocolVersion> ParseProtocolVersion(
    std::optional<int> protocol_version_value);

void RegisterProfilePrefs(PrefRegistrySimple* registry);
void RegisterLocalStatePrefs(PrefRegistrySimple* registry);
const char* GetPrefNameForCertProfiles(CertScope scope);
const char* GetPrefNameForSerialization(CertScope scope);

// Returns the nickname (CKA_LABEL) for keys created for the |profile_id|.
std::string GetKeyName(CertProfileId profile_id);
// Returns the flow type type for VA API calls for |scope|.
::attestation::VerifiedAccessFlow GetVaFlowType(CertScope scope);
chromeos::platform_keys::TokenId GetPlatformKeysTokenId(CertScope scope);

// This functions should be used to delete keys that were created by
// TpmChallengeKey* and were not registered yet. (To delete registered keys
// PlatformKeysService should be used.)
void DeleteVaKey(CertScope scope,
                 Profile* profile,
                 const std::string& key_name,
                 DeleteVaKeyCallback callback);
void DeleteVaKeysByPrefix(CertScope scope,
                          Profile* profile,
                          const std::string& key_prefix,
                          DeleteVaKeyCallback callback);

// Parses |data| using net::X509Certificate::FORMAT_AUTO as format specifier.
// Expects exactly one certificate to be the result and returns it.  If parsing
// fails or if more than one certificates were in |data|, returns an null ptr.
scoped_refptr<net::X509Certificate> CreateSingleCertificateFromBytes(
    const char* data,
    size_t length);

// Returns the PlatformKeysService to be used.
// If |scope| is CertScope::kDevice, |profile| is ignored and the
// device-wide PlatformKeysService is returned.
// If |scope| is CertScope::kUser, returns the service for |profile|.
// The returned object is owned by the Profile (user-specific) or globally
// (device-wide) and may only be used until it notifies its observers that it is
// being shut down.
platform_keys::PlatformKeysService* GetPlatformKeysService(CertScope scope,
                                                           Profile* profile);

// Returns the KeyPermissionsManager to be used.
// If |scope| is CertScope::kDevice, |profile| is ignored and the
// system token key permissions manager is returned.
// If |scope| is CertScope::kUser, returns the user private slot key permissions
// manager for |profile|.
platform_keys::KeyPermissionsManager* GetKeyPermissionsManager(
    CertScope scope,
    Profile* profile);

// Generates a random unique identifier for a certificate provisioning process.
// It is used to receive invalidations (to wake up waiting workers) and for
// consistent logging with the server-side code (see "cppId" in the logs).
std::string GenerateCertProvisioningId();

// Creates an invalidation listener type based the cert provisioning process id
// (see `GenerateCertProvisioningId()`). The type is a string that is
// constructed both server- and client-side and is used to deliver FCM
// invalidations from the server-side.
std::string MakeInvalidationListenerType(
    const std::string& cert_prov_process_id);

// Returns true if workers should only progress when they receive an
// invalidation (not on timeout).
bool ShouldOnlyUseInvalidations();

// Returns GCP number for cert provisioning invalidations of given `scope`.
int64_t GetCertProvisioningInvalidationProjectNumber(CertScope scope);

}  // namespace cert_provisioning
}  // namespace ash

#endif  // CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_COMMON_H_