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

#include "trunks/trunks_client_test.h"

#include <algorithm>
#include <map>
#include <memory>
#include <random>
#include <string>
#include <vector>

#include <base/bind.h>
#include <base/callback.h>
#include <base/callback_helpers.h>
#include <base/logging.h>
#include <base/rand_util.h>
#include <base/stl_util.h>
#include <crypto/openssl_util.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <crypto/sha2.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/rsa.h>

#include "trunks/authorization_delegate.h"
#include "trunks/error_codes.h"
#include "trunks/hmac_session.h"
#include "trunks/policy_session.h"
#include "trunks/scoped_key_handle.h"
#include "trunks/tpm_constants.h"
#include "trunks/tpm_generated.h"
#include "trunks/tpm_state.h"
#include "trunks/tpm_utility.h"
#include "trunks/trunks_factory_impl.h"

namespace {

std::string GetOpenSSLError() {
  BIO* bio = BIO_new(BIO_s_mem());
  ERR_print_errors(bio);
  char* data = nullptr;
  int data_len = BIO_get_mem_data(bio, &data);
  std::string error_string(data, data_len);
  BIO_free(bio);
  return error_string;
}

}  // namespace

namespace trunks {

TrunksClientTest::TrunksClientTest(const TrunksFactory& factory)
    : factory_(factory) {
  crypto::EnsureOpenSSLInit();
}

TrunksClientTest::~TrunksClientTest() {}

bool TrunksClientTest::RNGTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string entropy_data("entropy_data");
  std::string random_data;
  size_t num_bytes = 70;
  TPM_RC result = utility->StirRandom(entropy_data, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error stirring TPM RNG: " << GetErrorString(result);
    return false;
  }
  result =
      utility->GenerateRandom(num_bytes, session->GetDelegate(), &random_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting random bytes from TPM: "
               << GetErrorString(result);
    return false;
  }
  if (num_bytes != random_data.size()) {
    LOG(ERROR) << "Error not enough random bytes received.";
    return false;
  }
  return true;
}

bool TrunksClientTest::SignTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string key_authorization("sign");
  std::string key_blob;
  TPM_RC result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001,
      key_authorization, "", false,  // use_only_policy_authorization
      std::vector<uint32_t>(), session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating signing key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE signing_key;
  result = utility->LoadKey(key_blob, session->GetDelegate(), &signing_key);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading signing key: " << GetErrorString(result);
  }
  ScopedKeyHandle scoped_key(factory_, signing_key);
  session->SetEntityAuthorizationValue(key_authorization);
  std::string signature;
  result = utility->Sign(signing_key, TPM_ALG_RSASSA, TPM_ALG_SHA256,
                         std::string(32, 'a'), true /* generate_hash */,
                         session->GetDelegate(), &signature);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }
  std::string public_key;
  if (!GetRSAPublicKeyFromHandle(scoped_key, &public_key,
                                     session->GetDelegate())) {
    LOG(ERROR) << "Error fetching the public key to verify: "
               << GetErrorString(result);
    return false;
  }
  return VerifyRSASignature(public_key, std::string(32, 'a'), signature);
}

bool TrunksClientTest::DecryptTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string key_authorization("decrypt");
  std::string key_blob;
  TPM_RC result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001,
      key_authorization, "", false,  // use_only_policy_authorization
      std::vector<uint32_t>(), session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating decrypt key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE decrypt_key;
  result = utility->LoadKey(key_blob, session->GetDelegate(), &decrypt_key);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading decrypt key: " << GetErrorString(result);
  }
  ScopedKeyHandle scoped_key(factory_, decrypt_key);
  return PerformRSAEncryptAndDecrypt(scoped_key.get(), key_authorization,
                                     session.get());
}

bool TrunksClientTest::ImportTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string modulus;
  std::string prime_factor;
  GenerateRSAKeyPair(&modulus, &prime_factor, nullptr);
  std::string key_blob;
  std::string key_authorization("import");
  TPM_RC result = utility->ImportRSAKey(
      TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, modulus, 0x10001,
      prime_factor, key_authorization, session->GetDelegate(), &key_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error importing key into TPM: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading key into TPM: " << GetErrorString(result);
    return false;
  }
  ScopedKeyHandle scoped_key(factory_, key_handle);
  return PerformRSAEncryptAndDecrypt(scoped_key.get(), key_authorization,
                                     session.get());
}

bool TrunksClientTest::AuthChangeTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string key_authorization("new_pass");
  std::string key_blob;
  TPM_RC result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "old_pass",
      "", false,  // use_only_policy_authorization
      std::vector<uint32_t>(), session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating change auth key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading change auth key: " << GetErrorString(result);
  }
  ScopedKeyHandle scoped_key(factory_, key_handle);
  session->SetEntityAuthorizationValue("old_pass");
  result = utility->ChangeKeyAuthorizationData(
      key_handle, key_authorization, session->GetDelegate(), &key_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error changing auth data: " << GetErrorString(result);
    return false;
  }
  session->SetEntityAuthorizationValue("");
  result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reloading key: " << GetErrorString(result);
    return false;
  }
  scoped_key.reset(key_handle);
  return PerformRSAEncryptAndDecrypt(scoped_key.get(), key_authorization,
                                     session.get());
}

