// 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.
  return (tpm_init_task_->get_tpm()->IsEnabled() &&
          tpm_init_task_->get_tpm()->IsOwned() &&
          !tpm_init_task_->get_tpm()->IsBeingOwned() &&
          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;
  }

  // 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()->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.
  SecureBlob random(kOwnerPasswordLength / 2);
  CryptoLib::GetSecureRandom(random.data(), random.size());
  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
