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
|
// Copyright 2023 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_WORKER_STATIC_H_
#define CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_WORKER_STATIC_H_
#include <stddef.h>
#include <memory>
#include <optional>
#include <string>
#include <vector>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/time/time.h"
#include "chrome/browser/ash/attestation/tpm_challenge_key_subtle.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_client.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_common.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_invalidator.h"
#include "chrome/browser/ash/cert_provisioning/cert_provisioning_worker.h"
#include "chrome/browser/ash/platform_keys/platform_keys_service.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "net/base/backoff_entry.h"
class Profile;
class PrefService;
namespace ash::cert_provisioning {
class CertProvisioningWorkerStatic : public CertProvisioningWorker {
public:
CertProvisioningWorkerStatic(
std::string cert_provisioning_process_id,
CertScope cert_scope,
Profile* profile,
PrefService* pref_service,
const CertProfile& cert_profile,
CertProvisioningClient* cert_provisioning_client,
std::unique_ptr<CertProvisioningInvalidator> invalidator,
base::RepeatingClosure state_change_callback,
CertProvisioningWorkerCallback result_callback);
~CertProvisioningWorkerStatic() override;
// CertProvisioningWorker
void DoStep() override;
void Stop(CertProvisioningWorkerState state) override;
void Pause() override;
void MarkWorkerForReset() override;
bool IsWaiting() const override;
bool IsWorkerMarkedForReset() const override;
const std::string& GetProcessId() const override;
const CertProfile& GetCertProfile() const override;
const std::vector<uint8_t>& GetPublicKey() const override;
CertProvisioningWorkerState GetState() const override;
CertProvisioningWorkerState GetPreviousState() const override;
base::Time GetLastUpdateTime() const override;
const std::optional<BackendServerError>& GetLastBackendServerError()
const override;
std::string GetFailureMessageWithPii() const override;
private:
friend class CertProvisioningSerializer;
void GenerateKey();
void GenerateRegularKey();
void OnGenerateRegularKeyDone(std::vector<uint8_t> public_key_spki_der,
chromeos::platform_keys::Status status);
void GenerateKeyForVa();
void OnGenerateKeyForVaDone(const attestation::TpmChallengeKeyResult& result);
void StartCsr();
void OnStartCsrDone(policy::DeviceManagementStatus status,
std::optional<CertProvisioningResponseErrorType> error,
std::optional<int64_t> try_later,
const std::string& invalidation_topic,
const std::string& va_challenge,
enterprise_management::HashingAlgorithm hashing_algorithm,
std::vector<uint8_t> data_to_sign);
void ProcessStartCsrResponse();
void BuildVaChallengeResponse();
void OnBuildVaChallengeResponseDone(
const attestation::TpmChallengeKeyResult& result);
void RegisterKey();
void OnRegisterKeyDone(const attestation::TpmChallengeKeyResult& result);
void MarkKey();
void MarkKeyAsCorporate();
void OnAllowKeyForUsageDone(chromeos::platform_keys::Status status);
void OnMarkKeyDone(chromeos::platform_keys::Status status);
void SignCsr();
void OnSignCsrDone(std::vector<uint8_t> signature,
chromeos::platform_keys::Status status);
void FinishCsr();
void OnFinishCsrDone(policy::DeviceManagementStatus status,
std::optional<CertProvisioningResponseErrorType> error,
std::optional<int64_t> try_later);
void DownloadCert();
void OnDownloadCertDone(
policy::DeviceManagementStatus status,
std::optional<CertProvisioningResponseErrorType> error,
std::optional<int64_t> try_later,
const std::string& pem_encoded_certificate);
void ImportCert(const std::string& pem_encoded_certificate);
void OnImportCertDone(chromeos::platform_keys::Status status);
// Schedule the next step after the `delay`. If `try_provisioning_on_timeout`
// is true, the worker will automatically try contacting the server-side after
// it doesn't receive an invalidation for long enough. If it's false, it will
// require an invalidation to continue.
void ScheduleNextStep(base::TimeDelta delay,
bool try_provisioning_on_timeout);
void CancelScheduledTasks();
enum class ContinueReason {
kTimeout,
kSubscribedToInvalidation,
kInvalidationReceived
};
void OnShouldContinue(ContinueReason reason);
// Registers for |invalidation_topic_| that allows to receive notification
// when server side is ready to continue provisioning process.
void RegisterForInvalidationTopic();
// Should be called only when provisioning process is finished (successfully
// or not). Should not be called when the worker is destroyed, but will be
// deserialized back later.
void UnregisterFromInvalidationTopic();
// Callback from invalidations system.
void OnInvalidationEvent(InvalidationEvent invalidation_event);
// If it is called with kSucceed or kFailed, it will call the |callback_|. The
// worker can be destroyed in callback and should not use any member fields
// after that.
void UpdateState(const base::Location& from_here,
CertProvisioningWorkerState state);
// Serializes the worker or deletes serialized state according to the current
// state. Some states are considered unrecoverable, some can be reached again
// from previous ones.
void HandleSerialization();
// Handles recreation of some internal objects after deserialization. Intended
// to be called from CertProvisioningDeserializer.
void InitAfterDeserialization();
void CleanUpAndRunCallback();
void OnDeleteVaKeyDone(bool delete_result);
void OnRemoveKeyDone(chromeos::platform_keys::Status status);
void OnCleanUpDone();
CertProvisioningClient::ProvisioningProcess GetProvisioningProcessForClient();
base::TimeDelta GetTryLaterDelay(
DeviceManagementServerRequestType request_type);
// Returns true if there are no errors and the flow can be continued.
// |request_type| is the type of the request to which the DM server has
// responded with the given |status|.
bool ProcessResponseErrors(
DeviceManagementServerRequestType request_type,
policy::DeviceManagementStatus status,
std::optional<CertProvisioningResponseErrorType> error,
std::optional<int64_t> try_later);
// A convenience method to generate a string that contains some additional
// info and should be included in all logs.
std::string GetLogInfoBlock();
std::string process_id_;
CertScope cert_scope_ = CertScope::kUser;
raw_ptr<Profile> profile_ = nullptr;
raw_ptr<PrefService> pref_service_ = nullptr;
CertProfile cert_profile_;
base::RepeatingClosure state_change_callback_;
CertProvisioningWorkerCallback result_callback_;
// This field should be updated only via |UpdateState| function. It will
// trigger update of the serialized data.
CertProvisioningWorkerState state_ = CertProvisioningWorkerState::kInitState;
// State that was before the current one. Useful for debugging and cleaning
// on failure.
CertProvisioningWorkerState prev_state_ = state_;
// Time when this worker has been last updated. An update is when the worker
// advances to the next state or for states that wait for a backend-side
// condition (e.g CertProvisioningWorkerState:kFinishCsrResponseReceived):
// when it successfully checked with the backend that the condition is not
// fulfilled yet.
base::Time last_update_time_;
// Consequently, it is not updated if waiting for a backend-side condition,
// but communication with the backend is not possible (e.g. due to server
// errors or network connectivity issues).
// The last error received in communicating to the backend server.
std::optional<BackendServerError> last_backend_server_error_;
bool is_waiting_ = false;
bool is_schedueled_for_reset_ = false;
// Used for an UMA metric to track situation when the worker did not receive
// an invalidation for a completed server side task.
bool is_continued_without_invalidation_for_uma_ = false;
// Calculates retry timeout for network related failures.
net::BackoffEntry request_backoff_;
// Calculates retry timeout for DownloadCert "try later" cases.
net::BackoffEntry download_cert_request_backoff_;
// Public key - represented as DER-encoded X.509 SubjectPublicKeyInfo
// (binary).
std::vector<uint8_t> public_key_;
std::string invalidation_topic_;
// These variables may not contain valid values after
// kFinishCsrResponseReceived state because of deserialization (and they don't
// need to).
std::string csr_;
std::string va_challenge_;
std::string va_challenge_response_;
std::optional<chromeos::platform_keys::HashAlgorithm> hashing_algorithm_;
std::string signature_;
// Holds a message describing the reason for failure when the worker fails.
// This may not contain PII or stable identifiers as it will be logged.
// If the worker did not fail, this message is empty.
std::string failure_message_;
// Optionally holds a message like `failure_message_` but containing PII or
// stable identifiers for display on the UI.
// If the worker did not fail, this is absent.
// If the worker did fail and this is absent, the UI should display
// failure_message_.
std::optional<std::string> failure_message_ui_;
// IMPORTANT:
// Increment this when you add/change any member in
// CertProvisioningWorkerStatic that affects serialization (and update all
// functions that fail to compile because of it).
static constexpr int kVersion = 2;
// Unowned PlatformKeysService. Note that the CertProvisioningWorker does not
// observe the PlatformKeysService for shutdown events. Instead, it relies on
// the CertProvisioningScheduler to destroy all CertProvisioningWorker
// instances when the corresponding PlatformKeysService is shutting down.
raw_ptr<platform_keys::PlatformKeysService> platform_keys_service_ = nullptr;
std::unique_ptr<attestation::TpmChallengeKeySubtle>
tpm_challenge_key_subtle_impl_;
const raw_ptr<CertProvisioningClient> cert_provisioning_client_;
std::unique_ptr<CertProvisioningInvalidator> invalidator_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CertProvisioningWorkerStatic> weak_factory_{this};
};
} // namespace ash::cert_provisioning
#endif // CHROME_BROWSER_ASH_CERT_PROVISIONING_CERT_PROVISIONING_WORKER_STATIC_H_
|