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

// Test methods that run on a real TPM

#include "cryptohome/tpm_live_test.h"

#include <stdint.h>

#include <deque>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <utility>

#include <base/check_op.h>
#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <crypto/sha2.h>
#include <libhwsec/status.h>
#include <libhwsec-foundation/crypto/rsa.h>
#include <libhwsec-foundation/crypto/sha.h>
#include <libhwsec-foundation/error/error.h>
#include <libhwsec-foundation/tpm/tpm_version.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/rsa.h>
#include <openssl/x509.h>

#include "cryptohome/signature_sealing_backend.h"

#if USE_TPM1
#include <trousers/scoped_tss_type.h>
#include <trousers/tss.h>
#include <trousers/trousers.h>  // NOLINT(build/include_alpha) - needs tss.h

#include "cryptohome/tpm_impl.h"
#endif  // USE_TPM1

using brillo::Blob;
using brillo::BlobFromString;
using brillo::BlobToString;
using brillo::SecureBlob;
using hwsec::TPMErrorBase;
using hwsec_foundation::CreateRsaKey;
using hwsec_foundation::Sha256;

namespace cryptohome {

TpmLiveTest::TpmLiveTest() : tpm_(Tpm::GetSingleton()) {}

bool TpmLiveTest::RunLiveTests() {
  if (!PCRKeyTest()) {
    LOG(ERROR) << "Error running PCRKeyTest.";
    return false;
  }
  if (!DecryptionKeyTest()) {
    LOG(ERROR) << "Error running Decryption test.";
    return false;
  }
  if (!SealToPcrWithAuthorizationTest()) {
    LOG(ERROR) << "Error running SealToPcrWithAuthorizationTest.";
    return false;
  }
  if (!NvramTest()) {
    LOG(ERROR) << "Error running NvramTest.";
    return false;
  }
  if (!SignatureSealedSecretTest()) {
    LOG(ERROR) << "Error running SignatureSealedSecretTest.";
    return false;
  }
  LOG(INFO) << "All tests run successfully.";
  return true;
}

bool TpmLiveTest::SignData(const SecureBlob& pcr_bound_key,
                           const SecureBlob& public_key_der,
                           int index) {
  SecureBlob input_data("input_data");
  SecureBlob signature;
  if (!tpm_->Sign(pcr_bound_key, input_data, index, &signature)) {
    LOG(ERROR) << "Error signing with PCR bound key.";
    return false;
  }
  const unsigned char* public_key_data = public_key_der.data();
  crypto::ScopedRSA rsa(
      d2i_RSAPublicKey(nullptr, &public_key_data, public_key_der.size()));
  if (!rsa.get()) {
    LOG(ERROR) << "Failed to decode public key.";
    return false;
  }
  SecureBlob digest = Sha256(input_data);
  if (!RSA_verify(NID_sha256, digest.data(), digest.size(), signature.data(),
                  signature.size(), rsa.get())) {
    LOG(ERROR) << "Failed to verify signature.";
    return false;
  }
  return true;
}

bool TpmLiveTest::PCRKeyTest() {
  LOG(INFO) << "PCRKeyTest started";
  uint32_t index = 5;
  Blob pcr_data;
  if (!tpm_->ReadPCR(index, &pcr_data)) {
    LOG(ERROR) << "Error reading pcr value from TPM.";
    return false;
  }
  SecureBlob pcr_bound_key1;  // Sign key
  SecureBlob pcr_bound_key2;  // Decrypt key
  SecureBlob public_key_der1;
  SecureBlob public_key_der2;
  SecureBlob creation_blob1;
  SecureBlob creation_blob2;
  std::map<uint32_t, brillo::Blob> pcr_map({{index, pcr_data}});
  // Create the keys.
  if (!tpm_->CreatePCRBoundKey(pcr_map, AsymmetricKeyUsage::kSignKey,
                               &pcr_bound_key1, &public_key_der1,
                               &creation_blob1)) {
    LOG(ERROR) << "Error creating PCR bound signing key.";
    return false;
  }
  if (!tpm_->CreatePCRBoundKey(pcr_map, AsymmetricKeyUsage::kDecryptKey,
                               &pcr_bound_key2, &public_key_der2,
                               &creation_blob2)) {
    LOG(ERROR) << "Error creating PCR bound decryption key.";
    return false;
  }
  if (!tpm_->VerifyPCRBoundKey(pcr_map, pcr_bound_key1, creation_blob1) ||
      !tpm_->VerifyPCRBoundKey(pcr_map, pcr_bound_key2, creation_blob2)) {
    LOG(ERROR) << "Error verifying PCR bound key.";
    return false;
  }
  // Check that signing key works.
  if (!SignData(pcr_bound_key1, public_key_der1, index)) {
    LOG(ERROR) << "Error signing the blob.";
    return false;
  }
  // Check that signing data doesn't work (only for TPM2).
  if (tpm_->GetVersion() != Tpm::TPM_1_2) {
    if (SignData(pcr_bound_key2, public_key_der2, index)) {
      LOG(ERROR) << "Signing data succeeded with decryption only key.";
      return false;
    }
  }
  // Extend PCR to invalidate the keys.
  if (!tpm_->ExtendPCR(index, BlobFromString("01234567890123456789"))) {
    LOG(ERROR) << "Error extending PCR.";
    return false;
  }
  if (SignData(pcr_bound_key1, public_key_der1, index)) {
    LOG(ERROR) << "Sign succeeded without the correct PCR state.";
    return false;
  }
  LOG(INFO) << "PCRKeyTest ended successfully.";
  return true;
}

bool TpmLiveTest::DecryptionKeyTest() {
  LOG(INFO) << "DecryptionKeyTest started";
  SecureBlob n;
  SecureBlob p;
  uint32_t tpm_key_bits = 2048;
  if (!CreateRsaKey(tpm_key_bits, &n, &p)) {
    LOG(ERROR) << "Error creating RSA key.";
    return false;
  }
  SecureBlob wrapped_key;
  if (!tpm_->WrapRsaKey(n, p, &wrapped_key)) {
    LOG(ERROR) << "Error wrapping RSA key.";
    return false;
  }
  ScopedKeyHandle handle;
  if (hwsec::Status err = tpm_->LoadWrappedKey(wrapped_key, &handle)) {
    LOG(ERROR) << "Error loading key: " << err;
    return false;
  }
  SecureBlob aes_key(32, 'a');
  SecureBlob plaintext(32, 'b');
  SecureBlob ciphertext;
  if (hwsec::Status err =
          tpm_->EncryptBlob(handle.value(), plaintext, aes_key, &ciphertext)) {
    LOG(ERROR) << "Error encrypting blob: " << err;
    return false;
  }
  SecureBlob decrypted_plaintext;
  if (hwsec::Status err = tpm_->DecryptBlob(handle.value(), ciphertext, aes_key,
                                            &decrypted_plaintext)) {
    LOG(ERROR) << "Error decrypting blob: " << err;
    return false;
  }
  if (plaintext != decrypted_plaintext) {
    LOG(ERROR) << "Decrypted plaintext does not match plaintext.";
    return false;
  }
  LOG(INFO) << "DecryptionKeyTest ended successfully.";
  return true;
}

bool TpmLiveTest::SealToPcrWithAuthorizationTest() {
  LOG(INFO) << "SealToPcrWithAuthorizationTest started";
  SecureBlob n;
  SecureBlob p;
  uint32_t tpm_key_bits = 2048;
  if (!CreateRsaKey(tpm_key_bits, &n, &p)) {
    LOG(ERROR) << "Error creating RSA key.";
    return false;
  }
  SecureBlob wrapped_key;
  if (!tpm_->WrapRsaKey(n, p, &wrapped_key)) {
    LOG(ERROR) << "Error wrapping RSA key.";
    return false;
  }
  ScopedKeyHandle handle;
  if (hwsec::Status err = tpm_->LoadWrappedKey(wrapped_key, &handle)) {
    LOG(ERROR) << "Error loading key: " << err;
    return false;
  }

  uint32_t index1 = 4;
  uint32_t index2 = 11;
  std::map<uint32_t, brillo::Blob> pcr_map(
      {{index1, brillo::Blob()}, {index2, brillo::Blob()}});
  SecureBlob plaintext(32, 'a');
  SecureBlob pass_blob(256, 'b');
  SecureBlob ciphertext;
  brillo::SecureBlob auth_value;
  if (hwsec::Status err =
          tpm_->GetAuthValue(handle.value(), pass_blob, &auth_value)) {
    LOG(ERROR) << "Failed to get auth value: " << err;
    return false;
  }
  if (hwsec::Status err = tpm_->SealToPcrWithAuthorization(
          plaintext, auth_value, pcr_map, &ciphertext)) {
    LOG(ERROR) << "Error sealing the blob: " << err;
    return false;
  }
  SecureBlob unsealed_text;
  if (hwsec::Status err = tpm_->UnsealWithAuthorization(
          std::nullopt, ciphertext, auth_value, pcr_map, &unsealed_text)) {
    LOG(ERROR) << "Error unsealing blob: " << err;
    return false;
  }
  if (plaintext != unsealed_text) {
    LOG(ERROR) << "Unsealed plaintext does not match plaintext.";
    return false;
  }

  // Check that unsealing doesn't work with wrong pass_blob.
  pass_blob.char_data()[255] = 'a';
  if (hwsec::Status err =
          tpm_->GetAuthValue(handle.value(), pass_blob, &auth_value)) {
    LOG(ERROR) << "Failed to get auth value: " << err;
    return false;
  }
  if (tpm_->UnsealWithAuthorization(std::nullopt, ciphertext, auth_value,
                                    pcr_map, &unsealed_text) == nullptr &&
      plaintext == unsealed_text) {
    LOG(ERROR) << "UnsealWithAuthorization failed to fail.";
    return false;
  }

  LOG(INFO) << "SealToPcrWithAuthorizationTest ended successfully.";
  return true;
}

bool TpmLiveTest::NvramTest() {
  LOG(INFO) << "NvramTest started";
  uint32_t index = 12;
  SecureBlob nvram_data("nvram_data");
  if (tpm_->IsNvramDefined(index)) {
    if (!tpm_->DestroyNvram(index)) {
      LOG(ERROR) << "Error destroying old Nvram.";
      return false;
    }
    if (tpm_->IsNvramDefined(index)) {
      LOG(ERROR) << "Nvram still defined after it was destroyed.";
      return false;
    }
  }
  if (!tpm_->DefineNvram(
          index, nvram_data.size(),
          Tpm::kTpmNvramWriteDefine | Tpm::kTpmNvramBindToPCR0)) {
    LOG(ERROR) << "Defining Nvram index.";
    return false;
  }
  if (!tpm_->IsNvramDefined(index)) {
    LOG(ERROR) << "Nvram index is not defined after creating.";
    return false;
  }
  if (tpm_->GetNvramSize(index) != nvram_data.size()) {
    LOG(ERROR) << "Nvram space is of incorrect size.";
    return false;
  }
  if (tpm_->IsNvramLocked(index)) {
    LOG(ERROR) << "Nvram should not be locked before writing.";
    return false;
  }
  if (!tpm_->WriteNvram(index, nvram_data)) {
    LOG(ERROR) << "Error writing to Nvram.";
    return false;
  }
  if (!tpm_->WriteLockNvram(index)) {
    LOG(ERROR) << "Error locking Nvram space.";
    return false;
  }
  if (!tpm_->IsNvramLocked(index)) {
    LOG(ERROR) << "Nvram should be locked after locking.";
    return false;
  }
  SecureBlob data;
  if (!tpm_->ReadNvram(index, &data)) {
    LOG(ERROR) << "Error reading from Nvram.";
    return false;
  }
  if (data != nvram_data) {
    LOG(ERROR) << "Data read from Nvram did not match data written.";
    return false;
  }
  if (tpm_->WriteNvram(index, nvram_data)) {
    LOG(ERROR) << "We should not be able to write to a locked Nvram space.";
    return false;
  }
  if (!tpm_->DestroyNvram(index)) {
    LOG(ERROR) << "Error destroying Nvram space.";
    return false;
  }
  if (tpm_->IsNvramDefined(index)) {
    LOG(ERROR) << "Nvram still defined after it was destroyed.";
    return false;
  }
  LOG(INFO) << "NvramTest ended successfully.";
  return true;
}

namespace {

struct SignatureSealedSecretTestCaseParam {
  SignatureSealedSecretTestCaseParam(
      const std::string& test_case_description,
      Tpm* tpm,
      int key_size_bits,
      const std::vector<structure::ChallengeSignatureAlgorithm>&
          supported_algorithms,
      std::optional<structure::ChallengeSignatureAlgorithm> expected_algorithm,
      int openssl_algorithm_nid)
      : test_case_description(test_case_description),
        tpm(tpm),
        key_size_bits(key_size_bits),
        supported_algorithms(supported_algorithms),
        expected_algorithm(expected_algorithm),
        openssl_algorithm_nid(openssl_algorithm_nid) {}

