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 46 AttestationService::AttestationService() 47 : attestation_ca_origin_(kACAWebOrigin), 48 weak_factory_(this) {} 49 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 906 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 921 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 933 base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() { 934 return weak_factory_.GetWeakPtr(); 935 } 936 937 } // namespace attestation 938