bool TrunksClientTest::VerifyKeyCreationTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  std::string key_blob;
  std::string creation_blob;
  session->SetEntityAuthorizationValue("");
  TPM_RC result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "",
      false,  // use_only_policy_authorization
      std::vector<uint32_t>(), session->GetDelegate(),
      &key_blob, &creation_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating certify key: " << GetErrorString(result);
    return false;
  }
  std::string alternate_key_blob;
  result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptKey, 2048, 0x10001, "", "",
      false,  // use_only_policy_authorization
      std::vector<uint32_t>(), session->GetDelegate(), &alternate_key_blob,
      nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating alternate key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading certify key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE alternate_key_handle;
  result = utility->LoadKey(alternate_key_blob, session->GetDelegate(),
                            &alternate_key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading alternate key: " << GetErrorString(result);
    return false;
  }
  ScopedKeyHandle certify_key(factory_, key_handle);
  ScopedKeyHandle alternate_key(factory_, alternate_key_handle);
  result = utility->CertifyCreation(certify_key.get(), creation_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error certifying key: " << GetErrorString(result);
    return false;
  }
  result = utility->CertifyCreation(alternate_key.get(), creation_blob);
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error alternate key certified with wrong creation data.";
    return false;
  }
  return true;
}

bool TrunksClientTest::SealedDataTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  uint32_t pcr_index = 5;
  std::string policy_digest;
  TPM_RC result =
      utility->GetPolicyDigestForPcrValues(
          std::map<uint32_t, std::string>({{pcr_index, ""}}),
          true /* use_auth_value */, &policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result);
    return false;
  }
  std::string data_to_seal("seal_data");
  std::string auth_value("auth_value");
  std::string sealed_data;
  result = utility->SealData(data_to_seal, policy_digest, auth_value,
                             session->GetDelegate(), &sealed_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result);
    return false;
  }
  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyAuthValue();
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << __func__ << ": Error setting session to use auth_value: "
               << GetErrorString(result);
    return result;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to pcr value: "
               << GetErrorString(result);
    return false;
  }
  // Check fail scenario when no authorization value is given.
  std::string unsealed_data;
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result == TPM_RC_SUCCESS && data_to_seal == unsealed_data) {
    LOG(ERROR) << "Error: unseal succeeded without authorization.";
    return false;
  }
  // Check success scenario.
  policy_session->SetEntityAuthorizationValue(auth_value);
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
    return false;
  }
  if (data_to_seal != unsealed_data) {
    LOG(ERROR) << "Error unsealed data from TPM does not match original data.";
    return false;
  }
  result = utility->ExtendPCR(pcr_index, "extend", session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to pcr value: "
               << GetErrorString(result);
    return false;
  }
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error object was unsealed with wrong policy_digest.";
    return false;
  }
  return true;
}

bool TrunksClientTest::SealedToMultiplePCRDataTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  uint32_t pcr_index1 = 0;
  uint32_t pcr_index2 = 2;
  // Build policy digest.
  std::string policy_digest;
  TPM_RC result =
      utility->GetPolicyDigestForPcrValues(
          std::map<uint32_t, std::string>({{pcr_index1, ""}, {pcr_index2, ""}}),
          false /* use_auth_value */,
          &policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy_digest: " << GetErrorString(result);
    return false;
  }
  // Seal the data.
  std::string data_to_seal("seal_data");
  std::string sealed_data;
  result = utility->SealData(data_to_seal, policy_digest, "",
                             session->GetDelegate(), &sealed_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result);
    return false;
  }
  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index1, ""}, {pcr_index2, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to pcr value: "
               << GetErrorString(result);
    return false;
  }
  // Unseal the data under the same PCR.
  std::string unsealed_data;
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
    return false;
  }
  if (data_to_seal != unsealed_data) {
    LOG(ERROR) << "Error unsealed data from TPM does not match original data.";
    return false;
  }
  // Extend the PCR, thus making the data impossible to unseal.
  result = utility->ExtendPCR(pcr_index1, "extend", session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index1, ""}, {pcr_index2, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to pcr value: "
               << GetErrorString(result);
    return false;
  }
  // Try to unseal the data, after PCR change. It should fail.
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error object was unsealed with wrong policy_digest.";
    return false;
  }
  return true;
}

bool TrunksClientTest::PCRTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  // We are using PCR 2 because it is currently not used by ChromeOS.
  uint32_t pcr_index = 2;
  std::string extend_data("data");
  std::string old_data;
  TPM_RC result = utility->ReadPCR(pcr_index, &old_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
    return false;
  }
  result = utility->ExtendPCR(pcr_index, extend_data, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error extending PCR value: " << GetErrorString(result);
    return false;
  }
  std::string pcr_data;
  result = utility->ReadPCR(pcr_index, &pcr_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading from PCR: " << GetErrorString(result);
    return false;
  }
  std::string hashed_extend_data = crypto::SHA256HashString(extend_data);
  std::string expected_pcr_data =
      crypto::SHA256HashString(old_data + hashed_extend_data);
  if (pcr_data.compare(expected_pcr_data) != 0) {
    LOG(ERROR) << "PCR data does not match expected value.";
    return false;
  }
  return true;
}