  SignatureSealedSecretTestCaseParam(SignatureSealedSecretTestCaseParam&&) =
      default;

  static SignatureSealedSecretTestCaseParam MakeSuccessful(
      const std::string& test_case_description,
      Tpm* tpm,
      int key_size_bits,
      const std::vector<structure::ChallengeSignatureAlgorithm>&
          supported_algorithms,
      structure::ChallengeSignatureAlgorithm expected_algorithm,
      int openssl_algorithm_nid) {
    return SignatureSealedSecretTestCaseParam(
        test_case_description, tpm, key_size_bits, supported_algorithms,
        expected_algorithm, openssl_algorithm_nid);
  }

  static SignatureSealedSecretTestCaseParam MakeFailing(
      const std::string& test_case_description,
      Tpm* tpm,
      int key_size_bits,
      const std::vector<structure::ChallengeSignatureAlgorithm>&
          supported_algorithms) {
    return SignatureSealedSecretTestCaseParam(
        test_case_description, tpm, key_size_bits, supported_algorithms, {}, 0);
  }

  bool expect_success() const { return expected_algorithm.has_value(); }

  std::string test_case_description;
  Tpm* tpm;
  int key_size_bits;
  std::vector<structure::ChallengeSignatureAlgorithm> supported_algorithms;
  std::optional<structure::ChallengeSignatureAlgorithm> expected_algorithm;
  int openssl_algorithm_nid;
};

class SignatureSealedSecretTestCase final {
 public:
  using UnsealingSession = SignatureSealingBackend::UnsealingSession;

