// 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 "attestation/common/crypto_utility_impl.h"

#include <limits>
#include <string>
#include <vector>

#include <arpa/inet.h>
#include <base/check.h>
#include <base/check_op.h>
#include <base/hash/sha1.h>
#include <base/logging.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <crypto/libcrypto-compat.h>
#include <crypto/scoped_openssl_types.h>
#include <crypto/secure_util.h>
#include <crypto/sha2.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#include <openssl/x509.h>

namespace {

const size_t kAesKeySize = 32;
const size_t kAesBlockSize = 16;
const char kHashHeaderForEncrypt[] = "ENCRYPT";
const char kHashHeaderForMac[] = "MAC";
const unsigned int kWellKnownExponent = 65537;

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;
}

unsigned char* StringAsOpenSSLBuffer(std::string* s) {
  return reinterpret_cast<unsigned char*>(base::data(*s));
}

const unsigned char* StringAsConstOpenSSLBuffer(const std::string& s) {
  return reinterpret_cast<const unsigned char*>(s.data());
}

crypto::ScopedRSA CreateRSAFromHexModulus(const std::string& hex_modulus) {
  crypto::ScopedRSA rsa(RSA_new());
  crypto::ScopedBIGNUM e(BN_new()), n(BN_new());
  if (!rsa || !e || !n) {
    LOG(ERROR) << __func__ << ": Failed to allocate RSA or BIGNUMs.";
    return nullptr;
  }
  BIGNUM* pn = n.get();
  if (!BN_set_word(e.get(), kWellKnownExponent) ||
      !BN_hex2bn(&pn, hex_modulus.c_str())) {
    LOG(ERROR) << __func__ << ": Failed to generate exponent or modulus.";
    return nullptr;
  }
  if (!RSA_set0_key(rsa.get(), n.release(), e.release(), nullptr)) {
    LOG(ERROR) << __func__ << ": Failed to set exponent or modulus.";
    return nullptr;
  }
  return rsa;
}

crypto::ScopedOpenSSL<X509, X509_free> CreateX509FromCertificate(
    const std::string& certificate) {
  const unsigned char* asn1_ptr =
      reinterpret_cast<const unsigned char*>(certificate.data());
  crypto::ScopedOpenSSL<X509, X509_free> x509(
      d2i_X509(NULL, &asn1_ptr, certificate.size()));
  return x509;
}

}  // namespace

