// 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/server/attestation_service.h"

#include <algorithm>
#include <climits>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <attestation/proto_bindings/attestation_ca.pb.h>
#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/callback.h>
#include <base/hash/sha1.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>
#include <brillo/cryptohome.h>
#include <brillo/data_encoding.h>
#include <crypto/sha2.h>
#include <openssl/objects.h>
#include <policy/device_policy.h>
#include <policy/libpolicy.h>
#if USE_TPM2
#include <trunks/tpm_utility.h>
#endif
extern "C" {
#if USE_TPM2
#include <trunks/cr50_headers/virtual_nvmem.h>
#endif
#include <vboot/crossystem.h>
}

#include "attestation/common/database.pb.h"
#include "attestation/common/tpm_utility_factory.h"
#include "attestation/pca_agent/client/proxy_factory.h"
#include "attestation/server/attestation_flow.h"
#include "attestation/server/database_impl.h"
#include "attestation/server/google_keys.h"

namespace {

const size_t kNonceSize = 20;  // As per TPM_NONCE definition.
const int kNumTemporalValues = 5;

const char kKnownBootModes[8][3] = {{0, 0, 0}, {0, 0, 1}, {0, 1, 0}, {0, 1, 1},
                                    {1, 0, 0}, {1, 0, 1}, {1, 1, 0}, {1, 1, 1}};
const char kVerifiedBootMode[3] = {0, 0, 1};

// Context name to derive stable secret for attestation-based enterprise
// enrollment.
const char kAttestationBasedEnterpriseEnrollmentContextName[] =
    "attestation_based_enrollment";

struct CertificateAuthority {
  const char* issuer;
  const char* modulus;  // In hex format.
};

const CertificateAuthority kKnownEndorsementCA[] = {
    {"IFX TPM EK Intermediate CA 06",
     "de9e58a353313d21d683c687d6aaaab240248717557c077161c5e515f41d8efa"
     "48329f45658fb550f43f91d1ba0c2519429fb6ef964f89657098c90a9783ad6d"
     "3baea625db044734c478768db53b6022c556d8174ed744bd6e4455665715cd5c"
     "beb7c3fcb822ab3dfab1ecee1a628c3d53f6085983431598fb646f04347d5ae0"
     "021d5757cc6e3027c1e13f10633ae48bbf98732c079c17684b0db58bd0291add"
     "e277b037dd13fa3db910e81a4969622a79c85ac768d870f079b54c2b98c856e7"
     "15ef0ba9c01ee1da1241838a1307fe94b1ddfa65cdf7eeaa7e5b4b8a94c3dcd0"
     "29bb5ebcfc935e56641f4c8cb5e726c68f9dd6b41f8602ef6dc78d870a773571"},
    {"IFX TPM EK Intermediate CA 07",
     "f04c9b5b9f3cbc2509179f5e0f31dceb302900f528458e002c3e914d6b29e5e0"
     "924b0bcab2dd053f65d9d4a8eea8269c85c419dba640a88e14dc5f8c8c1a4269"
     "7a5ac4594b36f923110f91d1803d385540c01a433140b06054c77a144ee3a6a6"
     "5950c20f9215be3473b1002eb6b1756a22fbc18d21efacbbc8c270c66cf74982"
     "e24f057825cab51c0dd840a4f2d059032239c33e3f52c6ca06fe49bf4f60cc28"
     "a0fb1173d2ee05a141d30e8ffa32dbb86c1aeb5b309f76c2e462965612ec929a"
     "0d3b04acfa4525912c76f765e948be71f505d619cc673a889f0ed9e1d75f237b"
     "7af6a68550253cb4c3a8ff16c8091dbcbdea0ff8eee3d5bd92f49c53c5a15c93"},
    {"IFX TPM EK Intermediate CA 14",
     "D5B2EB8F8F23DD0B5CA0C15D4376E27A0380FD8EB1E52C2C270D961E8C0F66FD"
     "62E6ED6B3660FFBD8B0735179476F5E9C2EA4C762F5FEEDD3B5EB91785A724BC"
     "4C0617B83966336DD9DC407640871BF99DF4E1701EB5A1F5647FC57879CBB973"
     "B2A72BABA8536B2646A37AA5B73E32A4C8F03E35C8834B391AD363F1F7D1DF2B"
     "EE39233F47384F3E2D2E8EF83C9539B4DFC360C8AEB88B6111E757AF646DC01A"
     "68DAA908C7F8068894E9E991C59005068DD9B0F87113E6A80AB045DB4C1B23FF"
     "38A106098C2E184E1CF42A43EA68753F2649999048E8A3C3406032BEB1457070"
     "BCBE3A93E122638F6F18FF505C35FB827CE5D0C12F27F45C0F59C8A4A8697849"},
    {"IFX TPM EK Intermediate CA 16",
     "B98D42D5284620036A6613ED05A1BE11431AE7DE435EC55F72814652B9265EC2"
     "9035D401B538A9C84BB5B875450FAE8FBEDEF3430C4108D8516404F3DE4D4615"
     "2F471013673A7C7F236304C7363B91C0E0FD9FC7A9EC751521A60A6042839CF7"
     "7AEDE3243D0F51F47ACC39676D236BD5298E18B9A4783C60B2A1CD1B32124909"
     "D5844649EE4539D6AA05A5902C147B4F062D5145708EAE224EC65A8B51D7A418"
     "6327DA8F3B9E7C796F8B2DB3D2BDB39B829BDEBA8D2BF882CBADDB75D76FA8FA"
     "313682688BCD2835533A3A68A4AFDF7E597D8B965402FF22A5A4A418FDB4B549"
     "F218C3908E66BDCEAB3E2FE5EE0A4A1D9EB41A286ED07B6C112581FDAEA088D9"},
    {"IFX TPM EK Intermediate CA 17",
     "B0F3CC6F02E8C0486501102731069644A815F631ED41676C05CE3F7E5E5E40DF"
     "B3BF6D99787F2A9BE8F8B8035C03D5C2226072985230D4CE8407ACD6403F72E1"
     "A4DBF069504E56FA8C0807A704526EAC1E379AE559EB4BBAD9DB4E652B3B14E5"
     "38497A5E7768BCE0BFFAF800C61F1F2262775C526E1790A2BECF9A072A58F6A0"
     "F3042B5279FE9957BCADC3C9725428B66B15D5263F00C528AC47716DE6938199"
     "0FF23BC28F2C33B72D89B5F8EEEF9053B60D230431081D656EA8EC16C7CEFD9E"
     "F5A9061A3C921394D453D9AC77397D59B4C3BAF258266F65559469C3007987D5"
     "A8338E10FC54CD930303C37007D6E1E6C63F36BCFBA1E494AFB3ECD9A2407FF9"},
    {"IFX TPM EK Intermediate CA 21",
     "8149397109974D6C0850C8A60304ED7D209B1B88F435B695394DAD9FB4E64180"
     "02A3940966D2F04103C88659600EEA8E2A5C697C5F989F62D33A06DA10B50075"
     "F37F3CE6AD070413A0E109E16FE652B393C4DAFC5579CCB9915E9A70F5C05BCE"
     "0D341D6B887F43C4334BD8EC6A293FFAB737F77A45069CD0345D3D534E84D029"
     "029C37A267C0CC2D8DCE3E2C76F21A40F5D8D463882A8CBB92D8235685266753"
     "E8F051E78B681E87810A5B21EF719662A8208DFD94C55A126A112E39E0D732D7"
     "3C599095FAFF52BBC0E8C5B3DCD904D05DE00D5C5112F3DF7B76602ABE5DC0F8"
     "F89B55889A24C54EDBA1234AE498BE9B02CB5C8048D1DC90210705BAFC0E2837"},
    {"IFX TPM EK Intermediate CA 29",
     "cd424370776890ace339c62d7faae843bb2c765d27685c0441d278361a929062"
     "b4c95cc57213c864e91cbb92b1151f17a346a4e754c666f2a3e07ea9ffb9c80f"
     "e54d9479f73458c64bf7b0ca4e38821dd318e82d6fe387903ca73ca3e59db48e"
     "fe3b3c7c89599be87bb5e439a6f5843a412d4a321f154955448b71ca0b5fda47"
     "5c86a1c999dde7a01aa16436e65f0b04874c0db3970546bd806157058c5576a5"
     "c00b2bce7173c887f388dc4d5267c68fa5c47fcee3d8491071cd7742d43162cb"
     "285f5ba5e0daa0e910fdce566c5bbf7b3701d51660090344195fd7278456bd98"
     "48382fc5fceaebf93a2ec88c5722723519692e90d23f869c34d8b1af499d4127"},
    {"IFX TPM EK Intermediate CA 30",
     "a01cc43c4b66076d483086d0713a336f435e33ed23d3cda05f3c60a6f707416a"
     "9e53f0ef0de62c82a720e9ad94df29805b56b44279fd7389de4c60d498c81e3b"
     "a27692a045d993e9aaae152768588e5c62213721154529c95b09b201bcb3e573"
     "3d98e398d6e05215867d94e3d222e5b7df9f948c14533285821658b282be4bd7"
     "fe7197baa642f556d4f18738adef26b2eebfc64045cf4c5dcbff661aa95429f4"
     "e2c4921a8723bd8116f0efc038cd4530bb6e9299b7d70327e3fe8790d3d6db3a"
     "ebd3ccd12aef3d43cf89463a28ad1306a9d430b08c3411bfeeda63b9fdcc9a23"
     "1ff5cc203a7f5ee713d50e1930add1cd32ff64637fc740edb63380a5e6725381"},
    {"IFX TPM EK Intermediate CA 49",
     "b0bd7dd4a197edae12edeb5c98a31f57af00142ca98ed9d412e1a1e8c3d1f81b"
     "c152936ee6b1259cb49a870f358a7dca0c98d866df332727e6f897edcac5ea14"
     "2ec2be2f0bb814a72d5986dead0ad20ecefa492966c1ca44fefb0533c311783c"
     "d48d3f4027b996b6703d110a257d4bd0326f09e8f928020a6b953de4fb8f1dcb"
     "ec3eaa6142f6068c38b4c8e41e85444965a04dfe64cc2ea1c09e374cfd1f4d4d"
     "a76f31b57057ae79a803a8e96f5fd158920928ebcf1ff0fee75abce44ade9e71"
     "56122cc4a11a4baa0ddf73f926ae58743b493d8c4bc8a393018041b543d8b223"
     "d294de1d4fe8ec8f4d4e84646d1b6b78deadd34e507cccf472de1ca9ed0455bb"},
    {"NTC TPM EK Root CA 01",
     "e836ac61b43e3252d5e1a8a4061997a6a0a272ba3d519d6be6360cc8b4b79e8c"
     "d53c07a7ce9e9310ca84b82bbdad32184544ada357d458cf224c4a3130c97d00"
     "4933b5db232d8b6509412eb4777e9e1b093c58b82b1679c84e57a6b218b4d61f"
     "6dd4c3a66b2dd33b52cb1ffdff543289fa36dd71b7c83b66c1aae37caf7fe88d"
     "851a3523e3ea92b59a6b0ca095c5e1d191484c1bff8a33048c3976e826d4c12a"
     "e198f7199d183e0e70c8b46e8106edec3914397e051ae2b9a7f0b4bb9cd7f2ed"
     "f71064eb0eb473df27b7ccef9a018d715c5fe6ab012a8315f933c7f4fc35d34c"
     "efc27de224b2e3de3b3ba316d5df8b90b2eb879e219d270141b78dbb671a3a05"},
    {"STM TPM EK Intermediate CA 03",
     "a5152b4fbd2c70c0c9a0dd919f48ddcde2b5c0c9988cff3b04ecd844f6cc0035"
     "6c4e01b52463deb5179f36acf0c06d4574327c37572292fcd0f272c2d45ea7f2"
     "2e8d8d18aa62354c279e03be9220f0c3822d16de1ea1c130b59afc56e08f22f1"
     "902a07f881ebea3703badaa594ecbdf8fd1709211ba16769f73e76f348e2755d"
     "bba2f94c1869ef71e726f56f8ece987f345c622e8b5c2a5466d41093c0dc2982"
     "e6203d96f539b542347a08e87fc6e248a346d61a505f52add7f768a5203d70b8"
     "68b6ec92ef7a83a4e6d1e1d259018705755d812175489fae83c4ab2957f69a99"
     "9394ac7a243a5c1cd85f92b8648a8e0d23165fdd86fad06990bfd16fb3293379"},
    /* TODO(ngm): remove by: Aug 30 08:44:33 2020 GMT */
    {"CROS TPM DEV EK ROOT CA",
     "cdc108745dc50dd6a1098c31486fb31578607fd64f64b0d91b994244ca1a9a69"
     "a74c6bccc7f24923e1513e132dc0d9dbcb1b22089299bb6cb669cbf4b704c992"
     "27bb769fa1f91ab11f67fb464a065b34b1a0e824136af5e59d1ac04bda22c199"
     "9f7a5b34bd6b50c81b4a88cc097d4dfeb4dc695096463d9529d69f116e2a26de"
     "070ef3118287072bdbe94466b8737049809bb8e1276b245930051b2bbbad71dd"
     "20d26349d1d83cdb2ff9c65251a17dae4f400ecc3e77f89e27a75fe0709dc81f"
     "e172008a3e65de685d9df43e036c557e88f1a9aedf7a91644391523d9728f946"
     "45c0e8adaf37e9a15777021ad43b675583302402912d66233c59ad05fa3b34ed"},
    {"CROS TPM PRD EK ROOT CA",
     "bd6f0198ffa7f7d20c15f81642096e335e2cd74734f73008265fc9957bbe018d"
     "fbac0d2a0ea99f5fb7bbff6f0d367b81199e837c390527972aa5392c2ca0f2a3"
     "506ee7d4a938f47158a7c56a390df2b781344a82b885a62f1de78f37ec105749"
     "69d8abf3163f0cf5c67fa05dd4fb3eb07a7571888b7a87ed57735ce476156bf7"
     "d6eff6cb8c8b303c21ebfe0e11b660edbdf903c70ac16927345d0b38c72f1e60"
     "1460743584f5a3eaef303dbc5cfda48e4c7a1f338108c7f0c70a694f814b6691"
     "ba9d058ab988152bb7097a010e400462187811c3e062001bce8aa808db485bd8"
     "2f7f0e1e2a2ddb95c364dffea4c23e872fc3874c4756e85e6cf8eca6eb6a07bf"},
};

const CertificateAuthority kKnownCrosCoreEndorsementCA[] = {
    {"IFX TPM EK Intermediate CA 24",
     "9D3F39677EBDB7B95F383021EA6EF90AD2BEA4E38B10CA65DCD84D0B33D400FA"
     "E7E56FC553975FDADD425227F055C029B6544331E3BA50ED33F6CC02D833EA4E"
     "0EECFE9AD1ADD7095F3A804C560F031E8705A3AD5189CBD62678B5B8205C37ED"
     "780A3EDE8DE64A08980C048872E789937A49FC4048EADCAC9B3FD0F0DD085E76"
     "30DDF9C0C31EFF3B77C6C3601AA7C3DCD10F08616C01435697746A61F920335C"
     "0C45A41149F5D22FCD23DBE35003A9AF7FD91C18715E3709F86A38AB149113C4"
     "D5273C3C90599734FF627ACBF408B082C76E486091F27446E175C50D340DA0FE"
     "5C3FE3D590B8729F4E364E5BF7D854D9AE28EFBCD0CE8F19E6462B3A593983DF"},
    {"IFX TPM EK Intermediate CA 50",
     "ACB01856664D0C81B545DB926D25019FC2D06B4A97DFB91FD7A5AB1A803AA6F4"
     "12FEEE5E3DEF3634172F1271E893C6848B4D156485917DF6F0504947B39F0A5A"
     "E14FFBAB9FF00E70448E51F11DEEA1EA16287ABAAE05D3D00FEB1AA064F1CBD9"
     "E1E67C057087110F9D3023BFA0545C97BD51E473C5B183E50C2984BD9A2DA39B"
     "7D028B895BD939FF0822595DDC948640D06E57ED72EF43B8D8071D2C3C0497A0"
     "EC52F682D1637F06979733BAF56DD809D24C20354D73D3849A1C0DAD23AD5CCB"
     "F8C679242D13FFFE055CC2AB2692897F0329EEA55AF3BB10A4EB4E2937601196"
     "90D64FB352E3D34E05AB53BD4E01EFE3EF56F6DBE315B76A31B0100BF7096093"},
};

// Returns a human-readable description for a known 3-byte |mode|.
std::string GetDescriptionForMode(const char* mode) {
  return base::StringPrintf(
      "Developer Mode: %s, Recovery Mode: %s, Firmware Type: %s",
      mode[0] ? "On" : "Off", mode[1] ? "On" : "Off",
      mode[2] ? "Verified" : "Developer");
}

std::string GetHardwareID() {
  char buffer[VB_MAX_STRING_PROPERTY];
  const char* property =
      VbGetSystemPropertyString("hwid", buffer, base::size(buffer));
  if (property != nullptr) {
    return std::string(property);
  }
  LOG(WARNING) << "Could not read hwid property.";
  return std::string();
}

// Finds CA by |issuer_name| and |is_cros_core| flag. On success returns true
// and fills |public_key_hex| with CA public key hex modulus.
bool GetAuthorityPublicKey(const std::string& issuer_name,
                           bool is_cros_core,
                           std::string* public_key_hex) {
  const CertificateAuthority* const kKnownCA =
      is_cros_core ? kKnownCrosCoreEndorsementCA : kKnownEndorsementCA;
  const int kNumIssuers = is_cros_core ? base::size(kKnownCrosCoreEndorsementCA)
                                       : base::size(kKnownEndorsementCA);
  for (int i = 0; i < kNumIssuers; ++i) {
    if (issuer_name == kKnownCA[i].issuer) {
      public_key_hex->assign(kKnownCA[i].modulus);
      return true;
    }
  }
  return false;
}

std::string GetACAName(attestation::ACAType aca_type) {
  switch (aca_type) {
    case attestation::DEFAULT_ACA:
      return "the default ACA";
    case attestation::TEST_ACA:
      return "the test ACA";
    default: {
      std::ostringstream stream;
      stream << "ACA " << aca_type;
      return stream.str();
    }
  }
}

std::string GetIdentityFeaturesString(int identity_features) {
  unsigned features_count = 0;
  std::ostringstream stream;
  if (identity_features == attestation::NO_IDENTITY_FEATURES) {
    stream << "NO_IDENTITY_FEATURES";
  } else {
    // We don't have reflection, copy/paste and adapt these few lines when
    // adding a new enum value.
    if (identity_features &
        attestation::IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID) {
      ++features_count;
      if (stream.tellp() > 0) {
        stream << ", ";
      }
      stream << "IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID";
      identity_features &=
          ~attestation::IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID;
    }
    // Print other bits which may have been forgotten above.
    if (identity_features) {
      features_count += 2;  // Forces plural.
      if (stream.tellp() > 0) {
        stream << ", ";
      }
      stream << "(undecoded features: " << identity_features << ")";
    }
  }
  return std::string("identity feature") + (features_count != 1 ? "s " : " ") +
         stream.str();
}

std::string GetKeyTypeName(attestation::KeyType key_type) {
  switch (key_type) {
    case attestation::KEY_TYPE_ECC:
      return "ECC";
    case attestation::KEY_TYPE_RSA:
      return "RSA";
  }
  return "unknown";
}

void LogErrorFromCA(const std::string& func,
                    const std::string& details,
                    const std::string& extra_details) {
  std::ostringstream stream;
  stream << func << ": Received error from Attestation CA";
  if (!details.empty()) {
    stream << ": " << details;
    if (!extra_details.empty()) {
      stream << ". Extra details: " << extra_details;
    }
  }
  LOG(ERROR) << stream.str() << ".";
}

}  // namespace