  explicit SignatureSealedSecretTestCase(
      SignatureSealedSecretTestCaseParam param)
      : param_(std::move(param)) {
    LOG(INFO) << "SignatureSealedSecretTestCase: " << param_.key_size_bits
              << "-bit key, " << param_.test_case_description;
  }
  SignatureSealedSecretTestCase(const SignatureSealedSecretTestCase&) = delete;
  SignatureSealedSecretTestCase& operator=(
      const SignatureSealedSecretTestCase&) = delete;

  ~SignatureSealedSecretTestCase() {}

  bool SetUp() {
    if (!GenerateRsaKey(param_.key_size_bits, &pkey_, &key_spki_der_)) {
      LOG(ERROR) << "Error generating the RSA key";
      return false;
    }
    if (!InitDelegate()) {
      LOG(ERROR) << "Error creating the delegate";
      return false;
    }
    return true;
  }

  bool RunStage1() {
    if (!param_.expect_success()) {
      if (!CheckSecretCreationFails()) {
        LOG(ERROR) << "Error: successfully created secret unexpectedly";
        return false;
      }
      return true;
    }
    // Create a secret.
    SecureBlob secret_value;
    structure::SignatureSealedData sealed_secret_data;
    if (!CreateSecret(&secret_value, &sealed_secret_data)) {
      LOG(ERROR) << "Error creating a secret";
      return false;
    }
    // Unseal the secret.
    Blob first_challenge_value;
    Blob first_challenge_signature;
    SecureBlob first_unsealed_value;
    if (!Unseal(sealed_secret_data, &first_challenge_value,
                &first_challenge_signature, &first_unsealed_value)) {
      LOG(ERROR) << "Error unsealing a secret";
      return false;
    }
    if (first_unsealed_value != secret_value) {
      LOG(ERROR)
          << "Error: unsealing returned different value than at creation time";
      return false;
    }
    // Unseal the secret again - the challenge is different, but the result is
    // the same.
    Blob second_challenge_value;
    Blob second_challenge_signature;
    SecureBlob second_unsealed_value;
    if (!Unseal(sealed_secret_data, &second_challenge_value,
                &second_challenge_signature, &second_unsealed_value)) {
      LOG(ERROR) << "Error unsealing secret for the second time";
      return false;
    }
    if (first_challenge_value == second_challenge_value) {
      LOG(ERROR) << "Error: challenge value collision";
      return false;
    }
    if (second_unsealed_value != secret_value) {
      LOG(ERROR)
          << "Error: unsealing returned different value than at creation time";
      return false;
    }
    // Unsealing with a bad challenge response fails.
    if (!CheckUnsealingFailsWithOldSignature(sealed_secret_data,
                                             first_challenge_signature) ||
        !CheckUnsealingFailsWithBadAlgorithmSignature(sealed_secret_data) ||
        !CheckUnsealingFailsWithBadSignature(sealed_secret_data)) {
      LOG(ERROR) << "Failed testing against bad challenge responses";
      return false;
    }
    // Unsealing with a bad key fails.
    if (!CheckUnsealingFailsWithWrongAlgorithm(sealed_secret_data) ||
        !CheckUnsealingFailsWithWrongKey(sealed_secret_data)) {
      LOG(ERROR) << "Failed testing against bad keys";
      return false;
    }
    // Create and unseal another secret - it has a different value.
    SecureBlob another_secret_value;
    if (!CreateSecret(&another_secret_value, &another_sealed_secret_data_)) {
      LOG(ERROR) << "Error creating another secret";
      return false;
    }
    if (another_secret_value == secret_value) {
      LOG(ERROR) << "Error: secret value collision";
      return false;
    }
    Blob third_challenge_value;
    Blob third_challenge_signature;
    SecureBlob third_unsealed_value;
    if (!Unseal(another_sealed_secret_data_, &third_challenge_value,
                &third_challenge_signature, &third_unsealed_value)) {
      LOG(ERROR) << "Error unsealing another secret";
      return false;
    }
    if (third_unsealed_value != another_secret_value) {
      LOG(ERROR)
          << "Error: unsealing returned different value than at creation time";
      return false;
    }
    return true;
  }

