// 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/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/timer/timer.h"
#include "chromeos/attestation/attestation_flow_utils.h"
#include "chromeos/cryptohome/cryptohome_parameters.h"
#include "chromeos/dbus/attestation/attestation_client.h"
#include "chromeos/dbus/attestation/interface.pb.h"
#include "components/account_id/account_id.h"

namespace chromeos {
namespace attestation {

namespace {

base::Optional<::attestation::CertificateProfile> ProfileToAttestationProtoEnum(
    AttestationCertificateProfile p) {
  switch (p) {
    case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
      return ::attestation::CertificateProfile::ENTERPRISE_MACHINE_CERTIFICATE;
    case PROFILE_ENTERPRISE_USER_CERTIFICATE:
      return ::attestation::CertificateProfile::ENTERPRISE_USER_CERTIFICATE;
    case PROFILE_CONTENT_PROTECTION_CERTIFICATE:
      return ::attestation::CertificateProfile::CONTENT_PROTECTION_CERTIFICATE;
    case PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE:
      return ::attestation::CertificateProfile::
          ENTERPRISE_ENROLLMENT_CERTIFICATE;
  }
  return {};
}

::attestation::ACAType ToAcaType(PrivacyCAType type) {
  switch (type) {
    case DEFAULT_PCA:
      return ::attestation::DEFAULT_ACA;
    case TEST_PCA:
      return ::attestation::TEST_ACA;
  }
  LOG(DFATAL) << "Unknown type to convert: " << type;
  return ::attestation::DEFAULT_ACA;
}

// 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;

}  // 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;
}

AttestationFlow::AttestationFlow(std::unique_ptr<ServerProxy> server_proxy,
                                 ::attestation::KeyType crypto_key_type)
    : attestation_client_(AttestationClient::Get()),
      server_proxy_(std::move(server_proxy)),
      crypto_key_type_(crypto_key_type),
      ready_timeout_(base::TimeDelta::FromSeconds(kReadyTimeoutInSeconds)),
      retry_delay_(
          base::TimeDelta::FromMilliseconds(kRetryDelayInMilliseconds)) {}

AttestationFlow::AttestationFlow(std::unique_ptr<ServerProxy> server_proxy)
    : AttestationFlow(std::move(server_proxy), ::attestation::KEY_TYPE_RSA) {}

AttestationFlow::~AttestationFlow() = default;

void AttestationFlow::GetCertificate(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    bool force_new_key,
    const std::string& key_name,
    CertificateCallback callback) {
  std::string attestation_key_name =
      !key_name.empty()
          ? key_name
          : GetKeyNameForProfile(certificate_profile, request_origin);

  base::OnceCallback<void(bool)> start_certificate_request = base::BindOnce(
      &AttestationFlow::StartCertificateRequest, weak_factory_.GetWeakPtr(),
      certificate_profile, account_id, request_origin, force_new_key,
      attestation_key_name, std::move(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.
  attestation_client_->GetStatus(
      ::attestation::GetStatusRequest(),
      base::BindOnce(&AttestationFlow::OnEnrollmentCheckComplete,
                     weak_factory_.GetWeakPtr(),
                     std::move(start_certificate_request)));
}

void AttestationFlow::OnEnrollmentCheckComplete(
    base::OnceCallback<void(bool)> callback,
    const ::attestation::GetStatusReply& reply) {
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    LOG(ERROR) << "Attestation: Failed to check enrollment state. Status: "
               << reply.status();
    std::move(callback).Run(false);
    return;
  }

  if (reply.enrolled()) {
    std::move(callback).Run(true);
    return;
  }

  // The device is not enrolled; check if it's enrollment prepared.
  base::TimeTicks end_time = base::TimeTicks::Now() + ready_timeout_;
  WaitForAttestationPrepared(end_time, std::move(callback));
}

void AttestationFlow::WaitForAttestationPrepared(
    base::TimeTicks end_time,
    base::OnceCallback<void(bool)> callback) {
  ::attestation::GetEnrollmentPreparationsRequest request;
  attestation_client_->GetEnrollmentPreparations(
      request, base::BindOnce(&AttestationFlow::OnPreparedCheckComplete,
                              weak_factory_.GetWeakPtr(), end_time,
                              std::move(callback)));
}

void AttestationFlow::OnPreparedCheckComplete(
    base::TimeTicks end_time,
    base::OnceCallback<void(bool)> callback,
    const ::attestation::GetEnrollmentPreparationsReply& reply) {
  if (AttestationClient::IsAttestationPrepared(reply)) {
    // Get the attestation service to create a Privacy CA enrollment request.
    ::attestation::CreateEnrollRequestRequest request;
    request.set_aca_type(ToAcaType(server_proxy_->GetType()));
    AttestationClient::Get()->CreateEnrollRequest(
        request,
        base::BindOnce(&AttestationFlow::SendEnrollRequestToPCA,
                       weak_factory_.GetWeakPtr(), std::move(callback)));
    return;
  }

  if (base::TimeTicks::Now() < end_time) {
    LOG(WARNING) << "Attestation: Not prepared yet."
                 << " Retrying in " << retry_delay_ << ".";
    base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&AttestationFlow::WaitForAttestationPrepared,
                       weak_factory_.GetWeakPtr(), end_time,
                       std::move(callback)),
        retry_delay_);
    return;
  }

  LOG(ERROR) << "Attestation: Not prepared. Giving up on retrying.";
  std::move(callback).Run(false);
}

