// Copyright 2018 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/fake_le_credential_backend.h"

#include <openssl/sha.h>

#include <base/logging.h>
#include <brillo/secure_blob.h>
#include <libhwsec-foundation/crypto/sha.h>

#include "cryptohome/fake_le_credential_metadata.pb.h"

using ::hwsec_foundation::Sha256;
using ::hwsec_foundation::Sha256ToSecureBlob;

namespace cryptohome {

// Initial root hash when the leaf length is 14 bits, and each node
// has 4 children.
const uint8_t kInitRootHash14_4[SHA256_DIGEST_LENGTH] = {
    0x91, 0x3C, 0xA7, 0x20, 0x82, 0x23, 0xB8, 0xC8, 0x92, 0xA6, 0x1E,
    0x83, 0xD9, 0x68, 0x07, 0x28, 0xE3, 0xE1, 0xD6, 0xBB, 0x10, 0x63,
    0xF2, 0xDD, 0xCE, 0x92, 0x25, 0x71, 0x80, 0x3D, 0xA9, 0xEE};

FakeLECredentialBackend::FakeLECredentialBackend() {
  log_.reserve(kFakeLogSize);
  needs_pcr_binding_ = false;
}

bool FakeLECredentialBackend::Reset(std::vector<uint8_t>* new_root) {
  struct FakeLELogEntry fake_entry;
  fake_entry.entry.type = LE_LOG_RESET;
  fake_entry.entry.root = std::vector<uint8_t>(
      kInitRootHash14_4, kInitRootHash14_4 + SHA256_DIGEST_LENGTH);
  AddLogEntry(fake_entry);

  *new_root = CurrentRootHash();

  return true;
}

bool FakeLECredentialBackend::InsertCredential(
    const uint64_t label,
    const std::vector<std::vector<uint8_t>>& h_aux,
    const brillo::SecureBlob& le_secret,
    const brillo::SecureBlob& he_secret,
    const brillo::SecureBlob& reset_secret,
    const std::map<uint32_t, uint32_t>& delay_schedule,
    const ValidPcrCriteria& valid_pcr_criteria,
    std::vector<uint8_t>* cred_metadata,
    std::vector<uint8_t>* mac,
    std::vector<uint8_t>* new_root) {
  // Calculate the root hash, assuming new MAC is 32 bytes of 0.
  std::vector<uint8_t> leaf_mac(SHA256_DIGEST_LENGTH, 0);
  // Set |new_root| to the original value, in case we return errors.
  *new_root = CurrentRootHash();

  std::vector<uint8_t> root_hash = RecalculateRootHash(label, leaf_mac, h_aux);
  if (root_hash != CurrentRootHash()) {
    LOG(ERROR) << "h_aux and/or metadata don't match the current root hash.";
    return false;
  }

  // Generate the credential metadata structure.
  // TODO(pmalani): Still have to add support for the delay schedule.
  // The "encryption" of the credential is just a NOP.
  FakeLECredentialMetadata cred_metadata_entry;
  cred_metadata_entry.set_label(label);
  cred_metadata_entry.set_le_secret(le_secret.data(), le_secret.size());
  cred_metadata_entry.set_he_secret(he_secret.data(), he_secret.size());
  cred_metadata_entry.set_reset_secret(reset_secret.data(),
                                       reset_secret.size());
  cred_metadata_entry.set_attempt_count(0);
  if (valid_pcr_criteria.size() > 0) {
    cred_metadata_entry.set_valid_pcr_digest(valid_pcr_criteria[0].digest);
  }

  cred_metadata->resize(cred_metadata_entry.ByteSizeLong());
  if (!cred_metadata_entry.SerializeToArray(cred_metadata->data(),
                                            cred_metadata->size())) {
    LOG(ERROR) << "Couldn't serialize cred metadata, label: " << label;
    return false;
  }

  // Actual TPM will actually calculate the MAC, but for testing,
  // just a SHA should be sufficient.
  brillo::SecureBlob hash = Sha256ToSecureBlob(*cred_metadata);
  mac->assign(hash.begin(), hash.end());

  struct FakeLELogEntry fake_entry;
  fake_entry.entry.type = LE_LOG_INSERT;
  fake_entry.entry.root = RecalculateRootHash(label, *mac, h_aux);
  fake_entry.entry.label = label;
  fake_entry.entry.mac = *mac;
  AddLogEntry(fake_entry);

  *new_root = CurrentRootHash();

  return true;
}

bool FakeLECredentialBackend::NeedsPCRBinding(
    const std::vector<uint8_t>& cred_metadata) {
  return needs_pcr_binding_;
}

int FakeLECredentialBackend::GetWrongAuthAttempts(
    const std::vector<uint8_t>& cred_metadata) {
  FakeLECredentialMetadata metadata_tmp;
  if (!metadata_tmp.ParseFromArray(cred_metadata.data(),
                                   cred_metadata.size())) {
    LOG(INFO) << "Couldn't parse the data.";
    return -1;
  }
  return metadata_tmp.attempt_count();
}

void FakeLECredentialBackend::ExtendArcPCR(const std::string& data) {
  pcr_digest += data;
}

void FakeLECredentialBackend::ResetArcPCR() {
  pcr_digest.clear();
}

bool FakeLECredentialBackend::CheckCredential(
    const uint64_t label,
    const std::vector<std::vector<uint8_t>>& h_aux,
    const std::vector<uint8_t>& orig_cred_metadata,
    const brillo::SecureBlob& le_secret,
    std::vector<uint8_t>* new_cred_metadata,
    std::vector<uint8_t>* new_mac,
    brillo::SecureBlob* he_secret,
    brillo::SecureBlob* reset_secret,
    LECredBackendError* err,
    std::vector<uint8_t>* new_root) {
  *err = LE_TPM_SUCCESS;
  new_cred_metadata->clear();
  new_mac->clear();
  // Set |new_root| to the original value, in case we return errors.
  *new_root = CurrentRootHash();

  std::vector<uint8_t> orig_mac = Sha256(orig_cred_metadata);

  std::vector<uint8_t> root_hash = RecalculateRootHash(label, orig_mac, h_aux);
  if (root_hash != CurrentRootHash()) {
    LOG(ERROR) << "h_aux and/or metadata don't match the current root hash.";
    *err = LE_TPM_ERROR_HASH_TREE_SYNC;
    return false;
  }

  FakeLECredentialMetadata metadata_tmp;
  if (!metadata_tmp.ParseFromArray(orig_cred_metadata.data(),
                                   orig_cred_metadata.size())) {
    LOG(INFO) << "Couldn't deserialize cred metadata, label: " << label;
    *err = LE_TPM_ERROR_HASH_TREE_SYNC;
    return false;
  }

  if (metadata_tmp.attempt_count() >= LE_MAX_INCORRECT_ATTEMPTS) {
    *err = LE_TPM_ERROR_TOO_MANY_ATTEMPTS;
    return false;
  }

  // Check the PCR.
  if (!pcr_digest.empty() && metadata_tmp.valid_pcr_digest() != pcr_digest) {
    *err = LE_TPM_ERROR_PCR_NOT_MATCH;
    return false;
  }

  // Check the LE secret.
  if (!memcmp(metadata_tmp.le_secret().data(), le_secret.data(),
              le_secret.size())) {
    metadata_tmp.set_attempt_count(0);
    he_secret->assign(metadata_tmp.he_secret().begin(),
                      metadata_tmp.he_secret().end());
    reset_secret->assign(metadata_tmp.reset_secret().begin(),
                         metadata_tmp.reset_secret().end());
  } else {
    *err = LE_TPM_ERROR_INVALID_LE_SECRET;
    metadata_tmp.set_attempt_count(metadata_tmp.attempt_count() + 1);
  }

  new_cred_metadata->resize(metadata_tmp.ByteSizeLong());
  if (!metadata_tmp.SerializeToArray(new_cred_metadata->data(),
                                     new_cred_metadata->size())) {
    LOG(ERROR) << "Couldn't serialize new cred metadata, label: " << label;
    new_cred_metadata->clear();
    return false;
  }

  brillo::SecureBlob hash = Sha256ToSecureBlob(*new_cred_metadata);
  new_mac->assign(hash.begin(), hash.end());

  struct FakeLELogEntry fake_entry;
  fake_entry.entry.type = LE_LOG_CHECK;
  fake_entry.entry.label = label;
  fake_entry.entry.root = RecalculateRootHash(label, *new_mac, h_aux);
  fake_entry.entry.mac = *new_mac;
  fake_entry.check_success = (*err == LE_TPM_SUCCESS);
  AddLogEntry(fake_entry);

  *new_root = CurrentRootHash();

  return (*err == LE_TPM_SUCCESS);
}

bool FakeLECredentialBackend::ResetCredential(
    const uint64_t label,
    const std::vector<std::vector<uint8_t>>& h_aux,
    const std::vector<uint8_t>& orig_cred_metadata,
    const brillo::SecureBlob& reset_secret,
    std::vector<uint8_t>* new_cred_metadata,
    std::vector<uint8_t>* new_mac,
    LECredBackendError* err,
    std::vector<uint8_t>* new_root) {
  *err = LE_TPM_SUCCESS;
  new_cred_metadata->clear();
  new_mac->clear();
  // Set |new_root| to the original value, in case we return errors.
  *new_root = CurrentRootHash();

  std::vector<uint8_t> orig_mac = Sha256(orig_cred_metadata);

  std::vector<uint8_t> root_hash = RecalculateRootHash(label, orig_mac, h_aux);
  if (root_hash != CurrentRootHash()) {
    LOG(ERROR) << "h_aux and/or metadata don't match the current root hash.";
    *err = LE_TPM_ERROR_HASH_TREE_SYNC;
    return false;
  }

  FakeLECredentialMetadata metadata_tmp;
  if (!metadata_tmp.ParseFromArray(orig_cred_metadata.data(),
                                   orig_cred_metadata.size())) {
    LOG(INFO) << "Couldn't deserialize cred metadata, label: " << label;
    *err = LE_TPM_ERROR_HASH_TREE_SYNC;
    return false;
  }

  // Check the Reset secret.
  if (!memcmp(metadata_tmp.reset_secret().data(), reset_secret.data(),
              reset_secret.size())) {
    metadata_tmp.set_attempt_count(0);
  } else {
    *err = LE_TPM_ERROR_INVALID_RESET_SECRET;
  }

  new_cred_metadata->resize(metadata_tmp.ByteSizeLong());
  if (!metadata_tmp.SerializeToArray(new_cred_metadata->data(),
                                     new_cred_metadata->size())) {
    LOG(ERROR) << "Couldn't serialize new cred metadata, label: " << label;
    new_cred_metadata->clear();
    return false;
  }

  brillo::SecureBlob hash = Sha256ToSecureBlob(*new_cred_metadata);
  new_mac->assign(hash.begin(), hash.end());

  struct FakeLELogEntry fake_entry;
  fake_entry.entry.type = LE_LOG_CHECK;
  fake_entry.entry.label = label;
  fake_entry.entry.root = RecalculateRootHash(label, *new_mac, h_aux);
  fake_entry.check_success = (*err == LE_TPM_SUCCESS);
  fake_entry.entry.mac = *new_mac;
  AddLogEntry(fake_entry);

  *new_root = CurrentRootHash();

  return (*err == LE_TPM_SUCCESS);
}

bool FakeLECredentialBackend::RemoveCredential(
    const uint64_t label,
    const std::vector<std::vector<uint8_t>>& h_aux,
    const std::vector<uint8_t>& mac,
    std::vector<uint8_t>* new_root) {
  // Set |new_root| to the original value, in case we return errors.
  *new_root = CurrentRootHash();
  std::vector<uint8_t> root_hash = RecalculateRootHash(label, mac, h_aux);

  if (root_hash != CurrentRootHash()) {
    LOG(ERROR) << "h_aux and/or metadata don't match the current root hash.";
    return false;
  }

  // Create a new MAC which is all zeros.
  brillo::Blob new_mac(SHA256_DIGEST_LENGTH, 0);

  struct FakeLELogEntry fake_entry;
  fake_entry.entry.type = LE_LOG_REMOVE;
  fake_entry.entry.root = RecalculateRootHash(label, new_mac, h_aux);
  fake_entry.entry.label = label;
  AddLogEntry(fake_entry);

  *new_root = CurrentRootHash();

  return true;
}

bool FakeLECredentialBackend::GetLog(
    const std::vector<uint8_t>& cur_disk_root_hash,
    std::vector<uint8_t>* root_hash,
    std::vector<LELogEntry>* log) {
  *root_hash = CurrentRootHash();
  std::vector<struct LELogEntry> ret_log;
  for (const auto& fake_entry : log_) {
    ret_log.push_back(fake_entry.entry);
    if (fake_entry.entry.root == cur_disk_root_hash) {
      break;
    }
  }
  *log = ret_log;
  return true;
}

bool FakeLECredentialBackend::ReplayLogOperation(
    const std::vector<uint8_t>& cur_disk_root_hash,
    const std::vector<std::vector<uint8_t>>& h_aux,
    const std::vector<uint8_t>& orig_cred_metadata,
    std::vector<uint8_t>* new_cred_metadata,
    std::vector<uint8_t>* new_mac) {
  new_cred_metadata->clear();
  new_mac->clear();

  bool entry_found;
  bool check_success;
  uint64_t label;
  for (const auto& fake_entry : log_) {
    if (fake_entry.entry.root == cur_disk_root_hash) {
      label = fake_entry.entry.label;
      check_success = fake_entry.check_success;
      entry_found = true;
      break;
    }
  }

  if (!entry_found) {
    LOG(ERROR) << "Log entry not found in replay log.";
    return false;
  }

  FakeLECredentialMetadata metadata_tmp;
  if (!metadata_tmp.ParseFromArray(orig_cred_metadata.data(),
                                   orig_cred_metadata.size())) {
    LOG(INFO) << "Couldn't deserialize cred metadata, label: " << label;
    return false;
  }

  if (check_success) {
    metadata_tmp.set_attempt_count(0);
  } else {
    metadata_tmp.set_attempt_count(metadata_tmp.attempt_count() + 1);
  }

  new_cred_metadata->resize(metadata_tmp.ByteSizeLong());
  if (!metadata_tmp.SerializeToArray(new_cred_metadata->data(),
                                     new_cred_metadata->size())) {
    LOG(ERROR) << "Couldn't serialize new cred metadata, label: " << label;
    new_cred_metadata->clear();
    return false;
  }

  brillo::SecureBlob hash = Sha256ToSecureBlob(*new_cred_metadata);
  new_mac->assign(hash.begin(), hash.end());

  return true;
}

std::vector<uint8_t> FakeLECredentialBackend::RecalculateRootHash(
    const uint64_t label,
    const std::vector<uint8_t>& leaf_mac,
    const std::vector<std::vector<uint8_t>>& h_aux) {
  std::vector<uint8_t> cur_hash = leaf_mac;
  uint64_t cur_label = label;
  auto it = h_aux.begin();

  uint32_t height = kLengthLabels / kBitsPerLevel;
  while (height--) {
    std::vector<uint8_t> input_buffer;
    // Get bottom kBitsPerLevel bits of current label.
    uint64_t cur_suffix = cur_label & ((1 << kBitsPerLevel) - 1);
    // Go from left through right for all the sibling nodes. If we encounter the
    // suffix for the current node, add it to the input buffer, otherwise add
    // the sibling node.
    for (uint64_t i = 0; i < kNumChildren; i++) {
      if (i == cur_suffix) {
        input_buffer.insert(input_buffer.end(), cur_hash.begin(),
                            cur_hash.end());
      } else {
        auto sibling_hash = *it;
        input_buffer.insert(input_buffer.end(), sibling_hash.begin(),
                            sibling_hash.end());
        ++it;
      }
    }
    brillo::SecureBlob result_hash = Sha256ToSecureBlob(input_buffer);
    cur_hash.assign(result_hash.begin(), result_hash.end());
    cur_label = cur_label >> kBitsPerLevel;
  }

  return cur_hash;
}

void FakeLECredentialBackend::AddLogEntry(const struct FakeLELogEntry& entry) {
  if (log_.size() == kFakeLogSize) {
    log_.pop_back();
  }
  log_.insert(log_.begin(), entry);
}

}  // namespace cryptohome
