// Copyright (c) 2012 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.

#include "chromeos/attestation/attestation_flow.h"

#include <algorithm>
#include <utility>

#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop_current.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "chromeos/cryptohome/async_method_caller.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/cryptohome/cryptohome_client.h"
#include "components/account_id/account_id.h"

namespace chromeos {
namespace attestation {

namespace {

// A reasonable timeout that gives enough time for attestation to be ready,
// yet does not make the caller wait too long.
constexpr uint16_t kReadyTimeoutInSeconds = 60;

// Delay before checking again whether the TPM has been prepared for
// attestation.
constexpr uint16_t kRetryDelayInMilliseconds = 300;

// Redirects to one of three callbacks based on a boolean value and dbus call
// status.
//
// Parameters
//   on_true - Called when status=success and value=true.
//   on_false - Called when status=success and value=false.
//   on_fail - Called when status=failure.
//   result - The result returned by the D-Bus operation.
void DBusBoolRedirectCallback(const base::Closure& on_true,
                              const base::Closure& on_false,
                              const base::Closure& on_fail,
                              const std::string& on_fail_message,
                              base::Optional<bool> result) {
  if (!result.has_value()) {
    LOG(ERROR) << "Attestation: Failed to " << on_fail_message << ".";
    if (!on_fail.is_null())
      on_fail.Run();
    return;
  }
  const base::Closure& task = result.value() ? on_true : on_false;
  if (!task.is_null())
    task.Run();
}

void DBusCertificateMethodCallback(
    const AttestationFlow::CertificateCallback& callback,
    base::Optional<CryptohomeClient::TpmAttestationDataResult> result) {
  if (!result.has_value()) {
    LOG(ERROR) << "Attestation: DBus data operation failed.";
    if (!callback.is_null())
      callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
    return;
  }
  if (!callback.is_null()) {
    callback.Run(
        result->success ? ATTESTATION_SUCCESS : ATTESTATION_UNSPECIFIED_FAILURE,
        result->data);
  }
}

}  // namespace

AttestationKeyType AttestationFlow::GetKeyTypeForProfile(
    AttestationCertificateProfile certificate_profile) {
  switch (certificate_profile) {
    case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
    case PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE:
      return KEY_DEVICE;
    case PROFILE_ENTERPRISE_USER_CERTIFICATE:
    case PROFILE_CONTENT_PROTECTION_CERTIFICATE:
      return KEY_USER;
  }
  NOTREACHED();
  return KEY_USER;
}

std::string AttestationFlow::GetKeyNameForProfile(
    AttestationCertificateProfile certificate_profile,
    const std::string& request_origin) {
  switch (certificate_profile) {
    case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
      return kEnterpriseMachineKey;
    case PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE:
      return kEnterpriseEnrollmentKey;
    case PROFILE_ENTERPRISE_USER_CERTIFICATE:
      return kEnterpriseUserKey;
    case PROFILE_CONTENT_PROTECTION_CERTIFICATE:
      return std::string(kContentProtectionKeyPrefix) + request_origin;
  }
  NOTREACHED();
  return "";
}

AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
                                 CryptohomeClient* cryptohome_client,
                                 std::unique_ptr<ServerProxy> server_proxy)
    : async_caller_(async_caller),
      cryptohome_client_(cryptohome_client),
      server_proxy_(std::move(server_proxy)),
      ready_timeout_(base::TimeDelta::FromSeconds(kReadyTimeoutInSeconds)),
      retry_delay_(
          base::TimeDelta::FromMilliseconds(kRetryDelayInMilliseconds)),
      weak_factory_(this) {}

AttestationFlow::~AttestationFlow() = default;

void AttestationFlow::GetCertificate(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    bool force_new_key,
    const CertificateCallback& callback) {
  // If this device has not enrolled with the Privacy CA, we need to do that
  // first.  Once enrolled we can proceed with the certificate request.
  const base::Closure do_cert_request = base::Bind(
      &AttestationFlow::StartCertificateRequest, weak_factory_.GetWeakPtr(),
      certificate_profile, account_id, request_origin, force_new_key, callback);
  const base::RepeatingClosure on_failure =
      base::BindRepeating(callback, ATTESTATION_UNSPECIFIED_FAILURE, "");
  const base::Closure initiate_enroll = base::Bind(
      &AttestationFlow::WaitForAttestationReadyAndStartEnroll,
      weak_factory_.GetWeakPtr(), base::TimeTicks::Now() + ready_timeout_,
      on_failure,
      base::Bind(&AttestationFlow::StartEnroll, weak_factory_.GetWeakPtr(),
                 on_failure, do_cert_request));
  cryptohome_client_->TpmAttestationIsEnrolled(base::BindOnce(
      &DBusBoolRedirectCallback,
      do_cert_request,  // If enrolled, proceed with cert request.
      initiate_enroll,  // If not enrolled, initiate enrollment.
      on_failure, "check enrollment state"));
}

void AttestationFlow::WaitForAttestationReadyAndStartEnroll(
    base::TimeTicks end_time,
    const base::Closure& on_failure,
    const base::Closure& next_task) {
  const base::Closure retry_initiate_enroll =
      base::Bind(&AttestationFlow::CheckAttestationReadyAndReschedule,
                 weak_factory_.GetWeakPtr(), end_time, on_failure, next_task);
  cryptohome_client_->TpmAttestationIsPrepared(base::BindOnce(
      &DBusBoolRedirectCallback, next_task, retry_initiate_enroll, on_failure,
      "check for attestation readiness"));
}

void AttestationFlow::StartEnroll(const base::Closure& on_failure,
                                  const base::Closure& next_task) {
  // Get the attestation service to create a Privacy CA enrollment request.
  async_caller_->AsyncTpmAttestationCreateEnrollRequest(
      server_proxy_->GetType(),
      base::Bind(&AttestationFlow::SendEnrollRequestToPCA,
                 weak_factory_.GetWeakPtr(), on_failure, next_task));
}

void AttestationFlow::SendEnrollRequestToPCA(const base::Closure& on_failure,
                                             const base::Closure& next_task,
                                             bool success,
                                             const std::string& data) {
  if (!success) {
    LOG(ERROR) << "Attestation: Failed to create enroll request.";
    if (!on_failure.is_null())
      on_failure.Run();
    return;
  }

  // Send the request to the Privacy CA.
  server_proxy_->SendEnrollRequest(
      data, base::Bind(&AttestationFlow::SendEnrollResponseToDaemon,
                       weak_factory_.GetWeakPtr(), on_failure, next_task));
}

void AttestationFlow::SendEnrollResponseToDaemon(
    const base::Closure& on_failure,
    const base::Closure& next_task,
    bool success,
    const std::string& data) {
  if (!success) {
    LOG(ERROR) << "Attestation: Enroll request failed.";
    if (!on_failure.is_null())
      on_failure.Run();
    return;
  }

  // Forward the response to the attestation service to complete enrollment.
  async_caller_->AsyncTpmAttestationEnroll(
      server_proxy_->GetType(), data,
      base::Bind(&AttestationFlow::OnEnrollComplete, weak_factory_.GetWeakPtr(),
                 on_failure, next_task));
}

void AttestationFlow::OnEnrollComplete(const base::Closure& on_failure,
                                       const base::Closure& next_task,
                                       bool success,
                                       cryptohome::MountError /*not_used*/) {
  if (!success) {
    LOG(ERROR) << "Attestation: Failed to complete enrollment.";
    if (!on_failure.is_null())
      on_failure.Run();
    return;
  }

  // Enrollment has successfully completed, we can move on to whatever is next.
  if (!next_task.is_null())
    next_task.Run();
}

void AttestationFlow::StartCertificateRequest(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    bool generate_new_key,
    const CertificateCallback& callback) {
  AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile);
  std::string key_name =
      GetKeyNameForProfile(certificate_profile, request_origin);
  if (generate_new_key) {
    // Get the attestation service to create a Privacy CA certificate request.
    async_caller_->AsyncTpmAttestationCreateCertRequest(
        server_proxy_->GetType(), certificate_profile,
        cryptohome::Identification(account_id), request_origin,
        base::Bind(&AttestationFlow::SendCertificateRequestToPCA,
                   weak_factory_.GetWeakPtr(), key_type, account_id, key_name,
                   callback));
  } else {
    // If the key already exists, query the existing certificate.
    const base::Closure on_key_exists = base::Bind(
        &AttestationFlow::GetExistingCertificate, weak_factory_.GetWeakPtr(),
        key_type, account_id, key_name, callback);
    // If the key does not exist, call this method back with |generate_new_key|
    // set to true.
    const base::Closure on_key_not_exists = base::Bind(
        &AttestationFlow::StartCertificateRequest, weak_factory_.GetWeakPtr(),
        certificate_profile, account_id, request_origin, true, callback);
    cryptohome_client_->TpmAttestationDoesKeyExist(
        key_type, cryptohome::CreateAccountIdentifierFromAccountId(account_id),
        key_name,
        base::BindOnce(
            &DBusBoolRedirectCallback, on_key_exists, on_key_not_exists,
            base::BindRepeating(callback, ATTESTATION_UNSPECIFIED_FAILURE, ""),
            "check for existence of attestation key"));
  }
}