void AttestationFlow::SendEnrollRequestToPCA(
    base::OnceCallback<void(bool)> callback,
    const ::attestation::CreateEnrollRequestReply& reply) {
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    LOG(ERROR) << "Attestation: Failed to create enroll request; status: "
               << reply.status();
    std::move(callback).Run(false);
    return;
  }

  // Send the request to the Privacy CA.
  server_proxy_->SendEnrollRequest(
      reply.pca_request(),
      base::BindOnce(&AttestationFlow::SendEnrollResponseToDaemon,
                     weak_factory_.GetWeakPtr(), std::move(callback)));
}

void AttestationFlow::SendEnrollResponseToDaemon(
    base::OnceCallback<void(bool)> callback,
    bool success,
    const std::string& data) {
  if (!success) {
    LOG(ERROR) << "Attestation: Enroll request failed.";
    std::move(callback).Run(false);
    return;
  }

  // Forward the response to the attestation service to complete enrollment.
  ::attestation::FinishEnrollRequest request;
  request.set_pca_response(data);
  request.set_aca_type(ToAcaType(server_proxy_->GetType()));
  AttestationClient::Get()->FinishEnroll(
      request, base::BindOnce(&AttestationFlow::OnEnrollComplete,
                              weak_factory_.GetWeakPtr(), std::move(callback)));
}

void AttestationFlow::OnEnrollComplete(
    base::OnceCallback<void(bool)> callback,
    const ::attestation::FinishEnrollReply& reply) {
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    LOG(ERROR) << "Attestation: Failed to complete enrollment; status: "
               << reply.status();
    std::move(callback).Run(false);
    return;
  }

  std::move(callback).Run(true);
}

void AttestationFlow::StartCertificateRequest(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    bool generate_new_key,
    const std::string& key_name,
    CertificateCallback callback,
    bool enrolled) {
  if (!enrolled) {
    std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
    return;
  }

  AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile);
  if (generate_new_key) {
    // Get the attestation service to create a Privacy CA certificate request.
    const base::Optional<::attestation::CertificateProfile>
        attestation_profile =
            ProfileToAttestationProtoEnum(certificate_profile);
    if (!attestation_profile) {
      LOG(DFATAL) << "Attestation: Unrecognized profile type: "
                  << certificate_profile;
      return;
    }

    ::attestation::CreateCertificateRequestRequest request;
    if (key_type == KEY_USER) {
      request.set_username(cryptohome::Identification(account_id).id());
    }
    request.set_certificate_profile(*attestation_profile);
    request.set_request_origin(request_origin);
    request.set_key_type(crypto_key_type_);

    attestation_client_->CreateCertificateRequest(
        request, base::BindOnce(&AttestationFlow::SendCertificateRequestToPCA,
                                weak_factory_.GetWeakPtr(), key_type,
                                account_id, key_name, std::move(callback)));
    return;
  }

  ::attestation::GetKeyInfoRequest request;
  if (key_type == KEY_USER) {
    request.set_username(cryptohome::Identification(account_id).id());
  }
  request.set_key_label(key_name);
  attestation_client_->GetKeyInfo(
      request, base::BindOnce(&AttestationFlow::OnGetKeyInfoComplete,
                              weak_factory_.GetWeakPtr(), certificate_profile,
                              account_id, request_origin, key_name, key_type,
                              std::move(callback)));
}

void AttestationFlow::OnGetKeyInfoComplete(
    AttestationCertificateProfile certificate_profile,
    const AccountId& account_id,
    const std::string& request_origin,
    const std::string& key_name,
    AttestationKeyType key_type,
    CertificateCallback callback,
    const ::attestation::GetKeyInfoReply& reply) {
  // If the key already exists, return the existing certificate.
  if (reply.status() == ::attestation::STATUS_SUCCESS) {
    std::move(callback).Run(ATTESTATION_SUCCESS, reply.certificate());
    return;
  }

  // If the key does not exist, call this method back with |generate_new_key|
  // set to true.
  if (reply.status() == ::attestation::STATUS_INVALID_PARAMETER) {
    StartCertificateRequest(certificate_profile, account_id, request_origin,
                            /*generate_new_key=*/true, key_name,
                            std::move(callback), /*enrolled=*/true);
    return;
  }

  // Otherwise the key info query fails.
  LOG(ERROR) << "Attestation: Failed to check for existence of key; status: "
             << reply.status() << ".";
  std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
}

void AttestationFlow::SendCertificateRequestToPCA(
    AttestationKeyType key_type,
    const AccountId& account_id,
    const std::string& key_name,
    CertificateCallback callback,
    const ::attestation::CreateCertificateRequestReply& reply) {
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    LOG(ERROR) << "Attestation: Failed to create certificate request. Status: "
               << reply.status();
    std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
    return;
  }

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

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

  ::attestation::FinishCertificateRequestRequest request;
  if (key_type == KEY_USER) {
    request.set_username(cryptohome::Identification(account_id).id());
  }
  request.set_key_label(key_name);
  request.set_pca_response(data);
  AttestationClient::Get()->FinishCertificateRequest(
      request, base::BindOnce(&AttestationFlow::OnCertRequestFinished,
                              weak_factory_.GetWeakPtr(), std::move(callback)));
}

void AttestationFlow::OnCertRequestFinished(
    CertificateCallback callback,
    const ::attestation::FinishCertificateRequestReply& reply) {
  if (reply.status() == ::attestation::STATUS_SUCCESS) {
    std::move(callback).Run(ATTESTATION_SUCCESS, reply.certificate());
  } else {
    LOG(ERROR) << "Failed to finish certificate request; status: "
               << reply.status();
    std::move(callback).Run(ATTESTATION_SERVER_BAD_REQUEST_FAILURE,
                            /*pem_certificate_chain=*/"");
  }
}

ServerProxy::~ServerProxy() = default;

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

}  // namespace attestation
}  // namespace chromeos