  bool RunStage2() {
    if (!param_.expect_success()) {
      return true;
    }

    // Unsealing after PCRs change fails.
    if (!CheckUnsealingFail(another_sealed_secret_data_)) {
      LOG(ERROR) << "Failed testing against changed PCRs";
      return false;
    }
    return true;
  }

 private:
  const std::string kObfuscatedUsername = "obfuscated_username";
  const std::set<uint32_t> kPcrIndexes{kTpmSingleUserPCR};

  Tpm* tpm() { return param_.tpm; }

  SignatureSealingBackend* backend() {
    return tpm()->GetSignatureSealingBackend();
  }

  static bool GenerateRsaKey(int key_size_bits,
                             crypto::ScopedEVP_PKEY* pkey,
                             Blob* key_spki_der) {
    crypto::ScopedEVP_PKEY_CTX pkey_context(
        EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
    if (!pkey_context)
      return false;
    if (EVP_PKEY_keygen_init(pkey_context.get()) <= 0)
      return false;
    if (EVP_PKEY_CTX_set_rsa_keygen_bits(pkey_context.get(), key_size_bits) <=
        0) {
      return false;
    }
    EVP_PKEY* pkey_raw = nullptr;
    if (EVP_PKEY_keygen(pkey_context.get(), &pkey_raw) <= 0)
      return false;
    pkey->reset(pkey_raw);
    // Obtain the DER-encoded Subject Public Key Info.
    const int key_spki_der_length = i2d_PUBKEY(pkey->get(), nullptr);
    if (key_spki_der_length < 0)
      return false;
    key_spki_der->resize(key_spki_der_length);
    unsigned char* key_spki_der_buffer = key_spki_der->data();
    return i2d_PUBKEY(pkey->get(), &key_spki_der_buffer) ==
           key_spki_der->size();
  }

  // Init the delegate.
  bool InitDelegate() {
    bool has_reset_lock_permissions;
    return tpm()->GetDelegate(&delegate_blob_, &delegate_secret_,
                              &has_reset_lock_permissions);
  }

  bool CreateSecret(SecureBlob* secret_value,
                    structure::SignatureSealedData* sealed_secret_data) {
    if (hwsec::Status err = backend()->CreateSealedSecret(
            key_spki_der_, param_.supported_algorithms, kObfuscatedUsername,
            delegate_blob_, delegate_secret_, secret_value,
            sealed_secret_data)) {
      LOG(ERROR) << "Error creating signature-sealed secret: " << err;
      return false;
    }
    return true;
  }

  bool CheckSecretCreationFails() {
    SecureBlob secret_value;
    structure::SignatureSealedData sealed_secret_data;
    if (hwsec::Status err = backend()->CreateSealedSecret(
            key_spki_der_, param_.supported_algorithms, kObfuscatedUsername,
            delegate_blob_, delegate_secret_, &secret_value,
            &sealed_secret_data)) {
      // TODO(b/174816474): check the error message is expected.
      LOG(INFO) << "Successfully failed to create signature-sealed secret: "
                << err;
      return true;
    }
    LOG(ERROR) << "Error: secret creation completed unexpectedly";
    return false;
  }

  bool Unseal(const structure::SignatureSealedData& sealed_secret_data,
              Blob* challenge_value,
              Blob* challenge_signature,
              SecureBlob* unsealed_value) {
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      LOG(ERROR) << "Error starting the unsealing session: " << err;
      return false;
    }
    if (unsealing_session->GetChallengeAlgorithm() !=
        *param_.expected_algorithm) {
      LOG(ERROR) << "Wrong challenge signature algorithm";
      return false;
    }
    *challenge_value = unsealing_session->GetChallengeValue();
    if (challenge_value->empty()) {
      LOG(ERROR) << "The challenge is empty";
      return false;
    }
    if (!SignWithKey(*challenge_value, param_.openssl_algorithm_nid,
                     challenge_signature)) {
      LOG(ERROR) << "Error generating signature of challenge";
      return false;
    }
    if (hwsec::Status err =
            unsealing_session->Unseal(*challenge_signature, unsealed_value)) {
      LOG(ERROR) << "Error unsealing the secret: " << err;
      return false;
    }
    if (unsealed_value->empty()) {
      LOG(ERROR) << "Error: empty unsealing result";
      return false;
    }
    return true;
  }

