// 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.

// Contains the implementation of class TpmInit

#include "cryptohome/tpm_init.h"

#include <stdint.h>

#include <string>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>

#include "cryptohome/attestation.h"
#include "cryptohome/cryptolib.h"
#include "cryptohome/interface.h"

using base::FilePath;
using base::PlatformThread;
using base::PlatformThreadHandle;
using brillo::SecureBlob;

namespace cryptohome {

const int kMaxTimeoutRetries = 5;

const FilePath kMiscTpmCheckEnabledFile("/sys/class/misc/tpm0/device/enabled");
const FilePath kMiscTpmCheckOwnedFile("/sys/class/misc/tpm0/device/owned");
const FilePath kTpmTpmCheckEnabledFile("/sys/class/tpm/tpm0/device/enabled");
const FilePath kTpmTpmCheckOwnedFile("/sys/class/tpm/tpm0/device/owned");
const FilePath kDefaultCryptohomeKeyFile("/home/.shadow/cryptohome.key");

const int kOwnerPasswordLength = 12;
const unsigned int kDefaultTpmRsaKeyBits = 2048;

// TpmInitTask is a private class used to handle asynchronous initialization of
// the TPM.
class TpmInitTask : public PlatformThread::Delegate {
 public:
  TpmInitTask() : tpm_(NULL), init_(NULL) {}
  virtual ~TpmInitTask() {}

  void Init(TpmInit* init) {
    init_ = init;
    if (tpm_) {
      init->SetupTpm(false);
    }
  }

  virtual void ThreadMain() {
    if (init_) {
      init_->ThreadMain();
    }
  }

  void set_tpm(Tpm* tpm) { tpm_ = tpm; }
  Tpm* get_tpm() { return tpm_; }