bool TrunksClientTest::PolicyAuthValueTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
  TPM_RC result;
  result = trial_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = trial_session->PolicyAuthValue();
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to auth value knowledge: "
               << GetErrorString(result);
    return false;
  }
  std::string policy_digest;
  result = trial_session->GetDigest(&policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }
  // Now that we have the digest, we can close the trial session and use hmac.
  trial_session.reset();

  std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
  result = hmac_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }

  std::string key_blob;
  result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
      "password", policy_digest, true,  // use_only_policy_authorization
      std::vector<uint32_t>(), hmac_session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    return false;
  }

  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    return false;
  }
  ScopedKeyHandle scoped_key(factory_, key_handle);

  // Now we can reset the hmac_session.
  hmac_session.reset();

  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyAuthValue();
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to auth value knowledge: "
               << GetErrorString(result);
    return false;
  }
  std::string signature;
  policy_session->SetEntityAuthorizationValue("password");
  result = utility->Sign(scoped_key.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
                         std::string(32, 0), true /* generate_hash */,
                         policy_session->GetDelegate(), &signature);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error signing using RSA key: " << GetErrorString(result);
    return false;
  }
  std::string public_key;
  if (!GetRSAPublicKeyFromHandle(scoped_key, &public_key,
                                     policy_session->GetDelegate())) {
    LOG(ERROR) << "Error fetching the public key to verify: "
               << GetErrorString(result);
    return false;
  }
  if (!VerifyRSASignature(public_key, std::string(32, 0), signature)) {
    LOG(ERROR) << "Error verifying using RSA key: " << GetErrorString(result);
    return false;
  }
  std::string ciphertext;
  result =
      utility->AsymmetricEncrypt(scoped_key.get(), TPM_ALG_OAEP, TPM_ALG_SHA256,
                                 "plaintext", nullptr, &ciphertext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyAuthValue();
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to auth value knowledge: "
               << GetErrorString(result);
    return false;
  }
  std::string plaintext;
  policy_session->SetEntityAuthorizationValue("password");
  result = utility->AsymmetricDecrypt(
      scoped_key.get(), TPM_ALG_OAEP, TPM_ALG_SHA256, ciphertext,
      policy_session->GetDelegate(), &plaintext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error encrypting using RSA key: " << GetErrorString(result);
    return false;
  }
  if (plaintext.compare("plaintext") != 0) {
    LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
    return false;
  }
  return true;
}

bool TrunksClientTest::PolicyAndTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
  TPM_RC result;
  result = trial_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = trial_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  uint32_t pcr_index = 2;
  std::string pcr_value;
  result = utility->ReadPCR(pcr_index, &pcr_value);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading pcr: " << GetErrorString(result);
    return false;
  }
  std::string pcr_extend_data("extend");
  std::string next_pcr_value;
  std::string hashed_extend_data = crypto::SHA256HashString(pcr_extend_data);
  next_pcr_value = crypto::SHA256HashString(pcr_value + hashed_extend_data);

  result = trial_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, next_pcr_value}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string policy_digest;
  result = trial_session->GetDigest(&policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }
  // Now that we have the digest, we can close the trial session and use hmac.
  trial_session.reset();

  std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
  result = hmac_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  std::string key_authorization("password");
  std::string key_blob;
  // This key is created with a policy that dictates it can only be used
  // when pcr 2 remains unchanged, and when the command is TPM2_Sign.
  result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
      key_authorization, policy_digest, true,  // use_only_policy_authorization
      std::vector<uint32_t>(), hmac_session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    return false;
  }
  ScopedKeyHandle scoped_key(factory_, key_handle);

  // Now we can reset the hmac_session.
  hmac_session.reset();

  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string signature;
  policy_session->SetEntityAuthorizationValue(key_authorization);
  // Signing with this key when pcr 2 is unchanged fails.
  result = utility->Sign(scoped_key.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
                         std::string(32, 'a'), true /* generate_hash */,
                         policy_session->GetDelegate(), &signature);
  if (GetFormatOneError(result) != TPM_RC_POLICY_FAIL) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }
  std::unique_ptr<AuthorizationDelegate> delegate =
      factory_.GetPasswordAuthorization("");
  result = utility->ExtendPCR(pcr_index, pcr_extend_data, delegate.get());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error extending pcr: " << GetErrorString(result);
    return false;
  }
  // we have to restart the session because we changed the pcr values.
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  policy_session->SetEntityAuthorizationValue(key_authorization);
  // Signing with this key when pcr 2 is changed succeeds.
  result = utility->Sign(scoped_key.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
                         std::string(32, 'a'), true /* generate_hash */,
                         policy_session->GetDelegate(), &signature);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }
  std::string public_key;
  if (!GetRSAPublicKeyFromHandle(scoped_key, &public_key,
                                     policy_session->GetDelegate())) {
    LOG(ERROR) << "Error fetching the public key to verify: "
               << GetErrorString(result);
    return false;
  }
  if (!VerifyRSASignature(public_key, std::string(32, 'a'), signature)) {
    LOG(ERROR) << "Error using key to verify: " << GetErrorString(result);
    return false;
  }
  std::string ciphertext;
  result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256,
                                      "plaintext", nullptr, &ciphertext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyPCR(
      std::map<uint32_t, std::string>({{pcr_index, ""}}));
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string plaintext;
  policy_session->SetEntityAuthorizationValue(key_authorization);
  // This call is not authorized with the policy, because its command code
  // is not TPM_CC_SIGN. It should fail with TPM_RC_POLICY_CC.
  result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256,
                                      ciphertext, policy_session->GetDelegate(),
                                      &plaintext);
  if (GetFormatOneError(result) != TPM_RC_POLICY_CC) {
    LOG(ERROR) << "Error: " << GetErrorString(result);
    return false;
  }
  return true;
}

