blob: c1d20cf6590d44da65c4dacb95967663acb74f48 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_WORKER_H_
#define CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_WORKER_H_
#include <memory>
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h"
#include "chrome/browser/chromeos/cert_provisioning/cert_provisioning_common.h"
#include "chrome/browser/chromeos/platform_keys/platform_keys_service.h"
#include "components/policy/core/common/cloud/cloud_policy_constants.h"
#include "net/base/backoff_entry.h"
namespace policy {
class CloudPolicyClient;
}
class Profile;
class PrefService;
namespace chromeos {
namespace cert_provisioning {
class CertProvisioningInvalidator;
using CertProvisioningWorkerCallback =
base::OnceCallback<void(const CertProfile& profile,
CertProvisioningWorkerState state)>;
class CertProvisioningWorker;
class CertProvisioningWorkerFactory {
public:
virtual ~CertProvisioningWorkerFactory() = default;
static CertProvisioningWorkerFactory* Get();
virtual std::unique_ptr<CertProvisioningWorker> Create(
CertScope cert_scope,
Profile* profile,
PrefService* pref_service,
const CertProfile& cert_profile,
policy::CloudPolicyClient* cloud_policy_client,
std::unique_ptr<CertProvisioningInvalidator> invalidator,
CertProvisioningWorkerCallback callback);
virtual std::unique_ptr<CertProvisioningWorker> Deserialize(
CertScope cert_scope,
Profile* profile,
PrefService* pref_service,
const base::Value& saved_worker,
policy::CloudPolicyClient* cloud_policy_client,
std::unique_ptr<CertProvisioningInvalidator> invalidator,
CertProvisioningWorkerCallback callback);
// Doesn't take ownership.
static void SetFactoryForTesting(CertProvisioningWorkerFactory* test_factory);
private:
static CertProvisioningWorkerFactory* test_factory_;
};
// This class is a part of certificate provisioning feature. It takes a
// certificate profile, generates a key pair, communicates with DM Server to
// create a CSR for it and request a certificate, and imports it.
class CertProvisioningWorker {
public:
CertProvisioningWorker() = default;
CertProvisioningWorker(const CertProvisioningWorker&) = delete;
CertProvisioningWorker& operator=(const CertProvisioningWorker&) = delete;
virtual ~CertProvisioningWorker() = default;
// Continue provisioning a certificate.
virtual void DoStep() = 0;
// Sets worker's state to one of final ones. That triggers corresponding
// clean ups (deletes serialized state, keys, and so on) and returns |state|
// via callback.
virtual void Stop(CertProvisioningWorkerState state) = 0;
// Returns true, if the worker is waiting for some future event. |DoStep| can
// be called to try continue right now.
virtual bool IsWaiting() const = 0;
// Returns CertProfile that this worker is working on.
virtual const CertProfile& GetCertProfile() const = 0;
// Returns public key or an empty string if the key is not created yet.
virtual const std::string& GetPublicKey() const = 0;
// Returns current state.
virtual CertProvisioningWorkerState GetState() const = 0;
// Returns state that was before the current one. Especially helpful on failed
// workers.
virtual CertProvisioningWorkerState GetPreviousState() const = 0;
};
class CertProvisioningWorkerImpl : public CertProvisioningWorker {
public:
CertProvisioningWorkerImpl(
CertScope cert_scope,
Profile* profile,
PrefService* pref_service,
const CertProfile& cert_profile,
policy::CloudPolicyClient* cloud_policy_client,
std::unique_ptr<CertProvisioningInvalidator> invalidator,
CertProvisioningWorkerCallback callback);
~CertProvisioningWorkerImpl() override;
// CertProvisioningWorker
void DoStep() override;
void Stop(CertProvisioningWorkerState state) override;
bool IsWaiting() const override;
const CertProfile& GetCertProfile() const override;
const std::string& GetPublicKey() const override;
CertProvisioningWorkerState GetState() const override;
CertProvisioningWorkerState GetPreviousState() const override;
private:
friend class CertProvisioningSerializer;
void GenerateKey();
void OnGenerateKeyDone(base::TimeTicks start_time,
const attestation::TpmChallengeKeyResult& result);
void StartCsr();
void OnStartCsrDone(policy::DeviceManagementStatus status,
base::Optional<CertProvisioningResponseErrorType> error,
base::Optional<int64_t> try_later,
const std::string& invalidation_topic,
const std::string& va_challenge,
enterprise_management::HashingAlgorithm hashing_algorithm,
const std::string& data_to_sign);
void BuildVaChallengeResponse();
void OnBuildVaChallengeResponseDone(
base::TimeTicks start_time,
const attestation::TpmChallengeKeyResult& result);
void RegisterKey();
void OnRegisterKeyDone(const attestation::TpmChallengeKeyResult& result);
void MarkKey();
void OnMarkKeyDone(const std::string& error_message);
void SignCsr();
void OnSignCsrDone(base::TimeTicks start_time,
const std::string& signature,
const std::string& error_message);
void FinishCsr();
void OnFinishCsrDone(policy::DeviceManagementStatus status,
base::Optional<CertProvisioningResponseErrorType> error,
base::Optional<int64_t> try_later);
void DownloadCert();
void OnDownloadCertDone(
policy::DeviceManagementStatus status,
base::Optional<CertProvisioningResponseErrorType> error,
base::Optional<int64_t> try_later,
const std::string& pem_encoded_certificate);
void ImportCert(const std::string& pem_encoded_certificate);
void OnImportCertDone(const std::string& error_message);
void ScheduleNextStep(base::TimeDelta delay);
void CancelScheduledTasks();
enum class ContinueReason { kTimeout, kInvalidation };
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();
// 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(CertProvisioningWorkerState state);
// Serializes the worker or deletes serialized state accroding 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(base::Optional<bool> delete_result);
void OnRemoveKeyDone(const std::string& error_message);
void OnCleanUpDone();
// Returns true if there are no errors and the flow can be continued.
bool ProcessResponseErrors(
policy::DeviceManagementStatus status,
base::Optional<CertProvisioningResponseErrorType> error,
base::Optional<int64_t> try_later);
CertScope cert_scope_ = CertScope::kUser;
Profile* profile_ = nullptr;
PrefService* pref_service_ = nullptr;
CertProfile cert_profile_;
CertProvisioningWorkerCallback 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_;
bool is_waiting_ = 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_;
std::string 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_;
base::Optional<platform_keys::HashAlgorithm> hashing_algorithm_;
std::string signature_;
// IMPORTANT:
// Increment this when you add/change any member in CertProvisioningWorkerImpl
// that affects serialization (and update all functions that fail to compile
// because of it).
static constexpr int kVersion = 1;
platform_keys::PlatformKeysService* platform_keys_service_ = nullptr;
std::unique_ptr<attestation::TpmChallengeKeySubtle>
tpm_challenge_key_subtle_impl_;
policy::CloudPolicyClient* cloud_policy_client_ = nullptr;
std::unique_ptr<CertProvisioningInvalidator> invalidator_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<CertProvisioningWorkerImpl> weak_factory_{this};
};
} // namespace cert_provisioning
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_CERT_PROVISIONING_CERT_PROVISIONING_WORKER_H_