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

#include <string>
#include <vector>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <brillo/file_utils.h>
#include <crypto/secure_hash.h>
#include <crypto/sha2.h>
#include <trunks/tpm_constants.h>
#include <trunks/tpm_utility.h>

#include "cryptohome/bootlockbox/tpm2_nvspace_utility.h"
#include "cryptohome/bootlockbox/tpm_nvspace_interface.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/platform.h"

namespace cryptohome {

NVRamBootLockbox::NVRamBootLockbox(
  TPMNVSpaceUtilityInterface* tpm_nvspace_utility)
    : boot_lockbox_filepath_(base::FilePath(kNVRamBootLockboxFilePath)),
      tpm_nvspace_utility_(tpm_nvspace_utility) {}

NVRamBootLockbox::NVRamBootLockbox(
    TPMNVSpaceUtilityInterface* tpm_nvspace_utility,
    const base::FilePath& bootlockbox_file_path)
      : boot_lockbox_filepath_(bootlockbox_file_path),
        tpm_nvspace_utility_(tpm_nvspace_utility) {}

NVRamBootLockbox::~NVRamBootLockbox() {}

bool NVRamBootLockbox::Store(const std::string& key,
                             const std::string& digest,
                             BootLockboxErrorCode* error) {
  // Returns nvspace state to client.
  *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NOT_SET;
  if (nvspace_state_ == NVSpaceState::kNVSpaceWriteLocked) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_WRITE_LOCKED;
    return false;
  }
  if (nvspace_state_ == NVSpaceState::kNVSpaceUndefined) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NVSPACE_UNDEFINED;
    return false;
  }
  if (nvspace_state_ == NVSpaceState::kNVSpaceError) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NVSPACE_OTHER;
    return false;
  }

  // A temporaray key value map for writing.
  KeyValueMap updated_key_value_map = key_value_store_;
  updated_key_value_map[key] = digest;
  if (!FlushAndUpdate(updated_key_value_map)) {
    LOG(ERROR) << "Store Failed: Cannot flush to file.";
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_WRITE_FAILED;
    return false;
  }
  return true;
}

bool NVRamBootLockbox::Read(const std::string& key,
                            std::string* digest,
                            BootLockboxErrorCode* error) {
  // Returns nvspace state to client.
  *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NOT_SET;
  if (nvspace_state_ == NVSpaceState::kNVSpaceUndefined) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NVSPACE_UNDEFINED;
    return false;
  }
  if (nvspace_state_ == NVSpaceState::kNVSpaceUninitialized) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NVSPACE_UNINITIALIZED;
    return false;
  }
  if (nvspace_state_ == NVSpaceState::kNVSpaceError) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_NVSPACE_OTHER;
    return false;
  }

  KeyValueMap::const_iterator it = key_value_store_.find(key);
  if (it == key_value_store_.end()) {
    *error = BootLockboxErrorCode::BOOTLOCKBOX_ERROR_MISSING_KEY;
    return false;
  }
  *digest = it->second;
  return true;
}

bool NVRamBootLockbox::Finalize() {
  if (nvspace_state_ == NVSpaceState::kNVSpaceUndefined) {
    return false;
  }
  if (tpm_nvspace_utility_->LockNVSpace()) {
    nvspace_state_ = NVSpaceState::kNVSpaceWriteLocked;
    return true;
  }
  nvspace_state_ = NVSpaceState::kNVSpaceError;
  return false;
}

bool NVRamBootLockbox::DefineSpace() {
  if (tpm_nvspace_utility_->DefineNVSpace()) {
    nvspace_state_ = NVSpaceState::kNVSpaceUninitialized;
    return true;
  }
  nvspace_state_ = NVSpaceState::kNVSpaceUndefined;
  return false;
}

bool NVRamBootLockbox::Load() {
  if (!tpm_nvspace_utility_->ReadNVSpace(&root_digest_, &nvspace_state_)) {
    LOG(ERROR) << "Failed to read NVRAM space.";
    return false;
  }

  brillo::Blob data;
  if (!Platform().ReadFile(boot_lockbox_filepath_, &data)) {
    LOG(ERROR) << "Failed to read boot lockbox file.";
    return false;
  }

  brillo::Blob digest_blob = CryptoLib::Sha256(data);
  std::string digest(digest_blob.begin(), digest_blob.end());

  if (digest != root_digest_) {
    LOG(ERROR) << "The nvram boot lockbox file verification failed.";
    return false;
  }

  SerializedKeyValueMap message;
  if (!message.ParseFromArray(data.data(), data.size())) {
    LOG(ERROR) << "Failed to parse boot lockbox file.";
    return false;
  }

  if (!message.has_version() || message.version() != kVersion) {
    LOG(ERROR) << "Unsupported version " << message.version();
    return false;
  }

  KeyValueMap tmp(message.keyvals().begin(), message.keyvals().end());
  key_value_store_.swap(tmp);
  return true;
}

bool NVRamBootLockbox::FlushAndUpdate(const KeyValueMap& keyvals) {
  SerializedKeyValueMap message;
  message.set_version(kVersion);

  auto mutable_map = message.mutable_keyvals();
  KeyValueMap::const_iterator it;
  for (it = keyvals.begin(); it != keyvals.end(); ++it) {
    (*mutable_map)[it->first] = it->second;
  }

  brillo::Blob content(message.ByteSizeLong());
  message.SerializeWithCachedSizesToArray(content.data());

  brillo::Blob digest_blob = CryptoLib::Sha256(content);
  std::string digest(digest_blob.begin(), digest_blob.end());

  // It is hard to make this atomic. In the case the file digest
  // and NVRAM space content are inconsistent, the file is deleted and NVRAM
  // space is updated on write.
  if (!brillo::WriteBlobToFileAtomic(boot_lockbox_filepath_,
                                     content, 0600)) {
    LOG(ERROR) << "Failed to write to boot lockbox file";
    return false;
  }
  // Update tpm_nvram.
  if (!tpm_nvspace_utility_->WriteNVSpace(digest)) {
    LOG(ERROR) << "Failed to write boot lockbox NVRAM space";
    return false;
  }

  brillo::SyncFileOrDirectory(boot_lockbox_filepath_,
                              false /* is directory */, true /* data sync */);
  // Update in memory information.
  key_value_store_ = keyvals;
  root_digest_ = digest;
  nvspace_state_ = NVSpaceState::kNVSpaceNormal;
  return true;
}

NVSpaceState NVRamBootLockbox::GetState() {
  return nvspace_state_;
}

void NVRamBootLockbox::SetState(const NVSpaceState state) {
  nvspace_state_ = state;
}

}  // namespace cryptohome
