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