//
// Copyright (C) 2015 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "attestation/server/attestation_service.h"

#include <string>

#include <base/callback.h>
#include <chromeos/bind_lambda.h>
#include <chromeos/data_encoding.h>
#include <chromeos/http/http_utils.h>
#include <chromeos/mime_utils.h>
#include <crypto/sha2.h>

#include "attestation/common/attestation_ca.pb.h"
#include "attestation/common/database.pb.h"
#include "attestation/server/database_impl.h"

namespace {

#ifndef USE_TEST_ACA
const char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
#else
const char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
#endif
const size_t kNonceSize = 20;  // As per TPM_NONCE definition.
const int kNumTemporalValues = 5;

}  // namespace

namespace attestation {

AttestationService::AttestationService()
    : attestation_ca_origin_(kACAWebOrigin),
      weak_factory_(this) {}

bool AttestationService::Initialize() {
  LOG(INFO) << "Attestation service started.";
  worker_thread_.reset(new base::Thread("Attestation Service Worker"));
  worker_thread_->StartWithOptions(
      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
  if (!tpm_utility_) {
    default_tpm_utility_.reset(new TpmUtilityV1());
    if (!default_tpm_utility_->Initialize()) {
      return false;
    }
    tpm_utility_ = default_tpm_utility_.get();
  }
  if (!crypto_utility_) {
    default_crypto_utility_.reset(new CryptoUtilityImpl(tpm_utility_));
    crypto_utility_ = default_crypto_utility_.get();
  }
  if (!database_) {
    default_database_.reset(new DatabaseImpl(crypto_utility_));
    worker_thread_->task_runner()->PostTask(FROM_HERE, base::Bind(
        &DatabaseImpl::Initialize,
        base::Unretained(default_database_.get())));
    database_ = default_database_.get();
  }
  if (!key_store_) {
    pkcs11_token_manager_.reset(new chaps::TokenManagerClient());
    default_key_store_.reset(new Pkcs11KeyStore(pkcs11_token_manager_.get()));
    key_store_ = default_key_store_.get();
  }
  return true;
}

void AttestationService::CreateGoogleAttestedKey(
    const CreateGoogleAttestedKeyRequest& request,
    const CreateGoogleAttestedKeyCallback& callback) {
  auto result = std::make_shared<CreateGoogleAttestedKeyReply>();
  base::Closure task = base::Bind(
      &AttestationService::CreateGoogleAttestedKeyTask,
      base::Unretained(this),
      request,
      result);
  base::Closure reply = base::Bind(
      &AttestationService::TaskRelayCallback<CreateGoogleAttestedKeyReply>,
      GetWeakPtr(),
      callback,
      result);
  worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
}

void AttestationService::CreateGoogleAttestedKeyTask(
    const CreateGoogleAttestedKeyRequest& request,
    const std::shared_ptr<CreateGoogleAttestedKeyReply>& result) {
  LOG(INFO) << "Creating attested key: " << request.key_label();
  if (!IsPreparedForEnrollment()) {
    LOG(ERROR) << "Attestation: TPM is not ready.";
    result->set_status(STATUS_NOT_READY);
    return;
  }
  if (!IsEnrolled()) {
    std::string enroll_request;
    if (!CreateEnrollRequest(&enroll_request)) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
    std::string enroll_reply;
    if (!SendACARequestAndBlock(kEnroll,
                                enroll_request,
                                &enroll_reply)) {
      result->set_status(STATUS_CA_NOT_AVAILABLE);
      return;
    }
    std::string server_error;
    if (!FinishEnroll(enroll_reply, &server_error)) {
      if (server_error.empty()) {
        result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
        return;
      }
      result->set_status(STATUS_REQUEST_DENIED_BY_CA);
      result->set_server_error(server_error);
      return;
    }
  }
  CertifiedKey key;
  if (!CreateKey(request.username(), request.key_label(), request.key_type(),
                 request.key_usage(), &key)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  std::string certificate_request;
  std::string message_id;
  if (!CreateCertificateRequest(request.username(),
                                key,
                                request.certificate_profile(),
                                request.origin(),
                                &certificate_request,
                                &message_id)) {
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  std::string certificate_reply;
  if (!SendACARequestAndBlock(kGetCertificate,
                              certificate_request,
                              &certificate_reply)) {
    result->set_status(STATUS_CA_NOT_AVAILABLE);
    return;
  }
  std::string certificate_chain;
  std::string server_error;
  if (!FinishCertificateRequest(certificate_reply,
                                request.username(),
                                request.key_label(),
                                message_id,
                                &key,
                                &certificate_chain,
                                &server_error)) {
    if (server_error.empty()) {
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
    result->set_status(STATUS_REQUEST_DENIED_BY_CA);
    result->set_server_error(server_error);
    return;
  }
  result->set_certificate_chain(certificate_chain);
}

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

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

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

void AttestationService::GetEndorsementInfoTask(
    const GetEndorsementInfoRequest& request,
    const std::shared_ptr<GetEndorsementInfoReply>& result) {
  if (request.key_type() != KEY_TYPE_RSA) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  auto database_pb = database_->GetProtobuf();
  if (!database_pb.has_credentials() ||
      !database_pb.credentials().has_endorsement_public_key()) {
    // Try to read the public key directly.
    std::string public_key;
    if (!tpm_utility_->GetEndorsementPublicKey(&public_key)) {
      result->set_status(STATUS_NOT_AVAILABLE);
      return;
    }
    database_pb.mutable_credentials()->set_endorsement_public_key(public_key);
  }
  std::string public_key_info;
  if (!GetSubjectPublicKeyInfo(
      request.key_type(),
      database_pb.credentials().endorsement_public_key(),
      &public_key_info)) {
    LOG(ERROR) << __func__ << ": Bad public key.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  result->set_ek_public_key(public_key_info);
  if (database_pb.credentials().has_endorsement_credential()) {
    result->set_ek_certificate(
        database_pb.credentials().endorsement_credential());
  }
}

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

void AttestationService::GetAttestationKeyInfoTask(
    const GetAttestationKeyInfoRequest& request,
    const std::shared_ptr<GetAttestationKeyInfoReply>& result) {
  if (request.key_type() != KEY_TYPE_RSA) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  auto database_pb = database_->GetProtobuf();
  if (!IsPreparedForEnrollment() || !database_pb.has_identity_key()) {
    result->set_status(STATUS_NOT_AVAILABLE);
    return;
  }
  if (database_pb.identity_key().has_identity_public_key()) {
    std::string public_key_info;
    if (!GetSubjectPublicKeyInfo(
        request.key_type(),
        database_pb.identity_key().identity_public_key(),
        &public_key_info)) {
      LOG(ERROR) << __func__ << ": Bad public key.";
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
      return;
    }
    result->set_public_key(public_key_info);
  }
  if (database_pb.has_identity_binding() &&
      database_pb.identity_binding().has_identity_public_key()) {
    result->set_public_key_tpm_format(
        database_pb.identity_binding().identity_public_key());
  }
  if (database_pb.identity_key().has_identity_credential()) {
    result->set_certificate(database_pb.identity_key().identity_credential());
  }
  if (database_pb.has_pcr0_quote()) {
    *result->mutable_pcr0_quote() = database_pb.pcr0_quote();
  }
  if (database_pb.has_pcr1_quote()) {
    *result->mutable_pcr1_quote() = database_pb.pcr1_quote();
  }
}

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

void AttestationService::ActivateAttestationKeyTask(
    const ActivateAttestationKeyRequest& request,
    const std::shared_ptr<ActivateAttestationKeyReply>& result) {
  if (request.key_type() != KEY_TYPE_RSA) {
    result->set_status(STATUS_INVALID_PARAMETER);
    return;
  }
  std::string certificate;
  auto database_pb = database_->GetProtobuf();
  if (!tpm_utility_->ActivateIdentity(
      database_pb.delegate().blob(),
      database_pb.delegate().secret(),
      database_pb.identity_key().identity_key_blob(),
      request.encrypted_certificate().asym_ca_contents(),
      request.encrypted_certificate().sym_ca_attestation(),
      &certificate)) {
    LOG(ERROR) << __func__ << ": Failed to activate identity.";
    result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    return;
  }
  if (request.save_certificate()) {
    database_->GetMutableProtobuf()->mutable_identity_key()->
        set_identity_credential(certificate);
    if (!database_->SaveChanges()) {
      LOG(ERROR) << __func__ << ": Failed to persist database changes.";
      result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    }
  }
  result->set_certificate(certificate);
}

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

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

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

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

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

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

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

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

bool AttestationService::IsPreparedForEnrollment() {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  auto database_pb = database_->GetProtobuf();
  if (!database_pb.has_credentials()) {
    return false;
  }
  return (database_pb.credentials().has_endorsement_credential() ||
          database_pb.credentials()
              .has_default_encrypted_endorsement_credential());
}

bool AttestationService::IsEnrolled() {
  auto database_pb = database_->GetProtobuf();
  return database_pb.has_identity_key() &&
         database_pb.identity_key().has_identity_credential();
}

bool AttestationService::CreateEnrollRequest(std::string* enroll_request) {
  if (!IsPreparedForEnrollment()) {
    LOG(ERROR) << __func__ << ": Enrollment is not possible, attestation data "
               << "does not exist.";
    return false;
  }
  auto database_pb = database_->GetProtobuf();
  AttestationEnrollmentRequest request_pb;
  *request_pb.mutable_encrypted_endorsement_credential() =
      database_pb.credentials().default_encrypted_endorsement_credential();
  request_pb.set_identity_public_key(
      database_pb.identity_binding().identity_public_key());
  *request_pb.mutable_pcr0_quote() = database_pb.pcr0_quote();
  *request_pb.mutable_pcr1_quote() = database_pb.pcr1_quote();
  if (!request_pb.SerializeToString(enroll_request)) {
    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    return false;
  }
  return true;
}

bool AttestationService::FinishEnroll(const std::string& enroll_response,
                                      std::string* server_error) {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  AttestationEnrollmentResponse response_pb;
  if (!response_pb.ParseFromString(enroll_response)) {
    LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
    return false;
  }
  if (response_pb.status() != OK) {
    *server_error = response_pb.detail();
    LOG(ERROR) << __func__ << ": Error received from CA: "
               << response_pb.detail();
    return false;
  }
  std::string credential;
  auto database_pb = database_->GetProtobuf();
  if (!tpm_utility_->ActivateIdentity(
      database_pb.delegate().blob(),
      database_pb.delegate().secret(),
      database_pb.identity_key().identity_key_blob(),
      response_pb.encrypted_identity_credential().asym_ca_contents(),
      response_pb.encrypted_identity_credential().sym_ca_attestation(),
      &credential)) {
    LOG(ERROR) << __func__ << ": Failed to activate identity.";
    return false;
  }
  database_->GetMutableProtobuf()->mutable_identity_key()->
      set_identity_credential(credential);
  if (!database_->SaveChanges()) {
    LOG(ERROR) << __func__ << ": Failed to persist database changes.";
    return false;
  }
  LOG(INFO) << "Attestation: Enrollment complete.";
  return true;
}

bool AttestationService::CreateCertificateRequest(
    const std::string& username,
    const CertifiedKey& key,
    CertificateProfile profile,
    const std::string& origin,
    std::string* certificate_request,
    std::string* message_id) {
  if (!tpm_utility_->IsTpmReady()) {
    return false;
  }
  if (!IsEnrolled()) {
    LOG(ERROR) << __func__ << ": Device is not enrolled for attestation.";
    return false;
  }
  AttestationCertificateRequest request_pb;
  if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
    LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
    return false;
  }
  request_pb.set_message_id(*message_id);
  auto database_pb = database_->GetProtobuf();
  request_pb.set_identity_credential(
      database_pb.identity_key().identity_credential());
  request_pb.set_profile(profile);
  if (!origin.empty() &&
      (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
    request_pb.set_origin(origin);
    request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
  }
  request_pb.set_certified_public_key(key.public_key_tpm_format());
  request_pb.set_certified_key_info(key.certified_key_info());
  request_pb.set_certified_key_proof(key.certified_key_proof());
  if (!request_pb.SerializeToString(certificate_request)) {
    LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    return false;
  }
  return true;
}

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

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

bool AttestationService::SendACARequestAndBlock(ACARequestType request_type,
                                                const std::string& request,
                                                std::string* reply) {
  std::shared_ptr<chromeos::http::Transport> transport = http_transport_;
  if (!transport) {
    transport = chromeos::http::Transport::CreateDefault();
  }
  std::unique_ptr<chromeos::http::Response> response = PostBinaryAndBlock(
      GetACAURL(request_type),
      request.data(),
      request.size(),
      chromeos::mime::application::kOctet_stream,
      {},  // headers
      transport,
      nullptr);  // error
  if (!response || !response->IsSuccessful()) {
    LOG(ERROR) << "HTTP request to Attestation CA failed.";
    return false;
  }
  *reply = response->ExtractDataAsString();
  return true;
}

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

bool AttestationService::CreateKey(const std::string& username,
                                   const std::string& key_label,
                                   KeyType key_type,
                                   KeyUsage key_usage,
                                   CertifiedKey* key) {
  std::string nonce;
  if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
    LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
    return false;
  }
  std::string key_blob;
  std::string public_key;
  std::string public_key_tpm_format;
  std::string key_info;
  std::string proof;
  auto database_pb = database_->GetProtobuf();
  if (!tpm_utility_->CreateCertifiedKey(
      key_type,
      key_usage,
      database_pb.identity_key().identity_key_blob(),
      nonce,
      &key_blob,
      &public_key,
      &public_key_tpm_format,
      &key_info,
      &proof)) {
    return false;
  }
  key->set_key_blob(key_blob);
  key->set_public_key(public_key);
  key->set_key_name(key_label);
  key->set_public_key_tpm_format(public_key_tpm_format);
  key->set_certified_key_info(key_info);
  key->set_certified_key_proof(proof);
  return SaveKey(username, key_label, *key);
}

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

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

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

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

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

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

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


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

std::string AttestationService::GetACAURL(ACARequestType request_type) const {
  std::string url = attestation_ca_origin_;
  switch (request_type) {
    case kEnroll:
      url += "/enroll";
      break;
    case kGetCertificate:
      url += "/sign";
      break;
    default:
      NOTREACHED();
  }
  return url;
}

bool AttestationService::GetSubjectPublicKeyInfo(
    KeyType key_type,
    const std::string& public_key,
    std::string* public_key_info) const {
  // Only RSA is supported currently.
  if (key_type != KEY_TYPE_RSA) {
    return false;
  }
  return crypto_utility_->GetRSASubjectPublicKeyInfo(public_key,
                                                     public_key_info);
}

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

}  // namespace attestation