void AttestationFlow::SendCertificateRequestToPCA(
    AttestationKeyType key_type,
    const AccountId& account_id,
    const std::string& key_name,
    const CertificateCallback& callback,
    bool success,
    const std::string& data) {
  if (!success) {
    LOG(ERROR) << "Attestation: Failed to create certificate request.";
    if (!callback.is_null())
      callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
    return;
  }

  // Send the request to the Privacy CA.
  server_proxy_->SendCertificateRequest(
      data, base::Bind(&AttestationFlow::SendCertificateResponseToDaemon,
                       weak_factory_.GetWeakPtr(), key_type, account_id,
                       key_name, callback));
}

void AttestationFlow::SendCertificateResponseToDaemon(
    AttestationKeyType key_type,
    const AccountId& account_id,
    const std::string& key_name,
    const CertificateCallback& callback,
    bool success,
    const std::string& data) {
  if (!success) {
    LOG(ERROR) << "Attestation: Certificate request failed.";
    if (!callback.is_null())
      callback.Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
    return;
  }

  // Forward the response to the attestation service to complete the operation.
  async_caller_->AsyncTpmAttestationFinishCertRequest(
      data, key_type, cryptohome::Identification(account_id), key_name,
      base::BindRepeating(&AttestationFlow::OnCertRequestFinished,
                          weak_factory_.GetWeakPtr(), callback));
}