bool TrunksClientTest::PolicyOrTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();
  TPM_RC result;
  // Specify a policy that asserts either TPM_CC_Sign or TPM_CC_RSA_Decrypt.
  // A key created under this policy can only be used to sign or decrypt.
  result = trial_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = trial_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string sign_digest;
  result = trial_session->GetDigest(&sign_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }
  result = trial_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  result = trial_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string decrypt_digest;
  result = trial_session->GetDigest(&decrypt_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }
  std::vector<std::string> digests;
  digests.push_back(sign_digest);
  digests.push_back(decrypt_digest);
  result = trial_session->PolicyOR(digests);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string policy_digest;
  result = trial_session->GetDigest(&policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }
  // Now that we have the digest, we can close the trial session and use hmac.
  trial_session.reset();

  std::unique_ptr<HmacSession> hmac_session = factory_.GetHmacSession();
  result = hmac_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  std::string key_authorization("password");
  std::string key_blob;
  // This key is created with a policy that specifies that it can only be used
  // for sign and decrypt operations.
  result = utility->CreateRSAKeyPair(
      TpmUtility::AsymmetricKeyUsage::kDecryptAndSignKey, 2048, 0x10001,
      key_authorization, policy_digest, true,  // use_only_policy_authorization
      std::vector<uint32_t>(), hmac_session->GetDelegate(), &key_blob, nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating RSA key: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE key_handle;
  result = utility->LoadKey(key_blob, hmac_session->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading RSA key: " << GetErrorString(result);
    return false;
  }
  ScopedKeyHandle scoped_key(factory_, key_handle);

  // Now we can reset the hmac_session.
  hmac_session.reset();

  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();
  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }
  std::string ciphertext;
  result = utility->AsymmetricEncrypt(key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256,
                                      "plaintext", nullptr, &ciphertext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyCommandCode(TPM_CC_RSA_Decrypt);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyOR(digests);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string plaintext;
  policy_session->SetEntityAuthorizationValue(key_authorization);
  // We can freely use the key for decryption.
  result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256,
                                      ciphertext, policy_session->GetDelegate(),
                                      &plaintext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
    return false;
  }
  if (plaintext.compare("plaintext") != 0) {
    LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
    return false;
  }
  result = policy_session->PolicyCommandCode(TPM_CC_Sign);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  result = policy_session->PolicyOR(digests);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy: " << GetErrorString(result);
    return false;
  }
  std::string signature;
  policy_session->SetEntityAuthorizationValue(key_authorization);
  // However signing with a key only authorized for encrypt/decrypt should
  // fail with TPM_RC_POLICY_CC.
  result = utility->Sign(scoped_key.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
                         std::string(32, 'a'), true /* generate_hash */,
                         policy_session->GetDelegate(), &signature);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }
  return true;
}

bool TrunksClientTest::NvramTest(const std::string& owner_password) {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  TPM_RC result = session->StartUnboundSession(true /* salted */,
                                               true /* enable encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  uint32_t index = 1;
  session->SetEntityAuthorizationValue(owner_password);
  std::string nv_data("nv_data");
  TPMA_NV attributes = TPMA_NV_OWNERWRITE | TPMA_NV_AUTHREAD |
                       TPMA_NV_WRITE_STCLEAR | TPMA_NV_READ_STCLEAR;
  result = utility->DefineNVSpace(index, nv_data.size(), attributes, "", "",
                                  session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error defining nvram: " << GetErrorString(result);
    return false;
  }
  // Setup auto-cleanup of the NVRAM space.
  auto cleanup = base::Bind(
      [](HmacSession* session, const std::string& owner_password,
         TpmUtility* utility, uint32_t index) {
    session->SetEntityAuthorizationValue(owner_password);
    TPM_RC result = utility->DestroyNVSpace(index, session->GetDelegate());
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error destroying nvram: " << GetErrorString(result);
    }
  }, session.get(), owner_password, utility.get(), index);
  base::ScopedClosureRunner scoper(cleanup);

  session->SetEntityAuthorizationValue(owner_password);
  result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/,
                                 false /*extend*/, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error writing nvram: " << GetErrorString(result);
    return false;
  }
  std::string new_nvdata;
  session->SetEntityAuthorizationValue("");
  result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
                                &new_nvdata, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
    return false;
  }
  if (nv_data.compare(new_nvdata) != 0) {
    LOG(ERROR) << "NV space had different data than was written.";
    return false;
  }
  session->SetEntityAuthorizationValue(owner_password);
  result = utility->LockNVSpace(index, false /*lock_read*/, true /*lock_write*/,
                                false /*owner*/, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error locking nvram write: " << GetErrorString(result);
    return false;
  }
  session->SetEntityAuthorizationValue("");
  result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
                                &new_nvdata, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error reading nvram: " << GetErrorString(result);
    return false;
  }
  if (nv_data.compare(new_nvdata) != 0) {
    LOG(ERROR) << "NV space had different data than was written.";
    return false;
  }
  session->SetEntityAuthorizationValue(owner_password);
  result = utility->WriteNVSpace(index, 0, nv_data, true /*owner*/,
                                 false /*extend*/, session->GetDelegate());
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Wrote nvram after locking!";
    return false;
  }
  result = utility->LockNVSpace(index, true /*lock_read*/, false /*lock_write*/,
                                true /*owner*/, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error locking nvram read: " << GetErrorString(result);
    return false;
  }
  result = utility->ReadNVSpace(index, 0, nv_data.size(), false /*owner*/,
                                &new_nvdata, session->GetDelegate());
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Read nvram after locking!";
    return false;
  }
  return true;
}

