// 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 <base/logging.h>
#include <base/strings/string_number_conversions.h>

#include "cryptohome/cert_provision.h"
#include "cryptohome/cert_provision_cryptohome.h"
#include "cryptohome/cert_provision_keystore.h"
#include "cryptohome/cert_provision_pca.h"
#include "cryptohome/cert_provision_util.h"

#include "cert_provision.pb.h"  // NOLINT(build/include)

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;

const char kGetCertAction[] = "sign";
const char kEnrollAction[] = "enroll";

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

std::string GetDefaultPCAUrl(cert_provision::PCAType pca_type) {
  std::string url;
  switch (pca_type) {
    case cert_provision::PCAType::kDefaultPCA:
      url = "https://chromeos-ca.gstatic.com";
      break;
    case cert_provision::PCAType::kTestPCA:
      url = "https://asbestos-qa.corp.google.com";
      break;
    default:
      break;
  }
  return url;
}

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 {

Status ProvisionCertificate(PCAType pca_type,
                            const std::string& pca_url,
                            const std::string& label,
                            CertificateProfile cert_profile,
                            const ProgressCallback& progress_callback) {
  ProgressReporter reporter(progress_callback, kMaxSteps);
  std::string url(pca_url);
  if (url.empty()) {
    url = GetDefaultPCAUrl(pca_type);
    if (url.empty()) {
      return reporter.ReportAndReturn(Status::HttpError,
                                      "PCA url is not defined.");
    }
  }
  auto pca_proxy = PCAProxy::Create(url);
  auto c_proxy = CryptohomeProxy::Create();

  OpResult result = c_proxy->Init();
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  reporter.Step("Checking if enrolled");
  bool is_enrolled;
  result = c_proxy->CheckIfEnrolled(&is_enrolled);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  if (is_enrolled) {
    reporter.SetSteps(kNoEnrollSteps);
  } else {
    reporter.Step("Checking if ready for enrollment");
    bool is_prepared;
    result = c_proxy->CheckIfPrepared(&is_prepared);
    if (!result) {
      return reporter.ReportAndReturn(result);
    }
    if (!is_prepared) {
      return reporter.ReportAndReturn(Status::NotPrepared,
                                      "Not ready for enrollment.");
    }

    reporter.Step("Creating enroll request");
    brillo::SecureBlob request;
    result = c_proxy->CreateEnrollRequest(pca_type, &request);
    if (!result) {
      return reporter.ReportAndReturn(result);
    }
    reporter.Step("Sending enroll request");
    brillo::SecureBlob response;
    result = pca_proxy->MakeRequest(kEnrollAction, request, &response);
    if (!result) {
      return reporter.ReportAndReturn(result);
    }
    reporter.Step("Processing enroll response");
    result = c_proxy->ProcessEnrollResponse(pca_type, response);
    if (!result) {
      return reporter.ReportAndReturn(result);
    }
  }

  brillo::SecureBlob cert_chain;
  reporter.Step("Creating certificate request");
  brillo::SecureBlob request;
  result = c_proxy->CreateCertRequest(pca_type, cert_profile, &request);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }
  reporter.Step("Sending certificate request");
  brillo::SecureBlob response;
  result = pca_proxy->MakeRequest(kGetCertAction, request, &response);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }
  reporter.Step("Processing certificate response");
  result = c_proxy->ProcessCertResponse(label, response, &cert_chain);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  reporter.Step("Registering new keys");
  brillo::SecureBlob public_key;
  result = c_proxy->GetPublicKey(label, &public_key);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }
  std::string key_id = GetKeyID(public_key);
  if (key_id.empty()) {
    return reporter.ReportAndReturn(Status::KeyStoreError,
                                    "Failed to calculate key ID.");
  }
  VLOG(1) << "Obtained key id "
          << base::HexEncode(key_id.data(), key_id.size());

  result = c_proxy->Register(label);
  if (!result) {
    return reporter.ReportAndReturn(result);
  }

  reporter.Step("Updating provision status");
  auto key_store = KeyStore::Create();
  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());

  provision_status.set_provisioned(true);
  provision_status.set_key_id(key_id);
  provision_status.set_certificate_chain(cert_chain.to_string());
  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 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 += arraysize(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;
}

}  // namespace cert_provision
