// 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 <brillo/secure_blob.h>

#include "cryptohome/cryptolib.h"
#include "fake_le_credential_metadata.pb.h"  // NOLINT(build/include)

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);
}

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.ByteSize());
  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 = CryptoLib::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 false;
}

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 = CryptoLib::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.ByteSize());
  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 = CryptoLib::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 = CryptoLib::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.ByteSize());
  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 = CryptoLib::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.ByteSize());
  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 = CryptoLib::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 =
        CryptoLib::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
