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

#include "cryptohome/bootlockbox/boot_lockbox.h"

#include <stdint.h>
#include <sys/types.h>

#include <map>
#include <memory>
#include <string>

#include <base/files/file_path.h>
#include <crypto/scoped_openssl_types.h>
#include <openssl/objects.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>

#include "cryptohome/crypto.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/platform.h"
#include "cryptohome/tpm.h"

using base::FilePath;
using brillo::Blob;
using brillo::BlobFromString;
using brillo::BlobToString;
using brillo::SecureBlob;

namespace {

const uint32_t kPCRIndex = 15;

// This is an arbitrary value, our only goal is for the PCR to be non-zero.
const char kPCRExtension[] = "CROS_PCR15_845A4A757B94";

const char kKeyFilePath[] = "/var/lib/boot-lockbox/key";

const mode_t kKeyFilePermissions = 0600;

}  // namespace

namespace cryptohome {

size_t GetPcrValueSize(Tpm* tpm) {
  return (tpm && tpm->GetVersion() == Tpm::TpmVersion::TPM_2_0) ?
      SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH;
}

BootLockbox::BootLockbox(Tpm* tpm, Platform* platform, Crypto* crypto)
    : tpm_(tpm),
      platform_(platform),
      crypto_(crypto),
      initial_pcr_value_(GetPcrValueSize(tpm)) {}

BootLockbox::~BootLockbox() {}

bool BootLockbox::Sign(const brillo::Blob& data,
                       brillo::SecureBlob* signature) {
  CHECK(signature);
  if (IsFinalized()) {
    LOG(INFO) << "Can't sign: boot-lockbox is finalized.";
    return false;
  }
  brillo::SecureBlob key_blob;
  if (!GetKeyBlob(&key_blob)) {
    return false;
  }

  return tpm_->Sign(key_blob, brillo::SecureBlob(data), kPCRIndex, signature);
}

bool BootLockbox::Verify(const brillo::Blob& data,
                         const brillo::SecureBlob& signature) {
  brillo::Blob public_key;
  if (!GetPublicKey(&public_key)) {
    return false;
  }
  if (!VerifySignature(public_key, data, signature)) {
    return false;
  }
  brillo::SecureBlob key_blob;
  if (!GetKeyBlob(&key_blob)) {
    return false;
  }
  brillo::SecureBlob creation_blob;
  if (!GetCreationBlob(&creation_blob)) {
    return false;
  }
  if (!tpm_->VerifyPCRBoundKey(
          std::map<uint32_t, std::string>(
              {{kPCRIndex, BlobToString(initial_pcr_value_)}}),
          key_blob, creation_blob)) {
    return false;
  }
  return true;
}

bool BootLockbox::FinalizeBoot() {
  if (IsFinalized()) {
      // The PCR is already not at the initial value, no need to extend again.
      return true;
  }
  return tpm_->ExtendPCR(kPCRIndex,
                         CryptoLib::Sha1(BlobFromString(kPCRExtension)));
}

bool BootLockbox::IsFinalized() {
  Blob actual_pcr_value;
  return tpm_->ReadPCR(kPCRIndex, &actual_pcr_value) &&
         actual_pcr_value != initial_pcr_value_;
}

bool BootLockbox::PreLoadKey() {
  if (!key_.has_key_blob() && !LoadKey() && !CreateKey()) {
    return false;
  }
  return true;
}

bool BootLockbox::GetKeyBlob(brillo::SecureBlob* key_blob) {
  if (!key_.has_key_blob() && !LoadKey() && !CreateKey()) {
    return false;
  }
  CHECK(key_.has_key_blob());
  if (key_blob) {
    key_blob->assign(key_.key_blob().begin(), key_.key_blob().end());
  }
  return true;
}

bool BootLockbox::GetPublicKey(brillo::Blob* public_key) {
  if (!key_.has_public_key_der() && !LoadKey()) {
    return false;
  }
  CHECK(key_.has_public_key_der());
  if (public_key) {
    public_key->assign(key_.public_key_der().begin(),
                       key_.public_key_der().end());
  }
  return true;
}

bool BootLockbox::GetCreationBlob(brillo::SecureBlob* creation_blob) {
  if (!key_.has_creation_blob() && !LoadKey()) {
    return false;
  }
  if (creation_blob) {
    creation_blob->assign(key_.creation_blob().begin(),
                          key_.creation_blob().end());
  }
  return true;
}

bool BootLockbox::LoadKey() {
  std::string file_contents;
  if (!platform_->ReadFileToString(FilePath(kKeyFilePath), &file_contents)) {
    return false;
  }
  brillo::SecureBlob protobuf;
  if (!crypto_->DecryptWithTpm(file_contents, &protobuf)) {
    LOG(WARNING) << "Failed to decrypt boot-lockbox key.";
    return false;
  }
  if (!key_.ParseFromArray(protobuf.data(), protobuf.size())) {
    LOG(ERROR) << "Invalid boot-lockbox key.";
    return false;
  }
  return true;
}

bool BootLockbox::SaveKey() {
  brillo::SecureBlob protobuf(key_.ByteSizeLong());
  if (!key_.SerializeToArray(protobuf.data(), protobuf.size())) {
    LOG(ERROR) << "Failed to serialize boot-lockbox key.";
    return false;
  }
  std::string encrypted_protobuf;
  if (!crypto_->EncryptWithTpm(protobuf, &encrypted_protobuf)) {
    LOG(ERROR) << "Failed to encrypt boot-lockbox key.";
    return false;
  }
  if (!platform_->WriteStringToFileAtomicDurable(FilePath(kKeyFilePath),
                                                 encrypted_protobuf,
                                                 kKeyFilePermissions)) {
    LOG(ERROR) << "Failed to write boot-lockbox key.";
    return false;
  }
  return true;
}

bool BootLockbox::CreateKey() {
  LOG(INFO) <<  "Creating new boot-lockbox key.";
  brillo::SecureBlob key_blob;
  brillo::SecureBlob public_key;
  brillo::SecureBlob creation_blob;
  if (!tpm_->CreatePCRBoundKey(
          std::map<uint32_t, std::string>(
              {{kPCRIndex, BlobToString(initial_pcr_value_)}}),
          AsymmetricKeyUsage::kSignKey, &key_blob, &public_key,
          &creation_blob)) {
    LOG(ERROR) << "Failed to create boot-lockbox key.";
    return false;
  }
  if (IsFinalized()) {
    LOG(WARNING) << "Boot-lockbox finalized while creating key: aborting.";
    return false;
  }
  key_.set_key_blob(key_blob.to_string());
  key_.set_public_key_der(public_key.to_string());
  key_.set_creation_blob(creation_blob.to_string());
  return SaveKey();
}

bool BootLockbox::VerifySignature(const brillo::Blob& public_key,
                                  const brillo::Blob& signed_data,
                                  const brillo::SecureBlob& signature) {
  const unsigned char* asn1_ptr = public_key.data();
  crypto::ScopedRSA rsa(
      d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
  if (!rsa.get()) {
    LOG(ERROR) << "Failed to decode public key.";
    return false;
  }
  brillo::SecureBlob digest = CryptoLib::Sha256ToSecureBlob(signed_data);
  if (!RSA_verify(NID_sha256, digest.data(), digest.size(),
                  signature.data(), signature.size(), rsa.get())) {
    LOG(ERROR) << "Failed to verify signature.";
    return false;
  }
  return true;
}

}  // namespace cryptohome
