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

#include <attestation/proto_bindings/attestation_ca.pb.h>
#include <attestation/proto_bindings/pca_agent.pb.h>
#include <base/bind.h>
#include <base/bind_helpers.h>
#include <base/callback.h>
#include <base/run_loop.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/synchronization/waitable_event.h>
#include <base/test/task_environment.h>
#include <brillo/data_encoding.h>
#include <brillo/errors/error.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <policy/mock_device_policy.h>
#include <policy/mock_libpolicy.h>
#if USE_TPM2
#include <trunks/tpm_utility.h>
#endif
#if USE_TPM2
extern "C" {
#include <trunks/cr50_headers/virtual_nvmem.h>
}
#endif

#include "attestation/common/mock_crypto_utility.h"
#include "attestation/common/mock_tpm_utility.h"
#include "attestation/pca_agent/client/fake_pca_agent_proxy.h"
#include "attestation/server/attestation_service.h"
#include "attestation/server/google_keys.h"
#include "attestation/server/mock_database.h"
#include "attestation/server/mock_key_store.h"

using testing::_;
using testing::AtMost;
using testing::DoAll;
using testing::Invoke;
using testing::NiceMock;
using testing::Return;
using testing::ReturnRef;
using testing::SetArgPointee;
using testing::StrictMock;
using testing::WithArgs;

namespace attestation {

namespace {

#if USE_TPM2
constexpr TpmVersion kTpmVersionUnderTest = TPM_2_0;
#else
constexpr TpmVersion kTpmVersionUnderTest = TPM_1_2;
#endif

std::string CreateChallenge(const std::string& prefix) {
  Challenge challenge;
  challenge.set_prefix(prefix);
  challenge.set_nonce("nonce");
  challenge.set_timestamp(100500);
  std::string serialized;
  challenge.SerializeToString(&serialized);
  return serialized;
}

std::string CreateSignedChallenge(const std::string& prefix) {
  SignedData signed_data;
  signed_data.set_data(CreateChallenge(prefix));
  signed_data.set_signature("challenge_signature");
  std::string serialized;
  signed_data.SerializeToString(&serialized);
  return serialized;
}

EncryptedData MockEncryptedData(std::string data) {
  EncryptedData encrypted_data;
  encrypted_data.set_wrapped_key("wrapped_key");
  encrypted_data.set_iv("iv");
  encrypted_data.set_mac("mac");
  encrypted_data.set_encrypted_data(data);
  encrypted_data.set_wrapping_key_id("wrapping_key_id");
  return encrypted_data;
}

KeyInfo CreateChallengeKeyInfo() {
  KeyInfo key_info;
  key_info.set_key_type(EUK);
  key_info.set_domain("domain");
  key_info.set_device_id("device_id");
  key_info.set_certificate("");
  return key_info;
}

KeyInfo CreateMachineChallengeKeyInfoWithSPKAC(
    const std::string& certified_credential_of_key_for_spkac,
    const std::string& spkac) {
  // Create a PEM encoding of |certified_credential_of_key_for_spkac|.
  std::string pem_certificate_of_key_for_spkac =
      "-----BEGIN CERTIFICATE-----\n" +
      brillo::data_encoding::Base64EncodeWrapLines(
          certified_credential_of_key_for_spkac) +
      "-----END CERTIFICATE-----";

  KeyInfo key_info;
  key_info.set_key_type(EMK);
  key_info.set_customer_id("customer_id");
  key_info.set_device_id("device_id");
  key_info.set_certificate(pem_certificate_of_key_for_spkac);
  key_info.set_signed_public_key_and_challenge(spkac);
  return key_info;
}

std::string GetFakeCertificateChain() {
  const std::string kBeginCertificate = "-----BEGIN CERTIFICATE-----\n";
  const std::string kEndCertificate = "-----END CERTIFICATE-----";
  std::string pem = kBeginCertificate;
  pem += brillo::data_encoding::Base64EncodeWrapLines("fake_cert");
  pem += kEndCertificate + "\n" + kBeginCertificate;
  pem += brillo::data_encoding::Base64EncodeWrapLines("fake_ca_cert");
  pem += kEndCertificate + "\n" + kBeginCertificate;
  pem += brillo::data_encoding::Base64EncodeWrapLines("fake_ca_cert2");
  pem += kEndCertificate;
  return pem;
}

// testing::InvokeArgument<N> does not work with base::Callback, need to use
// |ACTION_TAMPLATE| along with predefined |args| tuple.
ACTION_TEMPLATE(InvokeCallbackArgument,
                HAS_1_TEMPLATE_PARAMS(int, k),
                AND_1_VALUE_PARAMS(p0)) {
  std::get<k>(args).Run(p0);
}

}  // namespace

class AttestationServiceBaseTest : public testing::Test {
 public:
  ~AttestationServiceBaseTest() override = default;

  void SetUp() override {
    service_.reset(new AttestationService(nullptr));
    service_->set_database(&mock_database_);
    service_->set_crypto_utility(&mock_crypto_utility_);
    service_->set_key_store(&mock_key_store_);
    service_->set_tpm_utility(&mock_tpm_utility_);
    service_->set_hwid("fake_hwid");
    service_->set_pca_agent_proxy(&fake_pca_agent_proxy_);
    mock_policy_provider_ = new StrictMock<policy::MockPolicyProvider>();
    service_->set_policy_provider(mock_policy_provider_);
    // Setup a fake wrapped EK certificate by default.
    (*mock_database_.GetMutableProtobuf()
          ->mutable_credentials()
          ->mutable_encrypted_endorsement_credentials())[DEFAULT_ACA]
        .set_wrapping_key_id("default");
    (*mock_database_.GetMutableProtobuf()
          ->mutable_credentials()
          ->mutable_encrypted_endorsement_credentials())[TEST_ACA]
        .set_wrapping_key_id("test");
    EXPECT_CALL(mock_tpm_utility_, IsPCR0Valid()).WillRepeatedly(Return(true));
    // Run out initialize task(s) to avoid any race conditions with tests that
    // need to change the default setup.
    CHECK(
        CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  }

 protected:
  void Run() { run_loop_.Run(); }

  void RunUntilIdle() { run_loop_.RunUntilIdle(); }

  void Quit() { run_loop_.Quit(); }

  base::Closure QuitClosure() { return run_loop_.QuitClosure(); }

  template <typename T>
  T CallAndWait(
      base::OnceCallback<T(AttestationService::InitializeCompleteCallback)>
          func) {
    base::WaitableEvent done(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
    T val = std::move(func).Run(
        base::BindOnce([](base::WaitableEvent* done, bool) { done->Signal(); },
                       base::Unretained(&done)));
    done.Wait();
    return val;
  }

  void SetUpIdentity(int identity) {
    auto* database = mock_database_.GetMutableProtobuf();
    AttestationDatabase::Identity* identity_data;
    if (database->identities().size() > identity) {
      identity_data = database->mutable_identities()->Mutable(identity);
    } else {
      for (int i = database->identities().size(); i <= identity; ++i) {
        identity_data = database->mutable_identities()->Add();
      }
    }
    identity_data->set_features(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID);
    identity_data->mutable_identity_key()->set_identity_public_key_der(
        "public_key");
    identity_data->mutable_identity_binding()
        ->set_identity_public_key_tpm_format("public_key_tpm");
    (*identity_data->mutable_pcr_quotes())[0].set_quote("pcr0");
    (*identity_data->mutable_pcr_quotes())[1].set_quote("pcr1");
#if USE_TPM2
    (*identity_data->mutable_nvram_quotes())[BOARD_ID].set_quote("board_id");
    (*identity_data->mutable_nvram_quotes())[SN_BITS].set_quote("sn_bits");
    if (service_->GetEndorsementKeyType() != KEY_TYPE_RSA) {
      (*identity_data->mutable_nvram_quotes())[RSA_PUB_EK_CERT].set_quote(
          "rsa_pub_ek_cert");
    }
#endif
  }

  // Generate a unique name for a certificate from an ACA.
  std::string GetCertificateName(int identity, ACAType aca_type) {
    std::ostringstream stream;
    stream << "certificate(" << identity << ", " << aca_type << ")";
    return stream.str();
  }

  // Create an identity certificate if needed and sets an ACA-signed
  // certificate. Once this exists, we consider that the identity has been
  // enrolled with the given ACA.
  void SetUpIdentityCertificate(int identity, ACAType aca_type) {
    auto identity_certificate = service_->FindOrCreateIdentityCertificate(
        identity, aca_type, nullptr /* cert_index */);
    EXPECT_NE(nullptr, identity_certificate);
    identity_certificate->set_identity_credential(
        GetCertificateName(identity, aca_type));
  }

  CertifiedKey GenerateFakeCertifiedKey() const {
    CertifiedKey key;
    key.set_public_key("public_key");
    key.set_certified_key_credential("fake_cert");
    key.set_intermediate_ca_cert("fake_ca_cert");
    *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
    key.set_key_name("label");
    key.set_certified_key_info("certify_info");
    key.set_certified_key_proof("signature");
    key.set_key_type(KEY_TYPE_RSA);
    key.set_key_usage(KEY_USAGE_SIGN);
    return key;
  }

  std::string GenerateSerializedFakeCertifiedKey() const {
    CertifiedKey key = GenerateFakeCertifiedKey();
    return key.SerializeAsString();
  }

  void ExpectGetCustomerId(std::string customer_id) {
    EXPECT_CALL(*mock_policy_provider_, Reload()).WillOnce(Return(true));
    EXPECT_CALL(*mock_policy_provider_, device_policy_is_loaded())
        .WillOnce(Return(true));
    EXPECT_CALL(*mock_policy_provider_, GetDevicePolicy())
        .WillOnce(ReturnRef(mock_device_policy_));
    EXPECT_CALL(mock_device_policy_, GetCustomerId(_))
        .WillOnce(DoAll(SetArgPointee<0>(customer_id), Return(true)));
  }

  // Verify Attestation CA-related data, including the default CA's identity
  // credential.
  void VerifyACAData(const AttestationDatabase& db,
                     const char* default_identity_credential) {
    ASSERT_EQ(default_identity_credential ? 1 : 0,
              db.identity_certificates().size());
    for (int aca = 0; aca < db.identity_certificates().size(); ++aca) {
      const AttestationDatabase::IdentityCertificate identity_certificate =
          db.identity_certificates().at(aca);
      ASSERT_EQ(0, identity_certificate.identity());
      ASSERT_EQ(aca, identity_certificate.aca());
      if (default_identity_credential && aca == DEFAULT_ACA) {
        ASSERT_EQ(default_identity_credential,
                  identity_certificate.identity_credential());
      } else {
        ASSERT_FALSE(identity_certificate.has_identity_credential());
      }
    }
    // All ACAs have encrypted credentials.
    for (int aca = AttestationService::kDefaultACA;
         aca < AttestationService::kMaxACATypeInternal; ++aca) {
      AttestationService::ACATypeInternal aca_int =
          static_cast<AttestationService::ACATypeInternal>(aca);
      ASSERT_TRUE(db.credentials().encrypted_endorsement_credentials().count(
          AttestationService::GetACAType(aca_int)));
    }
  }

  // Verify Attestation CA-related data, including the lack of default CA's
  // identity credential.
  void VerifyACAData(const AttestationDatabase& db) {
    VerifyACAData(db, nullptr);
  }

  std::string ComputeEnterpriseEnrollmentId() {
    return service_->ComputeEnterpriseEnrollmentId();
  }

  std::string GetEnrollmentId() {
    GetEnrollmentIdRequest request;
    auto result = std::make_shared<GetEnrollmentIdReply>();
    service_->GetEnrollmentIdTask(request, result);
    if (result->status() != STATUS_SUCCESS) {
      return "";
    }

    return result->enrollment_id();
  }

  NiceMock<MockCryptoUtility> mock_crypto_utility_;
  NiceMock<MockDatabase> mock_database_;
  NiceMock<MockKeyStore> mock_key_store_;
  NiceMock<MockTpmUtility> mock_tpm_utility_;
  StrictMock<policy::MockPolicyProvider>* mock_policy_provider_;  // Not Owned.
  StrictMock<policy::MockDevicePolicy> mock_device_policy_;
  StrictMock<pca_agent::client::FakePcaAgentProxy> fake_pca_agent_proxy_{
      kTpmVersionUnderTest};
  std::unique_ptr<AttestationService> service_;
  const int identity_ = AttestationService::kFirstIdentity;

 private:
  base::test::TaskEnvironment task_environment_{
      base::test::TaskEnvironment::ThreadingMode::MAIN_THREAD_ONLY};
  base::RunLoop run_loop_;
};

TEST_F(AttestationServiceBaseTest, MigrateAttestationDatabase) {
  // Simulate an older database.
  auto* db = mock_database_.GetMutableProtobuf();
  db->mutable_credentials()->clear_encrypted_endorsement_credentials();
  db->mutable_credentials()->set_endorsement_credential("endorsement_cred");
  EncryptedData default_encrypted_endorsement_credential;
  default_encrypted_endorsement_credential.set_wrapped_key("default_key");
  db->mutable_credentials()
      ->mutable_default_encrypted_endorsement_credential()
      ->CopyFrom(default_encrypted_endorsement_credential);
  db->clear_identities();
  db->clear_identity_certificates();
  db->mutable_identity_binding()->set_identity_binding("identity_binding");
  db->mutable_identity_binding()->set_identity_public_key_tpm_format(
      "identity_public_key");
  db->mutable_identity_key()->set_identity_credential("identity_cred");
  db->mutable_pcr0_quote()->set_quote("pcr0_quote");
  db->mutable_pcr1_quote()->set_quote("pcr1_quote");
  // Persist that older database.
  mock_database_.SaveChanges();

  // Simulate login.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  service_->PrepareForEnrollment(base::DoNothing());

  const auto& const_db = mock_database_.GetProtobuf();
  // The default encrypted endorsement credential has been migrated.
  // The deprecated field has not been cleared so that older code can still
  // use the database.
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .encrypted_endorsement_credentials()
                .at(DEFAULT_ACA)
                .wrapped_key());
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .default_encrypted_endorsement_credential()
                .wrapped_key());