 private:
  Tpm* tpm_;
  TpmInit* init_;
};

TpmInit::TpmInit(Tpm* tpm, Platform* platform)
    : tpm_init_task_(new TpmInitTask()),
      platform_(platform),
      tpm_persistent_state_(platform) {
  set_tpm(tpm);
}

TpmInit::~TpmInit() {
  if (!init_thread_.is_null()) {
    // Must wait for tpm init thread to complete, because when the main thread
    // exits some libtspi data structures are freed.
    PlatformThread::Join(init_thread_);
    init_thread_ = PlatformThreadHandle();
  }
}

void TpmInit::set_tpm(Tpm* value) {
  if (tpm_init_task_.get())
    tpm_init_task_->set_tpm(value);
}

Tpm* TpmInit::get_tpm() {
  if (tpm_init_task_.get())
    return tpm_init_task_->get_tpm();
  return NULL;
}

void TpmInit::Init(OwnershipCallback ownership_callback) {
  ownership_callback_ = ownership_callback;
  tpm_init_task_->Init(this);
}

bool TpmInit::AsyncTakeOwnership() {
  tpm_persistent_state_.SetShallInitialize(true);
  take_ownership_called_ = true;
  if (!PlatformThread::Create(0, tpm_init_task_.get(), &init_thread_)) {
    LOG(ERROR) << "Unable to create background thread to take TPM ownership.";
    return false;
  }
  return true;
}

bool TpmInit::IsTpmReady() {
  // The TPM is "ready" if it is enabled, owned, and not being owned.
  Tpm* tpm = tpm_init_task_->get_tpm();
  if (!tpm->IsEnabled() || !tpm->IsOwned() || tpm->IsBeingOwned()) {
    return false;
  }
  // When |tpm| implementation uses tpm manager, readiness flag in
  // |TpmPersistentState| is meaningless since the tpm manager also take care of
  // all the follow-up actions after taking ownership.
  return tpm->DoesUseTpmManager() || tpm_persistent_state_.IsReady();
}

bool TpmInit::IsTpmEnabled() {
  return tpm_init_task_->get_tpm()->IsEnabled();
}

bool TpmInit::IsTpmOwned() {
  return tpm_init_task_->get_tpm()->IsOwned();
}

void TpmInit::SetTpmOwned(bool owned) {
  tpm_init_task_->get_tpm()->SetIsOwned(owned);
}

bool TpmInit::IsTpmBeingOwned() {
  return tpm_init_task_->get_tpm()->IsBeingOwned();
}

void TpmInit::SetTpmBeingOwned(bool being_owned) {
  tpm_init_task_->get_tpm()->SetIsBeingOwned(being_owned);
}

bool TpmInit::OwnershipRequested() {
  return take_ownership_called_;
}

bool TpmInit::GetTpmPassword(brillo::SecureBlob* password) {
  return tpm_init_task_->get_tpm()->GetOwnerPassword(password);
}

void TpmInit::ClearStoredTpmPassword() {
  if (tpm_persistent_state_.ClearStoredPasswordIfNotNeeded()) {
    get_tpm()->ClearStoredPassword();
  }
}

void TpmInit::ThreadMain() {
  base::TimeTicks start = base::TimeTicks::Now();
  bool ownership_result = TakeOwnership(&took_ownership_);
  base::TimeDelta delta = (base::TimeTicks::Now() - start);
  initialization_time_ = delta.InMilliseconds();
  if (took_ownership_) {
    LOG(ERROR) << "Taking TPM ownership took " << initialization_time_ << "ms";
  }
  if (!ownership_callback_.is_null()) {
    ownership_callback_.Run(ownership_result, took_ownership_);
  }
}

bool TpmInit::SetupTpm(bool load_key) {
  const bool was_initialized = get_tpm()->IsInitialized();
  if (!was_initialized) {
    get_tpm()->SetIsInitialized(true);
    RestoreTpmStateFromStorage();
  }

  // Collect version statistics.
  if (!statistics_reported_) {
    Tpm::TpmVersionInfo version_info;
    if (get_tpm()->GetVersionInfo(&version_info)) {
      ReportVersionFingerprint(version_info.GetFingerprint());
      statistics_reported_ = true;
    }
  }

  if (load_key) {
    // load cryptohome key
    LoadOrCreateCryptohomeKey(&cryptohome_key_);
  }
  return !was_initialized;
}

void TpmInit::RestoreTpmStateFromStorage() {
  // Checking disabled and owned either via sysfs or via TSS calls will block if
  // ownership is being taken by another thread or process.  So for this to work
  // well, SetupTpm() needs to be called before TakeOwnership() is called.  At
  // that point, the public API for Tpm only checks these booleans, so other
  // threads can check without being blocked.  TakeOwnership() will reset the
  // TPM's is_owned_ bit on success.
  bool is_enabled = false;
  bool is_owned = false;
  bool successful_check = false;
  if (platform_->FileExists(kTpmTpmCheckEnabledFile)) {
    is_enabled = IsEnabledCheckViaSysfs(kTpmTpmCheckEnabledFile);
    is_owned = IsOwnedCheckViaSysfs(kTpmTpmCheckOwnedFile);
    successful_check = true;
  } else if (platform_->FileExists(kMiscTpmCheckEnabledFile)) {
    is_enabled = IsEnabledCheckViaSysfs(kMiscTpmCheckEnabledFile);
    is_owned = IsOwnedCheckViaSysfs(kMiscTpmCheckOwnedFile);
    successful_check = true;
  } else {
    if (get_tpm()->PerformEnabledOwnedCheck(&is_enabled, &is_owned)) {
      successful_check = true;
    }
  }

  get_tpm()->SetIsOwned(is_owned);
  get_tpm()->SetIsEnabled(is_enabled);

  if (successful_check && !is_owned) {
    tpm_persistent_state_.SetReady(false);
    tpm_persistent_state_.ClearStatus();
  }

  SecureBlob local_owner_password;
  if (LoadOwnerPassword(&local_owner_password)) {
    get_tpm()->SetOwnerPassword(local_owner_password);
  }
}

bool TpmInit::TakeOwnership(bool* OUT_took_ownership) {
  if (OUT_took_ownership) {
    *OUT_took_ownership = false;
  }

  if (!IsTpmEnabled()) {
    return false;
  }

  SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
  memcpy(default_owner_password.data(), kTpmWellKnownPassword,
         sizeof(kTpmWellKnownPassword));

  bool took_ownership = false;
  if (!IsTpmOwned()) {
    SetTpmBeingOwned(true);
    tpm_persistent_state_.SetReady(false);
    tpm_persistent_state_.ClearStatus();

    if (!get_tpm()->IsEndorsementKeyAvailable()) {
      if (!get_tpm()->CreateEndorsementKey()) {
        LOG(ERROR) << "Failed to create endorsement key";
        SetTpmBeingOwned(false);
        return false;
      }
    }

    if (!get_tpm()->IsEndorsementKeyAvailable()) {
      LOG(ERROR) << "Endorsement key is not available";
      SetTpmBeingOwned(false);
      return false;
    }

    if (!get_tpm()->TakeOwnership(kMaxTimeoutRetries, default_owner_password)) {
      LOG(ERROR) << "Take Ownership failed";
      SetTpmBeingOwned(false);
      return false;
    }

    tpm_persistent_state_.SetDefaultPassword();
    SetTpmOwned(true);
    took_ownership = true;
  }

  if (OUT_took_ownership) {
    *OUT_took_ownership = took_ownership;
  }

  // In monolithic mode, if we can open the TPM with the default password, then
  // we still need to zero the SRK password and unrestrict it, then change the
  // owner password.
  if (!tpm_persistent_state_.IsReady() &&
      !get_tpm()->DoesUseTpmManager() &&
      get_tpm()->TestTpmAuth(default_owner_password)) {
    if (!get_tpm()->InitializeSrk(default_owner_password)) {
      LOG(ERROR) << "Couldn't initialize the SRK";
      SetTpmBeingOwned(false);
      return false;
    }

    SecureBlob owner_password;
    CreateOwnerPassword(&owner_password);

    SecureBlob sealed_password;
    if (!get_tpm()->SealToPCR0(owner_password, &sealed_password)) {
      LOG(ERROR) << "Failed to seal owner password.";
      return false;
    }
    if (!tpm_persistent_state_.SetSealedPassword(sealed_password)) {
      LOG(ERROR) << "Couldn't store the owner password.";
      return false;
    }

    if ((!get_tpm()->ChangeOwnerPassword(default_owner_password,
                                         owner_password))) {
      LOG(ERROR) << "Couldn't change the owner password.";
      return false;
    }
    get_tpm()->SetOwnerPassword(owner_password);
  }

  // If we fall through here, either (1) we successfully completed the
  // initialization, or (2) then the TPM owned file doesn't exist, but we
  // couldn't auth with the well-known password. In the second case, we must
  // assume that the TPM has already been owned and set to a random password.
  // In any case, it's time to touch the TPM owned file to indicate that we
  // don't need to re-attempt completing initialization on the next boot.
  tpm_persistent_state_.SetReady(true);
  tpm_persistent_state_.SetShallInitialize(false);

  SetTpmBeingOwned(false);
  return true;
}

void TpmInit::CreateOwnerPassword(SecureBlob* password) {
  // Generate a random owner password.  The default is a 12-character,
  // hex-encoded password created from 6 bytes of random data.
  const auto random =
      CryptoLib::CreateSecureRandomBlob(kOwnerPasswordLength / 2);
  SecureBlob tpm_password(kOwnerPasswordLength);
  CryptoLib::SecureBlobToHexToBuffer(random,
                                     tpm_password.data(),
                                     tpm_password.size());
  password->swap(tpm_password);
}

bool TpmInit::LoadOwnerPassword(brillo::SecureBlob* owner_password) {
  SecureBlob sealed_password;
  if (!tpm_persistent_state_.GetSealedPassword(&sealed_password)) {
    return false;
  }
  if (sealed_password.empty()) {
    // Empty password means default password.
    owner_password->resize(sizeof(kTpmWellKnownPassword));
    memcpy(owner_password->data(), kTpmWellKnownPassword,
           sizeof(kTpmWellKnownPassword));
    return true;
  }
  if (!get_tpm()->Unseal(sealed_password, owner_password)) {
    LOG(ERROR) << "Failed to unseal the owner password.";
    return false;
  }
  return true;
}

void TpmInit::RemoveTpmOwnerDependency(
    TpmPersistentState::TpmOwnerDependency dependency) {
  if (!get_tpm()->RemoveOwnerDependency(dependency)) {
    return;
  }
  tpm_persistent_state_.ClearDependency(dependency);
}

bool TpmInit::CheckSysfsForOne(const FilePath& file_name) const {
  std::string contents;
  if (!platform_->ReadFileToString(file_name, &contents)) {
    return false;
  }
  if (contents.size() < 1) {
    return false;
  }
  return (contents[0] == '1');
}

bool TpmInit::IsEnabledCheckViaSysfs(const FilePath& enabled_file) {
  return CheckSysfsForOne(enabled_file);
}

bool TpmInit::IsOwnedCheckViaSysfs(const FilePath& owned_file) {
  return CheckSysfsForOne(owned_file);
}

bool TpmInit::CreateCryptohomeKey() {
  if (!IsTpmReady()) {
    LOG(WARNING) << "Canceled creating cryptohome key - TPM is not ready.";
    return false;
  }
  SecureBlob n;
  SecureBlob p;
  if (!CryptoLib::CreateRsaKey(kDefaultTpmRsaKeyBits, &n, &p)) {
    LOG(ERROR) << "Error creating RSA key";
    return false;
  }
  SecureBlob wrapped_key;
  if (!get_tpm()->WrapRsaKey(n, p, &wrapped_key)) {
    LOG(ERROR) << "Couldn't wrap cryptohome key";
    return false;
  }

  if (!SaveCryptohomeKey(wrapped_key)) {
    LOG(ERROR) << "Couldn't save cryptohome key";
    return false;
  }

  LOG(INFO) << "Created new cryptohome key.";
  return true;
}

bool TpmInit::SaveCryptohomeKey(const brillo::SecureBlob& wrapped_key) {
  bool ok = platform_->WriteSecureBlobToFileAtomicDurable(
      kDefaultCryptohomeKeyFile, wrapped_key, 0600);
  if (!ok)
    LOG(ERROR) << "Error writing key file of desired size: "
               << wrapped_key.size();
  return ok;
}

Tpm::TpmRetryAction TpmInit::LoadCryptohomeKey(ScopedKeyHandle* key_handle) {
  CHECK(key_handle);
  // First, try loading the key from the key file.
  {
    SecureBlob raw_key;
    if (platform_->ReadFileToSecureBlob(kDefaultCryptohomeKeyFile, &raw_key)) {
      Tpm::TpmRetryAction retry_action =
          get_tpm()->LoadWrappedKey(raw_key, key_handle);
      if (retry_action == Tpm::kTpmRetryNone ||
          get_tpm()->IsTransient(retry_action)) {
        return retry_action;
      }
    }
  }

  // Then try loading the key by the UUID (this is a legacy upgrade path).
  SecureBlob raw_key;
  if (!get_tpm()->LegacyLoadCryptohomeKey(key_handle, &raw_key)) {
    return Tpm::kTpmRetryFailNoRetry;
  }

  // Save the cryptohome key to the well-known location.
  if (!SaveCryptohomeKey(raw_key)) {
    LOG(ERROR) << "Couldn't save cryptohome key";
    return Tpm::kTpmRetryFailNoRetry;
  }
  return Tpm::kTpmRetryNone;
}

bool TpmInit::LoadOrCreateCryptohomeKey(ScopedKeyHandle* key_handle) {
  CHECK(key_handle);
  // Try to load the cryptohome key.
  Tpm::TpmRetryAction retry_action = LoadCryptohomeKey(key_handle);
  if (retry_action != Tpm::kTpmRetryNone &&
      !get_tpm()->IsTransient(retry_action)) {
    // The key couldn't be loaded, and it wasn't due to a transient error,
    // so we must create the key.
    if (CreateCryptohomeKey()) {
      retry_action = LoadCryptohomeKey(key_handle);
    }
  }
  return retry_action == Tpm::kTpmRetryNone;
}

bool TpmInit::HasCryptohomeKey() {
  return (cryptohome_key_.value() != kInvalidKeyHandle);
}

TpmKeyHandle TpmInit::GetCryptohomeKey() {
  return cryptohome_key_.value();
}

bool TpmInit::ReloadCryptohomeKey() {
  CHECK(HasCryptohomeKey());
  // Release the handle first, we know this handle doesn't contain a loaded key
  // since ReloadCryptohomeKey only called after we failed to use it.
  // Otherwise we may flush the newly loaded key and fail to use it again,
  // if it is loaded to the same handle.
  // TODO(crbug.com/687330): change to closing the handle and ignoring errors
  // once checking for stale virtual handles is implemented in trunksd.
  cryptohome_key_.release();
  if (LoadCryptohomeKey(&cryptohome_key_) != Tpm::kTpmRetryNone) {
    LOG(ERROR) << "Error reloading Cryptohome key.";
    return false;
  }
  return true;
}

bool TpmInit::GetVersion(Tpm::TpmVersionInfo* version_info) {
  return get_tpm() && get_tpm()->GetVersionInfo(version_info);
}

bool TpmInit::ShallInitialize() {
  return tpm_persistent_state_.ShallInitialize();
}

}  // namespace cryptohome
