| // Copyright 2016 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <string> |
| |
| #include <base/command_line.h> |
| #include <base/strings/string_number_conversions.h> |
| #include <base/strings/string_util.h> |
| |
| #include "cryptohome/service_monolithic.h" |
| |
| #include "cryptohome/attestation_task.h" |
| |
| namespace cryptohome { |
| |
| const char kRetainEndorsementDataSwitch[] = "retain_endorsement_data"; |
| |
| // A helper function which maps an integer to a valid CertificateProfile. |
| CertificateProfile GetProfile(int profile_value) { |
| // The protobuf compiler generates the _IsValid function. |
| if (!CertificateProfile_IsValid(profile_value)) |
| return ENTERPRISE_USER_CERTIFICATE; |
| return static_cast<CertificateProfile>(profile_value); |
| } |
| |
| // A helper function which maps an integer to a valid Attestation::PCAType |
| // lower than kMaxPCAType. |
| Attestation::PCAType GetPCAType(int value) { |
| if (value < 0 || value >= Attestation::kMaxPCAType) |
| return Attestation::kDefaultPCA; |
| return static_cast<Attestation::PCAType>(value); |
| } |
| |
| // A helper function which maps an integer to a valid Attestation::VAType. |
| // lower than kMaxVAType. |
| Attestation::VAType GetVAType(int value) { |
| if (value < 0 || value >= Attestation::kMaxVAType) { |
| return Attestation::kDefaultVA; |
| } |
| return static_cast<Attestation::VAType>(value); |
| } |
| |
| ServiceMonolithic::ServiceMonolithic(const std::string& abe_data) |
| : default_attestation_(new Attestation()), |
| attestation_(default_attestation_.get()) { |
| if (!GetAttestationBasedEnterpriseEnrollmentData(abe_data, &abe_data_)) { |
| LOG(FATAL) << "Invalid attestation-based enterprise enrollment data."; |
| } |
| } |
| |
| ServiceMonolithic::~ServiceMonolithic() { |
| // Must be called here. Otherwise, after this destructor, |
| // all pure virtual functions from Service overloaded here |
| // and all members defined for this class will be gone, while |
| // mount_thread_ will continue running tasks until stopped in |
| // ~Service. |
| StopTasks(); |
| } |
| |
| bool ServiceMonolithic::GetAttestationBasedEnterpriseEnrollmentData( |
| const std::string& data, brillo::SecureBlob* abe_data) { |
| // Remove trailing newlines. |
| std::string trimmed; |
| base::TrimWhitespaceASCII(data, base::TRIM_TRAILING, &trimmed); |
| if (trimmed.empty()) { |
| return true; // Empty is ok. |
| } |
| // The data must be a valid 32 bytes (256 bits) hexadecimal string. |
| if (!brillo::SecureBlob::HexStringToSecureBlob(trimmed, abe_data) || |
| abe_data->size() != 32) { |
| abe_data->clear(); |
| return false; |
| } |
| return true; |
| } |
| |
| void ServiceMonolithic::AttestationInitialize() { |
| // Get data for attestation-based enterprise enrollment. |
| if (abe_data_.empty()) |
| LOG(WARNING) << "Attestation-based enterprise enrollment" |
| << " will not be available."; |
| |
| // Pass in all the shared dependencies here rather than |
| // needing to always get the Attestation object to set them |
| // during testing. |
| attestation_->Initialize(tpm_, tpm_init_, platform_, crypto_, install_attrs_, |
| abe_data_, base::CommandLine::ForCurrentProcess()->HasSwitch( |
| kRetainEndorsementDataSwitch)); |
| } |
| |
| void ServiceMonolithic::AttestationInitializeTpm() { |
| attestation_->CacheEndorsementData(); |
| brillo::SecureBlob password; |
| if (tpm_init_->IsTpmReady() && tpm_init_->GetTpmPassword(&password)) { |
| attestation_->PrepareForEnrollmentAsync(); |
| } |
| } |
| |
| void ServiceMonolithic::AttestationInitializeTpmComplete() { |
| attestation_->PrepareForEnrollment(); |
| } |
| |
| void ServiceMonolithic::AttestationGetTpmStatus(GetTpmStatusReply* reply) { |
| reply->set_attestation_prepared(attestation_->IsPreparedForEnrollment()); |
| reply->set_attestation_enrolled(attestation_->IsEnrolled()); |
| for (int i = 0, count = attestation_->GetIdentitiesCount(); i < count; ++i) { |
| GetTpmStatusReply::Identity* identity = reply->mutable_identities()->Add(); |
| identity->set_features(attestation_->GetIdentityFeatures(i)); |
| } |
| Attestation::IdentityCertificateMap map = |
| attestation_->GetIdentityCertificateMap(); |
| for (auto it = map.cbegin(), end = map.cend(); it != end; ++it) { |
| GetTpmStatusReply::IdentityCertificate identity_certificate; |
| identity_certificate.set_identity(it->second.identity()); |
| identity_certificate.set_aca(it->second.aca()); |
| reply->mutable_identity_certificates()->insert( |
| google::protobuf::Map<int, GetTpmStatusReply::IdentityCertificate>:: |
| value_type(it->first, identity_certificate)); |
| } |
| for (int pca_type = Attestation::kDefaultPCA; |
| pca_type < Attestation::kMaxPCAType; ++pca_type) { |
| (*reply->mutable_enrollment_preparations())[pca_type] = |
| attestation_->IsPreparedForEnrollmentWith(GetPCAType(pca_type)); |
| } |
| reply->set_verified_boot_measured(attestation_->IsPCR0VerifiedMode()); |
| } |
| |
| bool ServiceMonolithic::AttestationGetDelegateCredentials( |
| brillo::Blob* blob, |
| brillo::Blob* secret, |
| bool* has_reset_lock_permissions) { |
| return attestation_->GetDelegateCredentials(blob, secret, |
| has_reset_lock_permissions); |
| } |
| |
| gboolean ServiceMonolithic::TpmIsAttestationPrepared( |
| gboolean* OUT_prepared, |
| GError** error) { |
| *OUT_prepared = attestation_->IsPreparedForEnrollment(); |
| return TRUE; |
| } |
| |
| bool ServiceMonolithic::AttestationGetEnrollmentPreparations( |
| const AttestationGetEnrollmentPreparationsRequest& request, |
| AttestationGetEnrollmentPreparationsReply* reply) { |
| for (int pca_type = Attestation::kDefaultPCA; |
| pca_type < Attestation::kMaxPCAType; ++pca_type) { |
| if (!request.has_pca_type() || request.pca_type() == pca_type) { |
| if (attestation_->IsPreparedForEnrollmentWith(GetPCAType(pca_type))) { |
| (*reply->mutable_enrollment_preparations())[pca_type] = true; |
| } |
| } |
| } |
| return true; |
| } |
| |
| gboolean ServiceMonolithic::TpmVerifyAttestationData( |
| gboolean is_cros_core, |
| gboolean* OUT_verified, |
| GError** error) { |
| *OUT_verified = attestation_->Verify(is_cros_core); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmVerifyEK( |
| gboolean is_cros_core, |
| gboolean* OUT_verified, |
| GError** error) { |
| *OUT_verified = attestation_->VerifyEK(is_cros_core); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationCreateEnrollRequest( |
| gint pca_type, |
| GArray** OUT_pca_request, |
| GError** error) { |
| // We must set the GArray now because if we return without setting it, |
| // dbus-glib loops forever. |
| *OUT_pca_request = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob blob; |
| if (attestation_->CreateEnrollRequest(GetPCAType(pca_type), &blob)) |
| g_array_append_vals(*OUT_pca_request, blob.data(), blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::AsyncTpmAttestationCreateEnrollRequest( |
| gint pca_type, |
| gint* OUT_async_id, |
| GError** error) { |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<CreateEnrollRequestTask> task = new CreateEnrollRequestTask( |
| observer, attestation_, GetPCAType(pca_type), NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&CreateEnrollRequestTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationEnroll( |
| gint pca_type, |
| GArray* pca_response, |
| gboolean* OUT_success, |
| GError** error) { |
| brillo::SecureBlob blob(pca_response->data, |
| pca_response->data + pca_response->len); |
| *OUT_success = attestation_->Enroll(GetPCAType(pca_type), blob); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::AsyncTpmAttestationEnroll( |
| gint pca_type, |
| GArray* pca_response, |
| gint* OUT_async_id, |
| GError** error) { |
| brillo::SecureBlob blob(pca_response->data, |
| pca_response->data + pca_response->len); |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<EnrollTask> task = new EnrollTask( |
| observer, attestation_, GetPCAType(pca_type), blob, NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&EnrollTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationCreateCertRequest( |
| gint pca_type, |
| gint certificate_profile, |
| gchar* username, |
| gchar* request_origin, |
| GArray** OUT_pca_request, |
| GError** error) { |
| // We must set the GArray now because if we return without setting it, |
| // dbus-glib loops forever. |
| *OUT_pca_request = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob blob; |
| if (attestation_->CreateCertRequest(GetPCAType(pca_type), |
| GetProfile(certificate_profile), |
| username, |
| request_origin, |
| &blob)) |
| g_array_append_vals(*OUT_pca_request, blob.data(), blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::AsyncTpmAttestationCreateCertRequest( |
| gint pca_type, |
| gint certificate_profile, |
| gchar* username, |
| gchar* request_origin, |
| gint* OUT_async_id, |
| GError** error) { |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<CreateCertRequestTask> task = |
| new CreateCertRequestTask(observer, |
| attestation_, |
| GetPCAType(pca_type), |
| GetProfile(certificate_profile), |
| username, |
| request_origin, |
| NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&CreateCertRequestTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationFinishCertRequest( |
| GArray* pca_response, |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray** OUT_cert, |
| gboolean* OUT_success, |
| GError** error) { |
| // We must set the GArray now because if we return without setting it, |
| // dbus-glib loops forever. |
| *OUT_cert = g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob response_blob(pca_response->data, |
| pca_response->data + pca_response->len); |
| brillo::SecureBlob cert_blob; |
| *OUT_success = attestation_->FinishCertRequest(response_blob, |
| is_user_specific, |
| username, |
| key_name, |
| &cert_blob); |
| if (*OUT_success) |
| g_array_append_vals(*OUT_cert, cert_blob.data(), cert_blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::AsyncTpmAttestationFinishCertRequest( |
| GArray* pca_response, |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| gint* OUT_async_id, |
| GError** error) { |
| brillo::SecureBlob blob(pca_response->data, |
| pca_response->data + pca_response->len); |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<FinishCertRequestTask> task = |
| new FinishCertRequestTask(observer, |
| attestation_, |
| blob, |
| is_user_specific, |
| username, |
| key_name, |
| NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&FinishCertRequestTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmIsAttestationEnrolled( |
| gboolean* OUT_is_enrolled, |
| GError** error) { |
| *OUT_is_enrolled = attestation_->IsEnrolled(); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationDoesKeyExist( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| gboolean *OUT_exists, |
| GError** error) { |
| *OUT_exists = attestation_->DoesKeyExist(is_user_specific, |
| username, |
| key_name); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationGetCertificate( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray **OUT_certificate, |
| gboolean* OUT_success, |
| GError** error) { |
| *OUT_certificate = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob blob; |
| *OUT_success = attestation_->GetCertificateChain(is_user_specific, |
| username, |
| key_name, |
| &blob); |
| if (*OUT_success) |
| g_array_append_vals(*OUT_certificate, blob.data(), blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationGetPublicKey( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray **OUT_public_key, |
| gboolean* OUT_success, |
| GError** error) { |
| *OUT_public_key = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob blob; |
| *OUT_success = attestation_->GetPublicKey(is_user_specific, |
| username, |
| key_name, |
| &blob); |
| if (*OUT_success) |
| g_array_append_vals(*OUT_public_key, blob.data(), blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationRegisterKey( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| gint *OUT_async_id, |
| GError** error) { |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<RegisterKeyTask> task = |
| new RegisterKeyTask(observer, |
| attestation_, |
| is_user_specific, |
| username, |
| key_name, |
| NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&RegisterKeyTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationSignEnterpriseChallenge( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| gchar* domain, |
| GArray* device_id, |
| gboolean include_signed_public_key, |
| GArray* challenge, |
| gint *OUT_async_id, |
| GError** error) { |
| return TpmAttestationSignEnterpriseVaChallenge( |
| Attestation::kDefaultVA, |
| is_user_specific, |
| username, |
| key_name, |
| domain, |
| device_id, |
| include_signed_public_key, |
| challenge, |
| OUT_async_id, |
| error); |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationSignEnterpriseVaChallenge( |
| gint va_type, |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| gchar* domain, |
| GArray* device_id, |
| gboolean include_signed_public_key, |
| GArray* challenge, |
| gint *OUT_async_id, |
| GError** error) { |
| brillo::SecureBlob device_id_blob(device_id->data, |
| device_id->data + device_id->len); |
| brillo::SecureBlob challenge_blob(challenge->data, |
| challenge->data + challenge->len); |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<SignChallengeTask> task = |
| new SignChallengeTask(observer, |
| attestation_, |
| GetVAType(va_type), |
| is_user_specific, |
| username, |
| key_name, |
| domain, |
| device_id_blob, |
| include_signed_public_key, |
| challenge_blob, |
| NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&SignChallengeTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationSignSimpleChallenge( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray* challenge, |
| gint *OUT_async_id, |
| GError** error) { |
| brillo::SecureBlob challenge_blob(challenge->data, |
| challenge->data + challenge->len); |
| AttestationTaskObserver* observer = |
| new MountTaskObserverBridge(NULL, &event_source_); |
| scoped_refptr<SignChallengeTask> task = |
| new SignChallengeTask(observer, |
| attestation_, |
| is_user_specific, |
| username, |
| key_name, |
| challenge_blob, |
| NextSequence()); |
| *OUT_async_id = task->sequence_id(); |
| LogAsyncIdInfo(*OUT_async_id, __func__, base::Time::Now()); |
| PostTask(FROM_HERE, base::Bind(&SignChallengeTask::Run, task.get())); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationGetKeyPayload( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray** OUT_payload, |
| gboolean* OUT_success, |
| GError** error) { |
| // We must set the GArray now because if we return without setting it, |
| // dbus-glib loops forever. |
| *OUT_payload = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob blob; |
| *OUT_success = attestation_->GetKeyPayload(is_user_specific, |
| username, |
| key_name, |
| &blob); |
| if (*OUT_success) |
| g_array_append_vals(*OUT_payload, blob.data(), blob.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationSetKeyPayload( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_name, |
| GArray* payload, |
| gboolean* OUT_success, |
| GError** error) { |
| brillo::SecureBlob blob(payload->data, payload->data + payload->len); |
| *OUT_success = attestation_->SetKeyPayload(is_user_specific, |
| username, |
| key_name, |
| blob); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationDeleteKeys( |
| gboolean is_user_specific, |
| gchar* username, |
| gchar* key_prefix, |
| gboolean* OUT_success, |
| GError** error) { |
| *OUT_success = attestation_->DeleteKeysByPrefix(is_user_specific, |
| username, |
| key_prefix); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationGetEK( |
| gchar** OUT_ek_info, |
| gboolean* OUT_success, |
| GError** error) { |
| std::string ek_info; |
| *OUT_success = attestation_->GetEKInfo(&ek_info); |
| *OUT_ek_info = g_strndup(ek_info.data(), ek_info.size()); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationResetIdentity( |
| gchar* reset_token, |
| GArray** OUT_reset_request, |
| gboolean* OUT_success, |
| GError** error) { |
| // We must set the GArray now because if we return without setting it, |
| // dbus-glib loops forever. |
| *OUT_reset_request = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob reset_request; |
| *OUT_success = attestation_->GetIdentityResetRequest( |
| std::string(reinterpret_cast<char*>(reset_token)), |
| &reset_request); |
| if (*OUT_success) |
| g_array_append_vals(*OUT_reset_request, |
| reset_request.data(), |
| reset_request.size()); |
| return TRUE; |
| } |
| |
| void ServiceMonolithic::DoGetEndorsementInfo(const brillo::SecureBlob& request, |
| DBusGMethodInvocation* context) { |
| GetEndorsementInfoRequest request_pb; |
| if (!request_pb.ParseFromArray(request.data(), request.size())) { |
| SendInvalidArgsReply(context, "Bad GetEndorsementInfoRequest"); |
| return; |
| } |
| BaseReply reply; |
| brillo::SecureBlob public_key; |
| brillo::SecureBlob certificate; |
| if (attestation_->GetCachedEndorsementData(&public_key, &certificate) || |
| (tpm_->GetEndorsementPublicKey(&public_key) == Tpm::kTpmRetryNone && |
| tpm_->GetEndorsementCredential(&certificate))) { |
| GetEndorsementInfoReply* extension = reply.MutableExtension( |
| GetEndorsementInfoReply::reply); |
| extension->set_ek_public_key(public_key.to_string()); |
| if (!certificate.empty()) { |
| extension->set_ek_certificate(certificate.to_string()); |
| } |
| } else { |
| reply.set_error(CRYPTOHOME_ERROR_TPM_EK_NOT_AVAILABLE); |
| } |
| SendReply(context, reply); |
| } |
| |
| gboolean ServiceMonolithic::GetEndorsementInfo(const GArray* request, |
| DBusGMethodInvocation* context) { |
| PostTask(FROM_HERE, |
| base::Bind( |
| &ServiceMonolithic::DoGetEndorsementInfo, base::Unretained(this), |
| brillo::SecureBlob(request->data, request->data + request->len), |
| base::Unretained(context))); |
| return TRUE; |
| } |
| |
| void ServiceMonolithic::DoInitializeCastKey(const brillo::SecureBlob& request, |
| DBusGMethodInvocation* context) { |
| const char kCastCertificateOrigin[] = "CAST"; |
| const char kCastKeyLabel[] = "CERTIFIED_CAST_KEY"; |
| |
| ReportDeprecatedApiCalled(DeprecatedApiEvent::kInitializeCastKey); |
| |
| LOG(INFO) << "Initializing Cast Key"; |
| InitializeCastKeyRequest request_pb; |
| if (!request_pb.ParseFromArray(request.data(), request.size())) { |
| SendInvalidArgsReply(context, "Bad InitializeCastKeyRequest"); |
| return; |
| } |
| BaseReply reply; |
| if (!attestation_->IsPreparedForEnrollment() || |
| !pkcs11_init_->IsSystemTokenOK()) { |
| reply.set_error(CRYPTOHOME_ERROR_ATTESTATION_NOT_READY); |
| SendReply(context, reply); |
| return; |
| } |
| if (!attestation_->IsEnrolled()) { |
| brillo::SecureBlob enroll_request; |
| if (!attestation_->CreateEnrollRequest(Attestation::kDefaultPCA, |
| &enroll_request)) { |
| reply.set_error(CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR); |
| SendReply(context, reply); |
| return; |
| } |
| brillo::SecureBlob enroll_reply; |
| if (!attestation_->SendPCARequestAndBlock(Attestation::kDefaultPCA, |
| Attestation::kEnroll, |
| enroll_request, |
| &enroll_reply)) { |
| reply.set_error(CRYPTOHOME_ERROR_CANNOT_CONNECT_TO_CA); |
| SendReply(context, reply); |
| return; |
| } |
| if (!attestation_->Enroll(Attestation::kDefaultPCA, enroll_reply)) { |
| reply.set_error(CRYPTOHOME_ERROR_CA_REFUSED_ENROLLMENT); |
| SendReply(context, reply); |
| return; |
| } |
| } |
| if (!attestation_->DoesKeyExist(false, // is_user_specific |
| "", // username |
| kCastKeyLabel)) { |
| brillo::SecureBlob certificate_request; |
| if (!attestation_->CreateCertRequest(Attestation::kDefaultPCA, |
| CAST_CERTIFICATE, |
| "", // username |
| kCastCertificateOrigin, |
| &certificate_request)) { |
| reply.set_error(CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR); |
| SendReply(context, reply); |
| return; |
| } |
| brillo::SecureBlob certificate_reply; |
| if (!attestation_->SendPCARequestAndBlock(Attestation::kDefaultPCA, |
| Attestation::kGetCertificate, |
| certificate_request, |
| &certificate_reply)) { |
| reply.set_error(CRYPTOHOME_ERROR_CANNOT_CONNECT_TO_CA); |
| SendReply(context, reply); |
| return; |
| } |
| brillo::SecureBlob certificate_chain; |
| if (!attestation_->FinishCertRequest(certificate_reply, |
| false, // is_user_specific |
| "", // username |
| kCastKeyLabel, |
| &certificate_chain)) { |
| reply.set_error(CRYPTOHOME_ERROR_CA_REFUSED_CERTIFICATE); |
| SendReply(context, reply); |
| return; |
| } |
| } |
| if (!attestation_->RegisterKey(false, // is_user_specific |
| "", // username |
| kCastKeyLabel, |
| true)) { // include_certificates |
| reply.set_error(CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR); |
| SendReply(context, reply); |
| return; |
| } |
| SendReply(context, reply); |
| } |
| |
| gboolean ServiceMonolithic::InitializeCastKey(const GArray* request, |
| DBusGMethodInvocation* context) { |
| PostTask(FROM_HERE, |
| base::Bind( |
| &ServiceMonolithic::DoInitializeCastKey, base::Unretained(this), |
| brillo::SecureBlob(request->data, request->data + request->len), |
| base::Unretained(context))); |
| return TRUE; |
| } |
| |
| gboolean ServiceMonolithic::TpmAttestationGetEnrollmentId( |
| gboolean ignore_cache, |
| GArray** OUT_enrollment_id, |
| gboolean* OUT_success, |
| GError** error) { |
| *OUT_enrollment_id = |
| g_array_new(false, false, sizeof(brillo::SecureBlob::value_type)); |
| brillo::SecureBlob enrollment_id; |
| if (ignore_cache) { |
| *OUT_success = |
| attestation_->ComputeEnterpriseEnrollmentId(&enrollment_id); |
| } else { |
| *OUT_success = |
| attestation_->GetEnterpriseEnrollmentId(&enrollment_id); |
| } |
| if (*OUT_success) { |
| g_array_append_vals(*OUT_enrollment_id, |
| enrollment_id.data(), |
| enrollment_id.size()); |
| } |
| return TRUE; |
| } |
| |
| void ServiceMonolithic::ConnectOwnershipTakenSignal() { |
| // Not supported by ServiceMonolithic, either because tpm_managerd doesn't |
| // exist or cryptohomed doesn't talk to tpm_managerd. |
| } |
| |
| } // namespace cryptohome |