  // The default identity has data copied from the deprecated database fields.
  // The deprecated fields have not been cleared so that older code can still
  // use the database.
  const AttestationDatabase::Identity& default_identity_data =
      const_db.identities().Get(DEFAULT_ACA);
  EXPECT_EQ(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID,
            default_identity_data.features());
  EXPECT_EQ("identity_binding",
            default_identity_data.identity_binding().identity_binding());
  EXPECT_EQ("identity_public_key", default_identity_data.identity_binding()
                                       .identity_public_key_tpm_format());
  EXPECT_EQ("identity_binding", const_db.identity_binding().identity_binding());
  EXPECT_EQ("identity_public_key",
            const_db.identity_binding().identity_public_key_tpm_format());
  EXPECT_EQ("pcr0_quote", default_identity_data.pcr_quotes().at(0).quote());
  EXPECT_EQ("pcr0_quote", const_db.pcr0_quote().quote());
  EXPECT_EQ("pcr1_quote", default_identity_data.pcr_quotes().at(1).quote());
  EXPECT_EQ("pcr1_quote", const_db.pcr1_quote().quote());

  // No other identity has been created.
  EXPECT_EQ(1, const_db.identities().size());

  // The identity credential was migrated into an identity certificate.
  // As a result, identity data does not use the identity credential. The
  // deprecated field has not been cleared so that older code can still
  // use the database.
  EXPECT_FALSE(default_identity_data.identity_key().has_identity_credential());
  EXPECT_EQ("identity_cred", const_db.identity_key().identity_credential());
  VerifyACAData(const_db, "identity_cred");
}

TEST_F(AttestationServiceBaseTest,
       MigrateAttestationDatabaseWithCorruptedFields) {
  // Simulate an older database.
  auto* db = mock_database_.GetMutableProtobuf();
  db->mutable_credentials()->clear_encrypted_endorsement_credentials();
  db->mutable_credentials()->set_endorsement_credential("endorsement_cred");
  EncryptedData default_encrypted_endorsement_credential;
  default_encrypted_endorsement_credential.set_wrapped_key("default_key");
  db->mutable_credentials()
      ->mutable_default_encrypted_endorsement_credential()
      ->CopyFrom(default_encrypted_endorsement_credential);
  db->clear_identities();
  db->clear_identity_certificates();
  db->mutable_identity_binding()->set_identity_binding("identity_binding");
  db->mutable_identity_binding()->set_identity_public_key_tpm_format(
      "identity_public_key");
  db->mutable_identity_key()->set_identity_credential("identity_cred");
  // Note that we are missing a PCR0 quote.
  db->mutable_pcr1_quote()->set_quote("pcr1_quote");
  // Persist that older database.
  mock_database_.SaveChanges();

  // Simulate login.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  service_->PrepareForEnrollment(base::DoNothing());

  const auto& const_db = mock_database_.GetProtobuf();
  // The default encrypted endorsement credential has been migrated.
  // The deprecated field has not been cleared so that older code can still
  // use the database.
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .encrypted_endorsement_credentials()
                .at(DEFAULT_ACA)
                .wrapped_key());
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .default_encrypted_endorsement_credential()
                .wrapped_key());

  // The default identity could not be copied from the deprecated database.
  // The deprecated fields have not been cleared so that older code can still
  // use the database.
  ASSERT_TRUE(const_db.identities().empty());
  ASSERT_EQ("identity_binding", const_db.identity_binding().identity_binding());
  ASSERT_EQ("identity_public_key",
            const_db.identity_binding().identity_public_key_tpm_format());
  EXPECT_EQ("pcr1_quote", const_db.pcr1_quote().quote());

  // There is no identity certificate since there is no identity.
  ASSERT_TRUE(const_db.identity_certificates().empty());
}

TEST_F(AttestationServiceBaseTest,
       MigrateAttestationDatabaseAllEndorsementCredentials) {
  // Simulate an older database.
  auto* db = mock_database_.GetMutableProtobuf();
  db->mutable_credentials()->clear_encrypted_endorsement_credentials();
  db->mutable_credentials()->set_endorsement_credential("endorsement_cred");
  EncryptedData default_encrypted_endorsement_credential;
  default_encrypted_endorsement_credential.set_wrapped_key("default_key");
  db->mutable_credentials()
      ->mutable_default_encrypted_endorsement_credential()
      ->CopyFrom(default_encrypted_endorsement_credential);
  EncryptedData test_encrypted_endorsement_credential;
  test_encrypted_endorsement_credential.set_wrapped_key("test_key");
  db->mutable_credentials()
      ->mutable_test_encrypted_endorsement_credential()
      ->CopyFrom(test_encrypted_endorsement_credential);
  db->clear_identities();
  db->clear_identity_certificates();
  db->mutable_identity_binding()->set_identity_binding("identity_binding");
  db->mutable_identity_binding()->set_identity_public_key_tpm_format(
      "identity_public_key");
  db->mutable_identity_key()->set_identity_credential("identity_cred");
  db->mutable_pcr0_quote()->set_quote("pcr0_quote");
  db->mutable_pcr1_quote()->set_quote("pcr1_quote");
  // Persist that older database.
  mock_database_.SaveChanges();

  // Simulate second login.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  service_->PrepareForEnrollment(base::DoNothing());

  const auto& const_db = mock_database_.GetProtobuf();
  // The encrypted endorsement credentials have both been migrated.
  // The deprecated fields have not been cleared so that older code can still
  // use the database.
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .encrypted_endorsement_credentials()
                .at(DEFAULT_ACA)
                .wrapped_key());
  EXPECT_EQ(default_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .default_encrypted_endorsement_credential()
                .wrapped_key());
  EXPECT_EQ(test_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .encrypted_endorsement_credentials()
                .at(TEST_ACA)
                .wrapped_key());
  EXPECT_EQ(test_encrypted_endorsement_credential.wrapped_key(),
            const_db.credentials()
                .test_encrypted_endorsement_credential()
                .wrapped_key());
}

