// 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/logging.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>
#include <trousers/scoped_tss_type.h>

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

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

namespace cryptohome {

const int kMaxTimeoutRetries = 5;

const char* kTpmCheckEnabledFile = "/sys/class/misc/tpm0/device/enabled";
const char* kTpmCheckOwnedFile = "/sys/class/misc/tpm0/device/owned";
const char* kTpmOwnedFileOld = "/var/lib/.tpm_owned";
const char* kTpmStatusFileOld = "/var/lib/.tpm_status";
const char* kTpmOwnedFile = "/mnt/stateful_partition/.tpm_owned";
const char* kTpmStatusFile = "/mnt/stateful_partition/.tpm_status";
const char* kOpenCryptokiPath = "/var/lib/opencryptoki";
const char kDefaultCryptohomeKeyFile[] = "/home/.shadow/cryptohome.key";

const int kOwnerPasswordLength = 12;
const unsigned int kDefaultTpmRsaKeyBits = 2048;
const char kTpmWellKnownPassword[] = TSS_WELL_KNOWN_SECRET;

// 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()),
      notify_callback_(NULL),
      initialize_called_(false),
      initialize_took_ownership_(false),
      initialization_time_(0),
      platform_(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(TpmInitCallback* notify_callback) {
  notify_callback_ = notify_callback;
  tpm_init_task_->Init(this);
}

bool TpmInit::AsyncInitializeTpm() {
  initialize_called_ = true;
  if (!PlatformThread::Create(0, tpm_init_task_.get(), &init_thread_)) {
    LOG(ERROR) << "Unable to create TPM initialization background thread.";
    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());
}

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::HasInitializeBeenCalled() {
  return initialize_called_;
}

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

void TpmInit::ClearStoredTpmPassword() {
  TpmStatus tpm_status;
  if (LoadTpmStatus(&tpm_status)) {
    int32_t dependency_flags = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
                               TpmStatus::ATTESTATION_NEEDS_OWNER;
    if (tpm_status.flags() & dependency_flags) {
      // The password is still needed, do not clear.
      return;
    }
    if (tpm_status.has_owner_password()) {
      tpm_status.clear_owner_password();
      StoreTpmStatus(tpm_status);
    }
  }
  SecureBlob empty;
  get_tpm()->SetOwnerPassword(empty);
}

void TpmInit::ThreadMain() {
  base::TimeTicks start = base::TimeTicks::Now();
  bool initialize_result = InitializeTpm(
      &initialize_took_ownership_);
  base::TimeDelta delta = (base::TimeTicks::Now() - start);
  initialization_time_ = delta.InMilliseconds();
  if (initialize_took_ownership_) {
    LOG(ERROR) << "TPM initialization took " << initialization_time_ << "ms";
  }
  if (notify_callback_) {
    notify_callback_->InitializeTpmComplete(initialize_result,
                                            initialize_took_ownership_);
  }
}

void TpmInit::MigrateStatusFiles() {
  if (!platform_->FileExists(kTpmOwnedFile) &&
      platform_->FileExists(kTpmOwnedFileOld)) {
    platform_->Move(kTpmOwnedFileOld, kTpmOwnedFile);
  }
  if (!platform_->FileExists(kTpmStatusFile) &&
      platform_->FileExists(kTpmStatusFileOld)) {
    platform_->Move(kTpmStatusFileOld, kTpmStatusFile);
  }
}

bool TpmInit::SetupTpm(bool load_key) {
  if (get_tpm()->IsInitialized()) {
    return false;
  }
  get_tpm()->SetIsInitialized(true);

  MigrateStatusFiles();

  // 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 InitializeTpm() is called.  At
  // that point, the public API for Tpm only checks these booleans, so other
  // threads can check without being blocked.  InitializeTpm() 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(kTpmCheckEnabledFile)) {
    is_enabled = IsEnabledCheckViaSysfs();
    is_owned = IsOwnedCheckViaSysfs();
    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) {
    platform_->DeleteFileDurable(kOpenCryptokiPath, true);
    platform_->DeleteFileDurable(kTpmOwnedFile, false);
    platform_->DeleteFileDurable(kTpmStatusFile, false);
  }
  if (successful_check && is_owned) {
    if (!platform_->FileExists(kTpmOwnedFile)) {
      platform_->TouchFileDurable(kTpmOwnedFile);
    }
  }

  TpmStatus tpm_status;
  if (LoadTpmStatus(&tpm_status)) {
    if (tpm_status.has_owner_password()) {
      SecureBlob local_owner_password;
      if (LoadOwnerPassword(tpm_status, &local_owner_password)) {
        get_tpm()->SetOwnerPassword(local_owner_password);
      }
    }
  }

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

bool TpmInit::InitializeTpm(bool* OUT_took_ownership) {
  TpmStatus tpm_status;

  if (!LoadTpmStatus(&tpm_status)) {
    tpm_status.Clear();
    tpm_status.set_flags(TpmStatus::NONE);
  }

  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);
    platform_->DeleteFileDurable(kOpenCryptokiPath, true);
    platform_->DeleteFileDurable(kTpmOwnedFile, false);
    platform_->DeleteFileDurable(kTpmStatusFile, false);

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

    SetTpmOwned(true);
    took_ownership = true;

    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
                         TpmStatus::USES_WELL_KNOWN_OWNER |
                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
                         TpmStatus::ATTESTATION_NEEDS_OWNER);
    tpm_status.clear_owner_password();
    StoreTpmStatus(tpm_status);
  }

  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 (!platform_->FileExists(kTpmOwnedFile) &&
      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);

    tpm_status.set_flags(TpmStatus::OWNED_BY_THIS_INSTALL |
                         TpmStatus::USES_RANDOM_OWNER |
                         TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER |
                         TpmStatus::ATTESTATION_NEEDS_OWNER);
    if (!StoreOwnerPassword(owner_password, &tpm_status)) {
      tpm_status.clear_owner_password();
    }
    StoreTpmStatus(tpm_status);

    if ((get_tpm()->ChangeOwnerPassword(default_owner_password,
                                        owner_password))) {
      get_tpm()->SetOwnerPassword(owner_password);
    }
    platform_->TouchFileDurable(kTpmOwnedFile);
  } else {
    // If we fall through here, then the TPM owned file doesn't exist, but we
    // couldn't auth with the well-known password.  In this case, we must assume
    // that the TPM has already been owned and set to a random password, so
    // touch the TPM owned file.
    if (!platform_->FileExists(kTpmOwnedFile)) {
      platform_->TouchFileDurable(kTpmOwnedFile);
    }
  }

  SetTpmBeingOwned(false);
  return true;
}