namespace attestation {

CryptoUtilityImpl::CryptoUtilityImpl(TpmUtility* tpm_utility)
    : tpm_utility_(tpm_utility) {
  OpenSSL_add_all_algorithms();
  EVP_PKEY_asn1_add_alias(EVP_PKEY_RSA, NID_rsaesOaep);
  ERR_load_crypto_strings();
}

CryptoUtilityImpl::~CryptoUtilityImpl() {
  EVP_cleanup();
  ERR_free_strings();
}

bool CryptoUtilityImpl::GetRandom(size_t num_bytes,
                                  std::string* random_data) const {
  // OpenSSL takes a signed integer.
  if (num_bytes > static_cast<size_t>(std::numeric_limits<int>::max())) {
    return false;
  }
  random_data->resize(num_bytes);
  unsigned char* buffer = StringAsOpenSSLBuffer(random_data);
  return (RAND_bytes(buffer, num_bytes) == 1);
}

bool CryptoUtilityImpl::CreateSealedKey(std::string* aes_key,
                                        std::string* sealed_key) {
  if (!GetRandom(kAesKeySize, aes_key)) {
    LOG(ERROR) << __func__ << ": GetRandom failed.";
    return false;
  }
  if (!tpm_utility_->SealToPCR0(*aes_key, sealed_key)) {
    LOG(ERROR) << __func__ << ": Failed to seal cipher key.";
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::EncryptData(const std::string& data,
                                    const std::string& aes_key,
                                    const std::string& sealed_key,
                                    std::string* encrypted_data) {
  EncryptedData encrypted_pb;
  encrypted_pb.set_wrapped_key(sealed_key);
  if (!EncryptWithSeed(KeyDerivationScheme::kNone, data, aes_key,
                       &encrypted_pb)) {
    return false;
  }
  if (!encrypted_pb.SerializeToString(encrypted_data)) {
    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::UnsealKey(const std::string& encrypted_data,
                                  std::string* aes_key,
                                  std::string* sealed_key) {
  EncryptedData encrypted_pb;
  if (!encrypted_pb.ParseFromString(encrypted_data)) {
    LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
    return false;
  }
  *sealed_key = encrypted_pb.wrapped_key();
  if (!tpm_utility_->Unseal(*sealed_key, aes_key)) {
    LOG(ERROR) << __func__ << ": Cannot unseal aes key.";
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::DecryptData(const std::string& encrypted_data,
                                    const std::string& aes_key,
                                    std::string* data) {
  EncryptedData encrypted_pb;
  if (!encrypted_pb.ParseFromString(encrypted_data)) {
    LOG(ERROR) << __func__ << ": Failed to parse protobuf.";
    return false;
  }
  return DecryptWithSeed(KeyDerivationScheme::kNone, encrypted_pb, aes_key,
                         data);
}

bool CryptoUtilityImpl::GetRSASubjectPublicKeyInfo(
    const std::string& public_key, std::string* public_key_info) {
  auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
  crypto::ScopedRSA rsa(
      d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
  if (!rsa.get()) {
    LOG(ERROR) << __func__
               << ": Failed to decode public key: " << GetOpenSSLError();
    return false;
  }
  unsigned char* buffer = nullptr;
  int length = i2d_RSA_PUBKEY(rsa.get(), &buffer);
  if (length <= 0) {
    LOG(ERROR) << __func__
               << ": Failed to encode public key: " << GetOpenSSLError();
    return false;
  }
  crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
  public_key_info->assign(reinterpret_cast<char*>(buffer), length);
  return true;
}

bool CryptoUtilityImpl::GetRSAPublicKey(const std::string& public_key_info,
                                        std::string* public_key) {
  auto asn1_ptr =
      reinterpret_cast<const unsigned char*>(public_key_info.data());
  crypto::ScopedRSA rsa(
      d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key_info.size()));
  if (!rsa.get()) {
    LOG(ERROR) << __func__
               << ": Failed to decode public key: " << GetOpenSSLError();
    return false;
  }
  unsigned char* buffer = NULL;
  int length = i2d_RSAPublicKey(rsa.get(), &buffer);
  if (length <= 0) {
    LOG(ERROR) << __func__
               << ": Failed to encode public key: " << GetOpenSSLError();
    return false;
  }
  crypto::ScopedOpenSSLBytes scoped_buffer(buffer);
  public_key->assign(reinterpret_cast<char*>(buffer), length);
  return true;
}

bool CryptoUtilityImpl::EncryptIdentityCredential(
    TpmVersion tpm_version,
    const std::string& credential,
    const std::string& ek_public_key_info,
    const std::string& aik_public_key,
    EncryptedIdentityCredential* encrypted) {
  auto asn1_ptr =
      reinterpret_cast<const unsigned char*>(ek_public_key_info.data());
  encrypted->set_tpm_version(tpm_version);
  if (tpm_version == TPM_1_2) {
    // TODO(crbug/942487): Only use d2i_RSA_PUBKEY for both TPM version and move
    // it back to the start of this function after the bug is resolved.
    crypto::ScopedRSA rsa(
        d2i_RSAPublicKey(NULL, &asn1_ptr, ek_public_key_info.size()));
    if (!rsa.get()) {
      LOG(ERROR) << __func__
                 << ": Failed to decode EK public key: " << GetOpenSSLError();
      return false;
    }
    const char kAlgAES256 = 9;   // This comes from TPM_ALG_AES256.
    const char kEncModeCBC = 2;  // This comes from TPM_SYM_MODE_CBC.
    const char kAsymContentHeader[] = {0, 0,           0, kAlgAES256,
                                       0, kEncModeCBC, 0, kAesKeySize};
    const char kSymContentHeader[12] = {};

    // Generate an AES key and encrypt the credential.
    std::string aes_key;
    if (!GetRandom(kAesKeySize, &aes_key)) {
      LOG(ERROR) << __func__ << ": GetRandom failed.";
      return false;
    }
    std::string encrypted_credential;
    if (!TssCompatibleEncrypt(credential, aes_key, &encrypted_credential)) {
      LOG(ERROR) << __func__ << ": Failed to encrypt credential.";
      return false;
    }

    // Construct a TPM_ASYM_CA_CONTENTS structure.
    std::string asym_header(std::begin(kAsymContentHeader),
                            std::end(kAsymContentHeader));
    std::string asym_content =
        asym_header + aes_key + base::SHA1HashString(aik_public_key);

    // Encrypt the TPM_ASYM_CA_CONTENTS with the EK public key.
    std::string encrypted_asym_content;
    if (!TpmCompatibleOAEPEncrypt(asym_content, rsa.get(),
                                  &encrypted_asym_content)) {
      LOG(ERROR) << __func__ << ": Failed to encrypt with EK public key.";
      return false;
    }

    // Construct a TPM_SYM_CA_ATTESTATION structure.
    uint32_t length = htonl(encrypted_credential.size());
    auto length_bytes = reinterpret_cast<const char*>(&length);
    std::string length_blob(length_bytes, sizeof(uint32_t));
    std::string sym_header(std::begin(kSymContentHeader),
                           std::end(kSymContentHeader));
    std::string sym_content = length_blob + sym_header + encrypted_credential;

    encrypted->set_asym_ca_contents(encrypted_asym_content);
    encrypted->set_sym_ca_attestation(sym_content);
  } else if (tpm_version == TPM_2_0) {
    crypto::ScopedRSA rsa(
        d2i_RSA_PUBKEY(NULL, &asn1_ptr, ek_public_key_info.size()));
    if (!rsa.get()) {
      LOG(ERROR) << __func__
                 << ": Failed to decode EK public key: " << GetOpenSSLError();
      return false;
    }
    // The 'credential' parameter is actually the certificate. The 'credential'
    // used in the wrapping process is referred to as 'inner_credential' below.
    std::string certificate = credential;
    // Generate a random seed and derive from it an AES and HMAC key as
    // documented in TPM 2.0 specification Part 1 Rev 1.16 Section 24.
    std::string seed;
    if (!GetRandom(kAesKeySize, &seed)) {
      return false;
    }
    std::string identity_key_name = GetTpm2KeyNameFromPublicKey(aik_public_key);
    std::string aes_key =
        Tpm2CompatibleKDFa(seed, "STORAGE", identity_key_name, 128);
    std::string hmac_key = Tpm2CompatibleKDFa(seed, "INTEGRITY", "", 256);
    // This will be the 'credential' that the TPM decrypts during activation.
    std::string inner_credential;
    if (!GetRandom(kAesKeySize, &inner_credential)) {
      return false;
    }
    // Wrap the credential with the seed using an Encrypt-then-MAC scheme
    // documented in TPM 2.0 specification Part 1 Rev 1.16 Section 24.
    std::string encrypted_credential;
    std::string iv(kAesBlockSize, 0);
    std::string inner_credential_size_bytes("\x00\x20", 2);  // Big-endian 32.
    if (!AesEncrypt(EVP_aes_128_cfb(),
                    inner_credential_size_bytes + inner_credential, aes_key, iv,
                    &encrypted_credential)) {
      return false;
    }
    encrypted->set_credential_mac(
        HmacSha256(hmac_key, encrypted_credential + identity_key_name));
    // Wrap the certificate with the credential using the scheme required by the
    // EncryptedIdentityCredential protobuf.
    EncryptedData* encrypted_certificate =
        encrypted->mutable_wrapped_certificate();
    if (!EncryptWithSeed(KeyDerivationScheme::kHashWithHeaders, certificate,
                         inner_credential, encrypted_certificate)) {
      return false;
    }
    encrypted_certificate->set_wrapped_key(encrypted_credential);
    // At this point, the credential can be recovered given the seed, and the
    // certificate can be recovered given the credential. All that remains is to
    // encrypt the seed with the EK public key.
    if (!Tpm2CompatibleOAEPEncrypt("IDENTITY", seed, rsa.get(),
                                   encrypted->mutable_encrypted_seed())) {
      return false;
    }
  } else {
    LOG(ERROR) << "Unsupported TPM version.";
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::DecryptIdentityCertificateForTpm2(
    const std::string& credential,
    const EncryptedData& encrypted_certificate,
    std::string* certificate) {
  return DecryptWithSeed(KeyDerivationScheme::kHashWithHeaders,
                         encrypted_certificate, credential, certificate);
}

bool CryptoUtilityImpl::EncryptForUnbind(const std::string& public_key,
                                         const std::string& data,
                                         std::string* encrypted_data) {
  // Construct a TPM_BOUND_DATA structure.
  const char kBoundDataHeader[] = {1, 1, 0, 0, 2 /* TPM_PT_BIND */};
  std::string header(std::begin(kBoundDataHeader), std::end(kBoundDataHeader));
  std::string bound_data = header + data;

  // Encrypt using the TPM_ES_RSAESOAEP_SHA1_MGF1 scheme.
  auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
  crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
  if (!rsa.get()) {
    LOG(ERROR) << __func__
               << ": Failed to decode public key: " << GetOpenSSLError();
    return false;
  }
  if (!TpmCompatibleOAEPEncrypt(bound_data, rsa.get(), encrypted_data)) {
    LOG(ERROR) << __func__ << ": Failed to encrypt with public key.";
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::VerifySignature(int digest_nid,
                                        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::ScopedEVP_PKEY pubkey(d2i_PUBKEY(NULL, &asn1_ptr, public_key.size()));
  if (!pubkey.get()) {
    LOG(ERROR) << __func__
               << ": Failed to decode public key: " << GetOpenSSLError();
    return false;
  }
  return VerifySignatureInner(digest_nid, pubkey, data, signature);
}

bool CryptoUtilityImpl::VerifySignatureUsingHexKey(
    int digest_nid,
    const std::string& public_key_hex,
    const std::string& data,
    const std::string& signature) {
  crypto::ScopedRSA rsa = CreateRSAFromHexModulus(public_key_hex);
  if (!rsa.get()) {
    LOG(ERROR) << __func__ << ": Failed to decode public key.";
    return false;
  }

  crypto::ScopedEVP_PKEY evp_pkey(EVP_PKEY_new());
  if (!evp_pkey.get()) {
    LOG(ERROR) << __func__ << ": Failed to allocate EVP PKEY.";
    return false;
  }
  EVP_PKEY_assign_RSA(evp_pkey.get(), rsa.release());
  return VerifySignatureInner(digest_nid, evp_pkey, data, signature);
}

bool CryptoUtilityImpl::VerifySignatureInner(
    int digest_nid,
    const crypto::ScopedEVP_PKEY& pubkey,
    const std::string& data,
    const std::string& signature) {
  const EVP_MD* md = EVP_get_digestbynid(digest_nid);
  if (md == nullptr) {
    LOG(ERROR) << __func__ << ": Failed to get hash algorithm from digest NID: "
               << digest_nid;
    return false;
  }

  crypto::ScopedEVP_MD_CTX mdctx(EVP_MD_CTX_new());
  if (!mdctx) {
    LOG(ERROR) << __func__
               << ": Failed to allocate EVP_MD_CTX: " << GetOpenSSLError();
    return false;
  }
  if (!EVP_DigestVerifyInit(mdctx.get(), nullptr, md, nullptr, pubkey.get())) {
    LOG(ERROR) << __func__ << ": Failed to initialize verifying process: "
               << GetOpenSSLError();
    return false;
  }

  if (!EVP_DigestVerifyUpdate(mdctx.get(), data.data(), data.length())) {
    LOG(ERROR) << __func__
               << ": Failed to hash the input data: " << GetOpenSSLError();
    return false;
  }

  return EVP_DigestVerifyFinal(
      mdctx.get(), StringAsConstOpenSSLBuffer(signature), signature.size());
}

bool CryptoUtilityImpl::EncryptDataForGoogle(const std::string& data,
                                             const std::string& public_key_hex,
                                             const std::string& key_id,
                                             EncryptedData* encrypted_data) {
  crypto::ScopedRSA rsa = CreateRSAFromHexModulus(public_key_hex);
  if (!rsa.get()) {
    LOG(ERROR) << __func__ << ": Failed to decode public key.";
    return false;
  }
  std::string key;
  if (!GetRandom(kAesKeySize, &key)) {
    return false;
  }
  if (!EncryptWithSeed(KeyDerivationScheme::kNone, data, key, encrypted_data)) {
    return false;
  }
  if (!WrapKeyOAEP(key, rsa.get(), key_id, encrypted_data)) {
    encrypted_data->Clear();
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::AesEncrypt(const EVP_CIPHER* cipher,
                                   const std::string& data,
                                   const std::string& key,
                                   const std::string& iv,
                                   std::string* encrypted_data) {
  if (key.size() != static_cast<size_t>(EVP_CIPHER_key_length(cipher)) ||
      iv.size() != kAesBlockSize) {
    return false;
  }
  if (data.size() > static_cast<size_t>(std::numeric_limits<int>::max())) {
    // EVP_EncryptUpdate takes a signed int.
    return false;
  }
  std::string mutable_data(data);
  unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_data);
  std::string mutable_key(key);
  unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
  std::string mutable_iv(iv);
  unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
  // Allocate enough space for the output (including padding).
  encrypted_data->resize(data.size() + kAesBlockSize);
  auto output_buffer =
      reinterpret_cast<unsigned char*>(base::data(*encrypted_data));
  int output_size = 0;
  crypto::ScopedEVP_CIPHER_CTX encryption_context(EVP_CIPHER_CTX_new());
  if (!encryption_context) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  if (!EVP_EncryptInit_ex(encryption_context.get(), cipher, nullptr, key_buffer,
                          iv_buffer)) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  if (!EVP_EncryptUpdate(encryption_context.get(), output_buffer, &output_size,
                         input_buffer, data.size())) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  size_t total_size = output_size;
  output_buffer += output_size;
  output_size = 0;
  if (!EVP_EncryptFinal_ex(encryption_context.get(), output_buffer,
                           &output_size)) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  total_size += output_size;
  encrypted_data->resize(total_size);
  return true;
}

bool CryptoUtilityImpl::AesDecrypt(const EVP_CIPHER* cipher,
                                   const std::string& encrypted_data,
                                   const std::string& key,
                                   const std::string& iv,
                                   std::string* data) {
  if (key.size() != static_cast<size_t>(EVP_CIPHER_key_length(cipher)) ||
      iv.size() != kAesBlockSize) {
    return false;
  }
  if (encrypted_data.size() >
      static_cast<size_t>(std::numeric_limits<int>::max())) {
    // EVP_DecryptUpdate takes a signed int.
    return false;
  }
  std::string mutable_encrypted_data(encrypted_data);
  unsigned char* input_buffer = StringAsOpenSSLBuffer(&mutable_encrypted_data);
  std::string mutable_key(key);
  unsigned char* key_buffer = StringAsOpenSSLBuffer(&mutable_key);
  std::string mutable_iv(iv);
  unsigned char* iv_buffer = StringAsOpenSSLBuffer(&mutable_iv);
  // Allocate enough space for the output.
  data->resize(encrypted_data.size());
  unsigned char* output_buffer = StringAsOpenSSLBuffer(data);
  int output_size = 0;
  crypto::ScopedEVP_CIPHER_CTX decryption_context(EVP_CIPHER_CTX_new());
  if (!decryption_context) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  if (!EVP_DecryptInit_ex(decryption_context.get(), cipher, nullptr, key_buffer,
                          iv_buffer)) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  if (!EVP_DecryptUpdate(decryption_context.get(), output_buffer, &output_size,
                         input_buffer, encrypted_data.size())) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  size_t total_size = output_size;
  output_buffer += output_size;
  output_size = 0;
  if (!EVP_DecryptFinal_ex(decryption_context.get(), output_buffer,
                           &output_size)) {
    LOG(ERROR) << __func__ << ": " << GetOpenSSLError();
    return false;
  }
  total_size += output_size;
  data->resize(total_size);
  return true;
}

std::string CryptoUtilityImpl::HmacSha256(const std::string& key,
                                          const std::string& data) {
  unsigned char mac[SHA256_DIGEST_LENGTH];
  std::string mutable_data(data);
  unsigned char* data_buffer = StringAsOpenSSLBuffer(&mutable_data);
  HMAC(EVP_sha256(), key.data(), key.size(), data_buffer, data.size(), mac,
       nullptr);
  return std::string(std::begin(mac), std::end(mac));
}

std::string CryptoUtilityImpl::HmacSha512(const std::string& key,
                                          const std::string& data) {
  unsigned char mac[SHA512_DIGEST_LENGTH];
  std::string mutable_data(data);
  unsigned char* data_buffer = StringAsOpenSSLBuffer(&mutable_data);
  HMAC(EVP_sha512(), key.data(), key.size(), data_buffer, data.size(), mac,
       nullptr);
  return std::string(std::begin(mac), std::end(mac));
}

int CryptoUtilityImpl::DefaultDigestAlgoForSignature() {
  switch (tpm_utility_->GetVersion()) {
    case attestation::TPM_2_0:
      return NID_sha256;
    case attestation::TPM_1_2:
      return NID_sha1;
  }
}

bool CryptoUtilityImpl::TssCompatibleEncrypt(const std::string& input,
                                             const std::string& key,
                                             std::string* output) {
  CHECK(output);
  CHECK_EQ(key.size(), kAesKeySize);
  std::string iv;
  if (!GetRandom(kAesBlockSize, &iv)) {
    LOG(ERROR) << __func__ << ": GetRandom failed.";
    return false;
  }
  std::string encrypted;
  if (!AesEncrypt(EVP_aes_256_cbc(), input, key, iv, &encrypted)) {
    LOG(ERROR) << __func__ << ": Encryption failed.";
    return false;
  }
  *output = iv + encrypted;
  return true;
}

bool CryptoUtilityImpl::TpmCompatibleOAEPEncrypt(const std::string& input,
                                                 RSA* key,
                                                 std::string* output) {
  CHECK(output);
  // The custom OAEP parameter as specified in TPM Main Part 1, Section 31.1.1.
  return OAEPEncryptWithLabel("TCPA", input, key, EVP_sha1(), EVP_sha1(),
                              output);
}

bool CryptoUtilityImpl::EncryptWithSeed(KeyDerivationScheme derivation_scheme,
                                        const std::string& input,
                                        const std::string& seed,
                                        EncryptedData* encrypted) {
  std::string iv;
  if (!GetRandom(kAesBlockSize, &iv)) {
    return false;
  }
  std::string aes_key;
  std::string hmac_key;
  if (derivation_scheme == KeyDerivationScheme::kNone) {
    aes_key = hmac_key = seed;
  } else if (derivation_scheme == KeyDerivationScheme::kHashWithHeaders) {
    aes_key = crypto::SHA256HashString(kHashHeaderForEncrypt + seed);
    hmac_key = crypto::SHA256HashString(kHashHeaderForMac + seed);
  }
  std::string encrypted_data;
  if (!AesEncrypt(EVP_aes_256_cbc(), input, aes_key, iv, &encrypted_data)) {
    return false;
  }
  encrypted->set_encrypted_data(encrypted_data);
  encrypted->set_iv(iv);
  encrypted->set_mac(HmacSha512(hmac_key, iv + encrypted_data));
  return true;
}

bool CryptoUtilityImpl::DecryptWithSeed(KeyDerivationScheme derivation_scheme,
                                        const EncryptedData& input,
                                        const std::string& seed,
                                        std::string* decrypted) {
  std::string aes_key;
  std::string hmac_key;
  if (derivation_scheme == KeyDerivationScheme::kNone) {
    aes_key = hmac_key = seed;
  } else if (derivation_scheme == KeyDerivationScheme::kHashWithHeaders) {
    aes_key = crypto::SHA256HashString(kHashHeaderForEncrypt + seed);
    hmac_key = crypto::SHA256HashString(kHashHeaderForMac + seed);
  }
  std::string expected_mac =
      HmacSha512(hmac_key, input.iv() + input.encrypted_data());
  if (expected_mac.length() != input.mac().length()) {
    LOG(ERROR) << __func__ << ": MAC length mismatch.";
    return false;
  }
  if (!crypto::SecureMemEqual(expected_mac.data(), input.mac().data(),
                              expected_mac.length())) {
    LOG(ERROR) << __func__ << ": MAC mismatch.";
    return false;
  }
  if (!AesDecrypt(EVP_aes_256_cbc(), input.encrypted_data(), aes_key,
                  input.iv(), decrypted)) {
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::WrapKeyOAEP(const std::string& key,
                                    RSA* wrapping_key,
                                    const std::string& wrapping_key_id,
                                    EncryptedData* output) {
  const unsigned char* key_buffer = StringAsConstOpenSSLBuffer(key);
  std::string encrypted_key;
  encrypted_key.resize(RSA_size(wrapping_key));
  unsigned char* encrypted_key_buffer = StringAsOpenSSLBuffer(&encrypted_key);
  int length = RSA_public_encrypt(key.size(), key_buffer, encrypted_key_buffer,
                                  wrapping_key, RSA_PKCS1_OAEP_PADDING);
  if (length == -1) {
    LOG(ERROR) << "RSA_public_encrypt failed.";
    return false;
  }
  encrypted_key.resize(length);
  output->set_wrapped_key(encrypted_key);
  output->set_wrapping_key_id(wrapping_key_id);
  return true;
}

std::string CryptoUtilityImpl::GetTpm2KeyNameFromPublicKey(
    const std::string& public_key_tpm_format) {
  // TPM_ALG_SHA256 = 0x000B, here in big-endian order.
  std::string prefix("\x00\x0B", 2);
  return prefix + crypto::SHA256HashString(public_key_tpm_format);
}

std::string CryptoUtilityImpl::Tpm2CompatibleKDFa(const std::string& key,
                                                  const std::string& label,
                                                  const std::string& context,
                                                  int bits) {
  // Due to the assumptions of SHA256 and a 128/256-bit output, we can simplify
  // to just one iteration.
  if (bits != 128 && bits != 256) {
    LOG(ERROR) << __func__ << ": Unsupported key size: " << bits;
    return std::string("");
  }
  std::string iteration("\x00\x00\x00\x01", 4);  // Big-endian 32-bit 1.
  std::string null_separator("\x00", 1);
  // Encode number of bits as big-endian 32-bit value (128 or 256).
  std::string b_buf(bits == 128 ? "\x00\x00\x00\x80" : "\x00\x00\x01\x00", 4);
  return HmacSha256(key, iteration + label + null_separator + context + b_buf)
      .substr(0, bits / 8);
}

bool CryptoUtilityImpl::Tpm2CompatibleOAEPEncrypt(const std::string& label,
                                                  const std::string& input,
                                                  RSA* key,
                                                  std::string* output) {
  std::string zero_terminated_label = label + std::string(1, '\x00');
  return OAEPEncryptWithLabel(zero_terminated_label, input, key, EVP_sha256(),
                              EVP_sha256(), output);
}

bool CryptoUtilityImpl::OAEPEncryptWithLabel(const std::string& label,
                                             const std::string& input,
                                             RSA* key,
                                             const EVP_MD* md,
                                             const EVP_MD* mgf1md,
                                             std::string* output) {
  std::string padded_input;
  padded_input.resize(RSA_size(key));
  auto padded_buffer =
      reinterpret_cast<unsigned char*>(base::data(padded_input));
  auto input_buffer = reinterpret_cast<const unsigned char*>(input.data());
  auto label_buffer = reinterpret_cast<const unsigned char*>(label.data());
  int result = RSA_padding_add_PKCS1_OAEP_mgf1(
      padded_buffer, padded_input.size(), input_buffer, input.size(),
      label_buffer, label.size(), md, mgf1md);
  if (!result) {
    LOG(ERROR) << __func__
               << ": Failed to add OAEP padding: " << GetOpenSSLError();
    return false;
  }
  output->resize(padded_input.size());
  auto output_buffer = reinterpret_cast<unsigned char*>(base::data(*output));
  result = RSA_public_encrypt(padded_input.size(), padded_buffer, output_buffer,
                              key, RSA_NO_PADDING);
  if (result == -1) {
    LOG(ERROR) << __func__ << ": Failed to encrypt OAEP padded input: "
               << GetOpenSSLError();
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::CreateSPKAC(const std::string& key_blob,
                                    const std::string& public_key,
                                    KeyType key_type,
                                    std::string* spkac) {
  // Get the certified public key as an EVP_PKEY.
  const unsigned char* asn1_ptr =
      reinterpret_cast<const unsigned char*>(public_key.data());
  crypto::ScopedEVP_PKEY evp_pkey(EVP_PKEY_new());
  if (!evp_pkey.get()) {
    LOG(ERROR) << __func__
               << ": Failed to call EVP_PKEY_new: " << GetOpenSSLError();
    return false;
  }
  if (key_type == KEY_TYPE_RSA) {
    crypto::ScopedRSA rsa(
        d2i_RSAPublicKey(nullptr, &asn1_ptr, public_key.size()));
    if (!rsa.get()) {
      LOG(ERROR) << __func__
                 << ": Failed to decode public key: " << GetOpenSSLError();
      return false;
    }
    if (!EVP_PKEY_set1_RSA(evp_pkey.get(), rsa.get())) {
      LOG(ERROR) << __func__
                 << ": Failed to call EVP_PKEY_set1_RSA: " << GetOpenSSLError();
      return false;
    }
  } else if (key_type == KEY_TYPE_ECC) {
    crypto::ScopedEC_KEY ec_key(
        d2i_EC_PUBKEY(nullptr, &asn1_ptr, public_key.size()));
    if (!ec_key.get()) {
      LOG(ERROR) << __func__
                 << ": Failed to decode ECC public key: " << GetOpenSSLError();
      return false;
    }
    if (EVP_PKEY_set1_EC_KEY(evp_pkey.get(), ec_key.get()) != 1) {
      LOG(ERROR) << __func__ << ": Failed to call EVP_PKEY_set1_EC_KEY: "
                 << GetOpenSSLError();
      return false;
    }
  } else {
    LOG(DFATAL) << __func__ << ": Unrecognized key type.";
    return false;
  }

  return CreateSPKACInternal(key_blob, evp_pkey, spkac);
}

bool CryptoUtilityImpl::CreateSPKACInternal(
    const std::string& key_blob,
    const crypto::ScopedEVP_PKEY& public_key,
    std::string* spkac) {
  CHECK(public_key.get());
  // Fill in the public key.
  crypto::ScopedOpenSSL<NETSCAPE_SPKI, NETSCAPE_SPKI_free> spki(
      NETSCAPE_SPKI_new());
  if (!spki.get()) {
    LOG(ERROR) << __func__ << ": Failed to create SPKI.";
    return false;
  }
  if (!NETSCAPE_SPKI_set_pubkey(spki.get(), public_key.get())) {
    LOG(ERROR) << __func__ << ": Failed to set pubkey for SPKI.";
    return false;
  }

  // Fill in a random challenge.
  std::string challenge;
  size_t challenge_size = (tpm_utility_->GetVersion() == TPM_1_2)
                              ? base::kSHA1Length
                              : crypto::kSHA256Length;
  if (!GetRandom(challenge_size, &challenge)) {
    LOG(ERROR) << __func__ << ": Failed to GetRandom(challenge).";
    return false;
  }
  std::string challenge_hex =
      base::HexEncode(challenge.data(), challenge.size());
  if (!ASN1_STRING_set(spki.get()->spkac->challenge, challenge_hex.data(),
                       challenge_hex.size())) {
    LOG(ERROR) << __func__ << ": Failed to set challenge in SPKAC.";
    return false;
  }

  // Generate the signature.
  unsigned char* buffer = NULL;
  int length = i2d_NETSCAPE_SPKAC(spki.get()->spkac, &buffer);
  if (length <= 0) {
    LOG(ERROR) << __func__ << ": Failed to get SPKAC.";
    return false;
  }
  std::string data_to_sign(reinterpret_cast<char*>(buffer), length);
  OPENSSL_free(buffer);
  std::string signature;
  if (!tpm_utility_->Sign(key_blob, data_to_sign, &signature)) {
    LOG(ERROR) << __func__ << ": Failed to sign SPKAC.";
    return false;
  }

  // Fill in the signature and algorithm.
  if (!ASN1_BIT_STRING_set(
          spki.get()->signature,
          reinterpret_cast<unsigned char*>(const_cast<char*>(signature.data())),
          signature.size())) {
    LOG(ERROR) << __func__ << ": Failed to set signature in SPKAC.";
    return false;
  }
  // Be explicit that there are zero unused bits; otherwise i2d below will
  // automatically detect unused bits but signatures require zero unused bits.
  spki.get()->signature->flags = ASN1_STRING_FLAG_BITS_LEFT;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
  X509_ALGOR* sig_algor = spki.get()->sig_algor;
#else
  X509_ALGOR* sig_algor = &spki.get()->sig_algor;
#endif
  const int sig_algo_nid = EVP_PKEY_base_id(public_key.get()) == EVP_PKEY_RSA
                               ? NID_sha256WithRSAEncryption
                               : NID_ecdsa_with_SHA256;
  X509_ALGOR_set0(sig_algor, OBJ_nid2obj(sig_algo_nid), V_ASN1_NULL, NULL);

  // DER encode.
  buffer = NULL;
  length = i2d_NETSCAPE_SPKI(spki.get(), &buffer);
  if (length <= 0) {
    LOG(ERROR) << __func__ << ": Failed to get SPKI.";
    return false;
  }
  spkac->assign(reinterpret_cast<char*>(buffer), length);
  OPENSSL_free(buffer);

  return true;
}

bool CryptoUtilityImpl::VerifyCertificate(
    const std::string& certificate, const std::string& ca_public_key_hex) {
  crypto::ScopedRSA rsa = CreateRSAFromHexModulus(ca_public_key_hex);
  if (!rsa.get()) {
    LOG(ERROR) << __func__ << ": Failed to decode CA public key.";
    return false;
  }
  crypto::ScopedEVP_PKEY issuer_key(EVP_PKEY_new());
  if (!issuer_key.get()) {
    LOG(ERROR) << __func__ << ": Failed to create EVP PKEY.";
    return false;
  }
  EVP_PKEY_assign_RSA(issuer_key.get(), rsa.release());
  auto x509 = CreateX509FromCertificate(certificate);
  if (!x509.get()) {
    LOG(ERROR) << __func__ << ": Failed to parse certificate.";
    return false;
  }
  if (X509_verify(x509.get(), issuer_key.get()) != 1) {
    LOG(ERROR) << __func__
               << ": Bad certificate signature: " << GetOpenSSLError();
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::VerifyCertificateWithSubjectPublicKey(
    const std::string& certificate, const std::string& ca_public_key_der_hex) {
  std::vector<uint8_t> ca_public_key_der_vec;
  if (!base::HexStringToBytes(ca_public_key_der_hex, &ca_public_key_der_vec)) {
    LOG(ERROR) << __func__ << "Failed to hex-decode subject public key info.";
    return false;
  }
  std::string ca_public_key_der(ca_public_key_der_vec.begin(),
                                ca_public_key_der_vec.end());

  auto openssl_buffer = StringAsConstOpenSSLBuffer(ca_public_key_der);
  crypto::ScopedEVP_PKEY issuer_key(
      d2i_PUBKEY(nullptr, &openssl_buffer, ca_public_key_der.size()));
  if (!issuer_key) {
    LOG(ERROR) << __func__
               << ": Failed to decode CA public key: " << GetOpenSSLError();
    return false;
  }
  auto x509 = CreateX509FromCertificate(certificate);
  if (!x509) {
    LOG(ERROR) << __func__ << ": Failed to parse certificate.";
    return false;
  }
  if (X509_verify(x509.get(), issuer_key.get()) != 1) {
    LOG(ERROR) << __func__
               << ": Bad certificate signature: " << GetOpenSSLError();
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::GetCertificateSubjectPublicKeyInfo(
    const std::string& certificate, std::string* public_key) {
  // Some TPM 1.2 certificates use OAEP key type (rsaOAEP (PKCS #1)). It is not
  // supported algorithm in OpenSSL, so we can't parse the public key data to
  // public key object.
  //
  // At here, we only decode X509 format and store raw byte string
  // (ASN1_BIT_STRING) of SubjectPublicKeyInfo to x509->cert_info->key, such
  // that we can safely pass this i2d_X509_PUBKEY, since it directly output raw
  // byte string. But we can't pass it some utility which attempt to parse it
  // such like X509_PUBKEY_get().
  auto x509 = CreateX509FromCertificate(certificate);
  if (!x509.get()) {
    LOG(ERROR) << __func__ << ": Failed to parse certificate.";
    return false;
  }

  unsigned char* pubkey_buffer = nullptr;
  int length =
      i2d_X509_PUBKEY(X509_get_X509_PUBKEY(x509.get()), &pubkey_buffer);
  if (length < 0) {
    LOG(ERROR) << __func__
               << ": Failed to dump SubjectPublicKeyInfo from cert.";
    return false;
  }
  crypto::ScopedOpenSSLBytes scoped_pubkey_buffer(pubkey_buffer);
  public_key->assign(reinterpret_cast<char*>(pubkey_buffer), length);
  return true;
}

bool CryptoUtilityImpl::GetCertificatePublicKey(const std::string& certificate,
                                                std::string* public_key) {
  auto x509 = CreateX509FromCertificate(certificate);
  if (!x509.get()) {
    LOG(ERROR) << __func__ << ": Failed to parse certificate.";
    return false;
  }
  crypto::ScopedEVP_PKEY pkey(X509_get_pubkey(x509.get()));
  if (!pkey) {
    LOG(ERROR) << __func__ << ": Failed to get EVP_PKEY from the certificate: "
               << GetOpenSSLError();
    return false;
  }
  crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey.get()));
  if (!rsa) {
    LOG(ERROR) << __func__
               << ": Failed to get RSA from EVP_PKEY: " << GetOpenSSLError();
    return false;
  }
  int der_length = i2d_RSAPublicKey(rsa.get(), nullptr);
  if (der_length < 0) {
    LOG(ERROR) << __func__
               << ": Bad length of der-encoded output: " << GetOpenSSLError();
    return false;
  }
  public_key->resize(der_length);
  unsigned char* der_buffer =
      reinterpret_cast<unsigned char*>(base::data(*public_key));
  if (i2d_RSAPublicKey(rsa.get(), &der_buffer) < 0) {
    LOG(ERROR) << __func__
               << ": Bad length of der-encoded output: " << GetOpenSSLError();
    return false;
  }
  return true;
}

bool CryptoUtilityImpl::GetCertificateIssuerName(const std::string& certificate,
                                                 std::string* issuer_name) {
  auto x509 = CreateX509FromCertificate(certificate);
  if (!x509.get()) {
    LOG(ERROR) << __func__ << ": Failed to parse certificate.";
    return false;
  }
  char issuer_buf[100];  // A longer CN will truncate.
  X509_NAME_get_text_by_NID(X509_get_issuer_name(x509.get()), NID_commonName,
                            issuer_buf, base::size(issuer_buf));
  issuer_name->assign(issuer_buf);
  return true;
}

bool CryptoUtilityImpl::GetKeyDigest(const std::string& public_key,
                                     std::string* key_digest) {
  auto asn1_ptr = reinterpret_cast<const unsigned char*>(public_key.data());
  crypto::ScopedRSA rsa(d2i_RSA_PUBKEY(NULL, &asn1_ptr, public_key.size()));
  if (!rsa.get()) {
    LOG(ERROR) << __func__ << ": Failed to decode certified public key.";
    return false;
  }
  std::vector<unsigned char> modulus(RSA_size(rsa.get()));
  const BIGNUM* n;
  RSA_get0_key(rsa.get(), &n, nullptr, nullptr);
  if (BN_bn2bin(n, modulus.data()) != modulus.size()) {
    LOG(ERROR) << __func__ << ": Failed to extract modulus.";
    return false;
  }
  char digest_buf[base::kSHA1Length];
  base::SHA1HashBytes(modulus.data(), modulus.size(),
                      reinterpret_cast<unsigned char*>(digest_buf));
  key_digest->assign(digest_buf, sizeof(digest_buf));
  return true;
}

}  // namespace attestation
