Home | History | Annotate | Download | only in server
      1 //
      2 // Copyright (C) 2015 The Android Open Source Project
      3 //
      4 // Licensed under the Apache License, Version 2.0 (the "License");
      5 // you may not use this file except in compliance with the License.
      6 // You may obtain a copy of the License at
      7 //
      8 //      http://www.apache.org/licenses/LICENSE-2.0
      9 //
     10 // Unless required by applicable law or agreed to in writing, software
     11 // distributed under the License is distributed on an "AS IS" BASIS,
     12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13 // See the License for the specific language governing permissions and
     14 // limitations under the License.
     15 //
     16 
     17 #include "attestation/server/attestation_service.h"
     18 
     19 #include <string>
     20 
     21 #include <base/callback.h>
     22 #include <brillo/bind_lambda.h>
     23 #include <brillo/data_encoding.h>
     24 #include <brillo/http/http_utils.h>
     25 #include <brillo/mime_utils.h>
     26 #include <crypto/sha2.h>
     27 
     28 #include "attestation/common/attestation_ca.pb.h"
     29 #include "attestation/common/database.pb.h"
     30 #include "attestation/server/database_impl.h"
     31 
     32 namespace {
     33 
     34 #ifndef USE_TEST_ACA
     35 const char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
     36 #else
     37 const char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
     38 #endif
     39 const size_t kNonceSize = 20;  // As per TPM_NONCE definition.
     40 const int kNumTemporalValues = 5;
     41 
     42 }  // namespace
     43 
     44 namespace attestation {
     45 
     46 AttestationService::AttestationService()
     47     : attestation_ca_origin_(kACAWebOrigin),
     48       weak_factory_(this) {}
     49 
     50 bool AttestationService::Initialize() {
     51   LOG(INFO) << "Attestation service started.";
     52   worker_thread_.reset(new base::Thread("Attestation Service Worker"));
     53   worker_thread_->StartWithOptions(
     54       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
     55   if (!tpm_utility_) {
     56     default_tpm_utility_.reset(new TpmUtilityV1());
     57     if (!default_tpm_utility_->Initialize()) {
     58       return false;
     59     }
     60     tpm_utility_ = default_tpm_utility_.get();
     61   }
     62   if (!crypto_utility_) {
     63     default_crypto_utility_.reset(new CryptoUtilityImpl(tpm_utility_));
     64     crypto_utility_ = default_crypto_utility_.get();
     65   }
     66   if (!database_) {
     67     default_database_.reset(new DatabaseImpl(crypto_utility_));
     68     worker_thread_->task_runner()->PostTask(FROM_HERE, base::Bind(
     69         &DatabaseImpl::Initialize,
     70         base::Unretained(default_database_.get())));
     71     database_ = default_database_.get();
     72   }
     73   if (!key_store_) {
     74     pkcs11_token_manager_.reset(new chaps::TokenManagerClient());
     75     default_key_store_.reset(new Pkcs11KeyStore(pkcs11_token_manager_.get()));
     76     key_store_ = default_key_store_.get();
     77   }
     78   return true;
     79 }
     80 
     81 void AttestationService::CreateGoogleAttestedKey(
     82     const CreateGoogleAttestedKeyRequest& request,
     83     const CreateGoogleAttestedKeyCallback& callback) {
     84   auto result = std::make_shared<CreateGoogleAttestedKeyReply>();
     85   base::Closure task = base::Bind(
     86       &AttestationService::CreateGoogleAttestedKeyTask,
     87       base::Unretained(this),
     88       request,
     89       result);
     90   base::Closure reply = base::Bind(
     91       &AttestationService::TaskRelayCallback<CreateGoogleAttestedKeyReply>,
     92       GetWeakPtr(),
     93       callback,
     94       result);
     95   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
     96 }
     97 
     98 void AttestationService::CreateGoogleAttestedKeyTask(
     99     const CreateGoogleAttestedKeyRequest& request,
    100     const std::shared_ptr<CreateGoogleAttestedKeyReply>& result) {
    101   LOG(INFO) << "Creating attested key: " << request.key_label();
    102   if (!IsPreparedForEnrollment()) {
    103     LOG(ERROR) << "Attestation: TPM is not ready.";
    104     result->set_status(STATUS_NOT_READY);
    105     return;
    106   }
    107   if (!IsEnrolled()) {
    108     std::string enroll_request;
    109     if (!CreateEnrollRequest(&enroll_request)) {
    110       result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    111       return;
    112     }
    113     std::string enroll_reply;
    114     if (!SendACARequestAndBlock(kEnroll,
    115                                 enroll_request,
    116                                 &enroll_reply)) {
    117       result->set_status(STATUS_CA_NOT_AVAILABLE);
    118       return;
    119     }
    120     std::string server_error;
    121     if (!FinishEnroll(enroll_reply, &server_error)) {
    122       if (server_error.empty()) {
    123         result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    124         return;
    125       }
    126       result->set_status(STATUS_REQUEST_DENIED_BY_CA);
    127       result->set_server_error(server_error);
    128       return;
    129     }
    130   }
    131   CertifiedKey key;
    132   if (!CreateKey(request.username(), request.key_label(), request.key_type(),
    133                  request.key_usage(), &key)) {
    134     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    135     return;
    136   }
    137   std::string certificate_request;
    138   std::string message_id;
    139   if (!CreateCertificateRequest(request.username(),
    140                                 key,
    141                                 request.certificate_profile(),
    142                                 request.origin(),
    143                                 &certificate_request,
    144                                 &message_id)) {
    145     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    146     return;
    147   }
    148   std::string certificate_reply;
    149   if (!SendACARequestAndBlock(kGetCertificate,
    150                               certificate_request,
    151                               &certificate_reply)) {
    152     result->set_status(STATUS_CA_NOT_AVAILABLE);
    153     return;
    154   }
    155   std::string certificate_chain;
    156   std::string server_error;
    157   if (!FinishCertificateRequest(certificate_reply,
    158                                 request.username(),
    159                                 request.key_label(),
    160                                 message_id,
    161                                 &key,
    162                                 &certificate_chain,
    163                                 &server_error)) {
    164     if (server_error.empty()) {
    165       result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    166       return;
    167     }
    168     result->set_status(STATUS_REQUEST_DENIED_BY_CA);
    169     result->set_server_error(server_error);
    170     return;
    171   }
    172   result->set_certificate_chain(certificate_chain);
    173 }
    174 
    175 void AttestationService::GetKeyInfo(const GetKeyInfoRequest& request,
    176                                     const GetKeyInfoCallback& callback) {
    177   auto result = std::make_shared<GetKeyInfoReply>();
    178   base::Closure task = base::Bind(
    179       &AttestationService::GetKeyInfoTask,
    180       base::Unretained(this),
    181       request,
    182       result);
    183   base::Closure reply = base::Bind(
    184       &AttestationService::TaskRelayCallback<GetKeyInfoReply>,
    185       GetWeakPtr(),
    186       callback,
    187       result);
    188   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    189 }
    190 
    191 void AttestationService::GetKeyInfoTask(
    192     const GetKeyInfoRequest& request,
    193     const std::shared_ptr<GetKeyInfoReply>& result) {
    194   CertifiedKey key;
    195   if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    196     result->set_status(STATUS_INVALID_PARAMETER);
    197     return;
    198   }
    199   std::string public_key_info;
    200   if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
    201                                &public_key_info)) {
    202     LOG(ERROR) << __func__ << ": Bad public key.";
    203     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    204     return;
    205   }
    206   result->set_key_type(key.key_type());
    207   result->set_key_usage(key.key_usage());
    208   result->set_public_key(public_key_info);
    209   result->set_certify_info(key.certified_key_info());
    210   result->set_certify_info_signature(key.certified_key_proof());
    211   if (key.has_intermediate_ca_cert()) {
    212     result->set_certificate(CreatePEMCertificateChain(key));
    213   } else {
    214     result->set_certificate(key.certified_key_credential());
    215   }
    216 }
    217 
    218 void AttestationService::GetEndorsementInfo(
    219     const GetEndorsementInfoRequest& request,
    220     const GetEndorsementInfoCallback& callback) {
    221   auto result = std::make_shared<GetEndorsementInfoReply>();
    222   base::Closure task = base::Bind(
    223       &AttestationService::GetEndorsementInfoTask,
    224       base::Unretained(this),
    225       request,
    226       result);
    227   base::Closure reply = base::Bind(
    228       &AttestationService::TaskRelayCallback<GetEndorsementInfoReply>,
    229       GetWeakPtr(),
    230       callback,
    231       result);
    232   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    233 }
    234 
    235 void AttestationService::GetEndorsementInfoTask(
    236     const GetEndorsementInfoRequest& request,
    237     const std::shared_ptr<GetEndorsementInfoReply>& result) {
    238   if (request.key_type() != KEY_TYPE_RSA) {
    239     result->set_status(STATUS_INVALID_PARAMETER);
    240     return;
    241   }
    242   auto database_pb = database_->GetProtobuf();
    243   if (!database_pb.has_credentials() ||
    244       !database_pb.credentials().has_endorsement_public_key()) {
    245     // Try to read the public key directly.
    246     std::string public_key;
    247     if (!tpm_utility_->GetEndorsementPublicKey(&public_key)) {
    248       result->set_status(STATUS_NOT_AVAILABLE);
    249       return;
    250     }
    251     database_pb.mutable_credentials()->set_endorsement_public_key(public_key);
    252   }
    253   std::string public_key_info;
    254   if (!GetSubjectPublicKeyInfo(
    255       request.key_type(),
    256       database_pb.credentials().endorsement_public_key(),
    257       &public_key_info)) {
    258     LOG(ERROR) << __func__ << ": Bad public key.";
    259     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    260     return;
    261   }
    262   result->set_ek_public_key(public_key_info);
    263   if (database_pb.credentials().has_endorsement_credential()) {
    264     result->set_ek_certificate(
    265         database_pb.credentials().endorsement_credential());
    266   }
    267 }
    268 
    269 void AttestationService::GetAttestationKeyInfo(
    270     const GetAttestationKeyInfoRequest& request,
    271     const GetAttestationKeyInfoCallback& callback) {
    272   auto result = std::make_shared<GetAttestationKeyInfoReply>();
    273   base::Closure task = base::Bind(
    274       &AttestationService::GetAttestationKeyInfoTask,
    275       base::Unretained(this),
    276       request,
    277       result);
    278   base::Closure reply = base::Bind(
    279       &AttestationService::TaskRelayCallback<GetAttestationKeyInfoReply>,
    280       GetWeakPtr(),
    281       callback,
    282       result);
    283   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    284 }
    285 
    286 void AttestationService::GetAttestationKeyInfoTask(
    287     const GetAttestationKeyInfoRequest& request,
    288     const std::shared_ptr<GetAttestationKeyInfoReply>& result) {
    289   if (request.key_type() != KEY_TYPE_RSA) {
    290     result->set_status(STATUS_INVALID_PARAMETER);
    291     return;
    292   }
    293   auto database_pb = database_->GetProtobuf();
    294   if (!IsPreparedForEnrollment() || !database_pb.has_identity_key()) {
    295     result->set_status(STATUS_NOT_AVAILABLE);
    296     return;
    297   }
    298   if (database_pb.identity_key().has_identity_public_key()) {
    299     std::string public_key_info;
    300     if (!GetSubjectPublicKeyInfo(
    301         request.key_type(),
    302         database_pb.identity_key().identity_public_key(),
    303         &public_key_info)) {
    304       LOG(ERROR) << __func__ << ": Bad public key.";
    305       result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    306       return;
    307     }
    308     result->set_public_key(public_key_info);
    309   }
    310   if (database_pb.has_identity_binding() &&
    311       database_pb.identity_binding().has_identity_public_key()) {
    312     result->set_public_key_tpm_format(
    313         database_pb.identity_binding().identity_public_key());
    314   }
    315   if (database_pb.identity_key().has_identity_credential()) {
    316     result->set_certificate(database_pb.identity_key().identity_credential());
    317   }
    318   if (database_pb.has_pcr0_quote()) {
    319     *result->mutable_pcr0_quote() = database_pb.pcr0_quote();
    320   }
    321   if (database_pb.has_pcr1_quote()) {
    322     *result->mutable_pcr1_quote() = database_pb.pcr1_quote();
    323   }
    324 }
    325 
    326 void AttestationService::ActivateAttestationKey(
    327     const ActivateAttestationKeyRequest& request,
    328     const ActivateAttestationKeyCallback& callback) {
    329   auto result = std::make_shared<ActivateAttestationKeyReply>();
    330   base::Closure task = base::Bind(
    331       &AttestationService::ActivateAttestationKeyTask,
    332       base::Unretained(this),
    333       request,
    334       result);
    335   base::Closure reply = base::Bind(
    336       &AttestationService::TaskRelayCallback<ActivateAttestationKeyReply>,
    337       GetWeakPtr(),
    338       callback,
    339       result);
    340   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    341 }
    342 
    343 void AttestationService::ActivateAttestationKeyTask(
    344     const ActivateAttestationKeyRequest& request,
    345     const std::shared_ptr<ActivateAttestationKeyReply>& result) {
    346   if (request.key_type() != KEY_TYPE_RSA) {
    347     result->set_status(STATUS_INVALID_PARAMETER);
    348     return;
    349   }
    350   std::string certificate;
    351   auto database_pb = database_->GetProtobuf();
    352   if (!tpm_utility_->ActivateIdentity(
    353       database_pb.delegate().blob(),
    354       database_pb.delegate().secret(),
    355       database_pb.identity_key().identity_key_blob(),
    356       request.encrypted_certificate().asym_ca_contents(),
    357       request.encrypted_certificate().sym_ca_attestation(),
    358       &certificate)) {
    359     LOG(ERROR) << __func__ << ": Failed to activate identity.";
    360     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    361     return;
    362   }
    363   if (request.save_certificate()) {
    364     database_->GetMutableProtobuf()->mutable_identity_key()->
    365         set_identity_credential(certificate);
    366     if (!database_->SaveChanges()) {
    367       LOG(ERROR) << __func__ << ": Failed to persist database changes.";
    368       result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    369     }
    370   }
    371   result->set_certificate(certificate);
    372 }
    373 
    374 void AttestationService::CreateCertifiableKey(
    375     const CreateCertifiableKeyRequest& request,
    376     const CreateCertifiableKeyCallback& callback) {
    377   auto result = std::make_shared<CreateCertifiableKeyReply>();
    378   base::Closure task = base::Bind(
    379       &AttestationService::CreateCertifiableKeyTask,
    380       base::Unretained(this),
    381       request,
    382       result);
    383   base::Closure reply = base::Bind(
    384       &AttestationService::TaskRelayCallback<CreateCertifiableKeyReply>,
    385       GetWeakPtr(),
    386       callback,
    387       result);
    388   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    389 }
    390 
    391 void AttestationService::CreateCertifiableKeyTask(
    392     const CreateCertifiableKeyRequest& request,
    393     const std::shared_ptr<CreateCertifiableKeyReply>& result) {
    394   CertifiedKey key;
    395   if (!CreateKey(request.username(), request.key_label(), request.key_type(),
    396                  request.key_usage(), &key)) {
    397     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    398     return;
    399   }
    400   std::string public_key_info;
    401   if (!GetSubjectPublicKeyInfo(key.key_type(), key.public_key(),
    402                                &public_key_info)) {
    403     LOG(ERROR) << __func__ << ": Bad public key.";
    404     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    405     return;
    406   }
    407   result->set_public_key(public_key_info);
    408   result->set_certify_info(key.certified_key_info());
    409   result->set_certify_info_signature(key.certified_key_proof());
    410 }
    411 
    412 void AttestationService::Decrypt(const DecryptRequest& request,
    413                                  const DecryptCallback& callback) {
    414   auto result = std::make_shared<DecryptReply>();
    415   base::Closure task = base::Bind(
    416       &AttestationService::DecryptTask,
    417       base::Unretained(this),
    418       request,
    419       result);
    420   base::Closure reply = base::Bind(
    421       &AttestationService::TaskRelayCallback<DecryptReply>,
    422       GetWeakPtr(),
    423       callback,
    424       result);
    425   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    426 }
    427 
    428 void AttestationService::DecryptTask(
    429     const DecryptRequest& request,
    430     const std::shared_ptr<DecryptReply>& result) {
    431   CertifiedKey key;
    432   if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    433     result->set_status(STATUS_INVALID_PARAMETER);
    434     return;
    435   }
    436   std::string data;
    437   if (!tpm_utility_->Unbind(key.key_blob(), request.encrypted_data(), &data)) {
    438     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    439     return;
    440   }
    441   result->set_decrypted_data(data);
    442 }
    443 
    444 void AttestationService::Sign(const SignRequest& request,
    445                               const SignCallback& callback) {
    446   auto result = std::make_shared<SignReply>();
    447   base::Closure task = base::Bind(
    448       &AttestationService::SignTask,
    449       base::Unretained(this),
    450       request,
    451       result);
    452   base::Closure reply = base::Bind(
    453       &AttestationService::TaskRelayCallback<SignReply>,
    454       GetWeakPtr(),
    455       callback,
    456       result);
    457   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    458 }
    459 
    460 void AttestationService::SignTask(const SignRequest& request,
    461                                   const std::shared_ptr<SignReply>& result) {
    462   CertifiedKey key;
    463   if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    464     result->set_status(STATUS_INVALID_PARAMETER);
    465     return;
    466   }
    467   std::string signature;
    468   if (!tpm_utility_->Sign(key.key_blob(), request.data_to_sign(), &signature)) {
    469     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    470     return;
    471   }
    472   result->set_signature(signature);
    473 }
    474 
    475 void AttestationService::RegisterKeyWithChapsToken(
    476     const RegisterKeyWithChapsTokenRequest& request,
    477     const RegisterKeyWithChapsTokenCallback& callback) {
    478   auto result = std::make_shared<RegisterKeyWithChapsTokenReply>();
    479   base::Closure task = base::Bind(
    480       &AttestationService::RegisterKeyWithChapsTokenTask,
    481       base::Unretained(this),
    482       request,
    483       result);
    484   base::Closure reply = base::Bind(
    485       &AttestationService::TaskRelayCallback<RegisterKeyWithChapsTokenReply>,
    486       GetWeakPtr(),
    487       callback,
    488       result);
    489   worker_thread_->task_runner()->PostTaskAndReply(FROM_HERE, task, reply);
    490 }
    491 
    492 void AttestationService::RegisterKeyWithChapsTokenTask(
    493     const RegisterKeyWithChapsTokenRequest& request,
    494     const std::shared_ptr<RegisterKeyWithChapsTokenReply>& result) {
    495   CertifiedKey key;
    496   if (!FindKeyByLabel(request.username(), request.key_label(), &key)) {
    497     result->set_status(STATUS_INVALID_PARAMETER);
    498     return;
    499   }
    500   if (!key_store_->Register(request.username(), request.key_label(),
    501                             key.key_type(), key.key_usage(), key.key_blob(),
    502                             key.public_key(), key.certified_key_credential())) {
    503     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    504     return;
    505   }
    506   if (key.has_intermediate_ca_cert() &&
    507       !key_store_->RegisterCertificate(request.username(),
    508                                        key.intermediate_ca_cert())) {
    509     result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    510     return;
    511   }
    512   for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
    513     if (!key_store_->RegisterCertificate(
    514             request.username(),
    515             key.additional_intermediate_ca_cert(i))) {
    516       result->set_status(STATUS_UNEXPECTED_DEVICE_ERROR);
    517       return;
    518     }
    519   }
    520   DeleteKey(request.username(), request.key_label());
    521 }
    522 
    523 bool AttestationService::IsPreparedForEnrollment() {
    524   if (!tpm_utility_->IsTpmReady()) {
    525     return false;
    526   }
    527   auto database_pb = database_->GetProtobuf();
    528   if (!database_pb.has_credentials()) {
    529     return false;
    530   }
    531   return (database_pb.credentials().has_endorsement_credential() ||
    532           database_pb.credentials()
    533               .has_default_encrypted_endorsement_credential());
    534 }
    535 
    536 bool AttestationService::IsEnrolled() {
    537   auto database_pb = database_->GetProtobuf();
    538   return database_pb.has_identity_key() &&
    539          database_pb.identity_key().has_identity_credential();
    540 }
    541 
    542 bool AttestationService::CreateEnrollRequest(std::string* enroll_request) {
    543   if (!IsPreparedForEnrollment()) {
    544     LOG(ERROR) << __func__ << ": Enrollment is not possible, attestation data "
    545                << "does not exist.";
    546     return false;
    547   }
    548   auto database_pb = database_->GetProtobuf();
    549   AttestationEnrollmentRequest request_pb;
    550   *request_pb.mutable_encrypted_endorsement_credential() =
    551       database_pb.credentials().default_encrypted_endorsement_credential();
    552   request_pb.set_identity_public_key(
    553       database_pb.identity_binding().identity_public_key());
    554   *request_pb.mutable_pcr0_quote() = database_pb.pcr0_quote();
    555   *request_pb.mutable_pcr1_quote() = database_pb.pcr1_quote();
    556   if (!request_pb.SerializeToString(enroll_request)) {
    557     LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    558     return false;
    559   }
    560   return true;
    561 }
    562 
    563 bool AttestationService::FinishEnroll(const std::string& enroll_response,
    564                                       std::string* server_error) {
    565   if (!tpm_utility_->IsTpmReady()) {
    566     return false;
    567   }
    568   AttestationEnrollmentResponse response_pb;
    569   if (!response_pb.ParseFromString(enroll_response)) {
    570     LOG(ERROR) << __func__ << ": Failed to parse response from CA.";
    571     return false;
    572   }
    573   if (response_pb.status() != OK) {
    574     *server_error = response_pb.detail();
    575     LOG(ERROR) << __func__ << ": Error received from CA: "
    576                << response_pb.detail();
    577     return false;
    578   }
    579   std::string credential;
    580   auto database_pb = database_->GetProtobuf();
    581   if (!tpm_utility_->ActivateIdentity(
    582       database_pb.delegate().blob(),
    583       database_pb.delegate().secret(),
    584       database_pb.identity_key().identity_key_blob(),
    585       response_pb.encrypted_identity_credential().asym_ca_contents(),
    586       response_pb.encrypted_identity_credential().sym_ca_attestation(),
    587       &credential)) {
    588     LOG(ERROR) << __func__ << ": Failed to activate identity.";
    589     return false;
    590   }
    591   database_->GetMutableProtobuf()->mutable_identity_key()->
    592       set_identity_credential(credential);
    593   if (!database_->SaveChanges()) {
    594     LOG(ERROR) << __func__ << ": Failed to persist database changes.";
    595     return false;
    596   }
    597   LOG(INFO) << "Attestation: Enrollment complete.";
    598   return true;
    599 }
    600 
    601 bool AttestationService::CreateCertificateRequest(
    602     const std::string& username,
    603     const CertifiedKey& key,
    604     CertificateProfile profile,
    605     const std::string& origin,
    606     std::string* certificate_request,
    607     std::string* message_id) {
    608   if (!tpm_utility_->IsTpmReady()) {
    609     return false;
    610   }
    611   if (!IsEnrolled()) {
    612     LOG(ERROR) << __func__ << ": Device is not enrolled for attestation.";
    613     return false;
    614   }
    615   AttestationCertificateRequest request_pb;
    616   if (!crypto_utility_->GetRandom(kNonceSize, message_id)) {
    617     LOG(ERROR) << __func__ << ": GetRandom(message_id) failed.";
    618     return false;
    619   }
    620   request_pb.set_message_id(*message_id);
    621   auto database_pb = database_->GetProtobuf();
    622   request_pb.set_identity_credential(
    623       database_pb.identity_key().identity_credential());
    624   request_pb.set_profile(profile);
    625   if (!origin.empty() &&
    626       (profile == CONTENT_PROTECTION_CERTIFICATE_WITH_STABLE_ID)) {
    627     request_pb.set_origin(origin);
    628     request_pb.set_temporal_index(ChooseTemporalIndex(username, origin));
    629   }
    630   request_pb.set_certified_public_key(key.public_key_tpm_format());
    631   request_pb.set_certified_key_info(key.certified_key_info());
    632   request_pb.set_certified_key_proof(key.certified_key_proof());
    633   if (!request_pb.SerializeToString(certificate_request)) {
    634     LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    635     return false;
    636   }
    637   return true;
    638 }
    639 
    640 bool AttestationService::FinishCertificateRequest(
    641     const std::string& certificate_response,
    642     const std::string& username,
    643     const std::string& key_label,
    644     const std::string& message_id,
    645     CertifiedKey* key,
    646     std::string* certificate_chain,
    647     std::string* server_error) {
    648   if (!tpm_utility_->IsTpmReady()) {
    649     return false;
    650   }
    651   AttestationCertificateResponse response_pb;
    652   if (!response_pb.ParseFromString(certificate_response)) {
    653     LOG(ERROR) << __func__ << ": Failed to parse response from Privacy CA.";
    654     return false;
    655   }
    656   if (response_pb.status() != OK) {
    657     *server_error = response_pb.detail();
    658     LOG(ERROR) << __func__ << ": Error received from Privacy CA: "
    659                << response_pb.detail();
    660     return false;
    661   }
    662   if (message_id != response_pb.message_id()) {
    663     LOG(ERROR) << __func__ << ": Message ID mismatch.";
    664     return false;
    665   }
    666 
    667   // Finish populating the CertifiedKey protobuf and store it.
    668   key->set_certified_key_credential(response_pb.certified_key_credential());
    669   key->set_intermediate_ca_cert(response_pb.intermediate_ca_cert());
    670   key->mutable_additional_intermediate_ca_cert()->MergeFrom(
    671       response_pb.additional_intermediate_ca_cert());
    672   if (!SaveKey(username, key_label, *key)) {
    673     return false;
    674   }
    675   LOG(INFO) << "Attestation: Certified key credential received and stored.";
    676   *certificate_chain = CreatePEMCertificateChain(*key);
    677   return true;
    678 }
    679 
    680 bool AttestationService::SendACARequestAndBlock(ACARequestType request_type,
    681                                                 const std::string& request,
    682                                                 std::string* reply) {
    683   std::shared_ptr<brillo::http::Transport> transport = http_transport_;
    684   if (!transport) {
    685     transport = brillo::http::Transport::CreateDefault();
    686   }
    687   std::unique_ptr<brillo::http::Response> response = PostBinaryAndBlock(
    688       GetACAURL(request_type),
    689       request.data(),
    690       request.size(),
    691       brillo::mime::application::kOctet_stream,
    692       {},  // headers
    693       transport,
    694       nullptr);  // error
    695   if (!response || !response->IsSuccessful()) {
    696     LOG(ERROR) << "HTTP request to Attestation CA failed.";
    697     return false;
    698   }
    699   *reply = response->ExtractDataAsString();
    700   return true;
    701 }
    702 
    703 bool AttestationService::FindKeyByLabel(const std::string& username,
    704                                         const std::string& key_label,
    705                                         CertifiedKey* key) {
    706   if (!username.empty()) {
    707     std::string key_data;
    708     if (!key_store_->Read(username, key_label, &key_data)) {
    709       LOG(INFO) << "Key not found: " << key_label;
    710       return false;
    711     }
    712     if (key && !key->ParseFromString(key_data)) {
    713       LOG(ERROR) << "Failed to parse key: " << key_label;
    714       return false;
    715     }
    716     return true;
    717   }
    718   auto database_pb = database_->GetProtobuf();
    719   for (int i = 0; i < database_pb.device_keys_size(); ++i) {
    720     if (database_pb.device_keys(i).key_name() == key_label) {
    721       *key = database_pb.device_keys(i);
    722       return true;
    723     }
    724   }
    725   LOG(INFO) << "Key not found: " << key_label;
    726   return false;
    727 }
    728 
    729 bool AttestationService::CreateKey(const std::string& username,
    730                                    const std::string& key_label,
    731                                    KeyType key_type,
    732                                    KeyUsage key_usage,
    733                                    CertifiedKey* key) {
    734   std::string nonce;
    735   if (!crypto_utility_->GetRandom(kNonceSize, &nonce)) {
    736     LOG(ERROR) << __func__ << ": GetRandom(nonce) failed.";
    737     return false;
    738   }
    739   std::string key_blob;
    740   std::string public_key;
    741   std::string public_key_tpm_format;
    742   std::string key_info;
    743   std::string proof;
    744   auto database_pb = database_->GetProtobuf();
    745   if (!tpm_utility_->CreateCertifiedKey(
    746       key_type,
    747       key_usage,
    748       database_pb.identity_key().identity_key_blob(),
    749       nonce,
    750       &key_blob,
    751       &public_key,
    752       &public_key_tpm_format,
    753       &key_info,
    754       &proof)) {
    755     return false;
    756   }
    757   key->set_key_blob(key_blob);
    758   key->set_public_key(public_key);
    759   key->set_key_name(key_label);
    760   key->set_public_key_tpm_format(public_key_tpm_format);
    761   key->set_certified_key_info(key_info);
    762   key->set_certified_key_proof(proof);
    763   return SaveKey(username, key_label, *key);
    764 }
    765 
    766 bool AttestationService::SaveKey(const std::string& username,
    767                                  const std::string& key_label,
    768                                  const CertifiedKey& key) {
    769   if (!username.empty()) {
    770     std::string key_data;
    771     if (!key.SerializeToString(&key_data)) {
    772       LOG(ERROR) << __func__ << ": Failed to serialize protobuf.";
    773       return false;
    774     }
    775     if (!key_store_->Write(username, key_label, key_data)) {
    776       LOG(ERROR) << __func__ << ": Failed to store certified key for user.";
    777       return false;
    778     }
    779   } else {
    780     if (!AddDeviceKey(key_label, key)) {
    781       LOG(ERROR) << __func__ << ": Failed to store certified key for device.";
    782       return false;
    783     }
    784   }
    785   return true;
    786 }
    787 
    788 void AttestationService::DeleteKey(const std::string& username,
    789                                    const std::string& key_label) {
    790   if (!username.empty()) {
    791     key_store_->Delete(username, key_label);
    792   } else {
    793     RemoveDeviceKey(key_label);
    794   }
    795 }
    796 
    797 bool AttestationService::AddDeviceKey(const std::string& key_label,
    798                                       const CertifiedKey& key) {
    799   // If a key by this name already exists, reuse the field.
    800   auto* database_pb = database_->GetMutableProtobuf();
    801   bool found = false;
    802   for (int i = 0; i < database_pb->device_keys_size(); ++i) {
    803     if (database_pb->device_keys(i).key_name() == key_label) {
    804       found = true;
    805       *database_pb->mutable_device_keys(i) = key;
    806       break;
    807     }
    808   }
    809   if (!found)
    810     *database_pb->add_device_keys() = key;
    811   return database_->SaveChanges();
    812 }
    813 
    814 void AttestationService::RemoveDeviceKey(const std::string& key_label) {
    815   auto* database_pb = database_->GetMutableProtobuf();
    816   bool found = false;
    817   for (int i = 0; i < database_pb->device_keys_size(); ++i) {
    818     if (database_pb->device_keys(i).key_name() == key_label) {
    819       found = true;
    820       int last = database_pb->device_keys_size() - 1;
    821       if (i < last) {
    822         database_pb->mutable_device_keys()->SwapElements(i, last);
    823       }
    824       database_pb->mutable_device_keys()->RemoveLast();
    825       break;
    826     }
    827   }
    828   if (found) {
    829     if (!database_->SaveChanges()) {
    830       LOG(WARNING) << __func__ << ": Failed to persist key deletion.";
    831     }
    832   }
    833 }
    834 
    835 std::string AttestationService::CreatePEMCertificateChain(
    836     const CertifiedKey& key) {
    837   if (key.certified_key_credential().empty()) {
    838     LOG(WARNING) << "Certificate is empty.";
    839     return std::string();
    840   }
    841   std::string pem = CreatePEMCertificate(key.certified_key_credential());
    842   if (!key.intermediate_ca_cert().empty()) {
    843     pem += "\n";
    844     pem += CreatePEMCertificate(key.intermediate_ca_cert());
    845   }
    846   for (int i = 0; i < key.additional_intermediate_ca_cert_size(); ++i) {
    847     pem += "\n";
    848     pem += CreatePEMCertificate(key.additional_intermediate_ca_cert(i));
    849   }
    850   return pem;
    851 }
    852 
    853 std::string AttestationService::CreatePEMCertificate(
    854     const std::string& certificate) {
    855   const char kBeginCertificate[] = "-----BEGIN CERTIFICATE-----\n";
    856   const char kEndCertificate[] = "-----END CERTIFICATE-----";
    857 
    858   std::string pem = kBeginCertificate;
    859   pem += brillo::data_encoding::Base64EncodeWrapLines(certificate);
    860   pem += kEndCertificate;
    861   return pem;
    862 }
    863 
    864 
    865 int AttestationService::ChooseTemporalIndex(const std::string& user,
    866                                             const std::string& origin) {
    867   std::string user_hash = crypto::SHA256HashString(user);
    868   std::string origin_hash = crypto::SHA256HashString(origin);
    869   int histogram[kNumTemporalValues] = {};
    870   auto database_pb = database_->GetProtobuf();
    871   for (int i = 0; i < database_pb.temporal_index_record_size(); ++i) {
    872     const AttestationDatabase::TemporalIndexRecord& record =
    873         database_pb.temporal_index_record(i);
    874     // Ignore out-of-range index values.
    875     if (record.temporal_index() < 0 ||
    876         record.temporal_index() >= kNumTemporalValues)
    877       continue;
    878     if (record.origin_hash() == origin_hash) {
    879       if (record.user_hash() == user_hash) {
    880         // We've previously chosen this index for this user, reuse it.
    881         return record.temporal_index();
    882       } else {
    883         // We've previously chosen this index for another user.
    884         ++histogram[record.temporal_index()];
    885       }
    886     }
    887   }
    888   int least_used_index = 0;
    889   for (int i = 1; i < kNumTemporalValues; ++i) {
    890     if (histogram[i] < histogram[least_used_index])
    891       least_used_index = i;
    892   }
    893   if (histogram[least_used_index] > 0) {
    894     LOG(WARNING) << "Unique origin-specific identifiers have been exhausted.";
    895   }
    896   // Record our choice for later reference.
    897   AttestationDatabase::TemporalIndexRecord* new_record =
    898       database_pb.add_temporal_index_record();
    899   new_record->set_origin_hash(origin_hash);
    900   new_record->set_user_hash(user_hash);
    901   new_record->set_temporal_index(least_used_index);
    902   database_->SaveChanges();
    903   return least_used_index;
    904 }
    905 
    906 std::string AttestationService::GetACAURL(ACARequestType request_type) const {
    907   std::string url = attestation_ca_origin_;
    908   switch (request_type) {
    909     case kEnroll:
    910       url += "/enroll";
    911       break;
    912     case kGetCertificate:
    913       url += "/sign";
    914       break;
    915     default:
    916       NOTREACHED();
    917   }
    918   return url;
    919 }
    920 
    921 bool AttestationService::GetSubjectPublicKeyInfo(
    922     KeyType key_type,
    923     const std::string& public_key,
    924     std::string* public_key_info) const {
    925   // Only RSA is supported currently.
    926   if (key_type != KEY_TYPE_RSA) {
    927     return false;
    928   }
    929   return crypto_utility_->GetRSASubjectPublicKeyInfo(public_key,
    930                                                      public_key_info);
    931 }
    932 
    933 base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
    934   return weak_factory_.GetWeakPtr();
    935 }
    936 
    937 }  // namespace attestation
    938