// Copyright 2018 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "cryptohome/signature_sealing_backend_tpm2_impl.h"

#include <stdint.h>
#include <cstring>
#include <string>
#include <utility>

#include <base/logging.h>
#include <base/memory/ptr_util.h>
#include <base/numerics/safe_conversions.h>
#include <base/optional.h>
#include <base/threading/thread_checker.h>
#include <brillo/secure_blob.h>
#include <google/protobuf/repeated_field.h>
#include <trunks/error_codes.h>
#include <trunks/policy_session.h>
#include <trunks/tpm_generated.h>
#include <trunks/trunks_factory_impl.h>
#include <trunks/hmac_session.h>
#include <trunks/tpm_utility.h>
#include <trunks/authorization_delegate.h>

#include "cryptohome/key.pb.h"
#include "cryptohome/signature_sealed_data.pb.h"
#include "cryptohome/tpm2_impl.h"

using brillo::Blob;
using brillo::BlobFromString;
using brillo::BlobToString;
using brillo::CombineBlobs;
using brillo::SecureBlob;
using trunks::GetErrorString;
using trunks::TPM_ALG_ID;
using trunks::TPM_ALG_NULL;
using trunks::TPM_RC;
using trunks::TPM_RC_SUCCESS;

namespace cryptohome {

namespace {

// Size, in bytes, of the secret value that is generated by
// SignatureSealingBackendTpm2Impl::CreateSealedSecret().
constexpr int kSecretSizeBytes = 32;

class UnsealingSessionTpm2Impl final
    : public SignatureSealingBackend::UnsealingSession {
 public:
  UnsealingSessionTpm2Impl(
      Tpm2Impl* tpm,
      Tpm2Impl::TrunksClientContext* trunks,
      const Blob& srk_wrapped_secret,
      const Blob& public_key_spki_der,
      ChallengeSignatureAlgorithm algorithm,
      TPM_ALG_ID scheme,
      TPM_ALG_ID hash_alg,
      std::unique_ptr<trunks::PolicySession> policy_session,
      const Blob& policy_session_tpm_nonce);
  UnsealingSessionTpm2Impl(const UnsealingSessionTpm2Impl&) = delete;
  UnsealingSessionTpm2Impl& operator=(const UnsealingSessionTpm2Impl&) = delete;

  ~UnsealingSessionTpm2Impl() override;

  // UnsealingSession:
  ChallengeSignatureAlgorithm GetChallengeAlgorithm() override;
  Blob GetChallengeValue() override;
  bool Unseal(const Blob& signed_challenge_value,
              SecureBlob* unsealed_value) override;

 private:
  // Unowned.
  Tpm2Impl* const tpm_;
  // Unowned.
  Tpm2Impl::TrunksClientContext* const trunks_;
  const Blob srk_wrapped_secret_;
  const Blob public_key_spki_der_;
  const ChallengeSignatureAlgorithm algorithm_;
  const TPM_ALG_ID scheme_;
  const TPM_ALG_ID hash_alg_;
  const std::unique_ptr<trunks::PolicySession> policy_session_;
  const Blob policy_session_tpm_nonce_;
  base::ThreadChecker thread_checker_;
};

// Obtains the TPM 2.0 signature scheme and hashing algorithms that correspond
// to the provided challenge signature algorithm.
bool GetAlgIdsByAlgorithm(ChallengeSignatureAlgorithm algorithm,
                          TPM_ALG_ID* scheme,
                          TPM_ALG_ID* hash_alg) {
  switch (algorithm) {
    case CHALLENGE_RSASSA_PKCS1_V1_5_SHA1:
      *scheme = trunks::TPM_ALG_RSASSA;
      *hash_alg = trunks::TPM_ALG_SHA1;
      return true;
    case CHALLENGE_RSASSA_PKCS1_V1_5_SHA256:
      *scheme = trunks::TPM_ALG_RSASSA;
      *hash_alg = trunks::TPM_ALG_SHA256;
      return true;
    case CHALLENGE_RSASSA_PKCS1_V1_5_SHA384:
      *scheme = trunks::TPM_ALG_RSASSA;
      *hash_alg = trunks::TPM_ALG_SHA384;
      return true;
    case CHALLENGE_RSASSA_PKCS1_V1_5_SHA512:
      *scheme = trunks::TPM_ALG_RSASSA;
      *hash_alg = trunks::TPM_ALG_SHA512;
      return true;
  }
  NOTREACHED();
  return false;
}

// Given the list of alternative sets of PCR restrictions, returns the one that
// is currently satisfied. Returns null if none is satisfied.
const SignatureSealedData_Tpm2PcrRestriction* GetSatisfiedPcrRestriction(
    const google::protobuf::RepeatedPtrField<
        SignatureSealedData_Tpm2PcrRestriction>& pcr_restrictions,
    Tpm* tpm) {
  std::map<uint32_t, Blob> current_pcr_values;
  for (const auto& pcr_restriction_proto : pcr_restrictions) {
    bool is_satisfied = true;
    for (const auto& pcr_value_proto : pcr_restriction_proto.pcr_values()) {
      const uint32_t pcr_index = pcr_value_proto.pcr_index();
      if (pcr_index >= IMPLEMENTATION_PCR) {
        LOG(WARNING) << "Invalid PCR index " << pcr_index;
        is_satisfied = false;
        break;
      }
      if (!current_pcr_values.count(pcr_index)) {
        Blob pcr_value;
        if (!tpm->ReadPCR(pcr_index, &pcr_value)) {
          is_satisfied = false;
          break;
        }
        current_pcr_values.emplace(pcr_index, pcr_value);
      }
      if (current_pcr_values[pcr_index] !=
          BlobFromString(pcr_value_proto.pcr_value())) {
        is_satisfied = false;
        break;
      }
    }
    if (is_satisfied)
      return &pcr_restriction_proto;
  }
  return nullptr;
}

UnsealingSessionTpm2Impl::UnsealingSessionTpm2Impl(
    Tpm2Impl* tpm,
    Tpm2Impl::TrunksClientContext* trunks,
    const Blob& srk_wrapped_secret,
    const Blob& public_key_spki_der,
    ChallengeSignatureAlgorithm algorithm,
    TPM_ALG_ID scheme,
    TPM_ALG_ID hash_alg,
    std::unique_ptr<trunks::PolicySession> policy_session,
    const Blob& policy_session_tpm_nonce)
    : tpm_(tpm),
      trunks_(trunks),
      srk_wrapped_secret_(srk_wrapped_secret),
      public_key_spki_der_(public_key_spki_der),
      algorithm_(algorithm),
      scheme_(scheme),
      hash_alg_(hash_alg),
      policy_session_(std::move(policy_session)),
      policy_session_tpm_nonce_(policy_session_tpm_nonce) {}

UnsealingSessionTpm2Impl::~UnsealingSessionTpm2Impl() {
  DCHECK(thread_checker_.CalledOnValidThread());
}

ChallengeSignatureAlgorithm UnsealingSessionTpm2Impl::GetChallengeAlgorithm() {
  DCHECK(thread_checker_.CalledOnValidThread());
  return algorithm_;
}

Blob UnsealingSessionTpm2Impl::GetChallengeValue() {
  DCHECK(thread_checker_.CalledOnValidThread());
  const Blob expiration_blob(4);  // zero expiration (4-byte integer)
  return CombineBlobs({policy_session_tpm_nonce_, expiration_blob});
}

bool UnsealingSessionTpm2Impl::Unseal(const Blob& signed_challenge_value,
                                      SecureBlob* unsealed_value) {
  DCHECK(thread_checker_.CalledOnValidThread());
  // Start a TPM authorization session.
  std::unique_ptr<trunks::HmacSession> session =
      trunks_->factory->GetHmacSession();
  TPM_RC tpm_result = trunks_->tpm_utility->StartSession(session.get());
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session.";
    return false;
  }
  // Load the protection public key onto the TPM.
  ScopedKeyHandle key_handle;
  if (!tpm_->LoadPublicKeyFromSpki(
          public_key_spki_der_, trunks::TpmUtility::kSignKey, scheme_,
          hash_alg_, session->GetDelegate(), &key_handle)) {
    LOG(ERROR) << "Error loading protection key";
    return false;
  }
  std::string key_name;
  tpm_result = trunks_->tpm_utility->GetKeyName(key_handle.value(), &key_name);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Failed to get key name";
    return false;
  }
  // Update the policy with the signature.
  trunks::TPMT_SIGNATURE signature;
  memset(&signature, 0, sizeof(trunks::TPMT_SIGNATURE));
  signature.sig_alg = scheme_;
  signature.signature.rsassa.hash = hash_alg_;
  signature.signature.rsassa.sig =
      trunks::Make_TPM2B_PUBLIC_KEY_RSA(BlobToString(signed_challenge_value));
  tpm_result = policy_session_->PolicySigned(
      key_handle.value(), key_name, BlobToString(policy_session_tpm_nonce_),
      std::string() /* cp_hash */, std::string() /* policy_ref */,
      0 /* expiration */, signature, session->GetDelegate());
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to signature with the public key: "
               << GetErrorString(tpm_result);
    return false;
  }
  // Obtain the resulting policy digest.
  std::string policy_digest;
  tpm_result = policy_session_->GetDigest(&policy_digest);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(tpm_result);
    return false;
  }
  // Unseal the secret value.
  std::string unsealed_value_string;
  tpm_result = trunks_->tpm_utility->UnsealData(
      BlobToString(srk_wrapped_secret_), policy_session_->GetDelegate(),
      &unsealed_value_string);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error unsealing object: " << GetErrorString(tpm_result);
    return false;
  }
  *unsealed_value = SecureBlob(unsealed_value_string);
  return true;
}

}  // namespace

