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),
48      weak_factory_(this) {}
49
50bool 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
81void 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
98void 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
175void 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
191void 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
218void 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
235void 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
269void 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
286void 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
326void 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
343void 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
374void 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
391void 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
412void 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
428void 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
444void 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
460void 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
475void 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
492void 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
523bool 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
536bool 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
542bool 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
563bool 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
601bool 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
640bool 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
680bool 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
703bool 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
729bool 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
766bool 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
788void 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
797bool 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
814void 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
835std::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
853std::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
865int 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
906std::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
921bool 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
933base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() {
934  return weak_factory_.GetWeakPtr();
935}
936
937}  // namespace attestation
938