TEST_F(AttestationServiceBaseTest, GetEndorsementInfoNoInfo) {
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementPublicKey(_, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetEndorsementInfoReply& reply) {
    EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status());
    EXPECT_FALSE(reply.has_ek_public_key());
    EXPECT_FALSE(reply.has_ek_certificate());
    quit_closure.Run();
  };
  GetEndorsementInfoRequest request;
  service_->GetEndorsementInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetEndorsementInfoNoCert) {
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementCertificate(_, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetEndorsementInfoReply& reply) {
    EXPECT_EQ(STATUS_UNEXPECTED_DEVICE_ERROR, reply.status());
    EXPECT_FALSE(reply.has_ek_public_key());
    EXPECT_FALSE(reply.has_ek_certificate());
    quit_closure.Run();
  };
  GetEndorsementInfoRequest request;
  service_->GetEndorsementInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetKeyInfoSuccess) {
  // Setup a certified key in the key store.
  CertifiedKey key;
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_certified_key_info("certify_info");
  key.set_certified_key_proof("signature");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(KEY_TYPE_RSA, reply.key_type());
    EXPECT_EQ(KEY_USAGE_SIGN, reply.key_usage());
    EXPECT_EQ("public_key", reply.public_key());
    EXPECT_EQ("certify_info", reply.certify_info());
    EXPECT_EQ("signature", reply.certify_info_signature());
    EXPECT_EQ(GetFakeCertificateChain(), reply.certificate());
    quit_closure.Run();
  };
  GetKeyInfoRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->GetKeyInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetKeyInfoSuccessNoUser) {
  // Setup a certified key in the device key store.
  CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_certified_key_info("certify_info");
  key.set_certified_key_proof("signature");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(KEY_TYPE_RSA, reply.key_type());
    EXPECT_EQ(KEY_USAGE_SIGN, reply.key_usage());
    EXPECT_EQ("public_key", reply.public_key());
    EXPECT_EQ("certify_info", reply.certify_info());
    EXPECT_EQ("signature", reply.certify_info_signature());
    EXPECT_EQ(GetFakeCertificateChain(), reply.certificate());
    quit_closure.Run();
  };
  GetKeyInfoRequest request;
  request.set_key_label("label");
  service_->GetKeyInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetKeyInfoNoKey) {
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillRepeatedly(Return(false));

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_INVALID_PARAMETER, reply.status());
    quit_closure.Run();
  };
  GetKeyInfoRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->GetKeyInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetKeyInfoBadPublicKey) {
  EXPECT_CALL(mock_crypto_utility_, GetRSASubjectPublicKeyInfo(_, _))
      .WillRepeatedly(Return(false));

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetKeyInfoReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  GetKeyInfoRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->GetKeyInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetEndorsementKeyTypeForExistingKey) {
  AttestationDatabase* database = mock_database_.GetMutableProtobuf();
  // Default key type is KEY_TYPE_RSA.
  database->mutable_credentials()->set_endorsement_public_key("public_key");
  database->mutable_credentials()->set_endorsement_credential("certificate");
  EXPECT_EQ(service_->GetEndorsementKeyType(), KEY_TYPE_RSA);

  database->mutable_credentials()->set_endorsement_key_type(KEY_TYPE_ECC);
  database->mutable_credentials()->set_endorsement_public_key("public_key");
  database->mutable_credentials()->set_endorsement_credential("certificate");
  EXPECT_EQ(service_->GetEndorsementKeyType(), KEY_TYPE_ECC);
}

TEST_F(AttestationServiceBaseTest,
       GetEndorsementKeyTypeForNewlyCreatedKeyInTpm2) {
  EXPECT_CALL(mock_tpm_utility_, GetVersion()).WillRepeatedly(Return(TPM_2_0));
  EXPECT_EQ(service_->GetEndorsementKeyType(), KEY_TYPE_ECC);
}

TEST_F(AttestationServiceBaseTest,
       GetEndorsementKeyTypeForNewlyCreatedKeyInTpm12) {
  EXPECT_CALL(mock_tpm_utility_, GetVersion()).WillRepeatedly(Return(TPM_1_2));
  EXPECT_EQ(service_->GetEndorsementKeyType(), KEY_TYPE_RSA);
}

TEST_F(AttestationServiceBaseTest, GetAttestationIdentityKeyTypeInTpm2) {
  EXPECT_CALL(mock_tpm_utility_, GetVersion()).WillRepeatedly(Return(TPM_2_0));
  EXPECT_EQ(service_->GetAttestationIdentityKeyType(), KEY_TYPE_ECC);
}

TEST_F(AttestationServiceBaseTest, GetAttestationIdentityKeyTypeInTpm12) {
  EXPECT_CALL(mock_tpm_utility_, GetVersion()).WillRepeatedly(Return(TPM_1_2));
  EXPECT_EQ(service_->GetAttestationIdentityKeyType(), KEY_TYPE_RSA);
}

TEST_F(AttestationServiceBaseTest, GetEndorsementInfoSuccess) {
  AttestationDatabase* database = mock_database_.GetMutableProtobuf();
  database->mutable_credentials()->set_endorsement_public_key("public_key");
  database->mutable_credentials()->set_endorsement_credential("certificate");
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetEndorsementInfoReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ("public_key", reply.ek_public_key());
    EXPECT_EQ("certificate", reply.ek_certificate());
    quit_closure.Run();
  };
  GetEndorsementInfoRequest request;
  service_->GetEndorsementInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, GetEnrollmentId) {
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementPublicKeyModulus(_, _))
      .WillRepeatedly(
          DoAll(SetArgPointee<1>(std::string("ekm")), Return(true)));
  brillo::SecureBlob abe_data(0xCA, 32);
  service_->set_abe_data(&abe_data);
  CryptoUtilityImpl crypto_utility(&mock_tpm_utility_);
  service_->set_crypto_utility(&crypto_utility);
  std::string enrollment_id = GetEnrollmentId();
  EXPECT_EQ("635c4526dfa583362273e2987944007b09131cfa0f4e5874e7a76d55d333e3cc",
            base::ToLowerASCII(
                base::HexEncode(enrollment_id.data(), enrollment_id.size())));

  // Cache the EID in the database.
  AttestationDatabase database_pb;
  database_pb.set_enrollment_id(enrollment_id);
  EXPECT_CALL(mock_database_, GetProtobuf()).WillOnce(ReturnRef(database_pb));

  // Change abe_data, and yet the EID remains the same.
  brillo::SecureBlob abe_data_new(0x89, 32);
  service_->set_abe_data(&abe_data_new);
  enrollment_id = GetEnrollmentId();
  EXPECT_EQ("635c4526dfa583362273e2987944007b09131cfa0f4e5874e7a76d55d333e3cc",
            base::ToLowerASCII(
                base::HexEncode(enrollment_id.data(), enrollment_id.size())));
}

TEST_F(AttestationServiceBaseTest, SignSimpleChallengeSuccess) {
  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _))
      .WillRepeatedly(
          DoAll(SetArgPointee<2>(std::string("signature")), Return(true)));
  auto callback = [](const base::Closure& quit_closure,
                     const SignSimpleChallengeReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_challenge_response());
    SignedData signed_data;
    EXPECT_TRUE(signed_data.ParseFromString(reply.challenge_response()));
    EXPECT_EQ("signature", signed_data.signature());
    EXPECT_EQ(0, signed_data.data().find("challenge"));
    EXPECT_NE("challenge", signed_data.data());
    quit_closure.Run();
  };
  SignSimpleChallengeRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_challenge("challenge");
  service_->SignSimpleChallenge(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_F(AttestationServiceBaseTest, SignSimpleChallengeInternalFailure) {
  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _)).WillRepeatedly(Return(false));
  auto callback = [](const base::Closure& quit_closure,
                     const SignSimpleChallengeReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_challenge_response());
    quit_closure.Run();
  };
  SignSimpleChallengeRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_challenge("challenge");
  service_->SignSimpleChallenge(request, base::Bind(callback, QuitClosure()));
  Run();
}

class AttestationServiceEnterpriseTest
    : public AttestationServiceBaseTest,
      public testing::WithParamInterface<VAType> {
 public:
  AttestationServiceEnterpriseTest() : va_type_(GetParam()) {}
  ~AttestationServiceEnterpriseTest() override = default;

 protected:
  VAType va_type_;
  // A default GoogleKeys instance that is supposed to be the identical key
  // database that |service_| uses.
  GoogleKeys google_keys_;
};

TEST_P(AttestationServiceEnterpriseTest, SignEnterpriseChallengeSuccess) {
  KeyInfo key_info = CreateChallengeKeyInfo();
  std::string key_info_str;
  key_info.SerializeToString(&key_info_str);
  EXPECT_CALL(
      mock_crypto_utility_,
      VerifySignatureUsingHexKey(
          _, google_keys_.va_signing_key(va_type_).modulus_in_hex(), _, _))
      .WillRepeatedly(Return(true));
  EXPECT_CALL(
      mock_crypto_utility_,
      EncryptDataForGoogle(
          key_info_str,
          google_keys_.va_encryption_key(va_type_).modulus_in_hex(), _, _))
      .WillRepeatedly(DoAll(SetArgPointee<3>(MockEncryptedData(key_info_str)),
                            Return(true)));
  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _))
      .WillRepeatedly(
          DoAll(SetArgPointee<2>(std::string("signature")), Return(true)));
  auto callback = [](const base::Closure& quit_closure,
                     const SignEnterpriseChallengeReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_challenge_response());
    SignedData signed_data;
    EXPECT_TRUE(signed_data.ParseFromString(reply.challenge_response()));
    EXPECT_EQ("signature", signed_data.signature());
    ChallengeResponse response_pb;
    EXPECT_TRUE(response_pb.ParseFromString(signed_data.data()));
    EXPECT_EQ(CreateChallenge("EnterpriseKeyChallenge"),
              response_pb.challenge().data());
    KeyInfo key_info = CreateChallengeKeyInfo();
    std::string key_info_str;
    key_info.SerializeToString(&key_info_str);
    EXPECT_EQ(key_info_str, response_pb.encrypted_key_info().encrypted_data());
    quit_closure.Run();
  };
  SignEnterpriseChallengeRequest request;
  request.set_va_type(va_type_);
  request.set_username("user");
  request.set_key_label("label");
  request.set_domain(key_info.domain());
  request.set_device_id(key_info.device_id());
  request.set_include_signed_public_key(false);
  request.set_challenge(CreateSignedChallenge("EnterpriseKeyChallenge"));
  service_->SignEnterpriseChallenge(request,
                                    base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceEnterpriseTest,
       SignEnterpriseChallengeInternalFailure) {
  KeyInfo key_info = CreateChallengeKeyInfo();
  std::string key_info_str;
  key_info.SerializeToString(&key_info_str);
  EXPECT_CALL(mock_crypto_utility_, VerifySignatureUsingHexKey(_, _, _, _))
      .WillRepeatedly(Return(true));
  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _)).WillRepeatedly(Return(false));
  auto callback = [](const base::Closure& quit_closure,
                     const SignEnterpriseChallengeReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_challenge_response());
    quit_closure.Run();
  };
  SignEnterpriseChallengeRequest request;
  request.set_va_type(va_type_);
  request.set_username("user");
  request.set_key_label("label");
  request.set_domain(key_info.domain());
  request.set_device_id(key_info.device_id());
  request.set_include_signed_public_key(false);
  request.set_challenge(CreateSignedChallenge("EnterpriseKeyChallenge"));
  service_->SignEnterpriseChallenge(request,
                                    base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceEnterpriseTest, SignEnterpriseChallengeBadPrefix) {
  KeyInfo key_info = CreateChallengeKeyInfo();
  std::string key_info_str;
  key_info.SerializeToString(&key_info_str);
  EXPECT_CALL(mock_crypto_utility_, VerifySignatureUsingHexKey(_, _, _, _))
      .WillRepeatedly(Return(true));
  auto callback = [](const base::Closure& quit_closure,
                     const SignEnterpriseChallengeReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_challenge_response());
    quit_closure.Run();
  };
  SignEnterpriseChallengeRequest request;
  request.set_va_type(va_type_);
  request.set_username("user");
  request.set_key_label("label");
  request.set_domain(key_info.domain());
  request.set_device_id(key_info.device_id());
  request.set_include_signed_public_key(false);
  request.set_challenge(CreateSignedChallenge("bad_prefix"));
  service_->SignEnterpriseChallenge(request,
                                    base::Bind(callback, QuitClosure()));
  Run();
}

