// 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/crypto/sha.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 = 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 = 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
