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_
|