namespace attestation {

namespace {

// Last PCR index to quote (we start at 0).
constexpr int kLastPcrToQuote = 1;

pca_agent::EnrollRequest ToPcaAgentEnrollRequest(
    const AttestationFlowData& data) {
  pca_agent::EnrollRequest ret;
  ret.set_aca_type(data.aca_type());
  ret.set_request(data.result_request());
  return ret;
}

pca_agent::GetCertificateRequest ToPcaAgentCertRequest(
    const AttestationFlowData& data) {
  pca_agent::GetCertificateRequest ret;
  ret.set_aca_type(data.aca_type());
  ret.set_request(data.result_request());
  return ret;
}

}  // namespace

#if USE_TPM2

// Description of virtual NVRAM indices used for attestation.
const struct {
  NVRAMQuoteType quote_type;
  const char* quote_name;
  uint32_t nv_index;  // From CertifyNV().
  uint16_t nv_size;   // From CertifyNV().
} kNvramIndexData[] = {
    {BOARD_ID, "BoardId", VIRTUAL_NV_INDEX_BOARD_ID,
     VIRTUAL_NV_INDEX_BOARD_ID_SIZE},
    {SN_BITS, "SN Bits", VIRTUAL_NV_INDEX_SN_DATA,
     VIRTUAL_NV_INDEX_SN_DATA_SIZE},
    {RSA_PUB_EK_CERT, "RSA Public EK Certificate",
     trunks::kRsaEndorsementCertificateIndex, 0},
    {RSU_DEVICE_ID, "RSU Device ID", VIRTUAL_NV_INDEX_RSU_DEV_ID,
     VIRTUAL_NV_INDEX_RSU_DEV_ID_SIZE}};

// Types of quotes being cached in the identity data.
const NVRAMQuoteType kNvramQuoteTypeInIdentityData[] = {BOARD_ID, SN_BITS};

// Types of quotes needed to obtain an enrollment certificate.
const NVRAMQuoteType kNvramQuoteTypeForEnrollmentCertificate[] = {
    BOARD_ID, SN_BITS, RSU_DEVICE_ID};

#endif

using QuoteMap = google::protobuf::Map<int, Quote>;

const size_t kChallengeSignatureNonceSize = 20;  // For all TPMs.

AttestationService::AttestationService(brillo::SecureBlob* abe_data)
    : abe_data_(abe_data), weak_factory_(this) {}

bool AttestationService::Initialize() {
  return InitializeWithCallback(base::DoNothing());
}

bool AttestationService::InitializeWithCallback(
    InitializeCompleteCallback callback) {
  if (!worker_thread_) {
    worker_thread_.reset(new ServiceWorkerThread(this));
    worker_thread_->StartWithOptions(
        base::Thread::Options(base::MessagePumpType::IO, 0));
    LOG(INFO) << "Attestation service started.";
  }
  // Creates |default_pca_agent_proxy_| here if needed; unlike other objects,
  // |default_pca_agent_proxy_| is used in the origin thread instead of worker
  // thread.
  if (!pca_agent_proxy_) {
    default_pca_agent_proxy_ =
        attestation::pca_agent::client::CreateWithDBusTaskRunner(
            worker_thread_->task_runner());
    pca_agent_proxy_ = default_pca_agent_proxy_.get();
  }
  worker_thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&AttestationService::InitializeTask,
                                base::Unretained(this), std::move(callback)));
  return true;
}

void AttestationService::InitializeTask(InitializeCompleteCallback callback) {
  if (!tpm_utility_) {
    default_tpm_utility_.reset(TpmUtilityFactory::New());
    CHECK(default_tpm_utility_->Initialize());
    tpm_utility_ = default_tpm_utility_.get();
  }
  if (!crypto_utility_) {
    default_crypto_utility_.reset(new CryptoUtilityImpl(tpm_utility_));
    crypto_utility_ = default_crypto_utility_.get();
  }
#if USE_TPM2
  for (int i = 0; i < base::size(kNvramIndexData); ++i) {
    nvram_quote_type_to_index_data_[kNvramIndexData[i].quote_type] = i;
  }
#endif
  bool existing_database;
  if (database_) {
    existing_database = true;
  } else {
    default_database_.reset(new DatabaseImpl(crypto_utility_, tpm_utility_));
    existing_database = default_database_->Initialize();
    database_ = default_database_.get();
  }
  if (existing_database && MigrateAttestationDatabase()) {
    if (!database_->SaveChanges()) {
      LOG(WARNING) << "Attestation: Failed to persist database changes.";
    }
  }
  if (!key_store_) {
    pkcs11_token_manager_.reset(new chaps::TokenManagerClient());
    default_key_store_.reset(new Pkcs11KeyStore(pkcs11_token_manager_.get()));
    key_store_ = default_key_store_.get();
  }
  if (hwid_.empty()) {
    hwid_ = GetHardwareID();
  }
  if (!IsPreparedForEnrollment()) {
    worker_thread_->task_runner()->PostTask(
        FROM_HERE, base::BindOnce(&AttestationService::PrepareForEnrollment,
                                  base::Unretained(this), std::move(callback)));
  } else {
    // Ignore errors. If failed this time, will be re-attempted on next boot.
    tpm_utility_->RemoveOwnerDependency();
    std::move(callback).Run(false);
  }
}

bool AttestationService::MigrateAttestationDatabase() {
  bool migrated = false;

  auto* database_pb = database_->GetMutableProtobuf();
  if (database_pb->has_credentials()) {
    if (!database_pb->credentials().encrypted_endorsement_credentials().count(
            DEFAULT_ACA) &&
        database_pb->credentials()
            .has_default_encrypted_endorsement_credential()) {
      LOG(INFO) << "Attestation: Migrating endorsement credential for "
                << GetACAName(DEFAULT_ACA) << ".";
      (*database_pb->mutable_credentials()
            ->mutable_encrypted_endorsement_credentials())[DEFAULT_ACA] =
          database_pb->credentials().default_encrypted_endorsement_credential();
      migrated = true;
    }
    if (!database_pb->credentials().encrypted_endorsement_credentials().count(
            TEST_ACA) &&
        database_pb->credentials()
            .has_test_encrypted_endorsement_credential()) {
      LOG(INFO) << "Attestation: Migrating endorsement credential for "
                << GetACAName(TEST_ACA) << ".";
      (*database_pb->mutable_credentials()
            ->mutable_encrypted_endorsement_credentials())[TEST_ACA] =
          database_pb->credentials().test_encrypted_endorsement_credential();
      migrated = true;
    }
  }

  // Migrate identity data if needed.
  migrated |= MigrateIdentityData();

  if (migrated) {
    EncryptAllEndorsementCredentials();
    LOG(INFO) << "Attestation: Migrated attestation database.";
  }

  // Migrate Rsa PublicKey Format to SubjectPublicKeyInfo
  if (database_pb->credentials().has_legacy_endorsement_public_key()) {
    std::string public_key_info;
    if (GetSubjectPublicKeyInfo(
            database_pb->credentials().endorsement_key_type(),
            database_pb->credentials().legacy_endorsement_public_key(),
            &public_key_info)) {
      database_pb->mutable_credentials()->set_endorsement_public_key(
          public_key_info);
    } else {
      // If the format conversion fails, that means the EK public key is broken
      // somehow, which should not happen. If it does, that means EK data
      // becomes invalid. Clean up all EK metadata to resolve this problem.
      LOG(ERROR) << __func__ << ": Migrate public format fail.";
      database_pb->mutable_credentials()->clear_endorsement_key_type();
      database_pb->mutable_credentials()->clear_endorsement_credential();
    }
    database_pb->mutable_credentials()->clear_legacy_endorsement_public_key();
    migrated |= true;
  }

  return migrated;
}

bool AttestationService::MigrateIdentityData() {
  auto* database_pb = database_->GetMutableProtobuf();
  if (database_pb->identities().size() > 0) {
    // We already migrated identity data.
    return false;
  }

  bool error = false;

  // The identity we're creating will have the next index in identities.
  LOG(INFO) << "Attestation: Migrating existing identity into identity "
            << database_pb->identities().size() << ".";
  CHECK(database_pb->identities().size() == kFirstIdentity);
  AttestationDatabase::Identity* identity_data =
      database_pb->mutable_identities()->Add();
  identity_data->set_features(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID);
  if (database_pb->has_identity_binding()) {
    identity_data->mutable_identity_binding()->CopyFrom(
        database_pb->identity_binding());
  }
  if (database_pb->has_identity_key()) {
    identity_data->mutable_identity_key()->CopyFrom(
        database_pb->identity_key());
    identity_data->mutable_identity_key()->clear_identity_credential();
    if (database_pb->identity_key().has_identity_credential()) {
      // Create an identity certificate for this identity and the default ACA.
      AttestationDatabase::IdentityCertificate identity_certificate;
      identity_certificate.set_identity(kFirstIdentity);
      identity_certificate.set_aca(DEFAULT_ACA);
      identity_certificate.set_identity_credential(
          database_pb->identity_key().identity_credential());
      auto* map = database_pb->mutable_identity_certificates();
      auto in = map->insert(IdentityCertificateMap::value_type(
          DEFAULT_ACA, identity_certificate));
      if (!in.second) {
        LOG(ERROR) << "Attestation: Could not migrate existing identity.";
        error = true;
      }
    }
    if (database_pb->identity_key().has_enrollment_id()) {
      database_->GetMutableProtobuf()->set_enrollment_id(
          database_pb->identity_key().enrollment_id());
    }
  }

  if (database_pb->has_pcr0_quote()) {
    auto in = identity_data->mutable_pcr_quotes()->insert(
        QuoteMap::value_type(0, database_pb->pcr0_quote()));
    if (!in.second) {
      LOG(ERROR) << "Attestation: Could not migrate existing identity.";
      error = true;
    }
  } else {
    LOG(ERROR) << "Attestation: Missing PCR0 quote in existing database.";
    error = true;
  }
  if (database_pb->has_pcr1_quote()) {
    auto in = identity_data->mutable_pcr_quotes()->insert(
        QuoteMap::value_type(1, database_pb->pcr1_quote()));
    if (!in.second) {
      LOG(ERROR) << "Attestation: Could not migrate existing identity.";
      error = true;
    }
  } else {
    LOG(ERROR) << "Attestation: Missing PCR1 quote in existing database.";
    error = true;
  }

  if (error) {
    database_pb->mutable_identities()->RemoveLast();
    database_pb->mutable_identity_certificates()->erase(DEFAULT_ACA);
  }

  return !error;
}

void AttestationService::ShutdownTask() {
  database_ = nullptr;
  default_database_.reset(nullptr);
  crypto_utility_ = nullptr;
  default_crypto_utility_.reset(nullptr);
  tpm_utility_ = nullptr;
  default_tpm_utility_.reset(nullptr);
}

