// Copyright (c) 2013 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/lockbox.h"

#include <arpa/inet.h>
#include <limits.h>
#include <openssl/sha.h>
#include <stdint.h>

#include <algorithm>
#include <string>
#include <utility>
#include <vector>

#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/strings/string_split.h>
#include <base/sys_byteorder.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <brillo/secure_blob.h>

#include "cryptohome/cryptolib.h"
#include "cryptohome/platform.h"

using base::FilePath;
using brillo::SecureBlob;

namespace cryptohome {
namespace {

// Literals for running mount-encrypted helper.
constexpr char kMountEncrypted[] = "/usr/sbin/mount-encrypted";
constexpr char kMountEncryptedFinalize[] = "finalize";

}  // namespace

std::ostream& operator<<(std::ostream& out, LockboxError error) {
  return out << static_cast<int>(error);
}

int GetNvramVersionNumber(NvramVersion version) {
  switch (version) {
    case NvramVersion::kVersion1:
      return 1;
    case NvramVersion::kVersion2:
      return 2;
  }
  NOTREACHED();
  return 0;
}

Lockbox::Lockbox(Tpm* tpm, uint32_t nvram_index)
    : tpm_(tpm),
      nvram_index_(nvram_index),
      default_process_(new brillo::ProcessImpl()),
      process_(default_process_.get()),
      default_platform_(new Platform()),
      platform_(default_platform_.get()) {}

Lockbox::~Lockbox() {}

bool Lockbox::Reset(LockboxError* error) {
  if (!tpm_ || !tpm_->IsEnabled() || !tpm_->IsOwned()) {
    *error = LockboxError::kTpmUnavailable;
    LOG(ERROR) << "TPM unavailable";
    return false;
  }

  // If we have authorization, recreate the lockbox space.
  brillo::SecureBlob owner_password;
  if (tpm_->GetOwnerPassword(&owner_password) && owner_password.size() != 0) {
    if (tpm_->IsNvramDefined(nvram_index_) &&
        !tpm_->DestroyNvram(nvram_index_)) {
      LOG(ERROR) << "Failed to destroy lockbox data before creation.";
      *error = LockboxError::kTpmError;
      return false;
    }

    // If we store the encryption salt in lockbox, protect it from reading
    // in non-verified boot mode.
    uint32_t nvram_perm =
        Tpm::kTpmNvramWriteDefine |
        (IsKeyMaterialInLockbox() ? Tpm::kTpmNvramBindToPCR0 : 0);
    uint32_t nvram_bytes = LockboxContents::GetNvramSize(nvram_version_);
    if (!tpm_->DefineNvram(nvram_index_, nvram_bytes, nvram_perm)) {
      *error = LockboxError::kTpmError;
      LOG(ERROR) << "Failed to define NVRAM space.";
      return false;
    }
    LOG(INFO) << "Lockbox created.";
    return true;
  } else {
    LOG(WARNING) << "No owner password when trying to reset LockBox.";
  }

  // Check if the space is already set up correctly.
  if (!tpm_->IsNvramDefined(nvram_index_)) {
    LOG(ERROR) << "NVRAM space absent when resetting LockBox.";
    *error = LockboxError::kNvramSpaceAbsent;
    return false;
  }

  if (tpm_->IsNvramLocked(nvram_index_)) {
    LOG(ERROR) << "NVRAM space locked after resetting LockBox.";
    *error = LockboxError::kNvramInvalid;
    return false;
  }

  // The NVRAM space that we are looking at is not created by us, and it is too
  // expensive to extensively inspect it. Given the above, we aren't sure about
  // all its attributes, all we know is that:
  // 1. It's not locked.
  // 2. It exists (is defined).
  // Therefore, it is highly likely that the NVRAM space is writable, and
  // suitable for our use case. The most probable scenario is that this NVRAM
  // index is created by previous installations of Chromium OS, so we'll just
  // continue to use it.
  LOG(INFO) << "Existing Lockbox seems writable.";
  return true;
}

bool Lockbox::Store(const brillo::Blob& blob, LockboxError* error) {
  if (!tpm_ || !tpm_->IsEnabled()) {
    *error = LockboxError::kTpmUnavailable;
    LOG(ERROR) << "TPM unavailable";
    return false;
  }

  if (!tpm_->IsNvramDefined(nvram_index_) ||
      tpm_->IsNvramLocked(nvram_index_)) {
    *error = LockboxError::kNvramInvalid;
    return false;
  }

  // Check defined NVRAM size and construct a suitable LockboxContents instance.
  unsigned int nvram_size = tpm_->GetNvramSize(nvram_index_);
  std::unique_ptr<LockboxContents> contents = LockboxContents::New(nvram_size);
  if (!contents) {
    LOG(ERROR) << "Unsupported NVRAM space size " << nvram_size << ".";
    *error = LockboxError::kNvramInvalid;
    return false;
  }

  // Grab key material from the TPM.
  brillo::SecureBlob key_material(contents->key_material_size());
  if (IsKeyMaterialInLockbox()) {
    if (!tpm_->GetRandomDataSecureBlob(key_material.size(), &key_material)) {
      LOG(ERROR) << "Failed to get key material from the TPM.";
      *error = LockboxError::kTpmError;
      return false;
    }
  } else {
    // Save a TPM command, and just fill the salt field with zeroes.
    LOG(INFO) << "Skipping random salt generation.";
  }

  brillo::SecureBlob nvram_blob;
  if (!contents->SetKeyMaterial(key_material) || !contents->Protect(blob) ||
      !contents->Encode(&nvram_blob)) {
    LOG(ERROR) << "Failed to set up lockbox contents.";
    *error = LockboxError::kNvramInvalid;
    return false;
  }

  // Write the hash to nvram
  if (!tpm_->WriteNvram(nvram_index_,
                        SecureBlob(nvram_blob.begin(), nvram_blob.end()))) {
    LOG(ERROR) << "Store() failed to write the attribute hash to NVRAM";
    *error = LockboxError::kTpmError;
    return false;
  }
  // Lock nvram index for writing.
  if (!tpm_->WriteLockNvram(nvram_index_)) {
    LOG(ERROR) << "Store() failed to lock the NVRAM space";
    *error = LockboxError::kTpmError;
    return false;
  }
  // Ensure the space is now locked.
  if (!tpm_->IsNvramLocked(nvram_index_)) {
    LOG(ERROR) << "NVRAM space did not lock as expected.";
    *error = LockboxError::kTpmError;
    return false;
  }

  // Call out to mount-encrypted now that salt has been written.
  FinalizeMountEncrypted(contents->version() == NvramVersion::kVersion1
                             ? nvram_blob
                             : key_material);

  return true;
}

// TODO(keescook) Write unittests for this.
void Lockbox::FinalizeMountEncrypted(const brillo::SecureBlob& entropy) const {
  std::string hex;
  FilePath outfile_path;
  FILE* outfile;
  int rc;

  // Take hash of entropy and convert to hex string for cmdline.
  SecureBlob hash = CryptoLib::Sha256(entropy);
  hex = CryptoLib::SecureBlobToHex(hash);

  process_->Reset(0);
  process_->AddArg(kMountEncrypted);
  process_->AddArg(kMountEncryptedFinalize);
  process_->AddArg(hex);

  // Redirect stdout/stderr somewhere useful for error reporting.
  outfile = platform_->CreateAndOpenTemporaryFile(&outfile_path);
  if (outfile) {
    process_->BindFd(fileno(outfile), STDOUT_FILENO);
    process_->BindFd(fileno(outfile), STDERR_FILENO);
  }

  rc = process_->Run();

  if (rc) {
    LOG(ERROR) << "Request to finalize encrypted mount failed ('"
               << kMountEncrypted << " " << kMountEncryptedFinalize << " "
               << hex << "', rc:" << rc << ")";
    if (outfile) {
      std::vector<std::string> output;
      std::vector<std::string>::iterator it;
      std::string contents;

      if (platform_->ReadFileToString(outfile_path, &contents)) {
        output = base::SplitString(contents, "\n", base::KEEP_WHITESPACE,
                                   base::SPLIT_WANT_ALL);
        for (it = output.begin(); it < output.end(); it++) {
          LOG(ERROR) << *it;
        }
      }
    }
  } else {
    LOG(INFO) << "Encrypted partition finalized.";
  }

  if (outfile)
    platform_->CloseFile(outfile);

  return;
}

// static
std::unique_ptr<LockboxContents> LockboxContents::New(size_t nvram_size) {
  // Make sure |nvram_size| corresponds to one of the encoding versions.
  if (GetNvramSize(NvramVersion::kVersion1) != nvram_size &&
      GetNvramSize(NvramVersion::kVersion2) != nvram_size) {
    return nullptr;
  }

  std::unique_ptr<LockboxContents> result(new LockboxContents());
  result->key_material_.resize(nvram_size - kFixedPartSize);
  return result;
}

bool LockboxContents::Decode(const brillo::SecureBlob& nvram_data) {
  // Reject data of incorrect size.
  if (nvram_data.size() != GetNvramSize(version())) {
    return false;
  }

  brillo::SecureBlob::const_iterator cursor = nvram_data.begin();

  // Extract the expected data size from the NVRAM. For historic reasons, this
  // is encoded in reverse host byte order (!).
  uint32_t reversed_size;
  uint8_t* reversed_size_ptr = reinterpret_cast<uint8_t*>(&reversed_size);
  std::copy(cursor, cursor + sizeof(reversed_size), reversed_size_ptr);
  cursor += sizeof(reversed_size);
  size_ = base::ByteSwap(reversed_size);

  // Grab the flags.
  flags_ = *cursor++;

  // Grab the key material.
  key_material_.assign(cursor, cursor + key_material_size());
  cursor += key_material_size();

  // Grab the hash.
  std::copy(cursor, cursor + sizeof(hash_), hash_);
  cursor += sizeof(hash_);

  // Per the checks at function entry we should have exactly reached the end.
  CHECK(cursor == nvram_data.end());

  return true;
}

bool LockboxContents::Encode(brillo::SecureBlob* blob) {
  // Encode the data size. For historic reasons, this is encoded in reverse host
  // byte order (!).
  uint32_t reversed_size = base::ByteSwap(size_);
  uint8_t* reversed_size_ptr = reinterpret_cast<uint8_t*>(&reversed_size);
  blob->insert(blob->end(), reversed_size_ptr,
               reversed_size_ptr + sizeof(reversed_size));

  // Append the flags byte.
  blob->push_back(flags_);

  // Append the key material.
  blob->insert(blob->end(), std::begin(key_material_), std::end(key_material_));

  // Append the hash.
  blob->insert(blob->end(), std::begin(hash_), std::end(hash_));

  return true;
}

bool LockboxContents::SetKeyMaterial(const brillo::SecureBlob& key_material) {
  if (key_material.size() != key_material_size()) {
    return false;
  }

  key_material_ = key_material;
  return true;
}

bool LockboxContents::Protect(const brillo::Blob& blob) {
  brillo::SecureBlob salty_blob(blob);
  salty_blob.insert(salty_blob.end(), key_material_.begin(),
                    key_material_.end());
  SecureBlob salty_blob_hash = CryptoLib::Sha256(salty_blob);
  CHECK_EQ(sizeof(hash_), salty_blob_hash.size());
  std::copy(salty_blob_hash.begin(), salty_blob_hash.end(), std::begin(hash_));
  size_ = blob.size();
  return true;
}

LockboxContents::VerificationResult LockboxContents::Verify(
    const brillo::Blob& blob) {
  // Make sure that the file size matches what was stored in nvram.
  if (blob.size() != size_) {
    LOG(ERROR) << "Verify() expected " << size_ << " , but received "
               << blob.size() << " bytes.";
    return VerificationResult::kSizeMismatch;
  }

  // Compute the hash of the blob to verify.
  brillo::SecureBlob salty_blob(blob);
  salty_blob.insert(salty_blob.end(), key_material_.begin(),
                    key_material_.end());
  SecureBlob salty_blob_hash = CryptoLib::Sha256(salty_blob);

  // Validate the blob hash versus the stored hash.
  if (sizeof(hash_) != salty_blob_hash.size() ||
      brillo::SecureMemcmp(hash_, salty_blob_hash.data(), sizeof(hash_))) {
    LOG(ERROR) << "Verify() hash mismatch!";
    return VerificationResult::kHashMismatch;
  }

  return VerificationResult::kValid;
}

}  // namespace cryptohome