// Test that if |key_name_for_spkac| is not empty then the key associated to it
// is used for SignedPublicKeyAndChallenge.
TEST_P(AttestationServiceEnterpriseTest,
       SignEnterpriseChallengeUseKeyForSPKAC) {
  static const char kKeyNameForSpkac[] = "attest-ent-machine_temp_id";
  static const char kKeyNameForSpkacPublicKey[] =
      "attest-ent-machine_public_key";

  CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
  key.set_public_key("public_key");
  key.set_key_name("label");

  // Create a machine key for SPKAC
  CertifiedKey& key_for_spkac =
      *mock_database_.GetMutableProtobuf()->add_device_keys();
  key_for_spkac.set_key_blob("key_blob");
  key_for_spkac.set_public_key(kKeyNameForSpkacPublicKey);
  key_for_spkac.set_key_name(kKeyNameForSpkac);
  key_for_spkac.set_certified_key_credential("fake_cert_data");

  KeyInfo expected_key_info =
      CreateMachineChallengeKeyInfoWithSPKAC("fake_cert_data", "fake_spkac");
  std::string expected_key_info_str;
  expected_key_info.SerializeToString(&expected_key_info_str);

  ExpectGetCustomerId("customer_id");
  EXPECT_CALL(
      mock_crypto_utility_,
      VerifySignatureUsingHexKey(
          _, google_keys_.va_signing_key(va_type_).modulus_in_hex(), _, _))
      .WillOnce(Return(true));
  EXPECT_CALL(
      mock_crypto_utility_,
      EncryptDataForGoogle(
          expected_key_info_str,
          google_keys_.va_encryption_key(va_type_).modulus_in_hex(), _, _))
      .WillOnce(
          DoAll(SetArgPointee<3>(MockEncryptedData(expected_key_info_str)),
                Return(true)));

  // Expect |CreateSPKAC| to be called for |key_name_for_spkac|.
  EXPECT_CALL(
      mock_crypto_utility_,
      CreateSPKAC(key_for_spkac.key_blob(), key_for_spkac.public_key(), _, _))
      .WillOnce(
          DoAll(SetArgPointee<3>(std::string("fake_spkac")), Return(true)));

  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _))
      .WillOnce(
          DoAll(SetArgPointee<2>(std::string("signature")), Return(true)));

  auto callback = [](const std::string& expected_key_info_str,
                     const base::Closure& quit_closure,
                     const SignEnterpriseChallengeReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_challenge_response());
    SignedData signed_data;
    EXPECT_TRUE(signed_data.ParseFromString(reply.challenge_response()));
    EXPECT_EQ("signature", signed_data.signature());
    ChallengeResponse response_pb;
    EXPECT_TRUE(response_pb.ParseFromString(signed_data.data()));
    // This relies on the fact that the mock for EncryptDataForGoogle just
    // passes the data unencrypted.
    EXPECT_EQ(expected_key_info_str,
              response_pb.encrypted_key_info().encrypted_data());
    quit_closure.Run();
  };
  SignEnterpriseChallengeRequest request;
  request.set_va_type(va_type_);
  request.set_key_label("label");
  request.set_domain("to_be_ignored");
  request.set_device_id(expected_key_info.device_id());
  request.set_include_signed_public_key(true);
  request.set_key_name_for_spkac(kKeyNameForSpkac);
  request.set_challenge(CreateSignedChallenge("EnterpriseKeyChallenge"));
  service_->SignEnterpriseChallenge(
      request, base::Bind(callback, expected_key_info_str, QuitClosure()));
  Run();
}

INSTANTIATE_TEST_SUITE_P(VerifiedAccessType,
                         AttestationServiceEnterpriseTest,
                         ::testing::Values(DEFAULT_VA, TEST_VA));

class AttestationServiceTest : public AttestationServiceBaseTest,
                               public testing::WithParamInterface<ACAType> {
 public:
  AttestationServiceTest() : aca_type_(GetParam()) {}
  ~AttestationServiceTest() override = default;

  void SetUp() override { AttestationServiceBaseTest::SetUp(); }

 protected:
  std::string CreateCAEnrollResponse(bool success) {
    AttestationEnrollmentResponse response_pb;
    if (success) {
      response_pb.set_status(OK);
      response_pb.set_detail("");
      response_pb.mutable_encrypted_identity_credential()->set_tpm_version(
          kTpmVersionUnderTest);
      response_pb.mutable_encrypted_identity_credential()->set_asym_ca_contents(
          "1234");
      response_pb.mutable_encrypted_identity_credential()
          ->set_sym_ca_attestation("5678");
      response_pb.mutable_encrypted_identity_credential()->set_encrypted_seed(
          "seed");
      response_pb.mutable_encrypted_identity_credential()->set_credential_mac(
          "mac");
      response_pb.mutable_encrypted_identity_credential()
          ->mutable_wrapped_certificate()
          ->set_wrapped_key("wrapped");
    } else {
      response_pb.set_status(SERVER_ERROR);
      response_pb.set_detail("fake_enroll_error");
    }
    std::string response_str;
    response_pb.SerializeToString(&response_str);
    return response_str;
  }

  std::string CreateCACertResponse(bool success, std::string message_id) {
    AttestationCertificateResponse response_pb;
    if (success) {
      response_pb.set_status(OK);
      response_pb.set_detail("");
      response_pb.set_message_id(message_id);
      response_pb.set_certified_key_credential("fake_cert");
      response_pb.set_intermediate_ca_cert("fake_ca_cert");
      *response_pb.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
    } else {
      response_pb.set_status(SERVER_ERROR);
      response_pb.set_message_id(message_id);
      response_pb.set_detail("fake_sign_error");
    }
    std::string response_str;
    response_pb.SerializeToString(&response_str);
    return response_str;
  }

  AttestationCertificateRequest GenerateCACertRequest() {
    SetUpIdentity(identity_);
    SetUpIdentityCertificate(identity_, DEFAULT_ACA);
    base::RunLoop loop;
    auto callback = [](base::RunLoop* loop,
                       AttestationCertificateRequest* pca_request,
                       const CreateCertificateRequestReply& reply) {
      pca_request->ParseFromString(reply.pca_request());
      loop->Quit();
    };
    CreateCertificateRequestRequest request;
    request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
    AttestationCertificateRequest pca_request;
    service_->CreateCertificateRequest(
        request, base::Bind(callback, &loop, &pca_request));
    loop.Run();
    return pca_request;
  }

  ACAType aca_type_;
};