void AttestationFlow::OnCertRequestFinished(const CertificateCallback& callback,
                                            bool success,
                                            const std::string& data) {
  if (success)
    callback.Run(ATTESTATION_SUCCESS, data);
  else
    callback.Run(ATTESTATION_SERVER_BAD_REQUEST_FAILURE, data);
}

void AttestationFlow::GetExistingCertificate(
    AttestationKeyType key_type,
    const AccountId& account_id,
    const std::string& key_name,
    const CertificateCallback& callback) {
  cryptohome_client_->TpmAttestationGetCertificate(
      key_type, cryptohome::CreateAccountIdentifierFromAccountId(account_id),
      key_name, base::BindOnce(&DBusCertificateMethodCallback, callback));
}

void AttestationFlow::CheckAttestationReadyAndReschedule(
    base::TimeTicks end_time,
    const base::Closure& on_failure,
    const base::Closure& next_task) {
  if (base::TimeTicks::Now() < end_time) {
    LOG(WARNING) << "Attestation: Not prepared yet."
                 << " Retrying in " << retry_delay_ << ".";
    base::MessageLoopCurrent::Get()->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&AttestationFlow::WaitForAttestationReadyAndStartEnroll,
                       weak_factory_.GetWeakPtr(), end_time, on_failure,
                       next_task),
        retry_delay_);
  } else {
    LOG(ERROR) << "Attestation: Not prepared. Giving up on retrying.";
    if (!on_failure.is_null())
      on_failure.Run();
  }
}

ServerProxy::~ServerProxy() = default;

PrivacyCAType ServerProxy::GetType() {
  return DEFAULT_PCA;
}

}  // namespace attestation
}  // namespace chromeos
