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), weak_factory_(this) {} 48 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 842 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 857 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 869 base::WeakPtr<AttestationService> AttestationService::GetWeakPtr() { 870 return weak_factory_.GetWeakPtr(); 871 } 872 873 } // namespace attestation 874