TEST_P(AttestationServiceTest, GetAttestationKeyInfoSuccess) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  // Set expectations on the outputs.
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const GetAttestationKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ("public_key", reply.public_key());
    EXPECT_EQ("public_key_tpm", reply.public_key_tpm_format());
    EXPECT_EQ(cert_name, reply.certificate());
    EXPECT_EQ("pcr0", reply.pcr0_quote().quote());
    EXPECT_EQ("pcr1", reply.pcr1_quote().quote());
    quit_closure.Run();
  };
  GetAttestationKeyInfoRequest request;
  request.set_aca_type(aca_type_);
  service_->GetAttestationKeyInfo(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetAttestationKeyInfoNoInfo) {
  SetUpIdentityCertificate(identity_, aca_type_);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const GetAttestationKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_NOT_AVAILABLE, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_public_key_tpm_format());
    EXPECT_FALSE(reply.has_certificate());
    EXPECT_FALSE(reply.has_pcr0_quote());
    EXPECT_FALSE(reply.has_pcr1_quote());
    quit_closure.Run();
  };
  GetAttestationKeyInfoRequest request;
  request.set_aca_type(aca_type_);
  service_->GetAttestationKeyInfo(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetAttestationKeyInfoSomeInfo) {
  SetUpIdentity(identity_);
  auto* identity_data =
      mock_database_.GetMutableProtobuf()->mutable_identities()->Mutable(
          identity_);
  identity_data->mutable_identity_key()->clear_identity_public_key_der();
  identity_data->mutable_identity_binding()
      ->clear_identity_public_key_tpm_format();
  identity_data->mutable_pcr_quotes()->erase(0);
  SetUpIdentityCertificate(identity_, aca_type_);
  // Set expectations on the outputs.
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const GetAttestationKeyInfoReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_public_key_tpm_format());
    EXPECT_EQ(cert_name, reply.certificate());
    EXPECT_FALSE(reply.has_pcr0_quote());
    EXPECT_EQ("pcr1", reply.pcr1_quote().quote());
    quit_closure.Run();
  };
  GetAttestationKeyInfoRequest request;
  request.set_aca_type(aca_type_);
  service_->GetAttestationKeyInfo(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, ActivateAttestationKeySuccess) {
  SetUpIdentity(identity_);
  EXPECT_CALL(mock_database_, SaveChanges()).Times(1);
  const std::string cert_name = GetCertificateName(identity_, aca_type_);
  if (kTpmVersionUnderTest == TPM_1_2) {
    EXPECT_CALL(mock_tpm_utility_,
                ActivateIdentity(_, "encrypted1", "encrypted2", _))
        .WillOnce(DoAll(SetArgPointee<3>(cert_name), Return(true)));
  } else {
    EXPECT_CALL(
        mock_tpm_utility_,
        ActivateIdentityForTpm2(KEY_TYPE_ECC, _, "seed", "mac", "wrapped", _))
        .WillOnce(DoAll(SetArgPointee<5>(cert_name), Return(true)));
  }
  // Set expectations on the outputs.
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const ActivateAttestationKeyReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(cert_name, reply.certificate());
    quit_closure.Run();
  };
  ActivateAttestationKeyRequest request;
  request.set_aca_type(aca_type_);
  request.mutable_encrypted_certificate()->set_tpm_version(
      kTpmVersionUnderTest);
  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
  request.mutable_encrypted_certificate()->set_encrypted_seed("seed");
  request.mutable_encrypted_certificate()->set_credential_mac("mac");
  request.mutable_encrypted_certificate()
      ->mutable_wrapped_certificate()
      ->set_wrapped_key("wrapped");
  request.set_save_certificate(true);
  service_->ActivateAttestationKey(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, ActivateAttestationKeySuccessNoSave) {
  SetUpIdentity(identity_);
  EXPECT_CALL(mock_database_, GetMutableProtobuf()).Times(0);
  EXPECT_CALL(mock_database_, SaveChanges()).Times(0);
  const std::string cert_name = GetCertificateName(identity_, aca_type_);
  if (kTpmVersionUnderTest == TPM_1_2) {
    EXPECT_CALL(mock_tpm_utility_,
                ActivateIdentity(_, "encrypted1", "encrypted2", _))
        .WillOnce(DoAll(SetArgPointee<3>(cert_name), Return(true)));
  } else {
    EXPECT_CALL(
        mock_tpm_utility_,
        ActivateIdentityForTpm2(KEY_TYPE_ECC, _, "seed", "mac", "wrapped", _))
        .WillOnce(DoAll(SetArgPointee<5>(cert_name), Return(true)));
  }
  // Set expectations on the outputs.
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const ActivateAttestationKeyReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(cert_name, reply.certificate());
    quit_closure.Run();
  };
  ActivateAttestationKeyRequest request;
  request.set_aca_type(aca_type_);
  request.mutable_encrypted_certificate()->set_tpm_version(
      kTpmVersionUnderTest);
  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
  request.mutable_encrypted_certificate()->set_encrypted_seed("seed");
  request.mutable_encrypted_certificate()->set_credential_mac("mac");
  request.mutable_encrypted_certificate()
      ->mutable_wrapped_certificate()
      ->set_wrapped_key("wrapped");
  service_->ActivateAttestationKey(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, ActivateAttestationKeySaveFailure) {
  SetUpIdentity(identity_);
  EXPECT_CALL(mock_database_, SaveChanges()).WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const ActivateAttestationKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  ActivateAttestationKeyRequest request;
  request.set_aca_type(aca_type_);
  request.mutable_encrypted_certificate()->set_tpm_version(
      kTpmVersionUnderTest);
  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
  request.mutable_encrypted_certificate()->set_encrypted_seed("seed");
  request.mutable_encrypted_certificate()->set_credential_mac("mac");
  request.mutable_encrypted_certificate()
      ->mutable_wrapped_certificate()
      ->set_wrapped_key("wrapped");
  request.set_save_certificate(true);
  service_->ActivateAttestationKey(request,
                                   base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, ActivateAttestationKeyActivateFailure) {
  SetUpIdentity(identity_);
  if (kTpmVersionUnderTest == TPM_1_2) {
    EXPECT_CALL(mock_tpm_utility_,
                ActivateIdentity(_, "encrypted1", "encrypted2", _))
        .WillRepeatedly(Return(false));
  } else {
    EXPECT_CALL(
        mock_tpm_utility_,
        ActivateIdentityForTpm2(KEY_TYPE_ECC, _, "seed", "mac", "wrapped", _))
        .WillRepeatedly(Return(false));
  }
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const ActivateAttestationKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  ActivateAttestationKeyRequest request;
  request.set_aca_type(aca_type_);
  request.mutable_encrypted_certificate()->set_tpm_version(
      kTpmVersionUnderTest);
  request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1");
  request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2");
  request.mutable_encrypted_certificate()->set_encrypted_seed("seed");
  request.mutable_encrypted_certificate()->set_credential_mac("mac");
  request.mutable_encrypted_certificate()
      ->mutable_wrapped_certificate()
      ->set_wrapped_key("wrapped");
  request.set_save_certificate(true);
  service_->ActivateAttestationKey(request,
                                   base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeySuccess) {
  // We need an identity to create a certifiable key.
  SetUpIdentity(identity_);

  // Configure a fake TPM response.
  EXPECT_CALL(
      mock_tpm_utility_,
      CreateCertifiedKey(KEY_TYPE_RSA, KEY_USAGE_SIGN, _, _, _, _, _, _, _))
      .WillOnce(DoAll(SetArgPointee<5>(std::string("public_key")),
                      SetArgPointee<7>(std::string("certify_info")),
                      SetArgPointee<8>(std::string("certify_info_signature")),
                      Return(true)));
  // Expect the key to be written exactly once.
  EXPECT_CALL(mock_key_store_, Write("user", "label", _)).Times(1);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ("public_key", reply.public_key());
    EXPECT_EQ("certify_info", reply.certify_info());
    EXPECT_EQ("certify_info_signature", reply.certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  request.set_username("user");
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeySuccessNoUser) {
  // We need an identity to create a certifiable key.
  SetUpIdentity(identity_);

  // Configure a fake TPM response.
  EXPECT_CALL(
      mock_tpm_utility_,
      CreateCertifiedKey(KEY_TYPE_RSA, KEY_USAGE_SIGN, _, _, _, _, _, _, _))
      .WillOnce(DoAll(SetArgPointee<5>(std::string("public_key")),
                      SetArgPointee<7>(std::string("certify_info")),
                      SetArgPointee<8>(std::string("certify_info_signature")),
                      Return(true)));
  // Expect the key to be written exactly once.
  EXPECT_CALL(mock_database_, SaveChanges()).Times(1);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ("public_key", reply.public_key());
    EXPECT_EQ("certify_info", reply.certify_info());
    EXPECT_EQ("certify_info_signature", reply.certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeyRNGFailure) {
  // We need an identity to make sure it didn't fail because of that.
  SetUpIdentity(identity_);

  EXPECT_CALL(mock_crypto_utility_, GetRandom(_, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_certify_info());
    EXPECT_FALSE(reply.has_certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeyNoIdentityFailure) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_certify_info());
    EXPECT_FALSE(reply.has_certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeyTpmCreateFailure) {
  // We need an identity to create a certifiable key.
  SetUpIdentity(identity_);

  EXPECT_CALL(mock_tpm_utility_, CreateCertifiedKey(_, _, _, _, _, _, _, _, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_certify_info());
    EXPECT_FALSE(reply.has_certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeyDBFailure) {
  // We need an identity to make sure it didn't fail because of that.
  SetUpIdentity(identity_);

  EXPECT_CALL(mock_key_store_, Write(_, _, _)).WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_certify_info());
    EXPECT_FALSE(reply.has_certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  request.set_username("username");
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertifiableKeyDBFailureNoUser) {
  // We need an identity to make sure it didn't fail because of that.
  SetUpIdentity(identity_);

  EXPECT_CALL(mock_database_, SaveChanges()).WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertifiableKeyReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_public_key());
    EXPECT_FALSE(reply.has_certify_info());
    EXPECT_FALSE(reply.has_certify_info_signature());
    quit_closure.Run();
  };
  CreateCertifiableKeyRequest request;
  request.set_key_label("label");
  request.set_key_type(KEY_TYPE_RSA);
  request.set_key_usage(KEY_USAGE_SIGN);
  service_->CreateCertifiableKey(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DecryptSuccess) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DecryptReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(MockTpmUtility::Transform("Unbind", "data"),
              reply.decrypted_data());
    quit_closure.Run();
  };
  DecryptRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_encrypted_data("data");
  service_->Decrypt(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DecryptSuccessNoUser) {
  mock_database_.GetMutableProtobuf()->add_device_keys()->set_key_name("label");
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DecryptReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(MockTpmUtility::Transform("Unbind", "data"),
              reply.decrypted_data());
    quit_closure.Run();
  };
  DecryptRequest request;
  request.set_key_label("label");
  request.set_encrypted_data("data");
  service_->Decrypt(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DecryptKeyNotFound) {
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DecryptReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_decrypted_data());
    quit_closure.Run();
  };
  DecryptRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_encrypted_data("data");
  service_->Decrypt(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DecryptKeyNotFoundNoUser) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DecryptReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_decrypted_data());
    quit_closure.Run();
  };
  DecryptRequest request;
  request.set_key_label("label");
  request.set_encrypted_data("data");
  service_->Decrypt(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DecryptUnbindFailure) {
  EXPECT_CALL(mock_tpm_utility_, Unbind(_, _, _)).WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DecryptReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_decrypted_data());
    quit_closure.Run();
  };
  DecryptRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_encrypted_data("data");
  service_->Decrypt(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, SignSuccess) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const SignReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(MockTpmUtility::Transform("Sign", "data"), reply.signature());
    quit_closure.Run();
  };
  SignRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_data_to_sign("data");
  service_->Sign(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, SignSuccessNoUser) {
  mock_database_.GetMutableProtobuf()->add_device_keys()->set_key_name("label");
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const SignReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(MockTpmUtility::Transform("Sign", "data"), reply.signature());
    quit_closure.Run();
  };
  SignRequest request;
  request.set_key_label("label");
  request.set_data_to_sign("data");
  service_->Sign(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, SignKeyNotFound) {
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const SignReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_signature());
    quit_closure.Run();
  };
  SignRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_data_to_sign("data");
  service_->Sign(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, SignKeyNotFoundNoUser) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const SignReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_signature());
    quit_closure.Run();
  };
  SignRequest request;
  request.set_key_label("label");
  request.set_data_to_sign("data");
  service_->Sign(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, SignUnbindFailure) {
  EXPECT_CALL(mock_tpm_utility_, Sign(_, _, _)).WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const SignReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_signature());
    quit_closure.Run();
  };
  SignRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_data_to_sign("data");
  service_->Sign(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterSuccess) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));
  // Cardinality is verified here to verify various steps are performed and to
  // catch performance regressions.
  EXPECT_CALL(mock_key_store_,
              Register("user", "label", KEY_TYPE_RSA, KEY_USAGE_SIGN,
                       "key_blob", "public_key", ""))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate(_, _)).Times(0);
  EXPECT_CALL(mock_key_store_, Delete("user", "label")).Times(1);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterSuccessNoUser) {
  // Setup a key in the device_keys field.
  CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  // Cardinality is verified here to verify various steps are performed and to
  // catch performance regressions.
  EXPECT_CALL(mock_key_store_,
              Register("", "label", KEY_TYPE_RSA, KEY_USAGE_SIGN, "key_blob",
                       "public_key", ""))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate(_, _)).Times(0);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure, Database* database,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(0, database->GetMutableProtobuf()->device_keys_size());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  service_->RegisterKeyWithChapsToken(
      request, base::Bind(callback, QuitClosure(), &mock_database_));
  Run();
}

