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