SignatureSealingBackendTpm2Impl::SignatureSealingBackendTpm2Impl(Tpm2Impl* tpm)
    : tpm_(tpm) {}

SignatureSealingBackendTpm2Impl::~SignatureSealingBackendTpm2Impl() = default;

bool SignatureSealingBackendTpm2Impl::CreateSealedSecret(
    const Blob& public_key_spki_der,
    const std::vector<ChallengeSignatureAlgorithm>& key_algorithms,
    const std::vector<std::map<uint32_t, brillo::Blob>>& pcr_restrictions,
    const Blob& /* delegate_blob */,
    const Blob& /* delegate_secret */,
    brillo::SecureBlob* secret_value,
    SignatureSealedData* sealed_secret_data) {
  // Choose the algorithm. Respect the input's algorithm prioritization, with
  // the exception of considering SHA-1 as the least preferred option.
  TPM_ALG_ID scheme = TPM_ALG_NULL;
  TPM_ALG_ID hash_alg = TPM_ALG_NULL;
  for (auto algorithm : key_algorithms) {
    TPM_ALG_ID current_scheme = TPM_ALG_NULL;
    TPM_ALG_ID current_hash_alg = TPM_ALG_NULL;
    if (GetAlgIdsByAlgorithm(algorithm, &current_scheme, &current_hash_alg)) {
      scheme = current_scheme;
      hash_alg = current_hash_alg;
      if (hash_alg != trunks::TPM_ALG_SHA1)
        break;
    }
  }
  if (scheme == TPM_ALG_NULL) {
    LOG(ERROR) << "Error choosing the signature algorithm";
    return false;
  }
  // Start a TPM authorization session.
  Tpm2Impl::TrunksClientContext* trunks = nullptr;
  if (!tpm_->GetTrunksContext(&trunks)) {
    LOG(ERROR) << "Error getting trunks context";
    return false;
  }
  std::unique_ptr<trunks::HmacSession> session =
      trunks->factory->GetHmacSession();
  TPM_RC tpm_result = trunks->tpm_utility->StartSession(session.get());
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting hmac session";
    return false;
  }
  // Load the protection public key onto the TPM.
  ScopedKeyHandle key_handle;
  if (!tpm_->LoadPublicKeyFromSpki(
          public_key_spki_der, trunks::TpmUtility::kSignKey, scheme, hash_alg,
          session->GetDelegate(), &key_handle)) {
    LOG(ERROR) << "Error loading protection key";
    return false;
  }
  std::string key_name;
  tpm_result = trunks->tpm_utility->GetKeyName(key_handle.value(), &key_name);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Failed to get key name";
    return false;
  }
  // Start a trial policy session for sealing the secret value.
  std::unique_ptr<trunks::PolicySession> policy_session =
      trunks->factory->GetTrialSession();
  tpm_result = policy_session->StartUnboundSession(true, false);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting a trial session: "
               << GetErrorString(tpm_result);
    return false;
  }
  // Calculate policy digests for each of the sets of PCR restrictions
  // separately. Rewind each time the policy session back to the initial state,
  // except when we're in the degenerate case of only one set of PCRs (so that
  // no PolicyOR command should be used, and we should just proceed with the
  // PolicyPCR result).
  std::vector<std::string> pcr_policy_digests;
  for (const auto& pcr_values : pcr_restrictions) {
    DCHECK(!pcr_values.empty());
    // Run PolicyPCR against the current PCR set.
    std::map<uint32_t, std::string> pcr_values_strings;
    for (const auto& pcr_index_and_value : pcr_values) {
      pcr_values_strings[pcr_index_and_value.first] =
          BlobToString(pcr_index_and_value.second);
    }
    tpm_result = policy_session->PolicyPCR(pcr_values_strings);
    if (tpm_result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error restricting policy to PCRs: "
                 << GetErrorString(tpm_result);
      return false;
    }
    // Remember the policy digest for the current PCR set.
    std::string pcr_policy_digest;
    tpm_result = policy_session->GetDigest(&pcr_policy_digest);
    if (tpm_result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error getting policy digest: "
                 << GetErrorString(tpm_result);
      return false;
    }
    pcr_policy_digests.push_back(pcr_policy_digest);
    // Restart the policy session when necessary.
    if (pcr_restrictions.size() > 1) {
      tpm_result = policy_session->PolicyRestart();
      if (tpm_result != TPM_RC_SUCCESS) {
        LOG(ERROR) << "Error restarting the policy session: "
                   << GetErrorString(tpm_result);
        return false;
      }
    }
  }
  // If necessary, apply PolicyOR for restricting to the disjunction of the
  // specified sets of PCR restrictions.
  if (pcr_restrictions.size() > 1) {
    tpm_result = policy_session->PolicyOR(pcr_policy_digests);
    if (tpm_result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error restricting policy to logical disjunction of PCRs: "
                 << GetErrorString(tpm_result);
      return false;
    }
  }
  // Update the policy with an empty signature that refers to the public key.
  trunks::TPMT_SIGNATURE signature;
  memset(&signature, 0, sizeof(trunks::TPMT_SIGNATURE));
  signature.sig_alg = scheme;
  signature.signature.rsassa.hash = hash_alg;
  signature.signature.rsassa.sig =
      trunks::Make_TPM2B_PUBLIC_KEY_RSA(std::string());
  tpm_result = policy_session->PolicySigned(
      key_handle.value(), key_name, std::string() /* nonce */,
      std::string() /* cp_hash */, std::string() /* policy_ref */,
      0 /* expiration */, signature, session->GetDelegate());
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error restricting policy to signature with the public key: "
               << GetErrorString(tpm_result);
    return false;
  }
  // Obtain the resulting policy digest.
  std::string policy_digest;
  tpm_result = policy_session->GetDigest(&policy_digest);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error getting policy digest: " << GetErrorString(tpm_result);
    return false;
  }
  if (policy_digest.size() != SHA256_DIGEST_SIZE) {
    LOG(ERROR) << "Unexpected policy digest size";
    return false;
  }
  // Generate the secret value randomly.
  if (!tpm_->GetRandomDataSecureBlob(kSecretSizeBytes, secret_value)) {
    LOG(ERROR) << "Error generating random secret";
    return false;
  }
  DCHECK_EQ(secret_value->size(), kSecretSizeBytes);
  // Seal the secret value.
  std::string sealed_value;
  tpm_result =
      trunks->tpm_utility->SealData(secret_value->to_string(), policy_digest,
                                    "", session->GetDelegate(), &sealed_value);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error sealing secret data: " << GetErrorString(tpm_result);
    return false;
  }
  // Fill the resulting proto with data required for unsealing.
  sealed_secret_data->Clear();
  SignatureSealedData_Tpm2PolicySignedData* const data_proto =
      sealed_secret_data->mutable_tpm2_policy_signed_data();
  data_proto->set_public_key_spki_der(BlobToString(public_key_spki_der));
  data_proto->set_srk_wrapped_secret(sealed_value);
  data_proto->set_scheme(scheme);
  data_proto->set_hash_alg(hash_alg);
  for (size_t restriction_index = 0;
       restriction_index < pcr_restrictions.size(); ++restriction_index) {
    const auto& pcr_values = pcr_restrictions[restriction_index];
    SignatureSealedData_Tpm2PcrRestriction* const pcr_restriction_proto =
        data_proto->add_pcr_restrictions();
    for (const auto& pcr_index_and_value : pcr_values) {
      SignatureSealedData_PcrValue* const pcr_value_proto =
          pcr_restriction_proto->add_pcr_values();
      pcr_value_proto->set_pcr_index(pcr_index_and_value.first);
      pcr_value_proto->set_pcr_value(BlobToString(pcr_index_and_value.second));
    }
    pcr_restriction_proto->set_policy_digest(
        pcr_policy_digests[restriction_index]);
  }
  return true;
}