TEST_P(AttestationServiceTest, RegisterSuccessWithCertificates) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));
  // Cardinality is verified here to verify various steps are performed and to
  // catch performance regressions.
  EXPECT_CALL(mock_key_store_,
              Register("user", "label", KEY_TYPE_RSA, KEY_USAGE_SIGN,
                       "key_blob", "public_key", "fake_cert"))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate("user", "fake_ca_cert"))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate("user", "fake_ca_cert2"))
      .Times(1);
  EXPECT_CALL(mock_key_store_, Delete("user", "label")).Times(1);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_include_certificates(true);
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterSuccessNoUserWithCertificates) {
  // Setup a key in the device_keys field.
  CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  // Cardinality is verified here to verify various steps are performed and to
  // catch performance regressions.
  EXPECT_CALL(mock_key_store_,
              Register("", "label", KEY_TYPE_RSA, KEY_USAGE_SIGN, "key_blob",
                       "public_key", "fake_cert"))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate("", "fake_ca_cert"))
      .Times(1);
  EXPECT_CALL(mock_key_store_, RegisterCertificate("", "fake_ca_cert2"))
      .Times(1);
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure, Database* database,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(0, database->GetMutableProtobuf()->device_keys_size());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_include_certificates(true);
  service_->RegisterKeyWithChapsToken(
      request, base::Bind(callback, QuitClosure(), &mock_database_));
  Run();
}

TEST_P(AttestationServiceTest, RegisterNoKey) {
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterNoKeyNoUser) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterFailure) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_name("label");
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));
  EXPECT_CALL(mock_key_store_, Register(_, _, _, _, _, _, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterIntermediateFailure) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_name("label");
  key.set_intermediate_ca_cert("fake_ca_cert");
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));
  EXPECT_CALL(mock_key_store_, RegisterCertificate(_, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_include_certificates(true);
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, RegisterAdditionalFailure) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_name("label");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  std::string key_bytes;
  key.SerializeToString(&key_bytes);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(key_bytes), Return(true)));
  EXPECT_CALL(mock_key_store_, RegisterCertificate(_, _))
      .WillRepeatedly(Return(false));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const RegisterKeyWithChapsTokenReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  RegisterKeyWithChapsTokenRequest request;
  request.set_key_label("label");
  request.set_username("user");
  request.set_include_certificates(true);
  service_->RegisterKeyWithChapsToken(request,
                                      base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeysByLabelSuccess) {
  // Setup a key in the user key store.
  CertifiedKey key;
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);
  std::string key_bytes;
  key.SerializeToString(&key_bytes);

  EXPECT_CALL(mock_key_store_, Delete("user", "label"))
      .Times(1)
      .WillOnce(Return(true));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  request.set_match_behavior(DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
  request.set_username("user");
  service_->DeleteKeys(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeyByLabelNoUserSuccess) {
  // Setup a key in the device_keys field.
  CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
  key.set_key_blob("key_blob");
  key.set_public_key("public_key");
  key.set_certified_key_credential("fake_cert");
  key.set_intermediate_ca_cert("fake_ca_cert");
  *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
  key.set_key_name("label");
  key.set_key_type(KEY_TYPE_RSA);
  key.set_key_usage(KEY_USAGE_SIGN);

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure, Database* database,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(0, database->GetMutableProtobuf()->device_keys_size());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  request.set_match_behavior(DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
  service_->DeleteKeys(request,
                       base::Bind(callback, QuitClosure(), &mock_database_));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeysByLabelNoKey) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  request.set_match_behavior(DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
  request.set_username("user");
  service_->DeleteKeys(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeyByLabelNoUserNoKey) {
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  request.set_match_behavior(DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
  service_->DeleteKeys(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeysByPrefixSuccess) {
  EXPECT_CALL(mock_key_store_, DeleteByPrefix("user", "label"))
      .Times(1)
      .WillOnce(Return(true));
  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  request.set_username("user");
  service_->DeleteKeys(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, DeleteKeyByPrefixNoUserSuccess) {
  // Setup a key in the device_keys field.
  const std::string key_labels[] = {"label1", "label2", "otherprefix"};
  for (const auto& key_label : key_labels) {
    CertifiedKey& key = *mock_database_.GetMutableProtobuf()->add_device_keys();
    key.set_key_blob("key_blob");
    key.set_public_key("public_key");
    key.set_certified_key_credential("fake_cert");
    key.set_intermediate_ca_cert("fake_ca_cert");
    *key.add_additional_intermediate_ca_cert() = "fake_ca_cert2";
    key.set_key_name(key_label);
    key.set_key_type(KEY_TYPE_RSA);
    key.set_key_usage(KEY_USAGE_SIGN);
  }

  // Set expectations on the outputs.
  auto callback = [](const base::Closure& quit_closure, Database* database,
                     const DeleteKeysReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_EQ(1, database->GetMutableProtobuf()->device_keys_size());
    EXPECT_EQ("otherprefix",
              database->GetMutableProtobuf()->device_keys()[0].key_name());
    quit_closure.Run();
  };
  DeleteKeysRequest request;
  request.set_key_label_match("label");
  service_->DeleteKeys(request,
                       base::Bind(callback, QuitClosure(), &mock_database_));
  Run();
}

TEST_P(AttestationServiceTest, PrepareForEnrollment) {
  // Start with an empty database.
  mock_database_.GetMutableProtobuf()->Clear();
  // Schedule initialization again to make sure it runs after this point.
  EXPECT_CALL(mock_tpm_utility_, GetNVDataSize(_, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(9487), Return(true)));
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  // One identity has been created.
  EXPECT_EQ(1, mock_database_.GetProtobuf().identities().size());
  const AttestationDatabase::Identity& identity_data =
      mock_database_.GetProtobuf().identities().Get(0);
  EXPECT_TRUE(identity_data.has_identity_binding());
  EXPECT_TRUE(identity_data.has_identity_key());
  EXPECT_EQ(1, identity_data.pcr_quotes().count(0));
  EXPECT_EQ(1, identity_data.pcr_quotes().count(1));
#if USE_TPM2
  EXPECT_EQ(1, identity_data.nvram_quotes().count(BOARD_ID));
  EXPECT_EQ(1, identity_data.nvram_quotes().count(SN_BITS));
  EXPECT_EQ(service_->GetEndorsementKeyType() != KEY_TYPE_RSA ? 1 : 0,
            identity_data.nvram_quotes().count(RSA_PUB_EK_CERT));
#else
  EXPECT_TRUE(identity_data.nvram_quotes().empty());
#endif
  EXPECT_EQ(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID,
            identity_data.features());
  // Deprecated identity-related values have not been set.
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_key());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_binding());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr0_quote());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr1_quote());
  // Verify Privacy CA-related data.
  VerifyACAData(mock_database_.GetProtobuf());
  // These deprecated fields have not been set either.
  EXPECT_TRUE(mock_database_.GetProtobuf().has_credentials());
  EXPECT_FALSE(mock_database_.GetProtobuf()
                   .credentials()
                   .has_default_encrypted_endorsement_credential());
}

#if USE_TPM2

TEST_P(AttestationServiceTest,
       PrepareForEnrollmentCannotQuoteOptionalNvramForRsaEK) {
  auto database_pb = mock_database_.GetMutableProtobuf();
  // Start with an empty database to trigger PrepareForEnrollment.
  database_pb->Clear();

  // Setup the database to make GetEndorsementKeyType to return specific key
  // type, but will still make IsPreparedForEnrollment return false.
  database_pb->mutable_credentials()->set_endorsement_key_type(KEY_TYPE_RSA);
  database_pb->mutable_credentials()->set_endorsement_public_key("pubkey");

  EXPECT_CALL(mock_tpm_utility_, CertifyNV(_, _, _, _, _))
      .WillRepeatedly(Return(false));

  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));

  // One identity has been created.
  EXPECT_EQ(1, mock_database_.GetProtobuf().identities().size());
  const AttestationDatabase::Identity& identity_data =
      mock_database_.GetProtobuf().identities().Get(0);
  EXPECT_TRUE(identity_data.has_identity_binding());
  EXPECT_TRUE(identity_data.has_identity_key());
  EXPECT_EQ(1, identity_data.pcr_quotes().count(0));
  EXPECT_EQ(1, identity_data.pcr_quotes().count(1));
  EXPECT_TRUE(identity_data.nvram_quotes().empty());
  EXPECT_EQ(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID,
            identity_data.features());
}

TEST_P(AttestationServiceTest,
       PrepareForEnrollmentCannotQuoteOptionalNvramForEccEK) {
  auto database_pb = mock_database_.GetMutableProtobuf();

  // Start with an empty database to trigger PrepareForEnrollment.
  database_pb->Clear();

  // Setup the database to make GetEndorsementKeyType to return specific key
  // type, but will still make IsPreparedForEnrollment return false.
  database_pb->mutable_credentials()->set_endorsement_key_type(KEY_TYPE_ECC);
  database_pb->mutable_credentials()->set_endorsement_public_key("pubkey");

  // Assume the NV indexes doesn't exist, except RSA EK cert which is required
  // when ECC EK is enabled.
  EXPECT_CALL(mock_tpm_utility_, GetNVDataSize(_, _))
      .WillRepeatedly(DoAll(SetArgPointee<1>(9487), Return(true)));
  EXPECT_CALL(mock_tpm_utility_, CertifyNV(_, _, _, _, _))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(mock_tpm_utility_,
              CertifyNV(trunks::kRsaEndorsementCertificateIndex, _, _, _, _))
      .WillRepeatedly(Return(true));

  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));

  // One identity has been created.
  EXPECT_EQ(1, mock_database_.GetProtobuf().identities().size());
  const AttestationDatabase::Identity& identity_data =
      mock_database_.GetProtobuf().identities().Get(0);
  EXPECT_TRUE(identity_data.has_identity_binding());
  EXPECT_TRUE(identity_data.has_identity_key());
  EXPECT_EQ(1, identity_data.pcr_quotes().count(0));
  EXPECT_EQ(1, identity_data.pcr_quotes().count(1));
  EXPECT_EQ(1, identity_data.nvram_quotes().size());
  EXPECT_EQ(1, identity_data.nvram_quotes().count(RSA_PUB_EK_CERT));
  EXPECT_EQ(IDENTITY_FEATURE_ENTERPRISE_ENROLLMENT_ID,
            identity_data.features());
}

TEST_P(AttestationServiceTest,
       PrepareForEnrollmentCannotQuoteRsaEKCertForEccEK) {
  auto database_pb = mock_database_.GetMutableProtobuf();

  // Start with an empty database to trigger PrepareForEnrollment.
  database_pb->Clear();

  // Setup the database to make GetEndorsementKeyType to return specific key
  // type, but will still make IsPreparedForEnrollment return false.
  database_pb->mutable_credentials()->set_endorsement_key_type(KEY_TYPE_ECC);
  database_pb->mutable_credentials()->set_endorsement_public_key("pubkey");

  EXPECT_CALL(mock_tpm_utility_, CertifyNV(_, _, _, _, _))
      .WillRepeatedly(Return(false));

  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));

  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_key());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_binding());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr0_quote());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr1_quote());
}

