// 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/boot_lockbox.h"

#include <sys/types.h>

#include <memory>
#include <string>

#include <base/files/file_path.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::SecureBlob;

namespace {

const int 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 FilePath::CharType kKeyFilePath[] = "/var/lib/boot-lockbox/key";

const mode_t kKeyFilePermissions = 0600;

// So we can use std::unique_ptr with openssl types.
struct RSADeleter {
  void operator()(void* ptr) const {
    if (ptr)
      RSA_free(reinterpret_cast<RSA*>(ptr));
  }
};

}  // 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), 0) {
}

BootLockbox::~BootLockbox() {}

bool BootLockbox::Sign(const brillo::SecureBlob& 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, data, kPCRIndex, signature);
}

bool BootLockbox::Verify(const brillo::SecureBlob& data,
                         const brillo::SecureBlob& signature) {
  brillo::SecureBlob 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(kPCRIndex, 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(
      brillo::SecureBlob(std::begin(kPCRExtension),
                           std::end(kPCRExtension))));
}

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

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::SecureBlob* 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_.ByteSize());
  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(kPCRIndex, initial_pcr_value_, &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::SecureBlob& public_key,
                                  const brillo::SecureBlob& signed_data,
                                  const brillo::SecureBlob& signature) {
  const unsigned char* asn1_ptr = public_key.data();
  std::unique_ptr<RSA, RSADeleter> rsa(
      d2i_RSAPublicKey(NULL, &asn1_ptr, public_key.size()));
  if (!rsa.get()) {
    LOG(ERROR) << "Failed to decode public key.";
    return false;
  }
  brillo::SecureBlob digest = CryptoLib::Sha256(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
