// 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/files/file_path.h>
#include <base/logging.h>
#include <base/notreached.h>
#include <base/time/time.h>

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

using base::FilePath;

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, Tpm::kLockboxIndex)),
      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(TpmInit* tpm_init) {
  // 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.
    tpm_init->RemoveTpmOwnerDependency(
        TpmPersistentState::TpmOwnerDependency::kInstallAttributes);
    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_init->IsTpmReady()) {
    // 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_init->IsTpmEnabled() && !tpm_init->IsTpmOwned()) {
      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;
        tpm_init->RemoveTpmOwnerDependency(
            TpmPersistentState::TpmOwnerDependency::kInstallAttributes);
        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;
  tpm_init->RemoveTpmOwnerDependency(
      TpmPersistentState::TpmOwnerDependency::kInstallAttributes);
  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
