// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Library that provides certificate provisioning/signing interface.

#include <string>

#include <base/check.h>

// This group goes first so the next group can see the needed definitions.
#include <attestation/proto_bindings/interface.pb.h>

#include <attestation-client/attestation/dbus-proxies.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/time/time.h>

#include "cert/cert_provision.pb.h"
#include "cryptohome/cert/cert_provision_keystore.h"
#include "cryptohome/cert/cert_provision_util.h"
#include "cryptohome/cert_provision.h"

namespace {

// Number of steps for different provision stages.
constexpr int kInitSteps = 1;
constexpr int kGetCertSteps = 3;
constexpr int kRegisterSteps = 3;
constexpr int kNoEnrollSteps = kInitSteps + kGetCertSteps + kRegisterSteps;
constexpr int kEnrollSteps = 4;
constexpr int kMaxSteps = kNoEnrollSteps + kEnrollSteps;

constexpr base::TimeDelta kGetCertificateTimeout =
    base::TimeDelta::FromSeconds(80);
constexpr base::TimeDelta kEnrollTimeout = base::TimeDelta::FromSeconds(50);

const char kEndCertificate[] = "-----END CERTIFICATE-----";

cert_provision::Status ReportAndReturn(cert_provision::Status status,
                                       const std::string& message) {
  LOG(ERROR) << message;
  return status;
}

cert_provision::Status ReportAndReturn(const cert_provision::OpResult& result) {
  return ReportAndReturn(result.status, result.message);
}

}  // namespace