bool TrunksClientTest::ManyKeysTest() {
  const size_t kNumKeys = 20;
  std::vector<std::unique_ptr<ScopedKeyHandle>> key_handles;
  std::map<TPM_HANDLE, std::string> public_key_map;
  for (size_t i = 0; i < kNumKeys; ++i) {
    std::unique_ptr<ScopedKeyHandle> key_handle(new ScopedKeyHandle(factory_));
    std::string public_key;
    if (!LoadSigningKey(key_handle.get(), &public_key)) {
      LOG(ERROR) << "Error loading key " << i << " into TPM.";
    }
    public_key_map[key_handle->get()] = public_key;
    key_handles.push_back(std::move(key_handle));
  }
  CHECK_EQ(key_handles.size(), kNumKeys);
  CHECK_EQ(public_key_map.size(), kNumKeys);
  std::unique_ptr<AuthorizationDelegate> delegate =
      factory_.GetPasswordAuthorization("");
  for (size_t i = 0; i < kNumKeys; ++i) {
    const ScopedKeyHandle& key_handle = *key_handles[i];
    const std::string& public_key = public_key_map[key_handle.get()];
    if (!SignAndVerify(key_handle, public_key, delegate.get())) {
      LOG(ERROR) << "Error signing with key " << i;
    }
  }
  // TODO(emaxx): This needs to be replaced by base::RandomShuffle() introduced
  // by https://crrev.com/c/1023495.
  std::mt19937 urng(base::RandUint64());
  std::shuffle(key_handles.begin(), key_handles.end(), urng);
  for (size_t i = 0; i < kNumKeys; ++i) {
    const ScopedKeyHandle& key_handle = *key_handles[i];
    const std::string& public_key = public_key_map[key_handle.get()];
    if (!SignAndVerify(key_handle, public_key, delegate.get())) {
      LOG(ERROR) << "Error signing with shuffled key " << i;
    }
  }
  return true;
}

bool TrunksClientTest::ManySessionsTest() {
  const size_t kNumSessions = 20;
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::vector<std::unique_ptr<HmacSession>> sessions;
  for (size_t i = 0; i < kNumSessions; ++i) {
    std::unique_ptr<HmacSession> session(factory_.GetHmacSession().release());
    TPM_RC result = session->StartUnboundSession(true /* salted */,
                                                 true /* enable encryption */);
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error starting hmac session " << i << ": "
                 << GetErrorString(result);
      return false;
    }
    sessions.push_back(std::move(session));
  }
  CHECK_EQ(sessions.size(), kNumSessions);
  ScopedKeyHandle key_handle(factory_);
  std::string public_key;
  if (!LoadSigningKey(&key_handle, &public_key)) {
    return false;
  }
  for (size_t i = 0; i < kNumSessions; ++i) {
    if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
      LOG(ERROR) << "Error signing with hmac session " << i;
    }
  }
  // TODO(emaxx): This needs to be replaced by base::RandomShuffle() introduced
  // by https://crrev.com/c/1023495.
  std::mt19937 urng(base::RandUint64());
  std::shuffle(sessions.begin(), sessions.end(), urng);
  for (size_t i = 0; i < kNumSessions; ++i) {
    if (!SignAndVerify(key_handle, public_key, sessions[i]->GetDelegate())) {
      LOG(ERROR) << "Error signing with shuffled hmac session " << i;
    }
  }
  return true;
}

bool TrunksClientTest::EndorsementTest(const std::string& endorsement_password,
                                       const std::string& owner_password) {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  TPM_RC result = session->StartUnboundSession(true /* salted */,
                                               false /* enable encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  session->SetEntityAuthorizationValue(endorsement_password);
  std::unique_ptr<HmacSession> session2 = factory_.GetHmacSession();
  result = session2->StartUnboundSession(true /* salted */,
                                         false /* enable encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  session2->SetEntityAuthorizationValue(owner_password);
  TPM_HANDLE key_handle;
  result = utility->GetEndorsementKey(TPM_ALG_RSA, session->GetDelegate(),
                                      session2->GetDelegate(), &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "GetEndorsementKey(RSA) failed: " << GetErrorString(result);
    return false;
  }
  result = utility->GetEndorsementKey(TPM_ALG_ECC, session->GetDelegate(),
                                      nullptr, &key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "GetEndorsementKey(ECC) failed: " << GetErrorString(result);
    return false;
  }
  return true;
}

bool TrunksClientTest::IdentityKeyTest() {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();
  TPM_RC result = session->StartUnboundSession(true /* salted */,
                                               false /* enable encryption */);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session: " << GetErrorString(result);
    return false;
  }
  std::string key_blob;
  result = utility->CreateIdentityKey(TPM_ALG_RSA, session->GetDelegate(),
                                      &key_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "CreateIdentityKey(RSA) failed: " << GetErrorString(result);
    return false;
  }
  std::unique_ptr<TpmState> tpm_state(factory_.GetTpmState());
  tpm_state->Initialize();
  if (tpm_state->IsECCSupported()) {
    result = utility->CreateIdentityKey(TPM_ALG_ECC, session->GetDelegate(),
                                        &key_blob);
    if (result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "CreateIdentityKey(ECC) failed: " << GetErrorString(result);
      return false;
    }
  }
  return true;
}

