blob: bfc6ccc71ee9420997dc7e1777a5f61fe2573fd8 [file] [log] [blame]
// 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 "cryptohome/service_distributed.h"
#include <brillo/bind_lambda.h>
#include "attestation/client/dbus_proxy.h"
#include "cryptohome/attestation.h"
#include "cryptohome/cryptolib.h"
using attestation::AttestationInterface;
using attestation::AttestationStatus;
namespace cryptohome {
// A helper function which maps an integer to a valid CertificateProfile.
attestation::CertificateProfile ServiceDistributed::GetProfile(
int profile_value) {
// The protobuf compiler generates the _IsValid function.
if (!attestation::CertificateProfile_IsValid(profile_value)) {
return attestation::CertificateProfile::ENTERPRISE_USER_CERTIFICATE;
}
return static_cast<attestation::CertificateProfile>(profile_value);
}
ServiceDistributed::ServiceDistributed()
: default_attestation_interface_(new attestation::DBusProxy()),
attestation_interface_(default_attestation_interface_.get()),
weak_factory_(this) {}
ServiceDistributed::~ServiceDistributed() {}
bool ServiceDistributed::PrepareInterface() {
if (attestation_thread_.IsRunning()) {
return true;
}
if (!attestation_thread_.StartWithOptions(base::Thread::Options(
base::MessageLoopForIO::TYPE_IO, 0 /* Default stack size. */))) {
LOG(ERROR) << "Failed to start attestation thread.";
return false;
}
DLOG(INFO) << "Started attestation thread.";
return true;
}
int ServiceDistributed::AllocateAsyncId() {
scoped_refptr<MountTask> task = new MountTask(NULL, NULL);
return task->sequence_id();
}
base::WeakPtr<ServiceDistributed> ServiceDistributed::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
void ServiceDistributed::ReportErrorFromStatus(
GError** error,
attestation::AttestationStatus status) {
VLOG(1) << "Attestation daemon returned status " << status;
g_set_error(error, DBUS_GERROR, DBUS_GERROR_FAILED,
"Attestation daemon returned status %d", status);
}
void ServiceDistributed::ReportSendFailure(GError** error) {
g_set_error_literal(error, DBUS_GERROR, DBUS_GERROR_FAILED,
"Failed sending to attestation daemon");
}
void ServiceDistributed::ReportUnsupportedPCAType(GError** error,
int pca_type) {
VLOG(1) << "PCA type is not supported: " << pca_type;
g_set_error(error, DBUS_GERROR, DBUS_GERROR_NOT_SUPPORTED,
"Alternate PCA type is not supported");
}
template <typename MethodType>
bool ServiceDistributed::Post(const MethodType& method) {
VLOG(2) << __func__;
if (!PrepareInterface()) {
return false;
}
attestation_thread_.task_runner()->PostTask(FROM_HERE, method);
VLOG(2) << __func__ << ": posted";
return true;
}
template <typename MethodType>
bool ServiceDistributed::PostAndWait(const MethodType& method) {
VLOG(2) << __func__;
base::WaitableEvent event(true /* manual_reset */,
false /* initially_signaled */);
auto sync_method = base::Bind(
[](const MethodType& method, base::WaitableEvent* event) {
method.Run();
event->Signal();
},
method, &event);
if (!Post(sync_method)) {
return false;
}
VLOG(2) << __func__ << ": posted";
event.Wait();
VLOG(2) << __func__ << ": completed";
return true;
}
template <typename ReplyProtoType, typename MethodType>
bool ServiceDistributed::SendRequestAndWait(const MethodType& method,
ReplyProtoType* reply_proto) {
VLOG(2) << __func__;
base::WaitableEvent event(true /* manual_reset */,
false /* initially_signaled */);
auto callback = base::Bind(
[](ReplyProtoType* reply_proto, base::WaitableEvent* event,
const ReplyProtoType& reply) {
*reply_proto = reply;
event->Signal();
},
reply_proto, &event);
if (!Post(base::Bind(method, callback))) {
return false;
}
event.Wait();
VLOG(2) << __func__ << ": completed";
return true;
}
template <typename ReplyProtoType>
void ServiceDistributed::ProcessStatusReply(int async_id,
const ReplyProtoType& reply) {
VLOG(1) << __func__;
MountTaskResult* r = new MountTaskResult();
VLOG(3) << "attestationd reply:"
<< " async_id=" << async_id << " status=" << reply.status();
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
r->set_sequence_id(async_id);
r->set_return_status(reply.status() == AttestationStatus::STATUS_SUCCESS);
event_source_.AddEvent(r);
}
template <typename ReplyProtoType>
void ServiceDistributed::ProcessDataReply(
const std::string& (ReplyProtoType::*func)() const,
int async_id,
const ReplyProtoType& reply) {
VLOG(1) << __func__;
MountTaskResult* r = new MountTaskResult();
VLOG(3) << "attestationd reply:"
<< " async_id=" << async_id << " status=" << reply.status();
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
r->set_sequence_id(async_id);
r->set_return_status(reply.status() == AttestationStatus::STATUS_SUCCESS);
brillo::SecureBlob blob((reply.*func)());
r->set_return_data(blob);
event_source_.AddEvent(r);
}
void ServiceDistributed::ProcessGetEndorsementInfoReply(
DBusGMethodInvocation* context,
const attestation::GetEndorsementInfoReply& reply) {
VLOG(1) << __func__;
BaseReply reply_out;
if (reply.status() == AttestationStatus::STATUS_SUCCESS) {
GetEndorsementInfoReply* extension =
reply_out.MutableExtension(GetEndorsementInfoReply::reply);
extension->set_ek_public_key(reply.ek_public_key());
if (!reply.ek_certificate().empty()) {
extension->set_ek_certificate(reply.ek_certificate());
}
} else {
VLOG(1) << "Attestation daemon returned status " << reply.status();
reply_out.set_error(CRYPTOHOME_ERROR_TPM_EK_NOT_AVAILABLE);
}
SendReply(context, reply_out);
}
bool ServiceDistributed::GetKeyInfo(gboolean is_user_specific,
gchar* username,
gchar* key_name,
attestation::GetKeyInfoReply* key_info) {
VLOG(3) << __func__;
attestation::GetKeyInfoRequest request;
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
auto method = base::Bind(&AttestationInterface::GetKeyInfo,
base::Unretained(attestation_interface_), request);
return SendRequestAndWait(method, key_info);
}
void ServiceDistributed::AttestationInitialize() {
VLOG(1) << __func__;
auto method = base::Bind(&AttestationInterface::Initialize,
base::Unretained(attestation_interface_));
PostAndWait(method);
}
void ServiceDistributed::AttestationInitializeTpm() {
VLOG(1) << __func__;
}
void ServiceDistributed::AttestationInitializeTpmComplete() {
VLOG(1) << __func__;
}
void ServiceDistributed::AttestationGetTpmStatus(GetTpmStatusReply* reply_out) {
VLOG(1) << __func__;
attestation::GetStatusRequest request;
request.set_extended_status(true);
attestation::GetStatusReply reply;
auto method = base::Bind(&AttestationInterface::GetStatus,
base::Unretained(attestation_interface_), request);
if (SendRequestAndWait(method, &reply) &&
reply.status() == AttestationStatus::STATUS_SUCCESS) {
reply_out->set_attestation_prepared(reply.prepared_for_enrollment());
reply_out->set_attestation_enrolled(reply.enrolled());
reply_out->set_verified_boot_measured(reply.verified_boot());
} else {
reply_out->set_attestation_prepared(false);
reply_out->set_attestation_enrolled(false);
reply_out->set_verified_boot_measured(false);
}
}
bool ServiceDistributed::AttestationGetDelegateCredentials(
brillo::SecureBlob* blob,
brillo::SecureBlob* secret,
bool* has_reset_lock_permissions) {
// TODO(apronin):
// Decide what to do here for TPM1.2 and 2.0. Possibly re-work the
// DA reset logic in Service.
//
// This method is only called from ResetDictionaryAttackMitigation,
// where the delegate credentials are used to reset the DA counter.
// If we just return false here, and the DA counter is > 0, the
// ResetDictionaryAttackMitigation will exit with kDelegateNotAvailable.
LOG(WARNING) << __func__ << ": Not implemented";
return false;
}
gboolean ServiceDistributed::TpmIsAttestationPrepared(gboolean* OUT_prepared,
GError** error) {
VLOG(1) << __func__;
attestation::GetStatusRequest request;
request.set_extended_status(false);
attestation::GetStatusReply reply;
auto method = base::Bind(&AttestationInterface::GetStatus,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
*OUT_prepared = reply.prepared_for_enrollment();
return TRUE;
}
gboolean ServiceDistributed::TpmVerifyAttestationData(gboolean is_cros_core,
gboolean* OUT_verified,
GError** error) {
VLOG(1) << __func__;
attestation::VerifyRequest request;
request.set_cros_core(is_cros_core);
request.set_ek_only(false);
attestation::VerifyReply reply;
auto method = base::Bind(&AttestationInterface::Verify,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
*OUT_verified = reply.verified();
return TRUE;
}
gboolean ServiceDistributed::TpmVerifyEK(gboolean is_cros_core,
gboolean* OUT_verified,
GError** error) {
VLOG(1) << __func__;
attestation::VerifyRequest request;
request.set_cros_core(is_cros_core);
request.set_ek_only(true);
attestation::VerifyReply reply;
auto method = base::Bind(&AttestationInterface::Verify,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
*OUT_verified = reply.verified();
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationCreateEnrollRequest(
gint pca_type,
GArray** OUT_pca_request,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
attestation::CreateEnrollRequestRequest request;
attestation::CreateEnrollRequestReply reply;
auto method = base::Bind(&AttestationInterface::CreateEnrollRequest,
base::Unretained(attestation_interface_), request);
// 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(SecureBlob::value_type));
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
g_array_append_vals(*OUT_pca_request, reply.pca_request().data(),
reply.pca_request().size());
return TRUE;
}
gboolean ServiceDistributed::AsyncTpmAttestationCreateEnrollRequest(
gint pca_type,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
*OUT_async_id = AllocateAsyncId();
attestation::CreateEnrollRequestRequest request;
auto callback = base::Bind(
&ServiceDistributed::ProcessDataReply<
attestation::CreateEnrollRequestReply>,
GetWeakPtr(), &attestation::CreateEnrollRequestReply::pca_request,
*OUT_async_id);
auto method =
base::Bind(&AttestationInterface::CreateEnrollRequest,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationEnroll(gint pca_type,
GArray* pca_response,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
attestation::FinishEnrollRequest request;
request.set_pca_response(pca_response->data, pca_response->len);
attestation::FinishEnrollReply reply;
auto method = base::Bind(&AttestationInterface::FinishEnroll,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
return TRUE;
}
gboolean ServiceDistributed::AsyncTpmAttestationEnroll(gint pca_type,
GArray* pca_response,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
*OUT_async_id = AllocateAsyncId();
attestation::FinishEnrollRequest request;
request.set_pca_response(pca_response->data, pca_response->len);
auto callback = base::Bind(
&ServiceDistributed::ProcessStatusReply<attestation::FinishEnrollReply>,
GetWeakPtr(), *OUT_async_id);
auto method =
base::Bind(&AttestationInterface::FinishEnroll,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationCreateCertRequest(
gint pca_type,
gint certificate_profile,
gchar* username,
gchar* request_origin,
GArray** OUT_pca_request,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
attestation::CreateCertificateRequestRequest request;
attestation::CreateCertificateRequestReply reply;
auto method = base::Bind(&AttestationInterface::CreateCertificateRequest,
base::Unretained(attestation_interface_), request);
// 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(SecureBlob::value_type));
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
g_array_append_vals(*OUT_pca_request, reply.pca_request().data(),
reply.pca_request().size());
return TRUE;
}
gboolean ServiceDistributed::AsyncTpmAttestationCreateCertRequest(
gint pca_type,
gint certificate_profile,
gchar* username,
gchar* request_origin,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
if (pca_type != Attestation::kDefaultPCA) {
ReportUnsupportedPCAType(error, pca_type);
return FALSE;
}
*OUT_async_id = AllocateAsyncId();
attestation::CreateCertificateRequestRequest request;
request.set_certificate_profile(GetProfile(certificate_profile));
request.set_username(username);
request.set_request_origin(request_origin);
auto callback = base::Bind(
&ServiceDistributed::ProcessDataReply<
attestation::CreateCertificateRequestReply>,
GetWeakPtr(), &attestation::CreateCertificateRequestReply::pca_request,
*OUT_async_id);
auto method =
base::Bind(&AttestationInterface::CreateCertificateRequest,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationFinishCertRequest(
GArray* pca_response,
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray** OUT_cert,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::FinishCertificateRequestRequest request;
request.set_pca_response(pca_response->data, pca_response->len);
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
attestation::FinishCertificateRequestReply reply;
auto method = base::Bind(&AttestationInterface::FinishCertificateRequest,
base::Unretained(attestation_interface_), request);
// 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(SecureBlob::value_type));
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
if (*OUT_success) {
g_array_append_vals(*OUT_cert, reply.certificate().data(),
reply.certificate().size());
}
return TRUE;
}
gboolean ServiceDistributed::AsyncTpmAttestationFinishCertRequest(
GArray* pca_response,
gboolean is_user_specific,
gchar* username,
gchar* key_name,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
*OUT_async_id = AllocateAsyncId();
attestation::FinishCertificateRequestRequest request;
request.set_pca_response(pca_response->data, pca_response->len);
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
auto callback = base::Bind(
&ServiceDistributed::ProcessDataReply<
attestation::FinishCertificateRequestReply>,
GetWeakPtr(), &attestation::FinishCertificateRequestReply::certificate,
*OUT_async_id);
auto method =
base::Bind(&AttestationInterface::FinishCertificateRequest,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmIsAttestationEnrolled(gboolean* OUT_is_enrolled,
GError** error) {
VLOG(1) << __func__;
attestation::GetStatusRequest request;
request.set_extended_status(false);
attestation::GetStatusReply reply;
auto method = base::Bind(&AttestationInterface::GetStatus,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
if (reply.status() != AttestationStatus::STATUS_SUCCESS) {
ReportErrorFromStatus(error, reply.status());
return FALSE;
}
*OUT_is_enrolled = reply.enrolled();
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationDoesKeyExist(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
gboolean* OUT_exists,
GError** error) {
VLOG(1) << __func__;
attestation::GetKeyInfoReply key_info;
if (!GetKeyInfo(is_user_specific, username, key_name, &key_info)) {
ReportSendFailure(error);
return FALSE;
}
if (key_info.status() == AttestationStatus::STATUS_SUCCESS) {
*OUT_exists = TRUE;
return TRUE;
} else if (key_info.status() == AttestationStatus::STATUS_INVALID_PARAMETER) {
*OUT_exists = FALSE;
return TRUE;
}
ReportErrorFromStatus(error, key_info.status());
return FALSE;
}
gboolean ServiceDistributed::TpmAttestationGetCertificate(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray** OUT_certificate,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::GetKeyInfoReply key_info;
// We must set the GArray now because if we return without setting it,
// dbus-glib loops forever.
*OUT_certificate = g_array_new(false, false, sizeof(SecureBlob::value_type));
if (!GetKeyInfo(is_user_specific, username, key_name, &key_info)) {
ReportSendFailure(error);
return FALSE;
}
if (key_info.status() == AttestationStatus::STATUS_SUCCESS) {
*OUT_success = TRUE;
g_array_append_vals(*OUT_certificate, key_info.certificate().data(),
key_info.certificate().size());
} else {
VLOG(1) << "Attestation daemon returned status " << key_info.status();
*OUT_success = FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationGetPublicKey(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray** OUT_public_key,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::GetKeyInfoReply key_info;
// We must set the GArray now because if we return without setting it,
// dbus-glib loops forever.
*OUT_public_key = g_array_new(false, false, sizeof(SecureBlob::value_type));
if (!GetKeyInfo(is_user_specific, username, key_name, &key_info)) {
ReportSendFailure(error);
return FALSE;
}
if (key_info.status() == AttestationStatus::STATUS_SUCCESS) {
*OUT_success = TRUE;
g_array_append_vals(*OUT_public_key, key_info.public_key().data(),
key_info.public_key().size());
} else {
VLOG(1) << "Attestation daemon returned status " << key_info.status();
*OUT_success = FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationRegisterKey(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
*OUT_async_id = AllocateAsyncId();
attestation::RegisterKeyWithChapsTokenRequest request;
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
auto callback = base::Bind(&ServiceDistributed::ProcessStatusReply<
attestation::RegisterKeyWithChapsTokenReply>,
GetWeakPtr(), *OUT_async_id);
auto method =
base::Bind(&AttestationInterface::RegisterKeyWithChapsToken,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::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) {
VLOG(1) << __func__;
*OUT_async_id = AllocateAsyncId();
attestation::SignEnterpriseChallengeRequest request;
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
request.set_domain(domain);
request.set_device_id(device_id->data, device_id->len);
request.set_include_signed_public_key(include_signed_public_key);
request.set_challenge(challenge->data, challenge->len);
auto callback =
base::Bind(&ServiceDistributed::ProcessDataReply<
attestation::SignEnterpriseChallengeReply>,
GetWeakPtr(),
&attestation::SignEnterpriseChallengeReply::challenge_response,
*OUT_async_id);
auto method =
base::Bind(&AttestationInterface::SignEnterpriseChallenge,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationSignSimpleChallenge(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray* challenge,
gint* OUT_async_id,
GError** error) {
VLOG(1) << __func__;
*OUT_async_id = AllocateAsyncId();
attestation::SignSimpleChallengeRequest request;
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
request.set_challenge(challenge->data, challenge->len);
auto callback = base::Bind(
&ServiceDistributed::ProcessDataReply<
attestation::SignSimpleChallengeReply>,
GetWeakPtr(), &attestation::SignSimpleChallengeReply::challenge_response,
*OUT_async_id);
auto method =
base::Bind(&AttestationInterface::SignSimpleChallenge,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
ReportSendFailure(error);
return FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationGetKeyPayload(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray** OUT_payload,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::GetKeyInfoReply key_info;
// 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(SecureBlob::value_type));
if (!GetKeyInfo(is_user_specific, username, key_name, &key_info)) {
ReportSendFailure(error);
return FALSE;
}
if (key_info.status() == AttestationStatus::STATUS_SUCCESS) {
*OUT_success = TRUE;
g_array_append_vals(*OUT_payload, key_info.payload().data(),
key_info.payload().size());
} else {
VLOG(1) << "Attestation daemon returned status " << key_info.status();
*OUT_success = FALSE;
}
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationSetKeyPayload(
gboolean is_user_specific,
gchar* username,
gchar* key_name,
GArray* payload,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::SetKeyPayloadRequest request;
request.set_key_label(key_name);
if (is_user_specific) {
request.set_username(username);
}
request.set_payload(payload->data, payload->len);
attestation::SetKeyPayloadReply reply;
auto method = base::Bind(&AttestationInterface::SetKeyPayload,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationDeleteKeys(gboolean is_user_specific,
gchar* username,
gchar* key_prefix,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::DeleteKeysRequest request;
request.set_key_prefix(key_prefix);
if (is_user_specific) {
request.set_username(username);
}
attestation::DeleteKeysReply reply;
auto method = base::Bind(&AttestationInterface::DeleteKeys,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationGetEK(gchar** OUT_ek_info,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::GetEndorsementInfoRequest request;
request.set_key_type(attestation::KeyType::KEY_TYPE_RSA);
attestation::GetEndorsementInfoReply reply;
auto method = base::Bind(&AttestationInterface::GetEndorsementInfo,
base::Unretained(attestation_interface_), request);
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
*OUT_ek_info = g_strndup(reply.ek_info().data(), reply.ek_info().size());
return TRUE;
}
gboolean ServiceDistributed::TpmAttestationResetIdentity(
gchar* reset_token,
GArray** OUT_reset_request,
gboolean* OUT_success,
GError** error) {
VLOG(1) << __func__;
attestation::ResetIdentityRequest request;
request.set_reset_token(reset_token);
attestation::ResetIdentityReply reply;
auto method = base::Bind(&AttestationInterface::ResetIdentity,
base::Unretained(attestation_interface_), request);
// 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(SecureBlob::value_type));
if (!SendRequestAndWait(method, &reply)) {
ReportSendFailure(error);
return FALSE;
}
VLOG_IF(1, reply.status() != AttestationStatus::STATUS_SUCCESS)
<< "Attestation daemon returned status " << reply.status();
*OUT_success = (reply.status() == AttestationStatus::STATUS_SUCCESS);
if (*OUT_success) {
g_array_append_vals(*OUT_reset_request, reply.reset_request().data(),
reply.reset_request().size());
}
return TRUE;
}
void ServiceDistributed::DoGetEndorsementInfo(
const brillo::SecureBlob& request_array,
DBusGMethodInvocation* context) {
VLOG(1) << __func__;
cryptohome::GetEndorsementInfoRequest request_in;
if (!request_in.ParseFromArray(request_array.data(), request_array.size())) {
SendInvalidArgsReply(context, "Bad GetEndorsementInfoRequest");
return;
}
attestation::GetEndorsementInfoRequest request;
request.set_key_type(attestation::KeyType::KEY_TYPE_RSA);
auto callback =
base::Bind(&ServiceDistributed::ProcessGetEndorsementInfoReply,
GetWeakPtr(), context);
auto method =
base::Bind(&AttestationInterface::GetEndorsementInfo,
base::Unretained(attestation_interface_), request, callback);
if (!Post(method)) {
SendFailureReply(context, "Failed to call GetEndorsementInfo");
}
}
gboolean ServiceDistributed::GetEndorsementInfo(
const GArray* request,
DBusGMethodInvocation* context) {
VLOG(1) << __func__;
auto method =
base::Bind(&ServiceDistributed::DoGetEndorsementInfo, GetWeakPtr(),
SecureBlob(request->data, request->data + request->len),
base::Unretained(context));
if (!Post(method)) {
return FALSE;
}
return TRUE;
}
void ServiceDistributed::DoInitializeCastKey(
const brillo::SecureBlob& request_array,
DBusGMethodInvocation* context) {
VLOG(1) << __func__;
cryptohome::InitializeCastKeyRequest request_in;
if (!request_in.ParseFromArray(request_array.data(), request_array.size())) {
SendInvalidArgsReply(context, "Bad InitializeCastKeyRequest");
return;
}
SendNotSupportedReply(context, "InitializeCastKeyRequest is not supported");
}
gboolean ServiceDistributed::InitializeCastKey(const GArray* request,
DBusGMethodInvocation* context) {
VLOG(1) << __func__;
auto method =
base::Bind(&ServiceDistributed::DoInitializeCastKey, GetWeakPtr(),
SecureBlob(request->data, request->data + request->len),
base::Unretained(context));
if (!Post(method)) {
return FALSE;
}
return TRUE;
}
} // namespace cryptohome