bool TpmInit::LoadTpmStatus(TpmStatus* serialized) {
  if (!platform_->FileExists(kTpmStatusFile)) {
    return false;
  }
  SecureBlob file_data;
  if (!platform_->ReadFile(kTpmStatusFile, &file_data)) {
    return false;
  }
  if (!serialized->ParseFromArray(file_data.data(), file_data.size())) {
    return false;
  }
  return true;
}

bool TpmInit::StoreTpmStatus(const TpmStatus& serialized) {
  if (platform_->FileExists(kTpmStatusFile)) {
    // Shred old status file, not very useful on SSD. :(
    do {
      int64_t file_size;
      if (!platform_->GetFileSize(kTpmStatusFile, &file_size)) {
        break;
      }
      SecureBlob random;
      if (!get_tpm()->GetRandomData(file_size, &random)) {
        break;
      }
      platform_->WriteFile(kTpmStatusFile, random);
      platform_->DataSyncFile(kTpmStatusFile);
    } while (false);
    platform_->DeleteFile(kTpmStatusFile, false);
  }

  SecureBlob final_blob(serialized.ByteSize());
  serialized.SerializeWithCachedSizesToArray(
      static_cast<google::protobuf::uint8*>(final_blob.data()));
  bool ok = platform_->WriteFileAtomicDurable(kTpmStatusFile, final_blob, 0600);
  return ok;
}

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::BlobToHexToBuffer(random,
                               tpm_password.data(),
                               tpm_password.size());
  password->swap(tpm_password);
}