std::unique_ptr<SignatureSealingBackend::UnsealingSession>
SignatureSealingBackendTpm2Impl::CreateUnsealingSession(
    const SignatureSealedData& sealed_secret_data,
    const Blob& public_key_spki_der,
    const std::vector<ChallengeSignatureAlgorithm>& key_algorithms,
    const Blob& /* delegate_blob */,
    const Blob& /* delegate_secret */) {
  // Validate the parameters.
  if (!sealed_secret_data.has_tpm2_policy_signed_data()) {
    LOG(ERROR) << "Error: sealed data is empty or uses unexpected method";
    return nullptr;
  }
  const SignatureSealedData_Tpm2PolicySignedData& data_proto =
      sealed_secret_data.tpm2_policy_signed_data();
  if (data_proto.public_key_spki_der() != BlobToString(public_key_spki_der)) {
    LOG(ERROR) << "Error: wrong subject public key info";
    return nullptr;
  }
  if (!base::IsValueInRangeForNumericType<TPM_ALG_ID>(data_proto.scheme())) {
    LOG(ERROR) << "Error parsing signature scheme";
    return nullptr;
  }
  const TPM_ALG_ID scheme = static_cast<TPM_ALG_ID>(data_proto.scheme());
  if (!base::IsValueInRangeForNumericType<TPM_ALG_ID>(data_proto.hash_alg())) {
    LOG(ERROR) << "Error parsing signature hash algorithm";
    return nullptr;
  }
  const TPM_ALG_ID hash_alg = static_cast<TPM_ALG_ID>(data_proto.hash_alg());
  base::Optional<ChallengeSignatureAlgorithm> chosen_algorithm;
  for (auto algorithm : key_algorithms) {
    TPM_ALG_ID current_scheme = TPM_ALG_NULL;
    TPM_ALG_ID current_hash_alg = TPM_ALG_NULL;
    if (GetAlgIdsByAlgorithm(algorithm, &current_scheme, &current_hash_alg) &&
        current_scheme == scheme && current_hash_alg == hash_alg) {
      chosen_algorithm = algorithm;
      break;
    }
  }
  if (!chosen_algorithm) {
    LOG(ERROR) << "Error: key doesn't support required algorithm";
    return nullptr;
  }
  // Obtain the trunks context to be used for the whole unsealing session.
  Tpm2Impl::TrunksClientContext* trunks = nullptr;
  if (!tpm_->GetTrunksContext(&trunks))
    return nullptr;
  // Start a policy session that will be used for obtaining the TPM nonce and
  // unsealing the secret value.
  std::unique_ptr<trunks::PolicySession> policy_session =
      trunks->factory->GetPolicySession();
  TPM_RC tpm_result = policy_session->StartUnboundSession(true, false);
  if (tpm_result != TPM_RC_SUCCESS) {
    LOG(ERROR) << "Error starting a policy session: "
               << GetErrorString(tpm_result);
    return nullptr;
  }
  // If PCR restrictions were applied, update the policy correspondingly.
  if (data_proto.pcr_restrictions_size()) {
    // Determine the satisfied set of PCR restrictions and update the policy
    // with it.
    const SignatureSealedData_Tpm2PcrRestriction* const
        satisfied_pcr_restriction_proto =
            GetSatisfiedPcrRestriction(data_proto.pcr_restrictions(), tpm_);
    if (!satisfied_pcr_restriction_proto) {
      LOG(ERROR) << "None of PCR restrictions is satisfied";
      return nullptr;
    }
    std::map<uint32_t, std::string> pcrs_to_apply;
    for (const auto& pcr_value_proto :
         satisfied_pcr_restriction_proto->pcr_values()) {
      pcrs_to_apply.emplace(pcr_value_proto.pcr_index(), std::string());
    }
    tpm_result = policy_session->PolicyPCR(pcrs_to_apply);
    if (tpm_result != TPM_RC_SUCCESS) {
      LOG(ERROR) << "Error restricting policy to PCRs: "
                 << GetErrorString(tpm_result);
      return nullptr;
    }
    // If more than one set of PCR restrictions was originally specified, update
    // the policy with the disjunction of their policy digests.
    if (data_proto.pcr_restrictions_size() > 1) {
      std::vector<std::string> pcr_policy_digests;
      for (const auto& pcr_restriction_proto : data_proto.pcr_restrictions()) {
        if (pcr_restriction_proto.policy_digest().size() !=
            SHA256_DIGEST_SIZE) {
          LOG(ERROR) << "Invalid policy digest size";
          return nullptr;
        }
        pcr_policy_digests.push_back(pcr_restriction_proto.policy_digest());
      }
      tpm_result = policy_session->PolicyOR(pcr_policy_digests);
      if (tpm_result != TPM_RC_SUCCESS) {
        LOG(ERROR)
            << "Error restricting policy to logical disjunction of PCRs: "
            << GetErrorString(tpm_result);
        return nullptr;
      }
    }
  }
  // Obtain the TPM nonce.
  std::string tpm_nonce;
  if (!policy_session->GetDelegate()->GetTpmNonce(&tpm_nonce)) {
    LOG(ERROR) << "Error obtaining TPM nonce";
    return nullptr;
  }
  // Create the unsealing session that will keep the required state.
  return std::make_unique<UnsealingSessionTpm2Impl>(
      tpm_, trunks, BlobFromString(data_proto.srk_wrapped_secret()),
      public_key_spki_der, *chosen_algorithm, scheme, hash_alg,
      std::move(policy_session), BlobFromString(tpm_nonce));
}

}  // namespace cryptohome
