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