bool TpmInit::LoadOwnerPassword(const TpmStatus& tpm_status,
                                brillo::Blob* owner_password) {
  if (!(tpm_status.flags() & TpmStatus::OWNED_BY_THIS_INSTALL)) {
    return false;
  }
  if ((tpm_status.flags() & TpmStatus::USES_WELL_KNOWN_OWNER)) {
    SecureBlob default_owner_password(sizeof(kTpmWellKnownPassword));
    memcpy(default_owner_password.data(), kTpmWellKnownPassword,
           sizeof(kTpmWellKnownPassword));
    owner_password->swap(default_owner_password);
    return true;
  }
  if (!(tpm_status.flags() & TpmStatus::USES_RANDOM_OWNER) ||
      !tpm_status.has_owner_password()) {
    return false;
  }

  SecureBlob local_owner_password(tpm_status.owner_password().length());
  tpm_status.owner_password().copy(
      local_owner_password.char_data(),
      tpm_status.owner_password().length(), 0);
  if (!get_tpm()->Unseal(local_owner_password, owner_password)) {
    LOG(ERROR) << "Failed to unseal the owner password.";
    return false;
  }
  return true;
}

bool TpmInit::StoreOwnerPassword(const brillo::Blob& owner_password,
                                 TpmStatus* tpm_status) {
  // Use PCR0 when sealing the data so that the owner password is only
  // available in the current boot mode.  This helps protect the password from
  // offline attacks until it has been presented and cleared.
  SecureBlob sealed_password;
  if (!get_tpm()->SealToPCR0(owner_password, &sealed_password)) {
    LOG(ERROR) << "StoreOwnerPassword: Failed to seal owner password.";
    return false;
  }
  tpm_status->set_owner_password(sealed_password.data(),
                                 sealed_password.size());
  return true;
}

void TpmInit::RemoveTpmOwnerDependency(TpmOwnerDependency dependency) {
  int32_t flag_to_clear = TpmStatus::NONE;
  switch (dependency) {
    case kInstallAttributes:
      flag_to_clear = TpmStatus::INSTALL_ATTRIBUTES_NEEDS_OWNER;
      break;
    case kAttestation:
      flag_to_clear = TpmStatus::ATTESTATION_NEEDS_OWNER;
      break;
    default:
      CHECK(false);
  }
  TpmStatus tpm_status;
  if (!LoadTpmStatus(&tpm_status))
    return;
  tpm_status.set_flags(tpm_status.flags() & ~flag_to_clear);
  StoreTpmStatus(tpm_status);
}

bool TpmInit::CheckSysfsForOne(const char* 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() {
  return CheckSysfsForOne(kTpmCheckEnabledFile);
}

bool TpmInit::IsOwnedCheckViaSysfs() {
  return CheckSysfsForOne(kTpmCheckOwnedFile);
}

bool TpmInit::CreateCryptohomeKey() {
  SecureBlob n;
  SecureBlob p;
  if (!CryptoLib::CreateRsaKey(kDefaultTpmRsaKeyBits, &n, &p)) {
    LOG(ERROR) << "Error creating RSA key";
    return false;
  }
  brillo::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& raw_key) {
  bool ok = platform_->WriteFileAtomicDurable(kDefaultCryptohomeKeyFile,
                                              raw_key, 0600);
  if (!ok)
    LOG(ERROR) << "Error writing key file of desired size: " << raw_key.size();
  return ok;
}

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

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

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

bool TpmInit::LoadOrCreateCryptohomeKey(ScopedKeyHandle* key_handle) {
  CHECK(key_handle);
  // Try to load the cryptohome key.
  if (LoadCryptohomeKey(key_handle)) {
    return true;
  }

  // Otherwise, the key couldn't be loaded, and it wasn't due to a transient
  // error, so we must create the key.
  if (CreateCryptohomeKey()) {
    if (LoadCryptohomeKey(key_handle)) {
      return true;
    }
  }
  return false;
}

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

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

bool TpmInit::ReloadCryptohomeKey() {
  CHECK(HasCryptohomeKey());
  if (!LoadCryptohomeKey(&cryptohome_key_)) {
    LOG(ERROR) << "Error reloading Cryptohome key.";
    return false;
  }
  return true;
}

}  // namespace cryptohome
