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