  bool CheckUnsealingFailsWithOldSignature(
      const structure::SignatureSealedData& sealed_secret_data,
      const Blob& challenge_signature) {
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      LOG(ERROR) << "Error starting the unsealing session: " << err;
      return false;
    }
    SecureBlob unsealed_value;
    if (unsealing_session->Unseal(challenge_signature, &unsealed_value) ==
        nullptr) {
      LOG(ERROR)
          << "Error: unsealing completed with an old challenge signature";
      return false;
    }
    return true;
  }

  bool CheckUnsealingFailsWithBadAlgorithmSignature(
      const structure::SignatureSealedData& sealed_secret_data) {
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      LOG(ERROR) << "Error starting the unsealing session: " << err;
      return false;
    }
    const int wrong_openssl_algorithm_nid =
        param_.openssl_algorithm_nid == NID_sha1 ? NID_sha256 : NID_sha1;
    Blob challenge_signature;
    if (!SignWithKey(unsealing_session->GetChallengeValue(),
                     wrong_openssl_algorithm_nid, &challenge_signature)) {
      LOG(ERROR) << "Error generating signature of challenge";
      return false;
    }
    SecureBlob unsealed_value;
    if (unsealing_session->Unseal(challenge_signature, &unsealed_value) ==
        nullptr) {
      LOG(ERROR) << "Error: unsealing completed with a wrong signature";
      return false;
    }
    return true;
  }

