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
32namespace {
33
34#ifndef USE_TEST_ACA
35const char kACAWebOrigin[] = "https://chromeos-ca.gstatic.com";
36#else
37const char kACAWebOrigin[] = "https://asbestos-qa.corp.google.com";
38#endif
39const size_t kNonceSize = 20;  // As per TPM_NONCE definition.
40const int kNumTemporalValues = 5;
41
42}  // namespace
43
44namespace attestation {
45
46AttestationService::AttestationService()
47    : attestation_ca_origin_(kACAWebOrigin), weak_factory_(this) {}
48
49bool 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
80void 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
93void 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
160void 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
171void 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
198void 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
210void 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
244void 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
257void 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
297void 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
310void 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
340void 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
352void 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
373void 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
384void 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
400void 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
411void 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
426void 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
439void 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
469bool 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
482bool 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
488bool 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
509bool 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
547bool 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
586bool 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
626bool 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
646bool 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
672bool 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
703bool 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
725void 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
734bool 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
751void 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
772std::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
790std::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
801int 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
842std::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
857bool 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
869base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
870  return weak_factory_.GetWeakPtr();
871}
872
873}  // namespace attestation
874