// 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/hash/sha1.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.";
    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