  bool CheckUnsealingFailsWithBadSignature(
      const structure::SignatureSealedData& sealed_secret_data) {
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      LOG(ERROR) << "Error starting the unsealing session: " << err;
      return false;
    }
    Blob challenge_signature;
    if (!SignWithKey(unsealing_session->GetChallengeValue(),
                     param_.openssl_algorithm_nid, &challenge_signature)) {
      LOG(ERROR) << "Error generating signature of challenge";
      return false;
    }
    challenge_signature.front() ^= 1;
    SecureBlob unsealed_value;
    if (unsealing_session->Unseal(challenge_signature, &unsealed_value) ==
        nullptr) {
      LOG(ERROR) << "Error: unsealing completed with a wrong signature";
      return false;
    }
    return true;
  }

  bool CheckUnsealingFailsWithWrongAlgorithm(
      const structure::SignatureSealedData& sealed_secret_data) {
    const structure::ChallengeSignatureAlgorithm wrong_algorithm =
        *param_.expected_algorithm ==
                structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1
            ? structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256
            : structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1;
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, {wrong_algorithm}, kPcrIndexes,
            delegate_blob_, delegate_secret_, /*locked_to_single_user=*/false,
            &unsealing_session)) {
      // TODO(b/174816474): check the error message is expected.
      return true;
    } else {
      LOG(ERROR) << "Error: unsealing session creation completed with a "
                    "wrong algorithm";
      return false;
    }
  }

  bool CheckUnsealingFailsWithWrongKey(
      const structure::SignatureSealedData& sealed_secret_data) {
    crypto::ScopedEVP_PKEY other_pkey;
    Blob other_key_spki_der;
    if (!GenerateRsaKey(param_.key_size_bits, &other_pkey,
                        &other_key_spki_der)) {
      LOG(ERROR) << "Error generating the other RSA key";
      return false;
    }
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, other_key_spki_der, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      // TODO(b/174816474): check the error message is expected.
      return true;
    } else {
      LOG(ERROR)
          << "Error: unsealing session creation completed with a wrong key";
      return false;
    }
  }

  bool CheckUnsealingFail(
      const structure::SignatureSealedData& sealed_secret_data) {
    std::unique_ptr<UnsealingSession> unsealing_session;
    if (hwsec::Status err = backend()->CreateUnsealingSession(
            sealed_secret_data, key_spki_der_, param_.supported_algorithms,
            kPcrIndexes, delegate_blob_, delegate_secret_,
            /*locked_to_single_user=*/false, &unsealing_session)) {
      // TODO(yich): check the error message is expected.
      LOG(INFO) << "Failed to starting the unsealing session: " << err;
      return true;
    }
    Blob challenge_signature;
    if (!SignWithKey(unsealing_session->GetChallengeValue(),
                     param_.openssl_algorithm_nid, &challenge_signature)) {
      LOG(ERROR) << "Error generating signature of challenge";
      return false;
    }
    SecureBlob unsealed_value;
    if (unsealing_session->Unseal(challenge_signature, &unsealed_value) ==
        nullptr) {
      LOG(ERROR) << "Error: unsealing completed with changed PCRs";
      return false;
    }
    return true;
  }

  bool SignWithKey(const Blob& unhashed_data,
                   int algorithm_nid,
                   Blob* signature) {
    signature->resize(EVP_PKEY_size(pkey_.get()));
    crypto::ScopedEVP_MD_CTX sign_context(EVP_MD_CTX_new());
    unsigned signature_size = 0;
    if (!sign_context) {
      LOG(ERROR) << "Error creating signing context";
      return false;
    }
    if (!EVP_SignInit(sign_context.get(), EVP_get_digestbynid(algorithm_nid))) {
      LOG(ERROR) << "Error initializing signature operation";
      return false;
    }
    if (!EVP_SignUpdate(sign_context.get(), unhashed_data.data(),
                        unhashed_data.size())) {
      LOG(ERROR) << "Error updating signature operation with data";
      return false;
    }
    if (!EVP_SignFinal(sign_context.get(), signature->data(), &signature_size,
                       pkey_.get())) {
      LOG(ERROR) << "Error finalizing signature operation";
      return false;
    }
    CHECK_LE(signature_size, signature->size());
    signature->resize(signature_size);
    return true;
  }

  const SignatureSealedSecretTestCaseParam param_;
  Blob delegate_blob_;
  Blob delegate_secret_;
  crypto::ScopedEVP_PKEY pkey_;
  Blob key_spki_der_;

  structure::SignatureSealedData another_sealed_secret_data_;
};

}  // namespace

