// Copyright 2020 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/tpm_bound_to_pcr_auth_block.h"

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include <absl/types/variant.h>
#include <base/check.h>
#include <base/logging.h>
#include <base/optional.h>
#include <brillo/secure_blob.h>

#include "cryptohome/crypto.h"
#include "cryptohome/crypto/aes.h"
#include "cryptohome/crypto/scrypt.h"
#include "cryptohome/crypto/secure_blob_util.h"
#include "cryptohome/crypto_error.h"
#include "cryptohome/cryptohome_keys_manager.h"
#include "cryptohome/cryptohome_metrics.h"
#include "cryptohome/tpm.h"
#include "cryptohome/tpm_auth_block_utils.h"
#include "cryptohome/vault_keyset.pb.h"

using hwsec::error::TPMError;
using hwsec::error::TPMErrorBase;
using hwsec_foundation::error::WrapError;

namespace cryptohome {

TpmBoundToPcrAuthBlock::TpmBoundToPcrAuthBlock(
    Tpm* tpm, CryptohomeKeysManager* cryptohome_keys_manager)
    : AuthBlock(kTpmBackedPcrBound),
      tpm_(tpm),
      cryptohome_key_loader_(
          cryptohome_keys_manager->GetKeyLoader(CryptohomeKeyType::kRSA)),
      utils_(tpm, cryptohome_key_loader_) {
  CHECK(tpm != nullptr);
  CHECK(cryptohome_key_loader_ != nullptr);

  // Create the scrypt thread.
  // TODO(yich): Create another thread in userdataauth and passing it to here.
  base::Thread::Options options;
  options.message_pump_type = base::MessagePumpType::IO;
  scrypt_thread_ = std::make_unique<base::Thread>("scrypt_thread");
  scrypt_thread_->StartWithOptions(options);
  scrypt_task_runner_ = scrypt_thread_->task_runner();
}

base::Optional<AuthBlockState> TpmBoundToPcrAuthBlock::Create(
    const AuthInput& user_input, KeyBlobs* key_blobs, CryptoError* error) {
  const brillo::SecureBlob& vault_key = user_input.user_input.value();
  const brillo::SecureBlob& salt = user_input.salt.value();
  const std::string& obfuscated_username =
      user_input.obfuscated_username.value();

  // If the cryptohome key isn't loaded, try to load it.
  if (!cryptohome_key_loader_->HasCryptohomeKey())
    cryptohome_key_loader_->Init();

  // If the key still isn't loaded, fail the operation.
  if (!cryptohome_key_loader_->HasCryptohomeKey())
    return base::nullopt;

  const auto vkk_key = CreateSecureRandomBlob(kDefaultAesKeySize);
  brillo::SecureBlob pass_blob(kDefaultPassBlobSize);
  brillo::SecureBlob vkk_iv(kAesBlockSize);
  if (!DeriveSecretsScrypt(vault_key, salt, {&pass_blob, &vkk_iv}))
    return base::nullopt;

  std::map<uint32_t, std::string> default_pcr_map =
      tpm_->GetPcrMap(obfuscated_username, false /* use_extended_pcr */);
  std::map<uint32_t, std::string> extended_pcr_map =
      tpm_->GetPcrMap(obfuscated_username, true /* use_extended_pcr */);

  // Encrypt the VKK using the TPM and the user's passkey. The output is two
  // encrypted blobs, sealed to PCR in |tpm_key| and |extended_tpm_key|,
  // which are stored in the serialized vault keyset.
  TpmKeyHandle cryptohome_key = cryptohome_key_loader_->GetCryptohomeKey();
  brillo::SecureBlob auth_value;
  if (TPMErrorBase err =
          tpm_->GetAuthValue(cryptohome_key, pass_blob, &auth_value)) {
    LOG(ERROR) << "Failed to get auth value: " << *err;
    return base::nullopt;
  }

  brillo::SecureBlob tpm_key;
  if (TPMErrorBase err = tpm_->SealToPcrWithAuthorization(
          vkk_key, auth_value, default_pcr_map, &tpm_key)) {
    LOG(ERROR) << "Failed to wrap vkk with creds: " << *err;
    return base::nullopt;
  }

  brillo::SecureBlob extended_tpm_key;
  if (TPMErrorBase err = tpm_->SealToPcrWithAuthorization(
          vkk_key, auth_value, extended_pcr_map, &extended_tpm_key)) {
    LOG(ERROR) << "Failed to wrap vkk with creds for extended PCR: " << *err;
    return base::nullopt;
  }

  TpmBoundToPcrAuthBlockState tpm_state;

  // Allow this to fail.  It is not absolutely necessary; it allows us to
  // detect a TPM clear.  If this fails due to a transient issue, then on next
  // successful login, the vault keyset will be re-saved anyway.
  brillo::SecureBlob pub_key_hash;
  if (TPMErrorBase err =
          tpm_->GetPublicKeyHash(cryptohome_key, &pub_key_hash)) {
    LOG(ERROR) << "Failed to get the TPM public key hash: " << *err;
  } else {
    tpm_state.tpm_public_key_hash = pub_key_hash;
  }

  tpm_state.scrypt_derived = true;
  tpm_state.tpm_key = tpm_key;
  tpm_state.extended_tpm_key = extended_tpm_key;

  // Pass back the vkk_key and vkk_iv so the generic secret wrapping can use it.
  key_blobs->vkk_key = vkk_key;
  // Note that one might expect the IV to be part of the AuthBlockState. But
  // since it's taken from the scrypt output, it's actually created by the auth
  // block, not used to initialize the auth block.
  key_blobs->vkk_iv = vkk_iv;
  key_blobs->chaps_iv = vkk_iv;

  AuthBlockState auth_block_state = {.state = std::move(tpm_state)};
  return auth_block_state;
}

bool TpmBoundToPcrAuthBlock::Derive(const AuthInput& auth_input,
                                    const AuthBlockState& state,
                                    KeyBlobs* key_out_data,
                                    CryptoError* error) {
  const TpmBoundToPcrAuthBlockState* tpm_state;
  if (!(tpm_state = absl::get_if<TpmBoundToPcrAuthBlockState>(&state.state))) {
    DLOG(FATAL) << "Called with an invalid auth block state";
    return false;
  }

  if (!tpm_state->scrypt_derived) {
    LOG(ERROR) << "All TpmBoundtoPcr operations should be scrypt derived.";
    return false;
  }

  brillo::SecureBlob tpm_public_key_hash =
      tpm_state->tpm_public_key_hash.value_or(brillo::SecureBlob());

  if (!utils_.CheckTPMReadiness(tpm_state->tpm_key.has_value(),
                                tpm_state->tpm_public_key_hash.has_value(),
                                tpm_public_key_hash, error)) {
    return false;
  }

  key_out_data->vkk_iv = brillo::SecureBlob(kAesBlockSize);
  key_out_data->vkk_key = brillo::SecureBlob(kDefaultAesKeySize);

  bool locked_to_single_user = auth_input.locked_to_single_user.value_or(false);
  if (!tpm_state->salt.has_value()) {
    DLOG(FATAL) << "Invalid TpmBoundToPcrAuthBlockState";
    return false;
  }
  brillo::SecureBlob salt = tpm_state->salt.value();
  base::Optional<brillo::SecureBlob> tpm_key =
      locked_to_single_user ? tpm_state->extended_tpm_key : tpm_state->tpm_key;
  if (!tpm_key.has_value()) {
    DLOG(FATAL) << "Invalid TpmBoundToPcrAuthBlockState";
    return false;
  }
  if (!DecryptTpmBoundToPcr(auth_input.user_input.value(), tpm_key.value(),
                            salt, error, &key_out_data->vkk_iv.value(),
                            &key_out_data->vkk_key.value())) {
    return false;
  }

  key_out_data->chaps_iv = key_out_data->vkk_iv;

  if (tpm_state->wrapped_reset_seed.has_value()) {
    key_out_data->wrapped_reset_seed = tpm_state->wrapped_reset_seed;
  }

  if (!tpm_state->tpm_public_key_hash.has_value() && error) {
    *error = CryptoError::CE_NO_PUBLIC_KEY_HASH;
  }

  return true;
}

bool TpmBoundToPcrAuthBlock::DecryptTpmBoundToPcr(
    const brillo::SecureBlob& vault_key,
    const brillo::SecureBlob& tpm_key,
    const brillo::SecureBlob& salt,
    CryptoError* error,
    brillo::SecureBlob* vkk_iv,
    brillo::SecureBlob* vkk_key) const {
  brillo::SecureBlob pass_blob(kDefaultPassBlobSize);

  // Prepare the parameters for scrypt.
  std::vector<brillo::SecureBlob*> gen_secrets{&pass_blob, vkk_iv};
  bool derive_result = false;

  base::WaitableEvent done(base::WaitableEvent::ResetPolicy::MANUAL,
                           base::WaitableEvent::InitialState::NOT_SIGNALED);

  // Derive secrets on scrypt task runner.
  scrypt_task_runner_->PostTask(
      FROM_HERE,
      base::BindOnce(
          [](const brillo::SecureBlob& passkey, const brillo::SecureBlob& salt,
             std::vector<brillo::SecureBlob*> gen_secrets, bool* result,
             base::WaitableEvent* done) {
            *result =
                DeriveSecretsScrypt(passkey, salt, std::move(gen_secrets));
            done->Signal();
          },
          vault_key, salt, gen_secrets, &derive_result, &done));

  // Preload the sealed data while deriving secrets in scrypt.
  ScopedKeyHandle preload_handle;
  TPMErrorBase err;
  for (int i = 0; i < kTpmDecryptMaxRetries; ++i) {
    err = tpm_->PreloadSealedData(tpm_key, &preload_handle);
    if (err == nullptr)
      break;

    if (!TpmAuthBlockUtils::TPMErrorIsRetriable(err))
      break;
  }

  // Wait for the scrypt finished.
  done.Wait();

  if (!derive_result) {
    LOG(ERROR) << "scrypt derivation failed";
    return false;
  }

  if (err) {
    LOG(ERROR) << "Failed to preload the sealed data: " << *err;
    return false;
  }

  // On TPM1.2 devices, preloading sealed data is meaningless and
  // UnsealWithAuthorization will check the preload_handle not containing any
  // value.
  base::Optional<TpmKeyHandle> handle;
  if (preload_handle.has_value()) {
    handle = preload_handle.value();
  }

  for (int i = 0; i < kTpmDecryptMaxRetries; ++i) {
    TpmKeyHandle cryptohome_key = cryptohome_key_loader_->GetCryptohomeKey();
    brillo::SecureBlob auth_value;
    if (TPMErrorBase auth_err =
            tpm_->GetAuthValue(cryptohome_key, pass_blob, &auth_value)) {
      err =
          WrapError<TPMError>(std::move(auth_err), "Failed to get auth value");
      // TODO(yich): Reload cryptohome key might be a better choice.
      break;
    }

    std::map<uint32_t, std::string> pcr_map({{kTpmSingleUserPCR, ""}});
    err = tpm_->UnsealWithAuthorization(handle, tpm_key, auth_value, pcr_map,
                                        vkk_key);

    if (err == nullptr)
      return true;

    if (!TpmAuthBlockUtils::TPMErrorIsRetriable(err))
      break;

    // If the error is retriable, reload the key first.
    if (!cryptohome_key_loader_->ReloadCryptohomeKey()) {
      LOG(ERROR) << "Unable to reload Cryptohome key.";
      break;
    }
  }
  if (err) {
    LOG(ERROR) << "Failed to unwrap VKK with creds: " << *err;
  }
  *error = TpmAuthBlockUtils::TPMErrorToCrypto(err);
  return false;
}

}  // namespace cryptohome