bool TrunksClientTest::PerformRSAEncryptAndDecrypt(
    TPM_HANDLE key_handle,
    const std::string& key_authorization,
    HmacSession* session) {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::string ciphertext;
  session->SetEntityAuthorizationValue("");
  TPM_RC result = utility->AsymmetricEncrypt(
      key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256, "plaintext",
      session->GetDelegate(), &ciphertext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to encrypt: " << GetErrorString(result);
    return false;
  }
  std::string plaintext;
  session->SetEntityAuthorizationValue(key_authorization);
  result = utility->AsymmetricDecrypt(key_handle, TPM_ALG_OAEP, TPM_ALG_SHA256,
                                      ciphertext, session->GetDelegate(),
                                      &plaintext);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to decrypt: " << GetErrorString(result);
    return false;
  }
  if (plaintext.compare("plaintext") != 0) {
    LOG(ERROR) << "Plaintext changed after encrypt + decrypt.";
    return false;
  }
  return true;
}

void TrunksClientTest::GenerateRSAKeyPair(std::string* modulus,
                                          std::string* prime_factor,
                                          std::string* public_key) {
  crypto::ScopedRSA rsa(RSA_new());
  CHECK(rsa);
  crypto::ScopedBIGNUM exponent(BN_new());
  CHECK(exponent);
  CHECK(BN_set_word(exponent.get(), RSA_F4));
  CHECK(RSA_generate_key_ex(rsa.get(), 2048, exponent.get(), nullptr))
      << "Failed to generate RSA key: " << GetOpenSSLError();
  modulus->resize(RSA_size(rsa.get()), 0);
  const BIGNUM* n;
  RSA_get0_key(rsa.get(), &n, nullptr, nullptr);
  CHECK(BN_bn2bin(n, reinterpret_cast<unsigned char*>(base::data(*modulus))));
  const BIGNUM* p;
  RSA_get0_factors(rsa.get(), &p, nullptr);
  prime_factor->resize(BN_num_bytes(p), 0);
  CHECK(BN_bn2bin(p,
                  reinterpret_cast<unsigned char*>(base::data(*prime_factor))));
  if (public_key) {
    unsigned char* buffer = NULL;
    int length = i2d_RSAPublicKey(rsa.get(), &buffer);
    CHECK_GT(length, 0);
    crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
    public_key->assign(reinterpret_cast<char*>(buffer), length);
  }
}

bool TrunksClientTest::VerifyRSASignature(const std::string& public_key,
                                          const std::string& data,
                                          const std::string& signature) {
  auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
  crypto::ScopedRSA rsa(
      d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
  CHECK(rsa.get());
  std::string digest = crypto::SHA256HashString(data);
  auto digest_buffer = reinterpret_cast<const unsigned char*>(digest.data());
  std::string mutable_signature(signature);
  unsigned char* signature_buffer =
      reinterpret_cast<unsigned char*>(base::data(mutable_signature));
  return (RSA_verify(NID_sha256, digest_buffer, digest.size(), signature_buffer,
                     signature.size(), rsa.get()) == 1);
}

bool TrunksClientTest::LoadSigningKey(ScopedKeyHandle* key_handle,
                                      std::string* public_key) {
  std::string modulus;
  std::string prime_factor;
  GenerateRSAKeyPair(&modulus, &prime_factor, public_key);
  std::string key_blob;
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  TPM_RC result = utility->ImportRSAKey(
      TpmUtility::AsymmetricKeyUsage::kSignKey, modulus, 0x10001, prime_factor,
      "",  // password
      factory_.GetPasswordAuthorization("").get(), &key_blob);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "ImportRSAKey: " << GetErrorString(result);
    return false;
  }
  TPM_HANDLE raw_key_handle;
  result = utility->LoadKey(
      key_blob, factory_.GetPasswordAuthorization("").get(), &raw_key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "LoadKey: " << GetErrorString(result);
    return false;
  }
  key_handle->reset(raw_key_handle);
  return true;
}

bool TrunksClientTest::SignAndVerify(const ScopedKeyHandle& key_handle,
                                     const std::string& public_key,
                                     AuthorizationDelegate* delegate) {
  std::string signature;
  std::string data_to_sign("sign_this");
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  TPM_RC result =
      utility->Sign(key_handle.get(), TPM_ALG_RSASSA, TPM_ALG_SHA256,
                    data_to_sign, true /* generate_hash */,
                    delegate, &signature);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Sign: " << GetErrorString(result);
    return false;
  }
  if (!VerifyRSASignature(public_key, data_to_sign, signature)) {
    LOG(ERROR) << "Signature verification failed: " << GetOpenSSLError();
    return false;
  }
  return true;
}