namespace cert_provision {

namespace {

::attestation::CertificateProfile ToAttestationCertProfile(
    CertificateProfile p) {
  // Enumerate all the valid conversion for better error-proof during compile
  // time.
  switch (p) {
    case ENTERPRISE_MACHINE_CERTIFICATE:
    case ENTERPRISE_USER_CERTIFICATE:
    case CONTENT_PROTECTION_CERTIFICATE:
    case CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID:
    case CAST_CERTIFICATE:
    case GFSC_CERTIFICATE:
    case JETSTREAM_CERTIFICATE:
    case ENTERPRISE_ENROLLMENT_CERTIFICATE:
    case XTS_CERTIFICATE:
    case ENTERPRISE_VTPM_EK_CERTIFICATE:
    case SOFT_BIND_CERTIFICATE:
      return static_cast<::attestation::CertificateProfile>(p);
  }
  LOG(DFATAL) << "Unknown value of profile: " << p;
  return ::attestation::ENTERPRISE_MACHINE_CERTIFICATE;
}

::attestation::ACAType ToAttestationAcaType(PCAType pca_type) {
  switch (pca_type) {
    case kDefaultPCA:
      return ::attestation::DEFAULT_ACA;
    case kTestPCA:
      return ::attestation::TEST_ACA;
  }
  LOG(DFATAL) << "Unknown value of pca type: " << pca_type;
  return ::attestation::DEFAULT_ACA;
}

}  // namespace

Status ProvisionCertificate(PCAType pca_type,
                            const std::string& label,
                            CertificateProfile cert_profile,
                            const ProgressCallback& progress_callback) {
  return ProvisionCertificate(pca_type, /*pca_url=*/std::string(), label,
                              cert_profile, progress_callback);
}

Status ProvisionCertificate(PCAType pca_type,
                            const std::string& pca_url,
                            const std::string& label,
                            CertificateProfile cert_profile,
                            const ProgressCallback& progress_callback) {
  DCHECK(pca_url.empty()) << "The arbitrary pca server URL is not supported.";

  ProgressReporter reporter(progress_callback, kMaxSteps);
  auto proxy = AttestationProxyFactory::Create();
  // By design, the factory must return a valid object.
  CHECK(proxy);

  reporter.Step("Checking if ready for enrollment");
  ::attestation::GetStatusReply get_status_reply;
  brillo::ErrorPtr error;
  if (!proxy->GetStatus(::attestation::GetStatusRequest(), &get_status_reply,
                        &error)) {
    return reporter.ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (get_status_reply.status() != ::attestation::STATUS_SUCCESS) {
    return reporter.ReportAndReturn(Status::AttestationError,
                                    "Failed to get attestation status.");
  }
  if (!get_status_reply.prepared_for_enrollment()) {
    return reporter.ReportAndReturn(Status::NotPrepared,
                                    "Not ready for enrollment.");
  }

  // The attestation is confirmed to be attestation prepared; get certificate.
  reporter.Step("Getting certificate");
  ::attestation::GetCertificateRequest request;
  request.set_aca_type(ToAttestationAcaType(pca_type));
  request.set_username("");
  request.set_key_label(label);
  request.set_forced(true);
  request.set_certificate_profile(ToAttestationCertProfile(cert_profile));
  request.set_request_origin("");
  request.set_shall_trigger_enrollment(true);

  ::attestation::GetCertificateReply reply;
  if (!proxy->GetCertificate(request, &reply, &error,
                             kGetCertificateTimeout.InMilliseconds())) {
    return reporter.ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    return reporter.ReportAndReturn(Status::AttestationError,
                                    "Failed to get cert.");
  }

  reporter.Step("Registering new keys");
  ::attestation::RegisterKeyWithChapsTokenRequest register_request;
  register_request.set_username("");
  register_request.set_key_label(label);
  ::attestation::RegisterKeyWithChapsTokenReply register_reply;
  if (!proxy->RegisterKeyWithChapsToken(register_request, &register_reply,
                                        &error)) {
    return reporter.ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (register_reply.status() != ::attestation::STATUS_SUCCESS) {
    return reporter.ReportAndReturn(Status::AttestationError,
                                    "Failed to register key.");
  }

  reporter.Step("Updating provision status");
  auto key_store = KeyStore::Create();
  OpResult result = key_store->Init();
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  ProvisionStatus provision_status;
  result = key_store->ReadProvisionStatus(label, &provision_status);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  std::string old_id;
  if (provision_status.provisioned()) {
    old_id = provision_status.key_id();
  }
  VLOG(1) << "Old key id " << base::HexEncode(old_id.data(), old_id.size());

  const std::string key_id = GetKeyID(brillo::SecureBlob(reply.public_key()));

  provision_status.set_provisioned(true);
  provision_status.set_key_id(key_id);
  provision_status.set_certificate_chain(reply.certificate());
  result = key_store->WriteProvisionStatus(label, provision_status);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  reporter.Step("Deleting old keys");
  if (!old_id.empty() && (key_id != old_id) &&
      !(result = key_store->DeleteKeys(old_id, label))) {
    return reporter.ReportAndReturn(result);
  }

  reporter.Done();
  return Status::Success;
}

Status ForceEnroll(PCAType pca_type,
                   const ProgressCallback& progress_callback) {
  return ForceEnroll(pca_type, /*pca_url=*/std::string(), progress_callback);
}

Status ForceEnroll(PCAType pca_type,
                   const std::string& pca_url,
                   const ProgressCallback& progress_callback) {
  DCHECK(pca_url.empty()) << "The arbitrary pca server URL is not supported.";

  ProgressReporter reporter(progress_callback, kEnrollSteps);
  auto proxy = AttestationProxyFactory::Create();
  // By design, the factory must return a valid object.
  CHECK(proxy);

  reporter.Step("Checking if ready for enrollment");
  ::attestation::GetStatusReply get_status_reply;
  brillo::ErrorPtr error;
  if (!proxy->GetStatus(::attestation::GetStatusRequest(), &get_status_reply,
                        &error)) {
    return reporter.ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (get_status_reply.status() != ::attestation::STATUS_SUCCESS) {
    return reporter.ReportAndReturn(Status::AttestationError,
                                    "Failed to get attestation status.");
  }
  if (!get_status_reply.prepared_for_enrollment()) {
    return reporter.ReportAndReturn(Status::NotPrepared,
                                    "Not ready for enrollment.");
  }

  // The attestation is confirmed to be attestation prepared; (re-)enroll the
  // device.
  reporter.Step("Enrolling");
  ::attestation::EnrollRequest request;
  request.set_aca_type(ToAttestationAcaType(pca_type));
  request.set_forced(true);
  ::attestation::EnrollReply reply;

  if (!proxy->Enroll(request, &reply, &error,
                     kEnrollTimeout.InMilliseconds())) {
    return reporter.ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    return reporter.ReportAndReturn(Status::AttestationError,
                                    "Failed to enroll.");
  }

  reporter.Done();
  return Status::Success;
}

Status GetCertificate(const std::string& label,
                      bool include_intermediate,
                      std::string* cert) {
  auto key_store = KeyStore::Create();
  ProvisionStatus provision_status;

  OpResult result = key_store->Init();
  if (!result) {
    return ReportAndReturn(result);
  }
  result = key_store->ReadProvisionStatus(label, &provision_status);
  if (!result) {
    return ReportAndReturn(result);
  }
  if (!provision_status.provisioned()) {
    return ReportAndReturn(Status::NotProvisioned, "Not provisioned");
  }

  size_t pos;
  if (include_intermediate) {
    pos = std::string::npos;
  } else {
    pos = provision_status.certificate_chain().find(kEndCertificate);
    if (pos != std::string::npos) {
      pos += base::size(kEndCertificate) - 1;
    }
  }
  cert->assign(provision_status.certificate_chain().substr(0, pos));

  return Status::Success;
}

Status Sign(const std::string& label,
            SignMechanism mechanism,
            const std::string& data,
            std::string* signature) {
  auto key_store = KeyStore::Create();
  ProvisionStatus provision_status;

  OpResult result = key_store->Init();
  if (!result) {
    return ReportAndReturn(result);
  }
  result = key_store->ReadProvisionStatus(label, &provision_status);
  if (!result) {
    return ReportAndReturn(result);
  }
  if (!provision_status.provisioned()) {
    return ReportAndReturn(Status::NotProvisioned, "Not provisioned");
  }
  VLOG(1) << "Signing with key id " << provision_status.key_id();
  result = key_store->Sign(provision_status.key_id(), label, mechanism, data,
                           signature);
  if (!result) {
    return ReportAndReturn(result);
  }
  return Status::Success;
}

Status GetEndorsementPublicKey(std::string* ek_public_key) {
  auto proxy = AttestationProxyFactory::Create();
  // By design, the factory must return a valid object.
  CHECK(proxy);
  ::attestation::GetEndorsementInfoReply reply;
  brillo::ErrorPtr error;
  if (!proxy->GetEndorsementInfo(attestation::GetEndorsementInfoRequest(),
                                 &reply, &error)) {
    return ReportAndReturn(Status::DBusError, error->GetMessage());
  }
  if (reply.status() != ::attestation::STATUS_SUCCESS) {
    return ReportAndReturn(Status::AttestationError,
                           "Failed to get endorsement info");
  }
  *ek_public_key = reply.ek_public_key();
  return Status::Success;
}

}  // namespace cert_provision