void AttestationService::GetKeyInfo(const GetKeyInfoRequest& request,
                                    const GetKeyInfoCallback& callback) {
  auto result = std::make_shared<GetKeyInfoReply>();
  base::Closure task = base::Bind(&AttestationService::GetKeyInfoTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<GetKeyInfoReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::GetKeyInfoTask(
    const GetKeyInfoRequest& request,
    const std::shared_ptr<GetKeyInfoReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  std::string public_key_info;
  if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
                               &public_key_info)) {
    LOG(ERROR) << __func__ << ": Bad public key.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_key_type(key.key_type());
  result->set_key_usage(key.key_usage());
  result->set_public_key(public_key_info);
  result->set_certify_info(key.certified_key_info());
  result->set_certify_info_signature(key.certified_key_proof());
  if (key.has_intermediate_ca_cert()) {
    result->set_certificate(CreatePEMCertificateChain(key));
  } else {
    result->set_certificate(key.certified_key_credential());
  }
  result->set_payload(key.payload());
}

void AttestationService::GetEndorsementInfo(
    const GetEndorsementInfoRequest& request,
    const GetEndorsementInfoCallback& callback) {
  auto result = std::make_shared<GetEndorsementInfoReply>();
  base::Closure task = base::Bind(&AttestationService::GetEndorsementInfoTask,
                                  base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<GetEndorsementInfoReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

base::Optional<std::string> AttestationService::GetEndorsementPublicKey()
    const {
  const auto& database_pb = database_->GetProtobuf();
  if (database_pb.has_credentials() &&
      database_pb.credentials().has_endorsement_public_key()) {
    return database_pb.credentials().endorsement_public_key();
  }

  // Try to read the public key directly.
  std::string public_key;
  if (!tpm_utility_->GetEndorsementPublicKey(GetEndorsementKeyType(),
                                             &public_key)) {
    return base::nullopt;
  }
  return public_key;
}

base::Optional<std::string> AttestationService::GetEndorsementCertificate()
    const {
  const auto& database_pb = database_->GetProtobuf();
  if (database_pb.has_credentials() &&
      database_pb.credentials().has_endorsement_credential()) {
    return database_pb.credentials().endorsement_credential();
  }

  // Try to read the certificate directly.
  std::string certificate;
  if (!tpm_utility_->GetEndorsementCertificate(GetEndorsementKeyType(),
                                               &certificate)) {
    return base::nullopt;
  }
  return certificate;
}

void AttestationService::GetEndorsementInfoTask(
    const GetEndorsementInfoRequest& request,
    const std::shared_ptr<GetEndorsementInfoReply>& result) {
  const auto& key_type = GetEndorsementKeyType();

  if (key_type != KEY_TYPE_RSA && key_type != KEY_TYPE_ECC) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }

  base::Optional<std::string> public_key = GetEndorsementPublicKey();
  if (!public_key.has_value()) {
    LOG(ERROR) << __func__ << ": Endorsement public key not available.";
    result->set_status(STATUS_NOT_AVAILABLE);
    return;
  }

  base::Optional<std::string> certificate = GetEndorsementCertificate();
  if (!certificate.has_value()) {
    LOG(ERROR) << __func__ << ": Endorsement cert not available.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }

  result->set_ek_public_key(public_key.value());
  result->set_ek_certificate(certificate.value());
  std::string hash = crypto::SHA256HashString(certificate.value());
  result->set_ek_info(
      base::StringPrintf("EK Certificate:\n%s\nHash:\n%s\n",
                         CreatePEMCertificate(certificate.value()).c_str(),
                         base::HexEncode(hash.data(), hash.size()).c_str()));
}

void AttestationService::GetAttestationKeyInfo(
    const GetAttestationKeyInfoRequest& request,
    const GetAttestationKeyInfoCallback& callback) {
  auto result = std::make_shared<GetAttestationKeyInfoReply>();
  base::Closure task =
      base::Bind(&AttestationService::GetAttestationKeyInfoTask,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<GetAttestationKeyInfoReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::GetAttestationKeyInfoTask(
    const GetAttestationKeyInfoRequest& request,
    const std::shared_ptr<GetAttestationKeyInfoReply>& result) {
  const int identity = kFirstIdentity;
  auto aca_type = request.aca_type();
  auto found = FindIdentityCertificate(identity, aca_type);
  if (found ==
      database_->GetMutableProtobuf()->mutable_identity_certificates()->end()) {
    LOG(ERROR) << __func__ << ": Identity " << identity
               << " is not enrolled for attestation with "
               << GetACAName(aca_type) << ".";
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  const auto& identity_certificate = found->second;
  if (!IsPreparedForEnrollment() ||
      identity_certificate.identity() >=
          database_->GetProtobuf().identities().size()) {
    result->set_status(STATUS_NOT_AVAILABLE);
    return;
  }
  const auto& identity_pb = database_->GetProtobuf().identities().Get(
      identity_certificate.identity());
  if (!identity_pb.has_identity_key()) {
    result->set_status(STATUS_NOT_AVAILABLE);
    return;
  }
  if (identity_pb.identity_key().has_identity_public_key_der()) {
    // TODO(crbug/942487): Use SubjectPublicKeyInfo for identity_public_key_der
    std::string public_key_info;
    if (!GetSubjectPublicKeyInfo(
            identity_pb.identity_key().identity_key_type(),
            identity_pb.identity_key().identity_public_key_der(),
            &public_key_info)) {
      LOG(ERROR) << __func__ << ": Bad public key.";
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
    result->set_public_key(public_key_info);
  }
  if (identity_pb.has_identity_binding() &&
      identity_pb.identity_binding().has_identity_public_key_tpm_format()) {
    result->set_public_key_tpm_format(
        identity_pb.identity_binding().identity_public_key_tpm_format());
  }
  if (identity_certificate.has_identity_credential()) {
    result->set_certificate(identity_certificate.identity_credential());
  }
  if (identity_pb.pcr_quotes().count(0)) {
    *result->mutable_pcr0_quote() = identity_pb.pcr_quotes().at(0);
  }
  if (identity_pb.pcr_quotes().count(1)) {
    *result->mutable_pcr1_quote() = identity_pb.pcr_quotes().at(1);
  }
}

void AttestationService::ActivateAttestationKey(
    const ActivateAttestationKeyRequest& request,
    const ActivateAttestationKeyCallback& callback) {
  auto result = std::make_shared<ActivateAttestationKeyReply>();
  base::Closure task =
      base::Bind(&AttestationService::ActivateAttestationKeyTask,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<ActivateAttestationKeyReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::ActivateAttestationKeyTask(
    const ActivateAttestationKeyRequest& request,
    const std::shared_ptr<ActivateAttestationKeyReply>& result) {
  if (request.encrypted_certificate().tpm_version() !=
      tpm_utility_->GetVersion()) {
    result->set_status(STATUS_INVALID_PARAMETER);
    LOG(ERROR) << __func__ << ": TPM version mismatch.";
    return;
  }
  std::string certificate;
  if (!ActivateAttestationKeyInternal(
          kFirstIdentity, request.aca_type(), GetEndorsementKeyType(),
          request.encrypted_certificate(), request.save_certificate(),
          &certificate, nullptr /* certificate_index */)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_certificate(certificate);
}

void AttestationService::CreateCertifiableKey(
    const CreateCertifiableKeyRequest& request,
    const CreateCertifiableKeyCallback& callback) {
  auto result = std::make_shared<CreateCertifiableKeyReply>();
  base::Closure task = base::Bind(&AttestationService::CreateCertifiableKeyTask,
                                  base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<CreateCertifiableKeyReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::CreateCertifiableKeyTask(
    const CreateCertifiableKeyRequest& request,
    const std::shared_ptr<CreateCertifiableKeyReply>& result) {
  CertifiedKey key;
  if (!CreateKey(request.username(), request.key_label(), request.key_type(),
                 request.key_usage(), &key)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  std::string public_key_info;
  if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
                               &public_key_info)) {
    LOG(ERROR) << __func__ << ": Bad public key.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_public_key(public_key_info);
  result->set_certify_info(key.certified_key_info());
  result->set_certify_info_signature(key.certified_key_proof());
}

void AttestationService::Decrypt(const DecryptRequest& request,
                                 const DecryptCallback& callback) {
  auto result = std::make_shared<DecryptReply>();
  base::Closure task = base::Bind(&AttestationService::DecryptTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<DecryptReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::DecryptTask(
    const DecryptRequest& request,
    const std::shared_ptr<DecryptReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  std::string data;
  if (!tpm_utility_->Unbind(key.key_blob(), request.encrypted_data(), &data)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_decrypted_data(data);
}

void AttestationService::Sign(const SignRequest& request,
                              const SignCallback& callback) {
  auto result = std::make_shared<SignReply>();
  base::Closure task = base::Bind(&AttestationService::SignTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<SignReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::SignTask(const SignRequest& request,
                                  const std::shared_ptr<SignReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  std::string signature;
  if (!tpm_utility_->Sign(key.key_blob(), request.data_to_sign(), &signature)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_signature(signature);
}

void AttestationService::RegisterKeyWithChapsToken(
    const RegisterKeyWithChapsTokenRequest& request,
    const RegisterKeyWithChapsTokenCallback& callback) {
  auto result = std::make_shared<RegisterKeyWithChapsTokenReply>();
  base::Closure task =
      base::Bind(&AttestationService::RegisterKeyWithChapsTokenTask,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<RegisterKeyWithChapsTokenReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::RegisterKeyWithChapsTokenTask(
    const RegisterKeyWithChapsTokenRequest& request,
    const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  std::string certificate;
  if (request.include_certificates()) {
    certificate = key.certified_key_credential();
  }
  if (!key_store_->Register(request.username(), request.key_label(),
                            key.key_type(), key.key_usage(), key.key_blob(),
                            key.public_key(), certificate)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (request.include_certificates()) {
    if (key.has_intermediate_ca_cert() &&
        !key_store_->RegisterCertificate(request.username(),
                                         key.intermediate_ca_cert())) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
    for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
      if (!key_store_->RegisterCertificate(
              request.username(), key.additional_intermediate_ca_cert(i))) {
        result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
        return;
      }
    }
  }
  DeleteKey(request.username(), request.key_label());
}

bool AttestationService::IsPreparedForEnrollment() {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  const auto& database_pb = database_->GetProtobuf();
  // Note that this function only checks for the existence of endorsement
  // credentials, but the identity key, identity key binding and pcr quotes
  // signed by the identity key are also required for enrollment.
  // In normal circumstances, existence of the endorsement credentials implies
  // the existence of the other identity key related pieces, but it is
  // possible for that not to be true, for instance, see crbug.com/899932
  return database_pb.credentials().has_endorsement_credential() ||
         database_pb.credentials().encrypted_endorsement_credentials().size() >
             TEST_ACA;
}

bool AttestationService::IsPreparedForEnrollmentWithACA(ACAType aca_type) {
  const auto& database_pb = database_->GetProtobuf();
  return database_pb.credentials().encrypted_endorsement_credentials().count(
      aca_type);
}
bool AttestationService::IsEnrolled() {
  return IsEnrolledWithACA(DEFAULT_ACA) || IsEnrolledWithACA(TEST_ACA);
}

bool AttestationService::IsEnrolledWithACA(ACAType aca_type) {
  return HasIdentityCertificate(kFirstIdentity, aca_type);
}

AttestationService::IdentityCertificateMap::iterator
AttestationService::FindIdentityCertificate(int identity, ACAType aca_type) {
  auto* database_pb = database_->GetMutableProtobuf();
  auto end = database_pb->mutable_identity_certificates()->end();
  for (auto it = database_pb->mutable_identity_certificates()->begin();
       it != end; ++it) {
    if (it->second.identity() == identity && it->second.aca() == aca_type) {
      return it;
    }
  }
  return end;
}

AttestationDatabase_IdentityCertificate*
AttestationService::FindOrCreateIdentityCertificate(int identity,
                                                    ACAType aca_type,
                                                    int* cert_index) {
  // Find an identity certificate to reuse or create a new one.
  int index;
  auto* database_pb = database_->GetMutableProtobuf();
  auto found = FindIdentityCertificate(identity, aca_type);
  if (found == database_pb->mutable_identity_certificates()->end()) {
    index = identity == kFirstIdentity
                ? aca_type
                : std::max(static_cast<size_t>(kMaxACATypeInternal),
                           database_pb->identity_certificates().size());
    AttestationDatabase::IdentityCertificate new_identity_certificate;
    new_identity_certificate.set_identity(identity);
    new_identity_certificate.set_aca(aca_type);
    auto* map = database_pb->mutable_identity_certificates();
    auto in = map->insert(
        IdentityCertificateMap::value_type(index, new_identity_certificate));
    if (!in.second) {
      LOG(ERROR) << __func__ << ": Failed to create identity certificate "
                 << index << " for identity " << identity << " and "
                 << GetACAName(aca_type) << ".";
      if (cert_index) {
        *cert_index = -1;
      }
      return nullptr;
    }
    found = in.first;
    LOG(INFO) << "Attestation: Creating identity certificate " << index
              << " for identity " << identity << " enrolled with "
              << GetACAName(aca_type);
  } else {
    index = found->first;
  }
  if (cert_index) {
    *cert_index = index;
  }
  return &found->second;
}

bool AttestationService::HasIdentityCertificate(int identity,
                                                ACAType aca_type) {
  return FindIdentityCertificate(identity, aca_type) !=
         database_->GetMutableProtobuf()
             ->mutable_identity_certificates()
             ->end();
}

bool AttestationService::CreateEnrollRequestInternal(
    ACAType aca_type, std::string* enroll_request) {
  const int identity = kFirstIdentity;
  if (!IsPreparedForEnrollmentWithACA(aca_type)) {
    LOG(ERROR) << __func__ << ": Enrollment with " << GetACAName(aca_type)
               << " is not possible, attestation data does not exist.";
    return false;
  }
  const auto& database_pb = database_->GetProtobuf();
  if (database_pb.identities().size() <= identity) {
    LOG(ERROR) << __func__ << ": Enrollment with " << GetACAName(aca_type)
               << " is not possible, identity " << identity
               << " does not exist.";
    return false;
  }
  AttestationEnrollmentRequest request_pb;
  request_pb.set_tpm_version(tpm_utility_->GetVersion());
  *request_pb.mutable_encrypted_endorsement_credential() =
      database_pb.credentials().encrypted_endorsement_credentials().at(
          aca_type);
  const AttestationDatabase::Identity& identity_data =
      database_pb.identities().Get(identity);
  request_pb.set_identity_public_key(
      identity_data.identity_binding().identity_public_key_tpm_format());
  *request_pb.mutable_pcr0_quote() = identity_data.pcr_quotes().at(0);
  *request_pb.mutable_pcr1_quote() = identity_data.pcr_quotes().at(1);

  if (identity_data.features() & IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID) {
    std::string enterprise_enrollment_nonce =
        ComputeEnterpriseEnrollmentNonce();
    if (!enterprise_enrollment_nonce.empty()) {
      request_pb.set_enterprise_enrollment_nonce(
          enterprise_enrollment_nonce.data(),
          enterprise_enrollment_nonce.size());
    }

    if (GetEndorsementKeyType() != KEY_TYPE_RSA) {
      // Include an encrypted quote of the RSA pub EK certificate so that
      // an EID can be computed during enrollment.

      auto found = identity_data.nvram_quotes().find(RSA_PUB_EK_CERT);
      if (found == identity_data.nvram_quotes().end()) {
        LOG(ERROR) << __func__
                   << ": Cannot find RSA pub EK certificate quote in identity "
                   << identity << ".";
        return false;
      }

      std::string serialized_quote;
      if (!found->second.SerializeToString(&serialized_quote)) {
        LOG(ERROR) << __func__
                   << ": Failed to serialize RSA pub EK quote protobuf.";
        return false;
      }
      if (!EncryptDataForAttestationCA(
              aca_type, serialized_quote,
              request_pb.mutable_encrypted_rsa_endorsement_quote())) {
        LOG(ERROR)
            << "Attestation: Failed to encrypt RSA pub EK certificate for "
            << GetACAName(aca_type) << ".";
        return false;
      }
    }
  }

  if (!request_pb.SerializeToString(enroll_request)) {
    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    return false;
  }
  return true;
}

bool AttestationService::FinishEnrollInternal(
    ACAType aca_type,
    const std::string& enroll_response,
    std::string* server_error) {
  const int identity = kFirstIdentity;
  if (!tpm_utility_->IsTpmReady()) {
    LOG(ERROR) << __func__
               << ": Cannot finish enrollment as the TPM is not ready.";
    return false;
  }
  AttestationEnrollmentResponse response_pb;
  if (!response_pb.ParseFromString(enroll_response)) {
    LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
    return false;
  }
  if (response_pb.status() != OK) {
    *server_error = response_pb.detail();
    LogErrorFromCA(__func__, response_pb.detail(), response_pb.extra_details());
    return false;
  }
  if (response_pb.encrypted_identity_credential().tpm_version() !=
      tpm_utility_->GetVersion()) {
    LOG(ERROR) << __func__ << ": TPM version mismatch.";
    return false;
  }
  int certificate_index;
  if (!ActivateAttestationKeyInternal(
          identity, aca_type, GetEndorsementKeyType(),
          response_pb.encrypted_identity_credential(),
          true /* save_certificate */, nullptr /* certificate */,
          &certificate_index)) {
    return false;
  }
  LOG(INFO) << __func__ << ": Enrollment of identity " << identity << " with "
            << GetACAName(aca_type) << " complete. Certificate #"
            << certificate_index << ".";
  return true;
}

bool AttestationService::CreateCertificateRequestInternal(
    ACAType aca_type,
    const std::string& username,
    const CertifiedKey& key,
    CertificateProfile profile,
    const std::string& origin,
    std::string* certificate_request,
    std::string* message_id) {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  if (!IsEnrolledWithACA(aca_type)) {
    LOG(ERROR) << __func__ << ": Device is not enrolled for attestation with "
               << GetACAName(aca_type) << ".";
    return false;
  }
  auto found = FindIdentityCertificate(kFirstIdentity, aca_type);
  if (found ==
      database_->GetMutableProtobuf()->mutable_identity_certificates()->end()) {
    LOG(ERROR) << __func__ << ": Identity " << kFirstIdentity
               << " is not enrolled for attestation with "
               << GetACAName(aca_type) << ".";
    return false;
  }
  const auto& identity_certificate = found->second;
  if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
    LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
    return false;
  }
  AttestationCertificateRequest request_pb;
  request_pb.set_tpm_version(tpm_utility_->GetVersion());
  request_pb.set_message_id(*message_id);
  request_pb.set_identity_credential(
      identity_certificate.identity_credential());
  request_pb.set_profile(profile);

#if USE_TPM2

  if (profile == ENTERPRISE_ENROLLMENT_CERTIFICATE) {
    const int identity = identity_certificate.identity();
    const AttestationDatabase::Identity& identity_data =
        database_->GetProtobuf().identities().Get(identity);
    // Copy NVRAM quotes to include in an enrollment certificate from the
    // identity if possible.
    std::set<NVRAMQuoteType> not_in_identity;
    for (int i = 0; i < base::size(kNvramQuoteTypeForEnrollmentCertificate);
         ++i) {
      const auto quote_type = kNvramQuoteTypeForEnrollmentCertificate[i];
      const auto found = identity_data.nvram_quotes().find(quote_type);
      if (found != identity_data.nvram_quotes().cend()) {
        (*request_pb.mutable_nvram_quotes())[quote_type] = found->second;
      } else {
        not_in_identity.insert(quote_type);
      }
    }
    // Data that is supposed to be in the identiy but is missing won't be
    // quoted now, as we want to drive everything from the identity.
    for (int i = 0; i < base::size(kNvramQuoteTypeInIdentityData); ++i) {
      const auto quote_type = kNvramQuoteTypeInIdentityData[i];
      if (not_in_identity.erase(quote_type)) {
        LOG(WARNING)
            << "Could not find "
            << kNvramIndexData[nvram_quote_type_to_index_data_[quote_type]]
                   .quote_name
            << " quote in identity " << identity
            << " to provide in enrollment cert request.";
      }
    }
    // Quote the other data now.
    for (auto it = not_in_identity.cbegin(), end = not_in_identity.cend();
         it != end; ++it) {
      Quote quote;
      if (QuoteNvramData(*it, identity_data.identity_key(), &quote)) {
        (*request_pb.mutable_nvram_quotes())[*it] = quote;
      } else {
        LOG(WARNING)
            << "Could not provide "
            << kNvramIndexData[nvram_quote_type_to_index_data_[*it]].quote_name
            << " quote in enrollment cert request.";
      }
    }
  }

#endif

  if (!origin.empty() &&
      (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
    request_pb.set_origin(origin);
    request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
  }
  request_pb.set_certified_public_key(key.public_key_tpm_format());
  request_pb.set_certified_key_info(key.certified_key_info());
  request_pb.set_certified_key_proof(key.certified_key_proof());
  if (!request_pb.SerializeToString(certificate_request)) {
    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    return false;
  }
  return true;
}

bool AttestationService::FinishCertificateRequestInternal(
    const std::string& certificate_response,
    const std::string& username,
    const std::string& key_label,
    const std::string& message_id,
    CertifiedKey* key,
    std::string* certificate_chain,
    std::string* server_error) {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  AttestationCertificateResponse response_pb;
  if (!response_pb.ParseFromString(certificate_response)) {
    LOG(ERROR) << __func__ << ": Failed to parse response from Attestation CA.";
    return false;
  }
  if (response_pb.status() != OK) {
    *server_error = response_pb.detail();
    LogErrorFromCA(__func__, response_pb.detail(), response_pb.extra_details());
    return false;
  }
  if (message_id != response_pb.message_id()) {
    LOG(ERROR) << __func__ << ": Message ID mismatch.";
    return false;
  }
  return PopulateAndStoreCertifiedKey(response_pb, username, key_label, key,
                                      certificate_chain);
}

bool AttestationService::PopulateAndStoreCertifiedKey(
    const AttestationCertificateResponse& response_pb,
    const std::string& username,
    const std::string& key_label,
    CertifiedKey* key,
    std::string* certificate_chain) {
  // Finish populating the CertifiedKey protobuf and store it.
  key->set_key_name(key_label);
  key->set_certified_key_credential(response_pb.certified_key_credential());
  key->set_intermediate_ca_cert(response_pb.intermediate_ca_cert());
  key->mutable_additional_intermediate_ca_cert()->MergeFrom(
      response_pb.additional_intermediate_ca_cert());
  if (!SaveKey(username, key_label, *key)) {
    return false;
  }
  LOG(INFO) << "Attestation: Certified key credential received and stored.";
  *certificate_chain = CreatePEMCertificateChain(*key);
  return true;
}

bool AttestationService::FindKeyByLabel(const std::string& username,
                                        const std::string& key_label,
                                        CertifiedKey* key) {
  if (!username.empty()) {
    std::string key_data;
    if (!key_store_->Read(username, key_label, &key_data)) {
      LOG(INFO) << "Key not found: " << key_label;
      return false;
    }
    if (key && !key->ParseFromString(key_data)) {
      LOG(ERROR) << "Failed to parse key: " << key_label;
      return false;
    }
    return true;
  }
  auto database_pb = database_->GetProtobuf();
  for (int i = 0; i < database_pb.device_keys_size(); ++i) {
    if (database_pb.device_keys(i).key_name() == key_label) {
      *key = database_pb.device_keys(i);
      return true;
    }
  }
  LOG(INFO) << "Key not found: " << key_label;
  return false;
}

bool AttestationService::CreateKey(const std::string& username,
                                   const std::string& key_label,
                                   KeyType key_type,
                                   KeyUsage key_usage,
                                   CertifiedKey* key) {
  auto database_pb = database_->GetProtobuf();
  const int identity = kFirstIdentity;
  if (database_pb.identities().size() <= identity) {
    LOG(ERROR) << __func__ << ": Cannot create a certificate request, identity "
               << identity << " does not exist.";
    return false;
  }

  std::string nonce;
  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
    return false;
  }
  std::string key_blob;
  std::string public_key;
  std::string public_key_tpm_format;
  std::string key_info;
  std::string proof;
  const auto& identity_data = database_pb.identities().Get(identity);
  if (!tpm_utility_->CreateCertifiedKey(
          key_type, key_usage, identity_data.identity_key().identity_key_blob(),
          nonce, &key_blob, &public_key, &public_key_tpm_format, &key_info,
          &proof)) {
    return false;
  }
  key->set_key_blob(key_blob);
  key->set_public_key(public_key);
  key->set_key_name(key_label);
  key->set_public_key_tpm_format(public_key_tpm_format);
  key->set_certified_key_info(key_info);
  key->set_certified_key_proof(proof);
  key->set_key_type(key_type);
  key->set_key_usage(key_usage);
  return SaveKey(username, key_label, *key);
}

bool AttestationService::SaveKey(const std::string& username,
                                 const std::string& key_label,
                                 const CertifiedKey& key) {
  if (!username.empty()) {
    std::string key_data;
    if (!key.SerializeToString(&key_data)) {
      LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
      return false;
    }
    if (!key_store_->Write(username, key_label, key_data)) {
      LOG(ERROR) << __func__ << ": Failed to store certified key for user.";
      return false;
    }
  } else {
    if (!AddDeviceKey(key_label, key)) {
      LOG(ERROR) << __func__ << ": Failed to store certified key for device.";
      return false;
    }
  }
  return true;
}

bool AttestationService::DeleteKey(const std::string& username,
                                   const std::string& key_label) {
  if (!username.empty()) {
    return key_store_->Delete(username, key_label);
  } else {
    return RemoveDeviceKey(key_label);
  }
}

bool AttestationService::DeleteKeysByPrefix(const std::string& username,
                                            const std::string& key_prefix) {
  if (!username.empty()) {
    return key_store_->DeleteByPrefix(username, key_prefix);
  }
  return RemoveDeviceKeysByPrefix(key_prefix);
}

bool AttestationService::AddDeviceKey(const std::string& key_label,
                                      const CertifiedKey& key) {
  // If a key by this name already exists, reuse the field.
  auto* database_pb = database_->GetMutableProtobuf();
  bool found = false;
  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
    if (database_pb->device_keys(i).key_name() == key_label) {
      found = true;
      *database_pb->mutable_device_keys(i) = key;
      break;
    }
  }
  if (!found)
    *database_pb->add_device_keys() = key;
  return database_->SaveChanges();
}

bool AttestationService::RemoveDeviceKey(const std::string& key_label) {
  auto* database_pb = database_->GetMutableProtobuf();
  bool found = false;
  for (int i = 0; i < database_pb->device_keys_size(); ++i) {
    if (database_pb->device_keys(i).key_name() == key_label) {
      found = true;
      int last = database_pb->device_keys_size() - 1;
      if (i < last) {
        database_pb->mutable_device_keys()->SwapElements(i, last);
      }
      database_pb->mutable_device_keys()->RemoveLast();
      break;
    }
  }
  if (found) {
    if (!database_->SaveChanges()) {
      LOG(WARNING) << __func__ << ": Failed to persist key deletion.";
      return false;
    }
  }
  return true;
}

bool AttestationService::RemoveDeviceKeysByPrefix(
    const std::string& key_prefix) {
  // Manipulate the device keys protobuf field.  Linear time strategy is to swap
  // all elements we want to keep to the front and then truncate.
  auto* device_keys = database_->GetMutableProtobuf()->mutable_device_keys();
  int next_keep_index = 0;
  for (int i = 0; i < device_keys->size(); ++i) {
    if (device_keys->Get(i).key_name().find(key_prefix) != 0) {
      // Prefix doesn't match -> keep.
      if (i != next_keep_index)
        device_keys->SwapElements(next_keep_index, i);
      ++next_keep_index;
    }
  }
  // If no matching keys, do nothing and return success.
  if (next_keep_index == device_keys->size()) {
    return true;
  }
  while (next_keep_index < device_keys->size()) {
    device_keys->RemoveLast();
  }
  return database_->SaveChanges();
}

std::string AttestationService::CreatePEMCertificateChain(
    const CertifiedKey& key) {
  if (key.certified_key_credential().empty()) {
    LOG(WARNING) << "Certificate is empty.";
    return std::string();
  }
  std::string pem = CreatePEMCertificate(key.certified_key_credential());
  if (!key.intermediate_ca_cert().empty()) {
    pem += "\n";
    pem += CreatePEMCertificate(key.intermediate_ca_cert());
  }
  for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
    pem += "\n";
    pem += CreatePEMCertificate(key.additional_intermediate_ca_cert(i));
  }
  return pem;
}

std::string AttestationService::CreatePEMCertificate(
    const std::string& certificate) {
  const char kBeginCertificate[] = "-----BEGIN CERTIFICATE-----\n";
  const char kEndCertificate[] = "-----END CERTIFICATE-----";

  std::string pem = kBeginCertificate;
  pem += brillo::data_encoding::Base64EncodeWrapLines(certificate);
  pem += kEndCertificate;
  return pem;
}

int AttestationService::ChooseTemporalIndex(const std::string& user,
                                            const std::string& origin) {
  std::string user_hash = crypto::SHA256HashString(user);
  std::string origin_hash = crypto::SHA256HashString(origin);
  int histogram[kNumTemporalValues] = {};
  auto database_pb = database_->GetProtobuf();
  for (int i = 0; i < database_pb.temporal_index_record_size(); ++i) {
    const AttestationDatabase::TemporalIndexRecord& record =
        database_pb.temporal_index_record(i);
    // Ignore out-of-range index values.
    if (record.temporal_index() < 0 ||
        record.temporal_index() >= kNumTemporalValues)
      continue;
    if (record.origin_hash() == origin_hash) {
      if (record.user_hash() == user_hash) {
        // We've previously chosen this index for this user, reuse it.
        return record.temporal_index();
      } else {
        // We've previously chosen this index for another user.
        ++histogram[record.temporal_index()];
      }
    }
  }
  int least_used_index = 0;
  for (int i = 1; i < kNumTemporalValues; ++i) {
    if (histogram[i] < histogram[least_used_index])
      least_used_index = i;
  }
  if (histogram[least_used_index] > 0) {
    LOG(WARNING) << "Unique origin-specific identifiers have been exhausted.";
  }
  // Record our choice for later reference.
  AttestationDatabase::TemporalIndexRecord* new_record =
      database_pb.add_temporal_index_record();
  new_record->set_origin_hash(origin_hash);
  new_record->set_user_hash(user_hash);
  new_record->set_temporal_index(least_used_index);
  if (!database_->SaveChanges()) {
    LOG(ERROR) << "Failed to save attestation db when choosing temporal index";
    // TODO(louiscollard): Check if any further actions are necessary.
  }
  return least_used_index;
}

bool AttestationService::GetSubjectPublicKeyInfo(
    KeyType key_type,
    const std::string& public_key,
    std::string* public_key_info) const {
  if (key_type == KEY_TYPE_RSA) {
    return crypto_utility_->GetRSASubjectPublicKeyInfo(public_key,
                                                       public_key_info);
  } else if (key_type == KEY_TYPE_ECC) {
    // Do nothing, since we always store SubjectPublicKeyInfo in |public_key|
    // field and will pass it this utility
    *public_key_info = public_key;
    return true;
  } else {
    LOG(ERROR) << __func__ << ": key_type " << key_type << " isn't supported.";
    return false;
  }
}

void AttestationService::PrepareForEnrollment(
    InitializeCompleteCallback callback) {
  if (IsPreparedForEnrollment()) {
    std::move(callback).Run(true);
    return;
  }
  if (!tpm_utility_->IsTpmReady()) {
    // Try again later.
    worker_thread_->task_runner()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&AttestationService::PrepareForEnrollment,
                       base::Unretained(this), std::move(callback)),
        base::TimeDelta::FromSeconds(3));
    return;
  }
  base::TimeTicks start = base::TimeTicks::Now();
  LOG(INFO) << "Attestation: Preparing for enrollment...";

  if (!tpm_utility_->IsPCR0Valid()) {
    LOG(ERROR) << __func__ << "Invalid PCR0 value, aborting.";
    metrics_.ReportAttestationOpsStatus(
        kAttestationPrepareForEnrollment,
        AttestationOpsStatus::kInvalidPcr0Value);
    return;
  }

  KeyType key_type = GetEndorsementKeyType();

  // Gather information about the endorsement key.
  std::string ek_public_key;
  if (!tpm_utility_->GetEndorsementPublicKey(key_type, &ek_public_key)) {
    LOG(ERROR) << __func__ << ": Failed to get EK public key with key_type "
               << key_type;
    std::move(callback).Run(false);
    return;
  }
  LOG(INFO) << "GetEndorsementPublicKey done. (from start: "
            << (base::TimeTicks::Now() - start).InMilliseconds() << "ms.)";

  std::string ek_certificate;
  if (!tpm_utility_->GetEndorsementCertificate(key_type, &ek_certificate)) {
    LOG(ERROR) << __func__ << ": Failed to get " << GetKeyTypeName(key_type)
               << " EK certificate.";
    std::move(callback).Run(false);
    return;
  }
  LOG(INFO) << "GetEndorsementCertificate done. (from start: "
            << (base::TimeTicks::Now() - start).InMilliseconds() << "ms.)";

  // Create a new AIK and PCR quotes for the first identity with default
  // identity features.
  if (CreateIdentity(default_identity_features_) < 0) {
    std::move(callback).Run(false);
    return;
  }
  LOG(INFO) << "CreateIdentity done. (from start: "
            << (base::TimeTicks::Now() - start).InMilliseconds() << "ms.)";

  // Store all this in the attestation database.
  auto* database_pb = database_->GetMutableProtobuf();
  TPMCredentials* credentials_pb = database_pb->mutable_credentials();
  credentials_pb->set_endorsement_key_type(key_type);
  credentials_pb->set_endorsement_public_key(ek_public_key);
  credentials_pb->set_endorsement_credential(ek_certificate);

  // Encrypt the endorsement credential for all the ACAs we know of.
  EncryptAllEndorsementCredentials();

  if (!database_->SaveChanges()) {
    LOG(ERROR) << "Attestation: Failed to write database.";
    std::move(callback).Run(false);
    return;
  }

  // Ignore errors when removing dependency. If failed this time, will be
  // re-attempted on next boot.
  tpm_utility_->RemoveOwnerDependency();

  base::TimeDelta delta = (base::TimeTicks::Now() - start);
  LOG(INFO) << "Attestation: Prepared successfully (" << delta.InMilliseconds()
            << "ms) with " << GetKeyTypeName(key_type) << " EK.";
  metrics_.ReportAttestationOpsStatus(kAttestationPrepareForEnrollment,
                                      AttestationOpsStatus::kSuccess);
  std::move(callback).Run(true);
}

int AttestationService::CreateIdentity(int identity_features) {
  // The identity we're creating will have the next index in identities.
  auto* database_pb = database_->GetMutableProtobuf();
  const int identity = database_pb->identities().size();
  KeyType identity_key_type = GetAttestationIdentityKeyType();
  LOG(INFO) << "Attestation: Creating identity " << identity << " with "
            << GetIdentityFeaturesString(identity_features) << " and "
            << GetKeyTypeName(identity_key_type) << " AIK.";
  AttestationDatabase::Identity new_identity_pb;

  new_identity_pb.set_features(identity_features);
  if (identity_features & IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID) {
    auto* identity_key = new_identity_pb.mutable_identity_key();
    identity_key->set_enrollment_id(database_pb->enrollment_id());
  }
  if (!tpm_utility_->CreateIdentity(identity_key_type, &new_identity_pb)) {
    LOG(ERROR) << __func__ << " failed to make a new identity.";
    return -1;
  }
  std::string identity_key_blob_for_quote =
      new_identity_pb.identity_key().identity_key_blob();

  // Quote PCRs and store them in the identity. These quotes are intended to
  // be valid for the lifetime of the identity key so they do not need
  // external data. This only works when firmware ensures that these PCRs
  // will not change unless the TPM owner is cleared.
  auto* pcr_quote_map = new_identity_pb.mutable_pcr_quotes();

  for (int pcr = 0; pcr <= kLastPcrToQuote; ++pcr) {
    std::string quoted_pcr_value;
    std::string quoted_data;
    std::string quote;
    if (tpm_utility_->QuotePCR(pcr, identity_key_blob_for_quote,
                               &quoted_pcr_value, &quoted_data, &quote)) {
      Quote quote_pb;
      quote_pb.set_quote(quote);
      quote_pb.set_quoted_data(quoted_data);
      quote_pb.set_quoted_pcr_value(quoted_pcr_value);
      switch (pcr) {
        case 1:
          quote_pb.set_pcr_source_hint(hwid_);
          break;
      }
      auto in = pcr_quote_map->insert(QuoteMap::value_type(pcr, quote_pb));
      if (!in.second) {
        LOG(ERROR) << "Attestation: Failed to store PCR" << pcr
                   << " quote for identity " << identity << ".";
        return -1;
      }
    } else {
      LOG(ERROR) << "Attestation: Failed to generate quote for PCR" << pcr
                 << ".";
      return -1;
    }
  }

#if USE_TPM2

  // Certify device-specific NV data and insert them in the identity when
  // we can certify them. This is an almost identical process to the PCR
  // quotes above.

  for (int i = 0; i < base::size(kNvramQuoteTypeInIdentityData); ++i) {
    if (!InsertCertifiedNvramData(kNvramQuoteTypeInIdentityData[i],
                                  false /* must_be_present */,
                                  &new_identity_pb)) {
      return -1;
    }
  }

  // Certify the RSA EK cert only when we are using non-RSA EK. In this case, we
  // don't provide the RSA EK cert which originally is used for calculating the
  // Enrollment ID.
  if ((identity_features & IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID) &&
      GetEndorsementKeyType() != KEY_TYPE_RSA) {
    if (!InsertCertifiedNvramData(RSA_PUB_EK_CERT, true /* must_be_present */,
                                  &new_identity_pb)) {
      return -1;
    }
  }

#endif
  database_pb->add_identities()->CopyFrom(new_identity_pb);
  // Return the index of the newly created identity.
  return database_pb->identities().size() - 1;
}

bool AttestationService::QuoteNvramData(NVRAMQuoteType quote_type,
                                        const IdentityKey& identity_key,
                                        Quote* quote) {
#if USE_TPM2
  const int id = nvram_quote_type_to_index_data_[quote_type];
  const char* quote_name = kNvramIndexData[id].quote_name;
  const uint32_t nv_index = kNvramIndexData[id].nv_index;
  uint16_t nv_size = kNvramIndexData[id].nv_size;

  if (!nv_size) {
    uint16_t nv_data_size = 0;
    if (tpm_utility_->GetNVDataSize(nv_index, &nv_data_size)) {
      nv_size = nv_data_size;
    } else {
      LOG(ERROR) << "Attestation: Failed to obtain data about the "
                 << quote_name << ".";
    }
  }

  if (nv_size) {
    auto identity_key_blob = identity_key.identity_key_blob();
    std::string certified_value;
    std::string signature;

    if (tpm_utility_->CertifyNV(nv_index, nv_size, identity_key_blob,
                                &certified_value, &signature)) {
      quote->set_quote(signature);
      quote->set_quoted_data(certified_value);
      return true;
    } else {
      LOG(WARNING) << "Attestation: Failed to certify " << quote_name
                   << " NV data of size " << nv_size << " at index " << std::hex
                   << std::showbase << nv_index << ".";
    }
  }
#else
  LOG(ERROR) << __func__ << ": Should not be called for TPM 1.2 devices.";
#endif

  return false;
}

bool AttestationService::InsertCertifiedNvramData(
    NVRAMQuoteType quote_type,
    bool must_be_present,
    AttestationDatabase::Identity* identity) {
#if USE_TPM2
  Quote quote;
  if (!QuoteNvramData(quote_type, identity->identity_key(), &quote)) {
    return !must_be_present;
  }

  auto* nv_quote_map = identity->mutable_nvram_quotes();
  auto in_bid = nv_quote_map->insert(QuoteMap::value_type(quote_type, quote));
  if (in_bid.second) {
    return true;
  } else {
    LOG(ERROR) << "Attestation: Failed to store "
               << kNvramIndexData[nvram_quote_type_to_index_data_[quote_type]]
                      .quote_name
               << " quote for identity " << identity << ".";
  }
#else
  LOG(ERROR) << __func__ << ": Should not be called for TPM 1.2 devices.";
#endif

  return false;
}

int AttestationService::GetIdentitiesCount() const {
  return database_->GetProtobuf().identities().size();
}

int AttestationService::GetIdentityFeatures(int identity) const {
  return database_->GetProtobuf().identities().Get(identity).features();
}

AttestationService::IdentityCertificateMap
AttestationService::GetIdentityCertificateMap() const {
  return database_->GetProtobuf().identity_certificates();
}

bool AttestationService::EncryptAllEndorsementCredentials() {
  auto* database_pb = database_->GetMutableProtobuf();
  base::Optional<std::string> ek_certificate = GetEndorsementCertificate();
  if (!ek_certificate.has_value()) {
    LOG(ERROR) << "Attestation: Failed to obtain endorsement certificate.";
    return false;
  }

  TPMCredentials* credentials_pb = database_pb->mutable_credentials();
  for (int aca = kDefaultACA; aca < kMaxACATypeInternal; ++aca) {
    if (credentials_pb->encrypted_endorsement_credentials().count(aca)) {
      continue;
    }
    ACAType aca_type = GetACAType(static_cast<ACATypeInternal>(aca));
    LOG(INFO) << "Attestation: Encrypting endorsement credential for "
              << GetACAName(aca_type) << ".";
    if (!EncryptDataForAttestationCA(
            aca_type, ek_certificate.value(),
            &(*credentials_pb
                   ->mutable_encrypted_endorsement_credentials())[aca])) {
      LOG(ERROR) << "Attestation: Failed to encrypt EK certificate for "
                 << GetACAName(static_cast<ACAType>(aca)) << ".";
      return false;
    }
  }
  return true;
}

bool AttestationService::EncryptDataForAttestationCA(
    ACAType aca_type, const std::string& data, EncryptedData* encrypted_data) {
  const GoogleRsaPublicKey& key = google_keys_.ca_encryption_key(aca_type);
  if (!crypto_utility_->EncryptDataForGoogle(data, key.modulus_in_hex(),
                                             key.key_id(), encrypted_data)) {
    return false;
  }
  return true;
}

bool AttestationService::ActivateAttestationKeyInternal(
    int identity,
    ACAType aca_type,
    KeyType ek_key_type,
    const EncryptedIdentityCredential& encrypted_certificate,
    bool save_certificate,
    std::string* certificate,
    int* certificate_index) {
  const auto& database_pb = database_->GetProtobuf();
  if (database_pb.identities().size() <= identity) {
    LOG(ERROR) << __func__ << ": Enrollment is not possible, identity "
               << identity << " does not exist.";
    return false;
  }
  const auto& identity_data = database_pb.identities().Get(identity);
  std::string certificate_local;
  if (encrypted_certificate.tpm_version() == TPM_1_2) {
    // TPM 1.2 style activate.
    if (!tpm_utility_->ActivateIdentity(
            identity_data.identity_key().identity_key_blob(),
            encrypted_certificate.asym_ca_contents(),
            encrypted_certificate.sym_ca_attestation(), &certificate_local)) {
      LOG(ERROR) << __func__ << ": Failed to activate identity " << identity
                 << ".";
      return false;
    }
  } else {
    // TPM 2.0 style activate.
    std::string credential;
    if (!tpm_utility_->ActivateIdentityForTpm2(
            ek_key_type, identity_data.identity_key().identity_key_blob(),
            encrypted_certificate.encrypted_seed(),
            encrypted_certificate.credential_mac(),
            encrypted_certificate.wrapped_certificate().wrapped_key(),
            &credential)) {
      LOG(ERROR) << __func__ << ": Failed to activate identity " << identity
                 << ".";
      return false;
    }
    if (!crypto_utility_->DecryptIdentityCertificateForTpm2(
            credential, encrypted_certificate.wrapped_certificate(),
            &certificate_local)) {
      LOG(ERROR) << __func__ << ": Failed to decrypt certificate for identity "
                 << identity << ".";
      return false;
    }
  }
  if (save_certificate) {
    if (!tpm_utility_->IsPCR0Valid()) {
      LOG(ERROR) << __func__ << "Invalid PCR0 value, aborting.";
      metrics_.ReportAttestationOpsStatus(
          kAttestationActivateAttestationKey,
          AttestationOpsStatus::kInvalidPcr0Value);
      return false;
    }

    int index;
    AttestationDatabase_IdentityCertificate* identity_certificate =
        FindOrCreateIdentityCertificate(identity, aca_type, &index);
    if (!identity_certificate) {
      LOG(ERROR) << __func__ << ": Failed to find or create an identity"
                 << " certificate for identity " << identity << " with "
                 << GetACAName(aca_type) << ".";
      return false;
    }
    // Set the credential obtained when activating the identity with the
    // response.
    identity_certificate->set_identity_credential(certificate_local);
    if (!database_->SaveChanges()) {
      LOG(ERROR) << __func__ << ": Failed to persist database changes.";
      return false;
    }
    if (certificate_index) {
      *certificate_index = index;
    }
  }
  if (certificate) {
    *certificate = certificate_local;
  }
  return true;
}

void AttestationService::GetEnrollmentPreparations(
    const GetEnrollmentPreparationsRequest& request,
    const GetEnrollmentPreparationsCallback& callback) {
  auto result = std::make_shared<GetEnrollmentPreparationsReply>();
  base::Closure task =
      base::Bind(&AttestationService::GetEnrollmentPreparationsTask,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<GetEnrollmentPreparationsReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::GetEnrollmentPreparationsTask(
    const GetEnrollmentPreparationsRequest& request,
    const std::shared_ptr<GetEnrollmentPreparationsReply>& result) {
  for (int aca = kDefaultACA; aca < kMaxACATypeInternal; ++aca) {
    ACAType aca_type = GetACAType(static_cast<ACATypeInternal>(aca));
    if (!request.has_aca_type() || aca_type == request.aca_type()) {
      (*result->mutable_enrollment_preparations())[aca_type] =
          IsPreparedForEnrollmentWithACA(aca_type);
    }
  }
}

void AttestationService::GetStatus(const GetStatusRequest& request,
                                   const GetStatusCallback& callback) {
  auto result = std::make_shared<GetStatusReply>();
  base::Closure task = base::Bind(&AttestationService::GetStatusTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<GetStatusReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

bool AttestationService::IsVerifiedMode() const {
  if (!tpm_utility_->IsTpmReady()) {
    VLOG(2) << __func__ << ": Tpm is not ready.";
    return false;
  }
  std::string pcr_value;
  if (!tpm_utility_->ReadPCR(0, &pcr_value)) {
    LOG(WARNING) << __func__ << ": Failed to read PCR0.";
    return false;
  }
  return (pcr_value == GetPCRValueForMode(kVerifiedBootMode));
}

void AttestationService::GetStatusTask(
    const GetStatusRequest& request,
    const std::shared_ptr<GetStatusReply>& result) {
  result->set_prepared_for_enrollment(IsPreparedForEnrollment());
  result->set_enrolled(IsEnrolled());
  for (int i = 0, count = GetIdentitiesCount(); i < count; ++i) {
    GetStatusReply::Identity* identity = result->mutable_identities()->Add();
    identity->set_features(GetIdentityFeatures(i));
  }
  AttestationService::IdentityCertificateMap map = GetIdentityCertificateMap();
  for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) {
    GetStatusReply::IdentityCertificate identity_certificate;
    identity_certificate.set_identity(it->second.identity());
    identity_certificate.set_aca(it->second.aca());
    result->mutable_identity_certificates()->insert(
        google::protobuf::Map<int, GetStatusReply::IdentityCertificate>::
            value_type(it->first, identity_certificate));
  }
  for (int aca = kDefaultACA; aca < kMaxACATypeInternal; ++aca) {
    ACAType aca_type = GetACAType(static_cast<ACATypeInternal>(aca));
    (*result->mutable_enrollment_preparations())[aca_type] =
        IsPreparedForEnrollmentWithACA(aca_type);
  }
  if (request.extended_status()) {
    result->set_verified_boot(IsVerifiedMode());
  }
}

void AttestationService::Verify(const VerifyRequest& request,
                                const VerifyCallback& callback) {
  auto result = std::make_shared<VerifyReply>();
  base::Closure task = base::Bind(&AttestationService::VerifyTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<VerifyReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

bool AttestationService::VerifyIdentityBinding(const IdentityBinding& binding) {
  if (tpm_utility_->GetVersion() == TPM_1_2) {
    // Reconstruct and hash a serialized TPM_IDENTITY_CONTENTS structure.
    const std::string header("\x01\x01\x00\x00\x00\x00\x00\x79", 8);
    std::string digest = base::SHA1HashString(binding.identity_label() +
                                              binding.pca_public_key());
    std::string identity_public_key_info;
    if (!GetSubjectPublicKeyInfo(KEY_TYPE_RSA,
                                 binding.identity_public_key_der(),
                                 &identity_public_key_info)) {
      LOG(ERROR) << __func__ << ": Failed to get identity public key info.";
      return false;
    }
    if (!crypto_utility_->VerifySignature(
            crypto_utility_->DefaultDigestAlgoForSignature(),
            identity_public_key_info,
            header + digest + binding.identity_public_key_tpm_format(),
            binding.identity_binding())) {
      LOG(ERROR) << __func__
                 << ": Failed to verify identity binding signature.";
      return false;
    }
  } else if (tpm_utility_->GetVersion() == TPM_2_0) {
    VLOG(1) << __func__ << ": Nothing to do for TPM 2.0.";
  } else {
    LOG(ERROR) << __func__ << ": Unsupported TPM version.";
    return false;
  }
  return true;
}

bool AttestationService::VerifyQuoteSignature(
    const std::string& aik_public_key_info,
    const Quote& quote,
    uint32_t pcr_index) {
  if (!crypto_utility_->VerifySignature(
          crypto_utility_->DefaultDigestAlgoForSignature(), aik_public_key_info,
          quote.quoted_data(), quote.quote())) {
    LOG(ERROR) << __func__ << ": Signature mismatch.";
    return false;
  }
  if (!tpm_utility_->IsQuoteForPCR(quote.quoted_pcr_value(),
                                   quote.quoted_data(), quote.quote(),
                                   pcr_index)) {
    LOG(ERROR) << __func__ << ": Invalid quote.";
    return false;
  }
  return true;
}

std::string AttestationService::GetPCRValueForMode(const char* mode) const {
  std::string mode_str(mode, 3);
  std::string mode_digest = base::SHA1HashString(mode_str);
  std::string pcr_value;
  if (tpm_utility_->GetVersion() == TPM_1_2) {
    // Use SHA-1 digests for TPM 1.2.
    std::string initial(base::kSHA1Length, 0);
    pcr_value = base::SHA1HashString(initial + mode_digest);
  } else if (tpm_utility_->GetVersion() == TPM_2_0) {
    // Use SHA-256 digests for TPM 2.0.
    std::string initial(crypto::kSHA256Length, 0);
    mode_digest.resize(crypto::kSHA256Length);
    pcr_value = crypto::SHA256HashString(initial + mode_digest);
  } else {
    LOG(ERROR) << __func__ << ": Unsupported TPM version.";
  }
  return pcr_value;
}

bool AttestationService::VerifyPCR0Quote(const std::string& aik_public_key_info,
                                         const Quote& pcr0_quote) {
  if (!VerifyQuoteSignature(aik_public_key_info, pcr0_quote, 0)) {
    return false;
  }

  // Check if the PCR0 value represents a known mode.
  for (size_t i = 0; i < base::size(kKnownBootModes); ++i) {
    std::string pcr_value = GetPCRValueForMode(kKnownBootModes[i]);
    if (pcr0_quote.quoted_pcr_value() == pcr_value) {
      LOG(INFO) << "PCR0: " << GetDescriptionForMode(kKnownBootModes[i]);
      return true;
    }
  }
  LOG(WARNING) << "PCR0 value not recognized.";
  return true;
}

bool AttestationService::VerifyPCR1Quote(const std::string& aik_public_key_info,
                                         const Quote& pcr1_quote) {
  if (!VerifyQuoteSignature(aik_public_key_info, pcr1_quote, 1)) {
    return false;
  }

  // Check that the source hint is correctly populated.
  if (hwid_ != pcr1_quote.pcr_source_hint()) {
    LOG(ERROR) << "PCR1 source hint does not match HWID: " << hwid_;
    return false;
  }

  LOG(INFO) << "PCR1 verified as " << hwid_;
  return true;
}

bool AttestationService::GetCertifiedKeyDigest(
    const std::string& public_key_info,
    const std::string& public_key_tpm_format,
    std::string* key_digest) {
  if (tpm_utility_->GetVersion() == TPM_1_2) {
    return crypto_utility_->GetKeyDigest(public_key_info, key_digest);
  } else if (tpm_utility_->GetVersion() == TPM_2_0) {
    // TPM_ALG_SHA256 = 0x000B, here in big-endian order.
    std::string prefix("\x00\x0B", 2);
    key_digest->assign(prefix +
                       crypto::SHA256HashString(public_key_tpm_format));
    return true;
  }
  LOG(ERROR) << __func__ << ": Unsupported TPM version.";
  return false;
}

bool AttestationService::VerifyCertifiedKey(
    const std::string& aik_public_key_info,
    const std::string& public_key_info,
    const std::string& public_key_tpm_format,
    const std::string& key_info,
    const std::string& proof) {
  if (!crypto_utility_->VerifySignature(
          crypto_utility_->DefaultDigestAlgoForSignature(), aik_public_key_info,
          key_info, proof)) {
    LOG(ERROR) << __func__ << ": Bad key signature.";
    return false;
  }
  std::string key_digest;
  if (!GetCertifiedKeyDigest(public_key_info, public_key_tpm_format,
                             &key_digest)) {
    LOG(ERROR) << __func__ << ": Failed to get key digest.";
    return false;
  }
  if (key_info.find(key_digest) == std::string::npos) {
    LOG(ERROR) << __func__ << ": Public key mismatch.";
    return false;
  }
  return true;
}

bool AttestationService::VerifyCertifiedKeyGeneration(
    const std::string& aik_key_blob, const std::string& aik_public_key_info) {
  std::string nonce;
  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
    return false;
  }
  std::vector<KeyType> key_type_candidates;
  if (tpm_utility_->GetVersion() == TPM_2_0) {
    key_type_candidates = {KEY_TYPE_RSA, KEY_TYPE_ECC};
  } else {
    key_type_candidates = {KEY_TYPE_RSA};
  }

  for (KeyType key_type : key_type_candidates) {
    std::string key_blob;
    std::string public_key_der;
    std::string public_key_tpm_format;
    std::string key_info;
    std::string proof;
    if (!tpm_utility_->CreateCertifiedKey(
            key_type, KEY_USAGE_SIGN, aik_key_blob, nonce, &key_blob,
            &public_key_der, &public_key_tpm_format, &key_info, &proof)) {
      LOG(ERROR) << __func__
                 << ": Failed to create certified key for key_type: "
                 << key_type;
      return false;
    }
    std::string public_key_info;
    if (!GetSubjectPublicKeyInfo(key_type, public_key_der, &public_key_info)) {
      LOG(ERROR) << __func__ << ": Failed to get public key info for key_type: "
                 << key_type;
      return false;
    }
    if (!VerifyCertifiedKey(aik_public_key_info, public_key_info,
                            public_key_tpm_format, key_info, proof)) {
      LOG(ERROR) << __func__
                 << ": Bad certified key for key_type: " << key_type;
      return false;
    }
  }
  return true;
}

bool AttestationService::VerifyActivateIdentity(
    const std::string& aik_public_key_tpm_format) {
  std::string rsa_ek_public_key;
  if (!tpm_utility_->GetEndorsementPublicKey(KEY_TYPE_RSA,
                                             &rsa_ek_public_key)) {
    LOG(ERROR) << __func__
               << ": Can't get RSA EK public key for VerifyActivateIdentity.";
    return false;
  }
  std::string test_credential = "test credential";
  EncryptedIdentityCredential encrypted_credential;
  if (!crypto_utility_->EncryptIdentityCredential(
          tpm_utility_->GetVersion(), test_credential, rsa_ek_public_key,
          aik_public_key_tpm_format, &encrypted_credential)) {
    LOG(ERROR) << __func__ << ": Failed to encrypt identity credential";
    return false;
  }
  if (!ActivateAttestationKeyInternal(kFirstIdentity, DEFAULT_ACA, KEY_TYPE_RSA,
                                      encrypted_credential, false, nullptr,
                                      nullptr)) {
    LOG(ERROR) << __func__ << ": Failed to activate identity";
    return false;
  }
  return true;
}

void AttestationService::VerifyTask(
    const VerifyRequest& request, const std::shared_ptr<VerifyReply>& result) {
  result->set_verified(false);

  base::Optional<std::string> ek_public_key = GetEndorsementPublicKey();
  if (!ek_public_key.has_value()) {
    LOG(ERROR) << __func__ << ": Endorsement key not available.";
    return;
  }

  base::Optional<std::string> ek_cert = GetEndorsementCertificate();
  if (!ek_cert.has_value()) {
    LOG(ERROR) << __func__ << ": Endorsement cert not available.";
    return;
  }

  std::string issuer;
  if (!crypto_utility_->GetCertificateIssuerName(ek_cert.value(), &issuer)) {
    LOG(ERROR) << __func__ << ": Failed to get certificate issuer.";
    return;
  }
  std::string ca_public_key;
  if (!GetAuthorityPublicKey(issuer, request.cros_core(), &ca_public_key)) {
    LOG(ERROR) << __func__ << ": Failed to get CA public key.";
    return;
  }
  if (!crypto_utility_->VerifyCertificate(ek_cert.value(), ca_public_key)) {
    LOG(WARNING) << __func__ << ": Bad endorsement credential.";
    return;
  }

  // Verifies that the given public key matches the one in the credential.

  // Gets the public key by GetCertificatePublicKey and
  // GetCertificateSubjectPublicKeyInfo for TPM1.2 and TPM2.0 respectively.
  // TODO(crbug/942487): Only use GetCertificateSubjectPublicKeyInfo after the
  // bug is resolved.
  std::string cert_public_key_info;
  switch (tpm_utility_->GetVersion()) {
    case TPM_1_2:
      if (!crypto_utility_->GetCertificatePublicKey(ek_cert.value(),
                                                    &cert_public_key_info)) {
        LOG(ERROR) << __func__ << ": Failed to call GetCertificatePublicKey.";
        return;
      }
      break;
    case TPM_2_0:
      if (!crypto_utility_->GetCertificateSubjectPublicKeyInfo(
              ek_cert.value(), &cert_public_key_info)) {
        LOG(ERROR) << __func__
                   << ": Failed to call GetCertificateSubjectPublicKeyInfo.";
        return;
      }
      break;
    default:
      NOTREACHED() << "Unexpected TPM version.";
  }

  // Note: Do not use any openssl functions that attempt to decode the public
  // key. These will fail because openssl does not recognize the OAEP key type,
  // which could happen for some TPM1.2 chips.
  if (cert_public_key_info != ek_public_key.value()) {
    LOG(ERROR) << __func__ << ": Bad certificate public key.";
    return;
  }

  // All done if we only needed to verify EK. Otherwise, continue with full
  // verification.
  if (request.ek_only()) {
    result->set_verified(true);
    return;
  }

  auto database_pb = database_->GetProtobuf();
  const auto& identity_data = database_pb.identities().Get(kFirstIdentity);
  std::string identity_public_key_info;
  if (!GetSubjectPublicKeyInfo(
          identity_data.identity_key().identity_key_type(),
          identity_data.identity_key().identity_public_key_der(),
          &identity_public_key_info)) {
    LOG(ERROR) << __func__ << ": Failed to get identity public key info.";
    return;
  }
  if (!VerifyIdentityBinding(identity_data.identity_binding())) {
    LOG(ERROR) << __func__ << ": Bad identity binding.";
    return;
  }
  if (!tpm_utility_->IsPCR0Valid()) {
    LOG(ERROR) << __func__ << ": Bad PCR0 value.";
    metrics_.ReportAttestationOpsStatus(
        kAttestationVerify, AttestationOpsStatus::kInvalidPcr0Value);
  }
  if (!VerifyPCR0Quote(identity_public_key_info,
                       identity_data.pcr_quotes().at(0))) {
    LOG(ERROR) << __func__ << ": Bad PCR0 quote.";
    return;
  }
  if (!VerifyPCR1Quote(identity_public_key_info,
                       identity_data.pcr_quotes().at(1))) {
    // Don't fail because many devices don't use PCR1.
    LOG(WARNING) << __func__ << ": Bad PCR1 quote.";
  }
  if (!VerifyCertifiedKeyGeneration(
          identity_data.identity_key().identity_key_blob(),
          identity_public_key_info)) {
    LOG(ERROR) << __func__ << ": Failed to verify certified key generation.";
    return;
  }

  // Originally, we use VerifyActivateIdentity to test ActivateIdentity TPM
  // command works in TPM 1.2, but we don't really need it for TPM 2.0. Because
  // we have more complete tests in Cr50, we are planning to obsolete the tests
  // in the service daemon. Moreover, supporting this would require simulating
  // the entire attestation flow but pointless. We decide to not to support this
  // test for ECC EK.
  if (!VerifyActivateIdentity(
          identity_data.identity_binding().identity_public_key_tpm_format())) {
    LOG(ERROR) << __func__ << ": Failed to verify identity activation.";
    return;
  }
  LOG(INFO) << "Attestation: Verified OK.";
  result->set_verified(true);
}

void AttestationService::CreateEnrollRequest(
    const CreateEnrollRequestRequest& request,
    const CreateEnrollRequestCallback& callback) {
  auto result = std::make_shared<CreateEnrollRequestReply>();
  base::Closure task = base::Bind(
      &AttestationService::CreateEnrollRequestTask<CreateEnrollRequestRequest>,
      base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<CreateEnrollRequestReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

template <typename RequestType>
void AttestationService::CreateEnrollRequestTask(
    const RequestType& request,
    const std::shared_ptr<CreateEnrollRequestReply>& result) {
  if (!CreateEnrollRequestInternal(request.aca_type(),
                                   result->mutable_pca_request())) {
    result->clear_pca_request();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
  }
}

void AttestationService::FinishEnroll(const FinishEnrollRequest& request,
                                      const FinishEnrollCallback& callback) {
  auto result = std::make_shared<FinishEnrollReply>();
  base::Closure task =
      base::Bind(&AttestationService::FinishEnrollTask<FinishEnrollReply>,
                 base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<FinishEnrollReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

template <typename ReplyType>
void AttestationService::FinishEnrollTask(
    const FinishEnrollRequest& request,
    const std::shared_ptr<ReplyType>& result) {
  std::string server_error;
  if (!FinishEnrollInternal(request.aca_type(), request.pca_response(),
                            &server_error)) {
    if (server_error.empty()) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    } else {
      result->set_status(STATUS_REQUEST_DENIED_BY_CA);
    }
  }
}

void AttestationService::PostStartEnrollTask(
    const std::shared_ptr<AttestationFlowData>& data) {
  base::Closure task = base::Bind(&AttestationService::StartEnrollTask,
                                  base::Unretained(this), data);
  base::Closure reply =
      base::Bind(&AttestationService::OnEnrollAction, GetWeakPtr(), data);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::Enroll(const EnrollRequest& request,
                                const EnrollCallback& callback) {
  PostStartEnrollTask(std::make_shared<AttestationFlowData>(request, callback));
}

void AttestationService::SendEnrollRequest(
    const std::shared_ptr<AttestationFlowData>& data) {
  auto pca_request = ToPcaAgentEnrollRequest(*data);
  auto on_success = base::Bind(&AttestationService::HandlePcaAgentEnrollReply,
                               GetWeakPtr(), data);
  auto on_error =
      base::Bind(&AttestationService::HandlePcaAgentEnrollRequestError,
                 GetWeakPtr(), data);
  pca_agent_proxy_->EnrollAsync(pca_request, on_success, on_error);
}

void AttestationService::HandlePcaAgentEnrollRequestError(
    const std::shared_ptr<AttestationFlowData>& data, brillo::Error*) {
  LOG(ERROR) << __func__ << ": Error sending enroll request to |pca_agent|";
  data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
  enrollment_statuses_[data->aca_type()] = EnrollmentStatus::kNotEnrolled;
  data->set_action(AttestationFlowAction::kAbort);
  OnEnrollAction(data);
}

void AttestationService::OnEnrollAction(
    const std::shared_ptr<AttestationFlowData>& data) {
  VLOG(1) << __func__ << ": action is : " << static_cast<int>(data->action());
  switch (data->action()) {
    default:
    case AttestationFlowAction::kUnknown:
      LOG(DFATAL) << "Unexpected action code: "
                  << static_cast<int>(data->action());
      data->set_status(STATUS_NOT_SUPPORTED);
      data->ReturnStatus();
      return;
    case AttestationFlowAction::kAbort:
      data->ReturnStatus();
      for (const auto& alias : enrollment_queue_.PopAll(data->aca_type())) {
        alias->set_status(data->status());
        alias->ReturnStatus();
      }
      return;
    case AttestationFlowAction::kProcessRequest:
      SendEnrollRequest(data);
      return;
    case AttestationFlowAction::kEnqueue:
      // If in the dbus calling thread the status has changed, re-posts the
      // task.
      if (enrollment_statuses_[data->aca_type()] !=
          EnrollmentStatus::kInProgress) {
        PostStartEnrollTask(data);
      } else {
        if (!enrollment_queue_.Push(data)) {
          data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
          data->ReturnStatus();
        }
      }
      return;
    case AttestationFlowAction::kNoop:
      PostStartCertificateTaskOrReturn(data);
      for (const auto& alias : enrollment_queue_.PopAll(data->aca_type())) {
        PostStartCertificateTaskOrReturn(alias);
      }
      return;
  }
}

void AttestationService::OnGetCertificateAction(
    const std::shared_ptr<AttestationFlowData>& data) {
  VLOG(1) << __func__ << ": action is : " << static_cast<int>(data->action());
  switch (data->action()) {
    default:
    case AttestationFlowAction::kUnknown:
      LOG(DFATAL) << "Unexpected action code: "
                  << static_cast<int>(data->action());
      data->set_status(STATUS_NOT_SUPPORTED);
      data->ReturnStatus();
      return;
    case AttestationFlowAction::kProcessRequest:
      SendGetCertificateRequest(data);
      return;
    case AttestationFlowAction::kEnqueue:
      // If no alias found, re-posts the task. Sadly the task will check the key
      // store again. The good news is, this case should be rare in practice.
      if (!certificate_queue_.HasAnyAlias(data)) {
        // Despite of the callee name, it always posts the task here since we
        // shall get certificate.
        PostStartCertificateTaskOrReturn(data);
      } else {
        // TODO(b/149723745): UMA for respective failure cases.
        CertificateQueue::PushResult result = certificate_queue_.Push(data);
        if (result != CertificateQueue::PushResult::kSuccess) {
          data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
          data->ReturnStatus();
        }
      }
      return;
    case AttestationFlowAction::kAbort:
    case AttestationFlowAction::kNoop:
      ReturnForAllCertificateRequestAliases(data);
      return;
  }
}

void AttestationService::ReturnForAllCertificateRequestAliases(
    const std::shared_ptr<AttestationFlowData>& data) {
  if (data->status() == STATUS_SUCCESS) {
    data->ReturnCertificate();
    std::string certificate = data->certificate();
    for (const auto& alias : certificate_queue_.PopAllAliases(data)) {
      if (data != alias) {
        alias->set_certificate(data->certificate());
        alias->ReturnCertificate();
      }
    }
  } else {
    data->ReturnStatus();
    for (const auto& alias : certificate_queue_.PopAllAliases(data)) {
      if (data != alias) {
        alias->set_status(data->status());
        alias->ReturnStatus();
      }
    }
  }
}

void AttestationService::StartEnrollTask(
    const std::shared_ptr<AttestationFlowData>& data) {
  // When the enrollment is in progress, all the attestation flow entries listen
  // to the same response.
  if (enrollment_statuses_[data->aca_type()] == EnrollmentStatus::kInProgress) {
    data->set_action(AttestationFlowAction::kEnqueue);
    return;
  }
  // This is the place we initialize the enrollment statuses; at this moment
  // there is no write operation in other threads, so we don't bother using
  // compare_and_exchange atomic operation.
  if (enrollment_statuses_[data->aca_type()] == EnrollmentStatus::kUnknown) {
    enrollment_statuses_[data->aca_type()] =
        IsEnrolledWithACA(data->aca_type()) ? EnrollmentStatus::kEnrolled
                                            : EnrollmentStatus::kNotEnrolled;
  }
  // At this point, possible statuses are : kEnrolled and kNotEnrolled.
  const bool is_enrolled =
      enrollment_statuses_[data->aca_type()] == EnrollmentStatus::kEnrolled;
  if (is_enrolled && !data->forced_enrollment()) {
    data->set_action(AttestationFlowAction::kNoop);
    return;
  }
  if (!is_enrolled && !data->shall_enroll()) {
    data->set_action(AttestationFlowAction::kAbort);
    data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  std::string result_request;
  if (!CreateEnrollRequestInternal(data->aca_type(), &result_request)) {
    data->set_action(AttestationFlowAction::kAbort);
    data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  enrollment_statuses_[data->aca_type()] = EnrollmentStatus::kInProgress;
  data->emplace_result_request(std::move(result_request));
  data->set_action(AttestationFlowAction::kProcessRequest);
}

void AttestationService::FinishEnrollTaskV2(
    const std::shared_ptr<AttestationFlowData>& data) {
  std::string server_error;
  if (!FinishEnrollInternal(data->aca_type(), data->result_response(),
                            &server_error)) {
    if (server_error.empty()) {
      data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    } else {
      data->set_status(STATUS_REQUEST_DENIED_BY_CA);
    }
    data->set_action(AttestationFlowAction::kAbort);
    enrollment_statuses_[data->aca_type()] = EnrollmentStatus::kNotEnrolled;
  } else {
    data->set_action(AttestationFlowAction::kNoop);
    enrollment_statuses_[data->aca_type()] = EnrollmentStatus::kEnrolled;
  }
}

void AttestationService::PostStartCertificateTaskOrReturn(
    const std::shared_ptr<AttestationFlowData>& data) {
  if (!data->shall_get_certificate()) {
    data->ReturnStatus();
    return;
  }
  base::Closure task = base::Bind(&AttestationService::StartCertificateTask,
                                  base::Unretained(this), data);
  base::Closure reply = base::Bind(&AttestationService::OnGetCertificateAction,
                                   GetWeakPtr(), data);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::StartCertificateTask(
    const std::shared_ptr<AttestationFlowData>& data) {
  DCHECK(data->shall_get_certificate());

  if (certificate_queue_.HasAnyAlias(data)) {
    data->set_action(AttestationFlowAction::kEnqueue);
    return;
  }

  CertifiedKey key;
  if (!data->forced_get_certificate() &&
      FindKeyByLabel(data->username(), data->key_label(), &key)) {
    std::string public_key_info;
    if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
                                 &public_key_info)) {
      LOG(ERROR) << __func__ << ": Failed to call `GetSubjectPublicKeyInfo()`.";
      data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      data->set_action(AttestationFlowAction::kAbort);
      return;
    }
    data->set_public_key(std::move(public_key_info));
    data->set_certificate(CreatePEMCertificateChain(key));
    data->set_action(AttestationFlowAction::kNoop);
    return;
  }
  // Indirects to the existing logic; by doing this we don't have to worry about
  // changing the current behavior.
  const GetCertificateRequest& request = data->get_certificate_request();
  auto reply = std::make_shared<CreateCertificateRequestReply>();
  CreateCertificateRequestTask(request, reply);
  if (reply->status() != STATUS_SUCCESS) {
    data->set_status(reply->status());
    data->set_action(AttestationFlowAction::kAbort);
    return;
  }
  data->emplace_result_request(std::move(*(reply->mutable_pca_request())));
  data->set_action(AttestationFlowAction::kProcessRequest);
  // Different from the way we handle enrollment, enqueues |data| right here so
  // we can check the existence of aliases to tell if the certification in
  // progress.
  CertificateQueue::PushResult push_result = certificate_queue_.Push(data);
  // the certificate queue is in a broken state since we already ensure
  // |HasAnyAlias| to be |false|; crashes |attestationd| to bring it back to
  // initial state in any case.
  CHECK_EQ(push_result, CertificateQueue::PushResult::kSuccess)
      << "Unexpected error during pushing the first alias to certificate "
         "queue.";
}

void AttestationService::FinishCertificateTask(
    const std::shared_ptr<AttestationFlowData>& data) {
  // Indirects to the existing logic; by doing this we don't have to worry about
  // changing the current behavior.
  FinishCertificateRequestRequest request;
  request.set_pca_response(data->result_response());
  request.set_username(data->username());
  request.set_key_label(data->key_label());
  auto reply = std::make_shared<FinishCertificateRequestReply>();
  FinishCertificateRequestTask(request, reply);
  if (reply->status() != STATUS_SUCCESS) {
    data->set_status(reply->status());
    data->set_action(AttestationFlowAction::kAbort);
    return;
  }
  data->set_public_key(std::move(*(reply->mutable_public_key())));
  data->set_certificate(std::move(*(reply->mutable_certificate())));
  data->set_action(AttestationFlowAction::kNoop);
}

void AttestationService::HandlePcaAgentEnrollReply(
    const std::shared_ptr<AttestationFlowData>& data,
    const pca_agent::EnrollReply& pca_reply) {
  if (pca_reply.status() != STATUS_SUCCESS) {
    enrollment_statuses_[data->aca_type()] = EnrollmentStatus::kNotEnrolled;
    data->set_status(pca_reply.status());
    data->set_action(AttestationFlowAction::kAbort);
    OnEnrollAction(data);
    return;
  }
  data->set_result_response(pca_reply.response());
  base::Closure task = base::Bind(&AttestationService::FinishEnrollTaskV2,
                                  base::Unretained(this), data);
  base::Closure reply =
      base::Bind(&AttestationService::OnEnrollAction, GetWeakPtr(), data);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::CreateCertificateRequest(
    const CreateCertificateRequestRequest& request,
    const CreateCertificateRequestCallback& callback) {
  auto result = std::make_shared<CreateCertificateRequestReply>();
  base::Closure task =
      base::Bind(&AttestationService::CreateCertificateRequestTask<
                     CreateCertificateRequestRequest>,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<CreateCertificateRequestReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

template <typename RequestType>
void AttestationService::CreateCertificateRequestTask(
    const RequestType& request,
    const std::shared_ptr<CreateCertificateRequestReply>& result) {
  const int identity = kFirstIdentity;
  auto database_pb = database_->GetProtobuf();
  if (database_pb.identities().size() <= identity) {
    LOG(ERROR) << __func__ << ": Cannot create a certificate request, identity "
               << identity << " does not exist.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }

  std::string nonce;
  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  KeyType key_type = request.key_type();
  std::string key_blob;
  std::string public_key_der;
  std::string public_key_tpm_format;
  std::string key_info;
  std::string proof;
  CertifiedKey key;
  const auto& identity_data = database_pb.identities().Get(identity);
  if (!tpm_utility_->CreateCertifiedKey(
          key_type, KEY_USAGE_SIGN,
          identity_data.identity_key().identity_key_blob(), nonce, &key_blob,
          &public_key_der, &public_key_tpm_format, &key_info, &proof)) {
    LOG(ERROR) << __func__ << ": Failed to create a key.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  key.set_key_blob(key_blob);
  key.set_public_key(public_key_der);
  key.set_public_key_tpm_format(public_key_tpm_format);
  key.set_certified_key_info(key_info);
  key.set_certified_key_proof(proof);
  key.set_key_type(key_type);
  key.set_key_usage(KEY_USAGE_SIGN);
  std::string message_id;
  if (!CreateCertificateRequestInternal(
          request.aca_type(), request.username(), key,
          request.certificate_profile(), request.request_origin(),
          result->mutable_pca_request(), &message_id)) {
    result->clear_pca_request();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  std::string serialized_key;
  if (!key.SerializeToString(&serialized_key)) {
    LOG(ERROR) << __func__ << ": Failed to serialize key protobuf.";
    result->clear_pca_request();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  pending_cert_requests_[message_id] = serialized_key;
}

void AttestationService::FinishCertificateRequest(
    const FinishCertificateRequestRequest& request,
    const FinishCertificateRequestCallback& callback) {
  auto result = std::make_shared<FinishCertificateRequestReply>();
  base::Closure task =
      base::Bind(&AttestationService::FinishCertificateRequestTask<
                     FinishCertificateRequestReply>,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<FinishCertificateRequestReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

template <typename ReplyType>
void AttestationService::FinishCertificateRequestTask(
    const FinishCertificateRequestRequest& request,
    const std::shared_ptr<ReplyType>& result) {
  AttestationCertificateResponse response_pb;
  if (!response_pb.ParseFromString(request.pca_response())) {
    LOG(ERROR) << __func__ << ": Failed to parse response from Attestation CA.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  CertRequestMap::iterator iter =
      pending_cert_requests_.find(response_pb.message_id());
  if (iter == pending_cert_requests_.end()) {
    LOG(ERROR) << __func__ << ": Pending request not found.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (response_pb.status() != OK) {
    LogErrorFromCA(__func__, response_pb.detail(), response_pb.extra_details());
    pending_cert_requests_.erase(iter);
    result->set_status(STATUS_REQUEST_DENIED_BY_CA);
    return;
  }
  CertifiedKey key;
  if (!key.ParseFromArray(iter->second.data(), iter->second.size())) {
    LOG(ERROR) << __func__ << ": Failed to parse pending request key.";
    pending_cert_requests_.erase(iter);
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
                               result->mutable_public_key())) {
    LOG(ERROR) << __func__ << ": Failed to call `GetSubjectPublicKeyInfo()`.";
    pending_cert_requests_.erase(iter);
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  pending_cert_requests_.erase(iter);
  if (!PopulateAndStoreCertifiedKey(response_pb, request.username(),
                                    request.key_label(), &key,
                                    result->mutable_certificate())) {
    result->clear_certificate();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
}

void AttestationService::GetCertificate(
    const GetCertificateRequest& request,
    const GetCertificateCallback& callback) {
  PostStartEnrollTask(std::make_shared<AttestationFlowData>(request, callback));
}

void AttestationService::SendGetCertificateRequest(
    const std::shared_ptr<AttestationFlowData>& data) {
  auto pca_request = ToPcaAgentCertRequest(*data);
  auto on_success =
      base::Bind(&AttestationService::HandlePcaAgentGetCertificateReply,
                 GetWeakPtr(), data);
  auto on_error =
      base::Bind(&AttestationService::HandlePcaAgentGetCertificateRequestError,
                 GetWeakPtr(), data);
  pca_agent_proxy_->GetCertificateAsync(pca_request, on_success, on_error);
}

void AttestationService::HandlePcaAgentGetCertificateRequestError(
    const std::shared_ptr<AttestationFlowData>& data, brillo::Error*) {
  LOG(ERROR) << __func__
             << ": Error sending certificate request to |pca_agent|";
  data->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
  data->set_action(AttestationFlowAction::kAbort);
  OnGetCertificateAction(data);
  return;
}

void AttestationService::HandlePcaAgentGetCertificateReply(
    const std::shared_ptr<AttestationFlowData>& data,
    const pca_agent::GetCertificateReply& pca_reply) {
  if (pca_reply.status() != STATUS_SUCCESS) {
    data->set_status(pca_reply.status());
    data->set_action(AttestationFlowAction::kAbort);
    OnGetCertificateAction(data);
    return;
  }
  data->set_result_response(pca_reply.response());
  base::Closure task = base::Bind(&AttestationService::FinishCertificateTask,
                                  base::Unretained(this), data);
  base::Closure reply = base::Bind(&AttestationService::OnGetCertificateAction,
                                   GetWeakPtr(), data);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

bool AttestationService::ValidateEnterpriseChallenge(
    VAType va_type, const SignedData& signed_challenge) {
  const char kExpectedChallengePrefix[] = "EnterpriseKeyChallenge";
  // VA server always use SHA256 as digest algorithm for signature.
  if (!crypto_utility_->VerifySignatureUsingHexKey(
          NID_sha256, google_keys_.va_signing_key(va_type).modulus_in_hex(),
          signed_challenge.data(), signed_challenge.signature())) {
    LOG(ERROR) << __func__ << ": Failed to verify challenge signature.";
    return false;
  }
  Challenge challenge;
  if (!challenge.ParseFromString(signed_challenge.data())) {
    LOG(ERROR) << __func__ << ": Failed to parse challenge protobuf.";
    return false;
  }
  if (challenge.prefix() != kExpectedChallengePrefix) {
    LOG(ERROR) << __func__ << ": Unexpected challenge prefix.";
    return false;
  }
  return true;
}

bool AttestationService::EncryptEnterpriseKeyInfo(
    VAType va_type, const KeyInfo& key_info, EncryptedData* encrypted_data) {
  std::string serialized;
  if (!key_info.SerializeToString(&serialized)) {
    LOG(ERROR) << "Failed to serialize key info.";
    return false;
  }
  return crypto_utility_->EncryptDataForGoogle(
      serialized, google_keys_.va_encryption_key(va_type).modulus_in_hex(),
      google_keys_.va_encryption_key(va_type).key_id(), encrypted_data);
}

void AttestationService::SignEnterpriseChallenge(
    const SignEnterpriseChallengeRequest& request,
    const SignEnterpriseChallengeCallback& callback) {
  auto result = std::make_shared<SignEnterpriseChallengeReply>();
  base::Closure task =
      base::Bind(&AttestationService::SignEnterpriseChallengeTask,
                 base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<SignEnterpriseChallengeReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::SignEnterpriseChallengeTask(
    const SignEnterpriseChallengeRequest& request,
    const std::shared_ptr<SignEnterpriseChallengeReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }

  // Validate that the challenge is coming from the expected source.
  SignedData signed_challenge;
  if (!signed_challenge.ParseFromString(request.challenge())) {
    LOG(ERROR) << __func__ << ": Failed to parse signed challenge.";
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  if (!ValidateEnterpriseChallenge(request.va_type(), signed_challenge)) {
    LOG(ERROR) << __func__ << ": Invalid challenge.";
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  // Add a nonce to ensure this service cannot be used to sign arbitrary data.
  std::string nonce;
  if (!crypto_utility_->GetRandom(kChallengeSignatureNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": Failed to generate nonce.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }

  const bool is_user_specific = !request.username().empty();
  KeyInfo key_info;
  // EUK -> Enterprise User Key
  // EMK -> Enterprise Machine Key
  if (is_user_specific) {
    key_info.set_key_type(EUK);
    key_info.set_domain(request.domain());
  } else {
    // For machine key, the customer_id should be included, not the domain
    // name.
    key_info.set_key_type(EMK);
    if (!PopulateCustomerId(&key_info)) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
  }
  key_info.set_device_id(request.device_id());

  base::Optional<CertifiedKey> key_for_certificate_and_spkac;
  if (is_user_specific) {
    // Always include the EUK certificate if an EUK is being challenged.
    // Note that if including SPKAC has been requested when challenging an EUK,
    // the SPKAC will also be created for the EUK. In other words,
    // |key_name_for_spkac| is currently ignored for EUKs.
    key_for_certificate_and_spkac = key;
  } else if (request.include_signed_public_key() &&
             !request.key_name_for_spkac().empty()) {
    // If a specific key name for SPKAC has been requested when challenging an
    // EMK, include the certificate for that key.
    CertifiedKey key_for_spkac;
    if (!FindKeyByLabel(std::string() /* username */,
                        request.key_name_for_spkac(), &key_for_spkac)) {
      result->set_status(STATUS_INVALID_PARAMETER);
      return;
    }
    key_for_certificate_and_spkac = key_for_spkac;
  }
  if (key_for_certificate_and_spkac) {
    key_info.set_certificate(
        CreatePEMCertificateChain(key_for_certificate_and_spkac.value()));
    if (request.include_signed_public_key()) {
      std::string spkac;
      if (!crypto_utility_->CreateSPKAC(
              key_for_certificate_and_spkac.value().key_blob(),
              key_for_certificate_and_spkac.value().public_key(),
              key_for_certificate_and_spkac.value().key_type(), &spkac)) {
        LOG(ERROR) << __func__ << ": Failed to create signed public key.";
        result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
        return;
      }
      key_info.set_signed_public_key_and_challenge(spkac);
    }
  }

  ChallengeResponse response_pb;
  *response_pb.mutable_challenge() = signed_challenge;
  response_pb.set_nonce(nonce);
  if (!EncryptEnterpriseKeyInfo(request.va_type(), key_info,
                                response_pb.mutable_encrypted_key_info())) {
    LOG(ERROR) << __func__ << ": Failed to encrypt KeyInfo.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }

  // Serialize and sign the response protobuf.
  std::string serialized;
  if (!response_pb.SerializeToString(&serialized)) {
    LOG(ERROR) << __func__ << ": Failed to serialize response protobuf.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (!SignChallengeData(key, serialized,
                         result->mutable_challenge_response())) {
    result->clear_challenge_response();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
}

void AttestationService::SignSimpleChallenge(
    const SignSimpleChallengeRequest& request,
    const SignSimpleChallengeCallback& callback) {
  auto result = std::make_shared<SignSimpleChallengeReply>();
  base::Closure task = base::Bind(&AttestationService::SignSimpleChallengeTask,
                                  base::Unretained(this), request, result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<SignSimpleChallengeReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::SignSimpleChallengeTask(
    const SignSimpleChallengeRequest& request,
    const std::shared_ptr<SignSimpleChallengeReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  // Add a nonce to ensure this service cannot be used to sign arbitrary data.
  std::string nonce;
  if (!crypto_utility_->GetRandom(kChallengeSignatureNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": Failed to generate nonce.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (!SignChallengeData(key, request.challenge() + nonce,
                         result->mutable_challenge_response())) {
    result->clear_challenge_response();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
}

bool AttestationService::SignChallengeData(const CertifiedKey& key,
                                           const std::string& data_to_sign,
                                           std::string* response) {
  std::string signature;
  if (!tpm_utility_->Sign(key.key_blob(), data_to_sign, &signature)) {
    LOG(ERROR) << __func__ << ": Failed to sign data.";
    return false;
  }
  SignedData signed_data;
  signed_data.set_data(data_to_sign);
  signed_data.set_signature(signature);
  if (!signed_data.SerializeToString(response)) {
    LOG(ERROR) << __func__ << ": Failed to serialize signed data.";
    return false;
  }
  return true;
}

void AttestationService::SetKeyPayload(const SetKeyPayloadRequest& request,
                                       const SetKeyPayloadCallback& callback) {
  auto result = std::make_shared<SetKeyPayloadReply>();
  base::Closure task = base::Bind(&AttestationService::SetKeyPayloadTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<SetKeyPayloadReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::SetKeyPayloadTask(
    const SetKeyPayloadRequest& request,
    const std::shared_ptr<SetKeyPayloadReply>& result) {
  CertifiedKey key;
  if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  key.set_payload(request.payload());
  if (!SaveKey(request.username(), request.key_label(), key)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
}

void AttestationService::DeleteKeys(const DeleteKeysRequest& request,
                                    const DeleteKeysCallback& callback) {
  auto result = std::make_shared<DeleteKeysReply>();
  base::Closure task = base::Bind(&AttestationService::DeleteKeysTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<DeleteKeysReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::DeleteKeysTask(
    const DeleteKeysRequest& request,
    const std::shared_ptr<DeleteKeysReply>& result) {
  if (request.has_match_behavior() &&
      request.match_behavior() == DeleteKeysRequest::MATCH_BEHAVIOR_EXACT) {
    if (!DeleteKey(request.username(), request.key_label_match())) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    }
    return;
  }
  if (!DeleteKeysByPrefix(request.username(), request.key_label_match())) {
    LOG(ERROR) << __func__ << ": Failed to delete keys with prefix: "
               << request.key_label_match();
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
  }
}

void AttestationService::ResetIdentity(const ResetIdentityRequest& request,
                                       const ResetIdentityCallback& callback) {
  auto result = std::make_shared<ResetIdentityReply>();
  base::Closure task = base::Bind(&AttestationService::ResetIdentityTask,
                                  base::Unretained(this), request, result);
  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<ResetIdentityReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::ResetIdentityTask(
    const ResetIdentityRequest& request,
    const std::shared_ptr<ResetIdentityReply>& result) {
  LOG(ERROR) << __func__ << ": Not implemented.";
  result->set_status(STATUS_NOT_SUPPORTED);
}

void AttestationService::GetEnrollmentId(
    const GetEnrollmentIdRequest& request,
    const GetEnrollmentIdCallback& callback) {
  auto result = std::make_shared<GetEnrollmentIdReply>();
  base::Closure task = base::Bind(&AttestationService::GetEnrollmentIdTask,
                                  base::Unretained(this), request, result);

  base::Closure reply =
      base::Bind(&AttestationService::TaskRelayCallback<GetEnrollmentIdReply>,
                 GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::GetEnrollmentIdTask(
    const GetEnrollmentIdRequest& request,
    const std::shared_ptr<GetEnrollmentIdReply>& result) {
  std::string enrollment_id;
  if (request.ignore_cache()) {
    enrollment_id = ComputeEnterpriseEnrollmentId();
  } else {
    const auto& database_pb = database_->GetProtobuf();
    if (database_pb.has_enrollment_id()) {
      enrollment_id = std::string(database_pb.enrollment_id());
    } else {
      enrollment_id = ComputeEnterpriseEnrollmentId();
      if (!enrollment_id.empty()) {
        database_->GetMutableProtobuf()->set_enrollment_id(enrollment_id);
        if (!database_->SaveChanges()) {
          LOG(WARNING) << __func__ << "Failed to save attestation db.";
        }
      }
    }
  }
  if (enrollment_id.empty()) {
    result->set_status(STATUS_NOT_AVAILABLE);
  }
  result->set_enrollment_id(enrollment_id);
}

void AttestationService::GetCertifiedNvIndex(
    const GetCertifiedNvIndexRequest& request,
    const GetCertifiedNvIndexCallback& callback) {
  auto result = std::make_shared<GetCertifiedNvIndexReply>();
  base::Closure task = base::Bind(&AttestationService::GetCertifiedNvIndexTask,
                                  base::Unretained(this), request, result);

  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<GetCertifiedNvIndexReply>,
      GetWeakPtr(), callback, result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::GetCertifiedNvIndexTask(
    const GetCertifiedNvIndexRequest& request,
    const std::shared_ptr<GetCertifiedNvIndexReply>& result) {
  result->set_status(STATUS_NOT_AVAILABLE);

  CertifiedKey key;
  if (!FindKeyByLabel(std::string(), request.key_label(), &key)) {
    LOG(WARNING) << "Attempted to certify NV space with missing key, label: "
                 << request.key_label();
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }

  std::string certified_value;
  std::string signature;

  if (!tpm_utility_->CertifyNV(request.nv_index(), request.nv_size(),
                               key.key_blob(), &certified_value, &signature)) {
    LOG(WARNING) << "Attestation: Failed to certify NV data of size "
                 << request.nv_size() << " at index " << std::hex
                 << std::showbase << request.nv_index()
                 << ", using key with label: " << request.key_label();
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }

  result->set_certified_data(certified_value);
  result->set_signature(signature);
  result->set_key_certificate(key.certified_key_credential());
  result->set_status(STATUS_SUCCESS);
}

std::string AttestationService::ComputeEnterpriseEnrollmentNonce() {
  if (!abe_data_ || abe_data_->empty()) {
    // If there was no device secret we cannot compute the DEN.
    // We do not want to fail attestation for those devices.
    return "";
  }

  std::string data(abe_data_->char_data(), abe_data_->size());
  std::string key(kAttestationBasedEnterpriseEnrollmentContextName);
  return crypto_utility_->HmacSha256(key, data);
}

std::string AttestationService::ComputeEnterpriseEnrollmentId() {
  std::string den = ComputeEnterpriseEnrollmentNonce();
  if (den.empty())
    return "";

  std::string ekm;
  if (!tpm_utility_->GetEndorsementPublicKeyModulus(KEY_TYPE_RSA, &ekm))
    return "";

  // Compute the EID based on den and ekm.
  return crypto_utility_->HmacSha256(den, ekm);
}

KeyType AttestationService::GetEndorsementKeyType() const {
  // If some EK information already exists in the database, we need to keep the
  // key type consistent.
  const auto& database_pb = database_->GetProtobuf();
  if (database_pb.credentials().has_endorsement_public_key() ||
      database_pb.credentials().has_endorsement_credential()) {
    // We use the default value of key_type for backward compatibility, no need
    // to check if endorsement_key_type is set.
    return database_pb.credentials().endorsement_key_type();
  }

  // We didn't generate any data yet. Use the suggested key type.
  return tpm_utility_->GetVersion() == TPM_2_0 ? KEY_TYPE_ECC : KEY_TYPE_RSA;
}

KeyType AttestationService::GetAttestationIdentityKeyType() const {
  return tpm_utility_->GetVersion() == TPM_2_0 ? KEY_TYPE_ECC : KEY_TYPE_RSA;
}

bool AttestationService::PopulateCustomerId(KeyInfo* key_info) {
  if (!policy_provider_.get())
    policy_provider_ = std::make_unique<policy::PolicyProvider>();
  policy_provider_->Reload();

  // If device_policy is still not loaded, return an error.
  if (!policy_provider_->device_policy_is_loaded()) {
    LOG(ERROR) << __func__ << ": Failed to get device policy.";
    return false;
  }
  std::string customer_id;
  if (!policy_provider_->GetDevicePolicy().GetCustomerId(&customer_id) ||
      customer_id.empty()) {
    LOG(ERROR) << __func__ << ": Failed to get customer ID.";
    return false;
  }
  key_info->set_customer_id(customer_id);
  return true;
}

base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

ACAType AttestationService::GetACAType(ACATypeInternal aca_type_internal) {
  switch (aca_type_internal) {
    case kDefaultACA:
      return DEFAULT_ACA;
    case kTestACA:
      return TEST_ACA;
    default:
      return DEFAULT_ACA;
  }
}

}  // namespace attestation