bool TrunksClientTest::GetRSAPublicKeyFromHandle(
    const ScopedKeyHandle& key_handle,
    std::string* public_key,
    AuthorizationDelegate* delegate) {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  TPMT_PUBLIC public_area;
  TPM_RC result = utility->GetKeyPublicArea(key_handle.get(), &public_area);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << __func__ << GetErrorString(result);
    return false;
  }
  // Copied from cryptohome::PublicAreaToPublicKeyDER
  crypto::ScopedRSA rsa(RSA_new());
  CHECK(rsa);
  crypto::ScopedBIGNUM e(BN_new()), n(BN_new());
  CHECK(e);
  CHECK(n);
  CHECK(BN_set_word(e.get(), 0x10001)) << "Error setting exponent for RSA.";
  CHECK(BN_bin2bn(public_area.unique.rsa.buffer,
                  public_area.unique.rsa.size,
                  n.get())) << "Error setting modulus for RSA.";
  CHECK(RSA_set0_key(rsa.get(), n.release(), e.release(), nullptr));

  int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to get DER-encoded public key length.";
    return false;
  }
  public_key->resize(der_length);
  unsigned char* der_buffer =
      reinterpret_cast<unsigned char*>(base::data(*public_key));
  der_length = i2d_RSAPublicKey(rsa.get(), &der_buffer);
  if (der_length < 0) {
    LOG(ERROR) << "Failed to DER-encode public key.";
    return false;
  }
  return true;
}

