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

#include <sys/types.h>

#include <limits>
#include <string>
#include <utility>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/time/time.h>
#include <libhwsec-foundation/tpm/tpm_version.h>

#include "cryptohome/install_attributes.pb.h"
#include "cryptohome/lockbox.h"
#include "cryptohome/tpm.h"

using base::FilePath;

namespace {

// Provides the TPM NVRAM index to be used by the underlying Lockbox instance.
uint32_t GetLockboxIndex() {
  TPM_SELECT_BEGIN;
  TPM1_SECTION({
    // See lockbox.md for information on how this was selected.
    return 0x20000004;
  });
  TPM2_SECTION({
    if (USE_TPM_DYNAMIC) {
      // For TPM runtime selection case.
      return 0x9da5b0;
    }
    return 0x800004;
  });
  OTHER_TPM_SECTION({
    LOG(ERROR) << "Failed to get the lockbox index on none supported TPM.";
    return 0;
  });
  TPM_SELECT_END;
}

}  // namespace

namespace cryptohome {

// Note: Changes in the format of the install attributes file might break
// rollback (go/rollback-data-restore). If possible, try to maintain backwards
// compatibility for four release cycles.
// By default, we store this with other cryptohome state.
const char InstallAttributes::kDefaultDataFile[] =
    "/home/.shadow/install_attributes.pb";
const mode_t InstallAttributes::kDataFilePermissions = 0644;
// This is the default location for the cache file.
const char InstallAttributes::kDefaultCacheFile[] =
    "/run/lockbox/install_attributes.pb";
const mode_t InstallAttributes::kCacheFilePermissions = 0644;

InstallAttributes::InstallAttributes(Tpm* tpm)
    : data_file_(kDefaultDataFile),
      cache_file_(kDefaultCacheFile),
      default_attributes_(new SerializedInstallAttributes()),
      default_lockbox_(new Lockbox(tpm, GetLockboxIndex())),
      default_platform_(new Platform()),
      attributes_(default_attributes_.get()),
      lockbox_(default_lockbox_.get()),
      platform_(default_platform_.get()) {
  SetTpm(tpm);  // make sure to check TPM status if needed.
  version_ = attributes_->version();  // versioning controlled by pb default.
}

InstallAttributes::~InstallAttributes() {}

void InstallAttributes::SetTpm(Tpm* tpm) {
  // Technically, it is safe to call SetTpm, then Init() again, but it could
  // also cause weirdness and report that data is TPM-backed when it isn't.
  DCHECK(status_ != Status::kValid && status_ != Status::kFirstInstall)
      << "SetTpm used after a successful Init().";
  if (tpm && !tpm->IsEnabled()) {
    LOG(WARNING) << "set_tpm() missing or disabled TPM provided.";
    tpm = NULL;  // Don't give it to Lockbox.
  }
  set_is_secure(tpm != NULL);
  lockbox_->set_tpm(tpm);
}

bool InstallAttributes::Init(Tpm* tpm) {
  // Ensure that if Init() was called and it failed, we can retry cleanly.
  attributes_->Clear();
  status_ = Status::kUnknown;

  // Read the cache file. If it exists, lockbox-cache has successfully
  // verified install attributes during early boot, so use them.
  brillo::Blob blob;
  if (platform_->ReadFile(cache_file_, &blob)) {
    if (!attributes_->ParseFromArray(
            static_cast<google::protobuf::uint8*>(blob.data()), blob.size())) {
      LOG(ERROR) << "Failed to parse data file (" << blob.size() << " bytes)";
      attributes_->Clear();
      status_ = Status::kInvalid;
      return false;
    }

    status_ = Status::kValid;
    // Install attributes are valid, no need to hold owner dependency. So,
    // repeat removing owner dependency in case it didn't succeed during the
    // first boot.
    if (tpm->RemoveOwnerDependency(
            Tpm::TpmOwnerDependency::kInstallAttributes)) {
      LOG(WARNING) << "Failed to RemoveOwnerDependency().";
    }
    LOG(INFO) << "Valid install attributes cache found.";
    return true;
  }

  // No cache file, so TPM lockbox is either not yet set up or data is invalid.
  if (!is_secure()) {
    LOG(INFO) << "Init() assuming first-time install for TPM-less system.";
    status_ = Status::kFirstInstall;
    return true;
  }

  // TPM not ready yet, i.e. setup after ownership not completed. Init() is
  // supposed to get invoked again once the TPM is owned and configured.
  if (!tpm->IsEnabled() || !tpm->IsOwned()) {
    // To ensure that we get a fresh start after taking ownership, remove the
    // data file when we boot up after a TPM clear. If we didn't do so, the
    // previous data file might validate against a left-around NVRAM space,
    // incorrectly indicating that install attributes are already initialized
    // and locked.
    //
    // Note that we theoretically could delete the file unconditionally here,
    // since IsTpmReady() should always return true after the TPM has been set
    // up correctly. However, previous experience tells us that there might be
    // hardware glitches or driver/firmware bugs that could make the TPM look
    // disabled. If we accidentally delete the data file in such a situation,
    // we'd make install attributes inconsistent until next TPM clear, which has
    // far-reaching consequences (enterprise enrollment would be lost for
    // example). Thus, be careful and only clear data if the TPM looks
    // positively unowned.
    if (tpm->IsEnabled() && !tpm->IsOwned()) {
      ClearData();
      // Don't flag invalid here - Chrome verifies that install attributes
      // aren't invalid before locking them as part of enterprise enrollment.
      LOG(INFO) << "Init() TPM is not ready and not owned, while install "
                << "attributes are missing or invalid.";
      status_ = Status::kTpmNotOwned;
      return false;
    }

    // Cases that don't look like a cleared TPM get flagged invalid.
    LOG(INFO) << "Init() TPM is not cleared, but install attributes are "
              << "missing or invalid.";
    status_ = Status::kInvalid;
    return false;
  }

  // The TPM is ready and we haven't found valid install attributes. This
  // usually means that we haven't written and locked the lockbox yet, so
  // attempt a reset. The reset may fail in various other edge cases and the
  // error code lets us identify and handle these edge cases correctly.
  LockboxError error_id;
  if (!lockbox()->Reset(&error_id)) {
    switch (error_id) {
      case LockboxError::kNvramSpaceAbsent:
        // Legacy install that didn't create space at OOBE.
        status_ = Status::kValid;
        if (tpm->RemoveOwnerDependency(
                Tpm::TpmOwnerDependency::kInstallAttributes)) {
          LOG(WARNING) << "Failed to RemoveOwnerDependency().";
        }
        LOG(INFO) << "Found legacy install that didn't create install "
                     "attributes NVRAM space at OOBE.";
        return true;
      case LockboxError::kNvramInvalid:
        LOG(ERROR) << "Inconsistent install attributes state.";
        status_ = Status::kInvalid;
        return false;
      case LockboxError::kTpmUnavailable:
        NOTREACHED() << "Should never call lockbox when TPM is unavailable.";
        status_ = Status::kInvalid;
        return false;
      case LockboxError::kTpmError:
        LOG(ERROR) << "TPM error on install attributes initialization.";
        status_ = Status::kInvalid;
        return false;
    }
  }

  // Reset succeeded, so we have a writable lockbox now.
  // Delete data file potentially left around from previous installation.
  if (!ClearData()) {
    // ClearData() will log its own error message if it fails.
    return false;
  }

  status_ = Status::kFirstInstall;
  if (tpm->RemoveOwnerDependency(Tpm::TpmOwnerDependency::kInstallAttributes)) {
    LOG(WARNING) << "Failed to RemoveOwnerDependency().";
  }
  LOG(INFO) << "Install attributes reset back to first install.";
  return true;
}

int InstallAttributes::FindIndexByName(const std::string& name) const {
  std::string name_str(name);
  for (int i = 0; i < attributes_->attributes_size(); ++i) {
    if (attributes_->attributes(i).name().compare(name_str) == 0)
      return i;
  }
  return -1;
}

bool InstallAttributes::Get(const std::string& name,
                            brillo::Blob* value) const {
  int index = FindIndexByName(name);
  if (index == -1)
    return false;
  return GetByIndex(index, NULL, value);
}

bool InstallAttributes::GetByIndex(int index,
                                   std::string* name,
                                   brillo::Blob* value) const {
  if (index < 0 || index >= attributes_->attributes_size()) {
    LOG(ERROR) << "GetByIndex called with invalid index.";
    return false;
  }
  const SerializedInstallAttributes::Attribute* const attr =
      &attributes_->attributes(index);
  if (name) {
    name->assign(attr->name());
  }
  if (value) {
    value->resize(attr->value().length());
    memcpy(&value->at(0), attr->value().c_str(), value->size());
  }
  return true;
}

bool InstallAttributes::Set(const std::string& name,
                            const brillo::Blob& value) {
  if (status_ != Status::kFirstInstall) {
    LOG(ERROR) << "Set() called on immutable attributes.";
    return false;
  }

  if (Count() == std::numeric_limits<int>::max()) {
    LOG(ERROR) << "Set() cannot insert into full attribute store.";
    return false;
  }

  // Clobber an existing entry if it exists.
  int index = FindIndexByName(name);
  if (index != -1) {
    SerializedInstallAttributes::Attribute* attr =
        attributes_->mutable_attributes(index);
    attr->set_value(
        std::string(reinterpret_cast<const char*>(value.data()), value.size()));
    return true;
  }

  SerializedInstallAttributes::Attribute* attr = attributes_->add_attributes();
  if (!attr) {
    LOG(ERROR) << "Failed to add a new attribute.";
    return false;
  }
  attr->set_name(name);
  attr->set_value(
      std::string(reinterpret_cast<const char*>(value.data()), value.size()));
  return true;
}

bool InstallAttributes::Finalize() {
  switch (status_) {
    case Status::kUnknown:
    case Status::kTpmNotOwned:
    case Status::kInvalid:
      LOG(ERROR) << "Finalize() called with invalid/uninitialized data.";
      return false;
    case Status::kValid:
      // Repeated calls to Finalize() are idempotent.
      return true;
    case Status::kFirstInstall:
      break;
    case Status::COUNT:
      NOTREACHED();
  }

  // Restamp the version.
  attributes_->set_version(version_);

  // Serialize the bytestream
  brillo::Blob attr_bytes;
  if (!SerializeAttributes(&attr_bytes)) {
    LOG(ERROR) << "Finalize() failed to serialize the attributes.";
    return false;
  }

  LockboxError error;
  DLOG(INFO) << "Finalizing() " << attr_bytes.size() << " bytes.";
  if (is_secure() && !lockbox()->Store(attr_bytes, &error)) {
    LOG(ERROR) << "Finalize() failed with Lockbox error: " << error;
    // It may be possible to recover from a failed NVRAM store. So the
    // instance is not marked invalid.
    return false;
  }

  if (!platform_->WriteFileAtomicDurable(data_file_, attr_bytes,
                                         kDataFilePermissions)) {
    LOG(ERROR) << "Finalize() write failed after locking the Lockbox.";
    attributes_->Clear();
    status_ = Status::kInvalid;
    return false;
  }

  // As the cache file is stored on tmpfs, durable write is not required but we
  // need atomicity to be safe in case of concurrent reads.
  if (!platform_->WriteFileAtomic(cache_file_, attr_bytes,
                                  kCacheFilePermissions)) {
    LOG(WARNING) << "Finalize() failed to create cache file.";
  }

  LOG(INFO) << "InstallAttributes have been finalized.";
  status_ = Status::kValid;
  NotifyFinalized();
  return true;
}

int InstallAttributes::Count() const {
  return attributes_->attributes_size();
}

bool InstallAttributes::SerializeAttributes(brillo::Blob* out_bytes) {
  out_bytes->resize(attributes_->ByteSizeLong());
  attributes_->SerializeWithCachedSizesToArray(
      static_cast<google::protobuf::uint8*>(out_bytes->data()));
  return true;
}

bool InstallAttributes::ClearData() {
  if (platform_->FileExists(data_file_) && !platform_->DeleteFile(data_file_)) {
    LOG(ERROR) << "Failed to delete install attributes data file!";
    return false;
  }
  return true;
}

base::Value InstallAttributes::GetStatus() {
  base::Value dv(base::Value::Type::DICTIONARY);
  dv.SetBoolKey("initialized",
                status_ == Status::kFirstInstall || status_ == Status::kValid);
  dv.SetIntKey("version", version());
  dv.SetIntKey("lockbox_index", lockbox()->nvram_index());
  dv.SetIntKey("lockbox_nvram_version",
               GetNvramVersionNumber(lockbox()->nvram_version()));
  dv.SetBoolKey("secure", is_secure());
  dv.SetBoolKey("invalid", status_ == Status::kInvalid);
  dv.SetBoolKey("first_install", status_ == Status::kFirstInstall);
  dv.SetIntKey("size", Count());
  if (Count()) {
    base::Value attrs(base::Value::Type::DICTIONARY);
    std::string key;
    brillo::Blob value;
    for (int i = 0; i < Count(); i++) {
      GetByIndex(i, &key, &value);
      std::string value_str(reinterpret_cast<const char*>(value.data()));
      attrs.SetStringKey(key, value_str);
    }
    dv.SetKey("attrs", std::move(attrs));
  }
  return dv;
}

}  // namespace cryptohome