#endif

TEST_P(AttestationServiceTest, PrepareForEnrollmentNoPublicKey) {
  // Start with an empty database.
  mock_database_.GetMutableProtobuf()->Clear();
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementPublicKey(_, _))
      .WillRepeatedly(Return(false));
  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  EXPECT_FALSE(mock_database_.GetProtobuf().has_credentials());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_key());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_binding());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr0_quote());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr1_quote());
}

TEST_P(AttestationServiceTest, PrepareForEnrollmentNoCert) {
  // Start with an empty database.
  mock_database_.GetMutableProtobuf()->Clear();
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementCertificate(_, _))
      .WillRepeatedly(Return(false));
  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  EXPECT_FALSE(mock_database_.GetProtobuf().has_credentials());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_key());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_binding());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr0_quote());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr1_quote());
}

TEST_P(AttestationServiceTest, PrepareForEnrollmentFailAIK) {
  // Start with an empty database.
  mock_database_.GetMutableProtobuf()->Clear();
  EXPECT_CALL(mock_tpm_utility_, CreateIdentity(_, _))
      .WillRepeatedly(Return(false));
  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  // No identity was created.
  EXPECT_EQ(0, mock_database_.GetProtobuf().identities().size());
  // And no credentials were stored.
  EXPECT_FALSE(mock_database_.GetProtobuf().has_credentials());
}

TEST_P(AttestationServiceTest, PrepareForEnrollmentFailQuote) {
  // Start with an empty database.
  mock_database_.GetMutableProtobuf()->Clear();
  EXPECT_CALL(mock_tpm_utility_, QuotePCR(_, _, _, _, _))
      .WillRepeatedly(Return(false));
  // Schedule initialization again to make sure it runs after this point.
  CHECK(CallAndWait(base::BindOnce(&AttestationService::InitializeWithCallback,
                                   base::Unretained(service_.get()))));
  EXPECT_FALSE(mock_database_.GetProtobuf().has_credentials());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_key());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_identity_binding());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr0_quote());
  EXPECT_FALSE(mock_database_.GetProtobuf().has_pcr1_quote());
}

TEST_P(AttestationServiceTest, ComputeEnterpriseEnrollmentId) {
  EXPECT_CALL(mock_tpm_utility_, GetEndorsementPublicKeyModulus(_, _))
      .WillRepeatedly(
          DoAll(SetArgPointee<1>(std::string("ekm")), Return(true)));
  brillo::SecureBlob abe_data(0xCA, 32);
  service_->set_abe_data(&abe_data);
  CryptoUtilityImpl crypto_utility(&mock_tpm_utility_);
  service_->set_crypto_utility(&crypto_utility);
  std::string enrollment_id = ComputeEnterpriseEnrollmentId();
  EXPECT_EQ("635c4526dfa583362273e2987944007b09131cfa0f4e5874e7a76d55d333e3cc",
            base::ToLowerASCII(
                base::HexEncode(enrollment_id.data(), enrollment_id.size())));
}

TEST_P(AttestationServiceTest, CreateCertificateRequestSuccess) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationCertificateRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ(ENTERPRISE_MACHINE_CERTIFICATE, pca_request.profile());
    EXPECT_TRUE(pca_request.nvram_quotes().empty());
    EXPECT_EQ(cert_name, pca_request.identity_credential());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateEnrollmentCertificateRequestSuccess) {
#if USE_TPM2
  EXPECT_CALL(mock_tpm_utility_,
              CertifyNV(VIRTUAL_NV_INDEX_RSU_DEV_ID, _, _, _, _))
      .WillRepeatedly(DoAll(SetArgPointee<3>("rsu_device_id_quoted_data"),
                            SetArgPointee<4>("rsu_device_id"), Return(true)));
#endif
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationCertificateRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ(ENTERPRISE_ENROLLMENT_CERTIFICATE, pca_request.profile());
#if USE_TPM2
    EXPECT_EQ(3, pca_request.nvram_quotes().size());
    EXPECT_EQ("board_id", pca_request.nvram_quotes().at(BOARD_ID).quote());
    EXPECT_EQ("sn_bits", pca_request.nvram_quotes().at(SN_BITS).quote());
    EXPECT_EQ("rsu_device_id",
              pca_request.nvram_quotes().at(RSU_DEVICE_ID).quote());
    EXPECT_EQ("rsu_device_id_quoted_data",
              pca_request.nvram_quotes().at(RSU_DEVICE_ID).quoted_data());
#else
    EXPECT_TRUE(pca_request.nvram_quotes().empty());
#endif
    EXPECT_EQ(cert_name, pca_request.identity_credential());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_ENROLLMENT_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest,
       CreateEnrollmentCertificateRequestSuccessWithUnattestedRsuDeviceId) {
#if USE_TPM2
  EXPECT_CALL(mock_tpm_utility_,
              CertifyNV(VIRTUAL_NV_INDEX_RSU_DEV_ID, _, _, _, _))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(mock_tpm_utility_, GetRsuDeviceId(_))
      .WillRepeatedly(DoAll(SetArgPointee<0>("rsu_device_id"), Return(true)));
#endif
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationCertificateRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ(ENTERPRISE_ENROLLMENT_CERTIFICATE, pca_request.profile());
#if USE_TPM2
    EXPECT_EQ(2, pca_request.nvram_quotes().size());
    EXPECT_EQ("board_id", pca_request.nvram_quotes().at(BOARD_ID).quote());
    EXPECT_EQ("sn_bits", pca_request.nvram_quotes().at(SN_BITS).quote());
    EXPECT_EQ(pca_request.nvram_quotes().end(),
              pca_request.nvram_quotes().find(RSU_DEVICE_ID));
#else
    EXPECT_TRUE(pca_request.nvram_quotes().empty());
#endif
    EXPECT_EQ(cert_name, pca_request.identity_credential());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_ENROLLMENT_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest,
       CreateEnrollmentCertificateRequestWithoutRsuDeviceIdSuccess) {
#if USE_TPM2
  EXPECT_CALL(mock_tpm_utility_,
              CertifyNV(VIRTUAL_NV_INDEX_RSU_DEV_ID, _, _, _, _))
      .WillRepeatedly(Return(false));
  EXPECT_CALL(mock_tpm_utility_, GetRsuDeviceId(_))
      .WillRepeatedly(Return(false));
#endif
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const std::string& cert_name,
                     const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationCertificateRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ(ENTERPRISE_ENROLLMENT_CERTIFICATE, pca_request.profile());
#if USE_TPM2
    EXPECT_EQ(2, pca_request.nvram_quotes().size());
    EXPECT_EQ("board_id", pca_request.nvram_quotes().at(BOARD_ID).quote());
    EXPECT_EQ("sn_bits", pca_request.nvram_quotes().at(SN_BITS).quote());
    EXPECT_EQ(pca_request.nvram_quotes().find(RSU_DEVICE_ID),
              pca_request.nvram_quotes().cend());
#else
    EXPECT_TRUE(pca_request.nvram_quotes().empty());
#endif
    EXPECT_EQ(cert_name, pca_request.identity_credential());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_ENROLLMENT_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(
      request, base::Bind(callback, GetCertificateName(identity_, aca_type_),
                          QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertificateRequestInternalFailure) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  EXPECT_CALL(mock_crypto_utility_, GetRandom(_, _))
      .WillRepeatedly(Return(false));
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_pca_request());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateCertificateRequestNotEnrolled) {
  // No identiy certificate, so not enrolled.
  mock_database_.GetMutableProtobuf()->Clear();
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const CreateCertificateRequestReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_pca_request());
    quit_closure.Run();
  };
  CreateCertificateRequestRequest request;
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  service_->CreateCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, FinishCertificateRequestSuccess) {
  auto callback = [](const base::Closure& quit_closure,
                     const FinishCertificateRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_certificate());
    quit_closure.Run();
  };
  AttestationCertificateRequest pca_request = GenerateCACertRequest();
  FinishCertificateRequestRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_pca_response(
      CreateCACertResponse(true, pca_request.message_id()));
  service_->FinishCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, FinishCertificateRequestInternalFailure) {
  EXPECT_CALL(mock_key_store_, Write(_, _, _)).WillRepeatedly(Return(false));
  auto callback = [](const base::Closure& quit_closure,
                     const FinishCertificateRequestReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_certificate());
    quit_closure.Run();
  };
  AttestationCertificateRequest pca_request = GenerateCACertRequest();
  FinishCertificateRequestRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_pca_response(
      CreateCACertResponse(true, pca_request.message_id()));
  service_->FinishCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, FinishCertificateRequestWrongMessageId) {
  auto callback = [](const base::Closure& quit_closure,
                     const FinishCertificateRequestReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_certificate());
    quit_closure.Run();
  };
  // Generate some request to populate pending_requests, but ignore its fields.
  GenerateCACertRequest();
  FinishCertificateRequestRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_pca_response(CreateCACertResponse(true, "wrong_id"));
  service_->FinishCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, FinishCertificateRequestServerFailure) {
  auto callback = [](const base::Closure& quit_closure,
                     const FinishCertificateRequestReply& reply) {
    EXPECT_NE(STATUS_SUCCESS, reply.status());
    EXPECT_FALSE(reply.has_certificate());
    quit_closure.Run();
  };
  // Generate some request to populate pending_requests, but ignore its fields.
  GenerateCACertRequest();
  FinishCertificateRequestRequest request;
  request.set_username("user");
  request.set_key_label("label");
  request.set_pca_response(CreateCACertResponse(false, ""));
  service_->FinishCertificateRequest(request,
                                     base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateEnrollRequestSuccessWithoutAbeData) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const CreateEnrollRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationEnrollmentRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ("wrapped_key",
              pca_request.encrypted_endorsement_credential().wrapped_key());
    EXPECT_EQ("public_key_tpm", pca_request.identity_public_key());
    EXPECT_EQ("pcr0", pca_request.pcr0_quote().quote());
    EXPECT_EQ("pcr1", pca_request.pcr1_quote().quote());
    EXPECT_FALSE(pca_request.has_enterprise_enrollment_nonce());
    quit_closure.Run();
  };
  CreateEnrollRequestRequest request;
  request.set_aca_type(aca_type_);
  service_->CreateEnrollRequest(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateEnrollRequestSuccessWithEmptyAbeData) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const CreateEnrollRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationEnrollmentRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ("wrapped_key",
              pca_request.encrypted_endorsement_credential().wrapped_key());
    EXPECT_EQ("public_key_tpm", pca_request.identity_public_key());
    EXPECT_EQ("pcr0", pca_request.pcr0_quote().quote());
    EXPECT_EQ("pcr1", pca_request.pcr1_quote().quote());
    EXPECT_FALSE(pca_request.has_enterprise_enrollment_nonce());
    quit_closure.Run();
  };
  brillo::SecureBlob abe_data;
  service_->set_abe_data(&abe_data);
  CreateEnrollRequestRequest request;
  request.set_aca_type(aca_type_);
  service_->CreateEnrollRequest(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, CreateEnrollRequestSuccessWithAbeData) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const CreateEnrollRequestReply& reply) {
    EXPECT_EQ(STATUS_SUCCESS, reply.status());
    EXPECT_TRUE(reply.has_pca_request());
    AttestationEnrollmentRequest pca_request;
    EXPECT_TRUE(pca_request.ParseFromString(reply.pca_request()));
    EXPECT_EQ(kTpmVersionUnderTest, pca_request.tpm_version());
    EXPECT_EQ("wrapped_key",
              pca_request.encrypted_endorsement_credential().wrapped_key());
    EXPECT_EQ("public_key_tpm", pca_request.identity_public_key());
    EXPECT_EQ("pcr0", pca_request.pcr0_quote().quote());
    EXPECT_EQ("pcr1", pca_request.pcr1_quote().quote());
    EXPECT_TRUE(pca_request.has_enterprise_enrollment_nonce());

    // Mocked CryptoUtility->HmacSha256 returns always a zeroed buffer.
    EXPECT_EQ(std::string(32, '\0'), pca_request.enterprise_enrollment_nonce());
    quit_closure.Run();
  };

  CreateEnrollRequestRequest request;
  request.set_aca_type(aca_type_);
  brillo::SecureBlob abe_data(0xCA, 32);
  service_->set_abe_data(&abe_data);
  service_->CreateEnrollRequest(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollSuccess) {
  SetUpIdentity(identity_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    quit_closure.Run();
  };

  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollSuccessNoop) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    quit_closure.Run();
  };
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(0);
  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollSuccessForced) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    quit_closure.Run();
  };

  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  request.set_forced(true);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollFailureNoIdentity) {
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(0);
  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollFailureBadPcaAgentStatus) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };

  fake_pca_agent_proxy_.SetEnrollDBusError();
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollFailureBadPcaAgentResponse) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_INVALID_PARAMETER);
    quit_closure.Run();
  };
  fake_pca_agent_proxy_.SetBadEnrollStatus(STATUS_INVALID_PARAMETER);
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, EnrollFailureBadPcaServerResponse) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_REQUEST_DENIED_BY_CA);
    quit_closure.Run();
  };

  fake_pca_agent_proxy_.SetBadEnrollPcaResponse();
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  service_->Enroll(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateSuccess) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    EXPECT_TRUE(reply.has_certificate());
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));

  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateSuccessNoop) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    EXPECT_TRUE(reply.has_public_key());
    EXPECT_TRUE(reply.has_certificate());
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(GenerateSerializedFakeCertifiedKey()),
                      Return(true)));
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(0);
  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateSuccessSavedBadPublicKey) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(DoAll(SetArgPointee<2>(GenerateSerializedFakeCertifiedKey()),
                      Return(true)));
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(0);
  EXPECT_CALL(mock_crypto_utility_, GetRSASubjectPublicKeyInfo(_, _))
      .WillOnce(Return(false));
  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateSuccessForced) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    EXPECT_TRUE(reply.has_certificate());
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  request.set_forced(true);
  // We shouldn't even check the key store.
  EXPECT_CALL(mock_key_store_, Read("user", "label", _)).Times(0);

  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateFailureNoIdentity) {
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(0);
  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateFailureBadPcaAgentStatus) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));
  brillo::ErrorPtr err = brillo::Error::Create(base::Location(), "", "", "");
  fake_pca_agent_proxy_.SetGetCertificateDBusError();
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateFailureBadPcaAgentResponse) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_NOT_AVAILABLE);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));

  pca_agent::GetCertificateReply reply;
  fake_pca_agent_proxy_.SetBadGetCertificateStatus(STATUS_NOT_AVAILABLE);
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, GetCertificateFailureBadPcaServerResponse) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_REQUEST_DENIED_BY_CA);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));

  fake_pca_agent_proxy_.SetBadGetCertificatePcaResponse();
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, AttestationFlowSuccess) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    EXPECT_TRUE(reply.has_certificate());
    EXPECT_TRUE(reply.has_public_key());
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  request.set_shall_trigger_enrollment(true);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));

  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, AttestationFlowBadPublicKey) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  request.set_shall_trigger_enrollment(true);
  EXPECT_CALL(mock_key_store_, Read("user", "label", _))
      .WillOnce(Return(false));

  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);
  EXPECT_CALL(mock_crypto_utility_, GetRSASubjectPublicKeyInfo(_, _))
      .WillOnce(Return(false));

  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

