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

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

#include "install_attributes.pb.h"  // NOLINT(build/include)

using base::FilePath;

namespace cryptohome {

// By default, we store this with other cryptohome state.
const FilePath::CharType InstallAttributes::kDefaultDataFile[] =
  "/home/.shadow/install_attributes.pb";
const mode_t InstallAttributes::kDataFilePermissions = 0644;
// This is the default location for the cache file.
const FilePath::CharType InstallAttributes::kDefaultCacheFile[] =
  "/var/run/lockbox/install_attributes.pb";
const mode_t InstallAttributes::kCacheFilePermissions = 0644;

InstallAttributes::InstallAttributes(Tpm* tpm)
  : is_first_install_(false),
    is_invalid_(false),
    is_initialized_(false),
    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() {
}

bool InstallAttributes::PrepareSystem() {
  set_is_first_install(true);
  Lockbox::ErrorId error_id;
  // Delete the attributes file if it exists.
  if (platform_->FileExists(data_file_) &&
      !platform_->DeleteFile(data_file_, false)) {
    LOG(ERROR) << "PrepareSystem() unable to delete old data!";
    return false;
  }
  // If a TPM is in use, let's clean up the lockbox.
  if (is_secure())
    return lockbox()->Destroy(&error_id);
  return true;
}

void InstallAttributes::SetIsInvalid(bool is_invalid) {
  // If a store is invalid, make sure it is forced to be empty.
  is_invalid_ = is_invalid;
  if (is_invalid) {
    set_is_first_install(false);
    attributes_->Clear();
  }
}

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(!is_initialized()) << "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) {
  Lockbox::ErrorId error_id;

  // Insure that if Init() was called and it failed, we can retry cleanly.
  attributes_->Clear();
  SetIsInvalid(false);
  set_is_initialized(false);

  if (is_first_install()) {
    if (!is_secure()) {
      LOG(WARNING) << "InstallAttributes are insecure without a TPM.";
      set_is_initialized(true);
      return true;
    }
    if (!lockbox()->Create(&error_id)) {
      if (error_id == Lockbox::kErrorIdInsufficientAuthorization)
        LOG(ERROR) << "First install, but no TPM credentials provided.";
      SetIsInvalid(true);
      return false;
    }

    set_is_initialized(true);
    tpm_init->RemoveTpmOwnerDependency(TpmInit::kInstallAttributes);
    return true;
  }

  if (is_secure() && !lockbox()->Load(&error_id)) {
    // There are two non-terminal error cases:
    // 1. No NVRAM space is defined.  This will occur on systems that
    //    are autoupdated with this code but never went through the OOBE,
    //    or if creation was interrupted after TPM Ownership happened.
    // 2. NVRAM space exists and is unlocked. It means the system was powered
    //    off before any data was stored.
    switch (error_id) {
    case Lockbox::kErrorIdNoNvramSpace:
      LOG(INFO) << "Resuming interrupted InstallAttributes. (Create needed.)";
      if (!lockbox()->Create(&error_id)) {
        if (error_id == Lockbox::kErrorIdInsufficientAuthorization)
          DLOG(INFO) << "Legacy install. (Can never create NVRAM space.)";
        else
          LOG(ERROR) << "Create failed, Lockbox error: " << error_id;
      } else {
        // Create worked, so act like the kErrorIdNoNvramData path now.
        set_is_first_install(true);
      }
      set_is_initialized(true);
      // No data.
      return true;
      break;
    case Lockbox::kErrorIdNoNvramData:
      LOG(INFO) << "Resuming interrupted InstallAttributes. (Store needed.)";
      set_is_first_install(true);
      set_is_initialized(true);
      // Since we write when we finalize, we don't try to reparse.
      return true;
      break;
    default:
      LOG(ERROR) << "InstallAttributes failed to initialize.";
      SetIsInvalid(true);
      return false;
    }
  }

  // Load the file from disk.
  brillo::Blob blob;
  if (!platform_->ReadFile(data_file_, &blob)) {
    LOG(WARNING) << "Init() failed to read attributes file.";
    // If this is an insecure install, then we can just start the
    // file fresh, otherwise it signifies tampering.
    if (is_secure()) {
      SetIsInvalid(true);
      return false;
    }
    LOG(INFO) << "Init() assuming first-time install for TPM-less system.";
    set_is_first_install(true);
    set_is_initialized(true);
    return true;
  }

  // Prior to attempting to deserialize the data, ensure it has not
  // been tampered with.
  if (is_secure() && !lockbox()->Verify(blob, &error_id)) {
    LOG(ERROR) << "Init() could not verify attribute data!";
    SetIsInvalid(true);
    return false;
  }

  if (!attributes_->ParseFromArray(
         static_cast<google::protobuf::uint8*>(blob.data()),
         blob.size())) {
    LOG(ERROR) << "Failed to parse data file (" << blob.size() << " bytes)";
    SetIsInvalid(true);
    return false;
  }

  set_is_initialized(true);
  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 (!is_first_install()) {
    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() {
  if (!IsReady()) {
    LOG(ERROR) << "Finalize() called with invalid/uninitialized data.";
    return false;
  }
  // Repeated calls to Finalize() are idempotent.
  if (!is_first_install())
    return true;

  // 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;
  }

  Lockbox::ErrorId 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.";
    SetIsInvalid(true);
    return false;
  }

  // Since the cache file is re-created upon every boot, atomic write is not
  // required.
  if (!platform_->WriteFile(cache_file_, attr_bytes) ||
      !platform_->SetPermissions(cache_file_, kCacheFilePermissions)) {
    LOG(WARNING) << "Finalize() failed to create cache file.";
  }

  LOG(INFO) << "InstallAttributes have been finalized.";
  set_is_first_install(false);
  NotifyFinalized();
  return true;
}

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

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

base::Value* InstallAttributes::GetStatus() {
  base::DictionaryValue* dv = new base::DictionaryValue();
  dv->SetBoolean("initialized", is_initialized());
  dv->SetInteger("version", version());
  dv->SetInteger("lockbox_index", lockbox()->nvram_index());
  dv->SetInteger("lockbox_nvram_version", lockbox()->nvram_version());
  dv->SetBoolean("secure", is_secure());
  dv->SetBoolean("invalid", is_invalid());
  dv->SetBoolean("first_install", is_first_install());
  dv->SetInteger("size", Count());
  if (Count()) {
    base::DictionaryValue* attrs = new base::DictionaryValue();
    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->SetString(key, value_str);
    }
    dv->Set("attrs", attrs);
  }
  return dv;
}

}  // namespace cryptohome