bool TpmLiveTest::SignatureSealedSecretTest() {
  using TestCaseParam = SignatureSealedSecretTestCaseParam;
  if (!tpm_->GetSignatureSealingBackend()) {
    // Not supported by the Tpm implementation, just skip the test.
    return true;
  }
  LOG(INFO) << "SignatureSealedSecretTest started";
  std::vector<TestCaseParam> test_case_params;
  for (int key_size_bits : {1024, 2048}) {
    test_case_params.push_back(TestCaseParam::MakeSuccessful(
        "SHA-1", tpm_, key_size_bits,
        {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1},
        structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1, NID_sha1));
    if (tpm_->GetVersion() == Tpm::TPM_1_2) {
      test_case_params.push_back(TestCaseParam::MakeFailing(
          "SHA-256", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256}));
      test_case_params.push_back(TestCaseParam::MakeFailing(
          "SHA-384", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha384}));
      test_case_params.push_back(TestCaseParam::MakeFailing(
          "SHA-512", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha512}));
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "{SHA-1,SHA-256}", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256,
           structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1,
          NID_sha1));
    } else {
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "SHA-256", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256,
          NID_sha256));
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "SHA-384", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha384},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha384,
          NID_sha384));
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "SHA-512", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha512},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha512,
          NID_sha512));
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "{SHA-384,SHA-256,SHA-512}", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha384,
           structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256,
           structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha512},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha384,
          NID_sha384));
      test_case_params.push_back(TestCaseParam::MakeSuccessful(
          "{SHA-1,SHA-256}", tpm_, key_size_bits,
          {structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha1,
           structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256},
          structure::ChallengeSignatureAlgorithm::kRsassaPkcs1V15Sha256,
          NID_sha256));
    }
  }

  std::deque<SignatureSealedSecretTestCase> test_cases;

  for (auto&& test_case_param : test_case_params) {
    test_cases.emplace_back(std::move(test_case_param));
    if (!test_cases.back().SetUp() || !test_cases.back().RunStage1())
      return false;
  }

  if (!tpm_->ExtendPCR(kTpmSingleUserPCR,
                       BlobFromString("01234567890123456789"))) {
    LOG(ERROR) << "Error extending PCR";
    return false;
  }

  for (auto& test_case : test_cases) {
    if (!test_case.RunStage2())
      return false;
  }

  test_cases.clear();

  LOG(INFO) << "SignatureSealedSecretTest ended successfully.";
  return true;
}

}  // namespace cryptohome