TEST_P(AttestationServiceTest, AttestationFlowFailureNotEnrolled) {
  SetUpIdentity(identity_);
  auto callback = [](const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
    quit_closure.Run();
  };
  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(0);
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(0);
  service_->GetCertificate(request, base::Bind(callback, QuitClosure()));
  Run();
}

// the extensive unittests that are worth being kept but unable to be in the
// standard set of unittest for any reason, e.g., flakiness.
#ifdef EXTENSIVE_UNITTEST

TEST_P(AttestationServiceTest, EnrollSuccessQueued) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");

  // Offset by 1; for enrollment request the request under process doesn't
  // count.
  int request_count = service_->kEnrollmentRequestLimit + 1;
  auto callback = [](int* count, const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    *count -= 1;
    if (*count == 0) {
      quit_closure.Run();
    }
  };

  auto failure_callback = [](const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
  };

  fake_pca_agent_proxy_.SetEnrollCallbackDelay(
      base::TimeDelta::FromMilliseconds(125));
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  request.set_forced(true);
  for (int i = 0; i < request_count; ++i) {
    service_->Enroll(request,
                     base::Bind(callback, &request_count, QuitClosure()));
  }
  // Reaching the limit, this request should get error.
  service_->Enroll(request, base::Bind(failure_callback));
  Run();
  ASSERT_EQ(request_count, 0);
}

TEST_P(AttestationServiceTest, EnrollFailureQueued) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);
  (*mock_database_.GetMutableProtobuf()
        ->mutable_credentials()
        ->mutable_encrypted_endorsement_credentials())[aca_type_]
      .set_wrapped_key("wrapped_key");

  // Offset by 1; for enrollment request the request under process doesn't
  // count.
  int request_count = service_->kEnrollmentRequestLimit + 1;
  auto callback = [](int* count, const base::Closure& quit_closure,
                     const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_INVALID_PARAMETER);
    *count -= 1;
    if (*count == 0) {
      quit_closure.Run();
    }
  };

  auto failure_callback = [](const EnrollReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
  };

  fake_pca_agent_proxy_.SetBadEnrollStatus(STATUS_INVALID_PARAMETER);
  fake_pca_agent_proxy_.SetEnrollCallbackDelay(
      base::TimeDelta::FromMilliseconds(125));
  EXPECT_CALL(fake_pca_agent_proxy_, EnrollAsync(_, _, _, _)).Times(1);

  EnrollRequest request;
  request.set_aca_type(aca_type_);
  request.set_forced(true);
  for (int i = 0; i < request_count; ++i) {
    service_->Enroll(request,
                     base::Bind(callback, &request_count, QuitClosure()));
  }
  // Reaching the limit, this request should get error.
  service_->Enroll(request, base::Bind(failure_callback));
  Run();
  ASSERT_EQ(request_count, 0);
}

TEST_P(AttestationServiceTest, GetCertificateSuccessQueued) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);

  int request_count = service_->kCertificateRequestAliasLimit;
  auto callback = [](int* count, const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_SUCCESS);
    *count -= 1;
    if (*count == 0) {
      quit_closure.Run();
    }
  };
  auto failure_callback = [](const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
  };

  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  request.set_forced(true);
  // We shouldn't even check the key store.
  EXPECT_CALL(mock_key_store_, Read("user", "label", _)).Times(0);

  fake_pca_agent_proxy_.SetGetCertificateCallbackDelay(
      base::TimeDelta::FromMilliseconds(125));
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  for (int i = 0; i < request_count; ++i) {
    service_->GetCertificate(
        request, base::Bind(callback, &request_count, QuitClosure()));
  }
  // This should due to alias contention.
  service_->GetCertificate(request, base::Bind(failure_callback));
  Run();
  ASSERT_EQ(request_count, 0);
}

TEST_P(AttestationServiceTest, GetCertificateFailureQueued) {
  SetUpIdentity(identity_);
  SetUpIdentityCertificate(identity_, aca_type_);

  int request_count = service_->kCertificateRequestAliasLimit;
  auto callback = [](int* count, const base::Closure& quit_closure,
                     const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_NOT_AVAILABLE);
    *count -= 1;
    if (*count == 0) {
      quit_closure.Run();
    }
  };
  auto failure_callback = [](const GetCertificateReply& reply) {
    EXPECT_EQ(reply.status(), STATUS_UNEXPECTED_DEVICE_ERROR);
  };

  GetCertificateRequest request;
  request.set_aca_type(aca_type_);
  request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
  request.set_username("user");
  request.set_request_origin("origin");
  request.set_key_label("label");
  request.set_forced(true);
  // We shouldn't even check the key store.
  EXPECT_CALL(mock_key_store_, Read("user", "label", _)).Times(0);

  fake_pca_agent_proxy_.SetBadGetCertificateStatus(STATUS_NOT_AVAILABLE);
  fake_pca_agent_proxy_.SetGetCertificateCallbackDelay(
      base::TimeDelta::FromMilliseconds(125));
  EXPECT_CALL(fake_pca_agent_proxy_, GetCertificateAsync(_, _, _, _)).Times(1);

  for (int i = 0; i < request_count; ++i) {
    service_->GetCertificate(
        request, base::Bind(callback, &request_count, QuitClosure()));
  }
  // This should due to alias contention.
  service_->GetCertificate(request, base::Bind(failure_callback));
  Run();
  ASSERT_EQ(request_count, 0);
}

#endif

INSTANTIATE_TEST_SUITE_P(AcaType,
                         AttestationServiceTest,
                         ::testing::Values(DEFAULT_ACA, TEST_ACA));

}  // namespace attestation
