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