bool TrunksClientTest::PolicyFidoSignedTest(TPM_ALG_ID signing_algo) {
  std::unique_ptr<TpmUtility> utility = factory_.GetTpmUtility();
  std::unique_ptr<HmacSession> session = factory_.GetHmacSession();

  TPM_RC result;

  // 1. Prepare a key to sign.
  // 1-a) Create a key pair
  if (utility->StartSession(session.get()) != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }

  std::string key_blob;

  switch (signing_algo) {
    case TPM_ALG_RSASSA:
    case TPM_ALG_RSAPSS:
      result = utility->CreateRSAKeyPair(
          TpmUtility::AsymmetricKeyUsage::kSignKey, 2048, 0x10001, "", "",
          false, std::vector<uint32_t>(), session->GetDelegate(), &key_blob,
          nullptr);
      break;

    case TPM_ALG_ECDSA:
    case TPM_ALG_ECDAA:
    case TPM_ALG_SM2:
    case TPM_ALG_ECSCHNORR:
      result = utility->CreateECCKeyPair(
          TpmUtility::AsymmetricKeyUsage::kSignKey, TPM_ECC_NIST_P256, "", "",
          false, std::vector<uint32_t>(), session->GetDelegate(), &key_blob,
          nullptr);
      break;

    default:
      result = TPM_RC_SCHEME;
      LOG(ERROR) << "Unknown hash algorithm: " << GetErrorString(result);
      return result;
  }
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating signing key: " << GetErrorString(result);
    return false;
  }

  // 1-b) Load the key
  TPM_HANDLE signing_key_handle;
  result =
      utility->LoadKey(key_blob, session->GetDelegate(), &signing_key_handle);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error loading signing key: " << GetErrorString(result);
    return false;
  }

  // 2. PolicyFidoSigned in trial session
  // 2-a) Start Auth session
  std::unique_ptr<PolicySession> trial_session = factory_.GetTrialSession();

  result = trial_session->StartUnboundSession(true, true);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }

  // 2-b) Sign the authenticatorData and session nonce
  const std::string auth_data_fixed =
      crypto::SHA256HashString("chromeos:login:nobody");
  const std::string auth_data =
      std::string("ghijklmn", 8) + auth_data_fixed + std::string("opqrstuv", 8);

  const std::vector<trunks::FIDO_DATA_RANGE> auth_data_descr = {
      {.offset = 0x0008, .size = 0x0010}, {.offset = 0x0018, .size = 0x0010}};

  std::string nonce;
  trial_session->GetDelegate()->GetTpmNonce(&nonce);

  TPM_ALG_ID hash_algo = TPM_ALG_SHA256;

  TPMT_SIGNATURE auth;
  result = utility->RawSign(signing_key_handle, signing_algo, hash_algo,
                            auth_data + nonce,
                            true,  // generate_hash
                            session->GetDelegate(), &auth);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }

  // 2-c) Policy Fido Signed (with loaded pub key from 1-b)
  std::string signing_key_name;

  result = utility->GetKeyName(signing_key_handle, &signing_key_name);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error in getting key name: " << GetErrorString(result);
    return false;
  }

  result = trial_session->PolicyFidoSigned(signing_key_handle, signing_key_name,
                                           auth_data, auth_data_descr, auth,
                                           nullptr);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error with PolicyFidoSigned in trial session: "
               << GetErrorString(result);
    return false;
  }

  // 2-d) Get Policy digest
  std::string policy_digest;
  result = trial_session->GetDigest(&policy_digest);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(result);
    return false;
  }

  // Now that we have the digest, we can close the trial session and use hmac.
  trial_session.reset();

  // 3. Seal an secret object.
  const std::string data_to_seal("sealed_data_for_PolicyFidoSigned");
  std::string sealed_data;

  result = utility->SealData(data_to_seal, policy_digest, "",
                             session->GetDelegate(), &sealed_data);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error creating Sealed Object: " << GetErrorString(result);
    return false;
  }

  // 4. Test failing cases
  // 4-1. Start Auth Session ((TPM_SE_POLICY = 0x01))
  std::unique_ptr<PolicySession> policy_session = factory_.GetPolicySession();

  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }

  const std::string auth_data2 =
      std::string("XXXXXXXX", 8) + auth_data_fixed + std::string("ZZZZZZZZ", 8);

  // 4-2. Check PolicyFidoSigned fail with the wrong data auth
  result = policy_session->PolicyFidoSigned(
      signing_key_handle, signing_key_name, auth_data2, auth_data_descr,
      TPMT_SIGNATURE(), session->GetDelegate());
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Unexpected success with PolicyFidoSigned "
               << "with the empty auth: " << GetErrorString(result);
    return false;
  }

  // 4-3. Check PolicyFidoSigned fail with the wrong auth data
  // 4-3-1. Sign the command parameters
  policy_session->GetDelegate()->GetTpmNonce(&nonce);
  result = utility->RawSign(signing_key_handle, signing_algo, hash_algo,
                            std::string(64, '0') + nonce,  // <- wrong authData
                            true,                          // generate_hash
                            session->GetDelegate(), &auth);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }

  // 4-3-2. Call PolicyFidoSigned with the wrong authData
  result = policy_session->PolicyFidoSigned(
      signing_key_handle, signing_key_name,
      std::string(64, '0'),  // <- wrong authData
      auth_data_descr, auth, session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error with PolicyFidoSigned in policy session: "
               << GetErrorString(result);
    return false;
  }

  // 4-3-3. check UnsealData fail
  std::string unsealed_data;
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Unexpected success in unsealing object: "
               << GetErrorString(result);
    return false;
  }

  // 4-4. Check PolicyFidoSigned fail with the wrong auth_data_descr.
  policy_session->GetDelegate()->GetTpmNonce(&nonce);
  result = utility->RawSign(signing_key_handle, signing_algo, hash_algo,
                            auth_data2 + nonce,
                            true,  // generate_hash
                            session->GetDelegate(), &auth);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }

  const std::vector<trunks::FIDO_DATA_RANGE> auth_data_descr2 = {
      {.offset = 0x0008, .size = 0x0010},
      {.offset = 0x0018, .size = 0x00f0}};  // <-- out of range

  result = policy_session->PolicyFidoSigned(
      signing_key_handle, signing_key_name, auth_data2, auth_data_descr2, auth,
      session->GetDelegate());
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Unexpected success with PolicyFidoSigned in policy session: "
               << GetErrorString(result);
    return false;
  }

  // 4-5. Check PolicyFidoSigned fail with a different auth_data_descr
  const std::vector<trunks::FIDO_DATA_RANGE> auth_data_descr3 = {
      {.offset = 0x0008, .size = 0x0020}};

  policy_session->GetDelegate()->GetTpmNonce(&nonce);
  result = utility->RawSign(signing_key_handle, signing_algo, hash_algo,
                            auth_data + nonce,
                            true,  // generate_hash
                            session->GetDelegate(), &auth);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }

  result = policy_session->PolicyFidoSigned(
      signing_key_handle, signing_key_name, auth_data, auth_data_descr3, auth,
      session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error with PolicyFidoSigned in policy session: "
               << GetErrorString(result);
    return false;
  }

  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data);
  if (result == TPM_RC_SUCCESS) {
    LOG(ERROR) << "Unexpected success in unsealing object: "
               << GetErrorString(result);
    return false;
  }

  policy_session.reset();

  // 5. Test success cases
  // 5-1. Check PolicyFidoSigned success
  policy_session = factory_.GetPolicySession();

  result = policy_session->StartUnboundSession(true, false);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting policy session: " << GetErrorString(result);
    return false;
  }

  // 5-1-1. Sign the command
  policy_session->GetDelegate()->GetTpmNonce(&nonce);
  result = utility->RawSign(signing_key_handle, signing_algo, hash_algo,
                            auth_data2 + nonce,
                            true,  // generate_hash
                            session->GetDelegate(), &auth);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error using key to sign: " << GetErrorString(result);
    return false;
  }

  // 5-1-2. PolicyFidoSigned
  result = policy_session->PolicyFidoSigned(
      signing_key_handle, signing_key_name, auth_data2, auth_data_descr, auth,
      session->GetDelegate());
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error with PolicyFidoSigned in policy session: "
               << GetErrorString(result);
    return false;
  }

  // 5-1-3. Unseal
  std::string unsealed_data2;
  result = utility->UnsealData(sealed_data, policy_session->GetDelegate(),
                               &unsealed_data2);
  if (result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error unsealing object: " << GetErrorString(result);
    return false;
  }
  if (data_to_seal != unsealed_data2) {
    LOG(ERROR) << "Error unsealed data from TPM does not match original data.";
    return false;
  }

  policy_session.reset();

  return true;
}

}  // namespace trunks
