Implemented asynchronous attestation calls.
BUG=chromium-os:36561
TEST=Ran unit tests
Ran platform_Attestation
Ran platform_Attestation after modifying to use --async
Change-Id: Ibb83b40b3328fbd31ba7632c7f762a52843d0769
Reviewed-on: https://gerrit.chromium.org/gerrit/38780
Reviewed-by: Gaurav Shah <gauravsh@chromium.org>
Commit-Ready: Darren Krahn <dkrahn@chromium.org>
Tested-by: Darren Krahn <dkrahn@chromium.org>
diff --git a/attestation_task.cc b/attestation_task.cc
new file mode 100644
index 0000000..a88d434
--- /dev/null
+++ b/attestation_task.cc
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 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.
+//
+// Asynchronous attestation tasks.
+
+#include "attestation_task.h"
+
+#include "attestation.h"
+
+namespace cryptohome {
+
+AttestationTask::AttestationTask(AttestationTaskObserver* observer,
+ Attestation* attestation)
+ : MountTask(observer, NULL, UsernamePasskey()),
+ attestation_(attestation) {
+}
+
+AttestationTask::~AttestationTask() {}
+
+CreateEnrollRequestTask::CreateEnrollRequestTask(
+ AttestationTaskObserver* observer,
+ Attestation* attestation)
+ : AttestationTask(observer, attestation) {
+}
+
+CreateEnrollRequestTask::~CreateEnrollRequestTask() {}
+
+void CreateEnrollRequestTask::Run() {
+ result()->set_return_status(FALSE);
+ if (attestation_) {
+ SecureBlob pca_request;
+ bool status = attestation_->CreateEnrollRequest(&pca_request);
+ result()->set_return_status(status);
+ result()->set_return_data(pca_request);
+ }
+ Notify();
+}
+
+EnrollTask::EnrollTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ const SecureBlob& pca_response)
+ : AttestationTask(observer, attestation),
+ pca_response_(pca_response) {
+}
+
+EnrollTask::~EnrollTask() {}
+
+void EnrollTask::Run() {
+ result()->set_return_status(FALSE);
+ if (attestation_) {
+ bool status = attestation_->Enroll(pca_response_);
+ result()->set_return_status(status);
+ }
+ Notify();
+}
+
+CreateCertRequestTask::CreateCertRequestTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ bool is_cert_for_owner)
+ : AttestationTask(observer, attestation),
+ is_cert_for_owner_(is_cert_for_owner) {
+}
+
+CreateCertRequestTask::~CreateCertRequestTask() {}
+
+void CreateCertRequestTask::Run() {
+ result()->set_return_status(FALSE);
+ if (attestation_) {
+ SecureBlob pca_request;
+ bool status = attestation_->CreateCertRequest(is_cert_for_owner_,
+ &pca_request);
+ result()->set_return_status(status);
+ result()->set_return_data(pca_request);
+ }
+ Notify();
+}
+
+FinishCertRequestTask::FinishCertRequestTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ const SecureBlob& pca_response)
+ : AttestationTask(observer, attestation),
+ pca_response_(pca_response) {
+}
+
+FinishCertRequestTask::~FinishCertRequestTask() {}
+
+void FinishCertRequestTask::Run() {
+ result()->set_return_status(FALSE);
+ if (attestation_) {
+ SecureBlob cert;
+ bool status = attestation_->FinishCertRequest(pca_response_, &cert);
+ result()->set_return_status(status);
+ result()->set_return_data(cert);
+ }
+ Notify();
+}
+
+} // namespace cryptohome
diff --git a/attestation_task.h b/attestation_task.h
new file mode 100644
index 0000000..fc1bdc7
--- /dev/null
+++ b/attestation_task.h
@@ -0,0 +1,84 @@
+// Copyright (c) 2012 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.
+//
+// Asynchronous attestation tasks.
+
+#include "mount_task.h"
+
+namespace cryptohome {
+
+class Attestation;
+
+typedef MountTaskObserver AttestationTaskObserver;
+
+// This class represents an attestation task. Inherit MountTask to reuse basic
+// async code, especially the sequence counter.
+class AttestationTask : public MountTask {
+ public:
+ AttestationTask(AttestationTaskObserver* observer, Attestation* attestation);
+ virtual ~AttestationTask();
+
+ protected:
+ // The Attestation instance which will do the actual work.
+ Attestation* attestation_;
+};
+
+class CreateEnrollRequestTask : public AttestationTask {
+ public:
+ CreateEnrollRequestTask(AttestationTaskObserver* observer,
+ Attestation* attestation);
+ virtual ~CreateEnrollRequestTask();
+
+ virtual void Run();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CreateEnrollRequestTask);
+};
+
+class EnrollTask : public AttestationTask {
+ public:
+ EnrollTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ const SecureBlob& pca_response);
+ virtual ~EnrollTask();
+
+ virtual void Run();
+
+ private:
+ SecureBlob pca_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(EnrollTask);
+};
+
+class CreateCertRequestTask : public AttestationTask {
+ public:
+ CreateCertRequestTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ bool is_cert_for_owner);
+ virtual ~CreateCertRequestTask();
+
+ virtual void Run();
+
+ private:
+ bool is_cert_for_owner_;
+
+ DISALLOW_COPY_AND_ASSIGN(CreateCertRequestTask);
+};
+
+class FinishCertRequestTask : public AttestationTask {
+ public:
+ FinishCertRequestTask(AttestationTaskObserver* observer,
+ Attestation* attestation,
+ const SecureBlob& pca_response);
+ virtual ~FinishCertRequestTask();
+
+ virtual void Run();
+
+ private:
+ SecureBlob pca_response_;
+
+ DISALLOW_COPY_AND_ASSIGN(FinishCertRequestTask);
+};
+
+} // namespace cryptohome
diff --git a/mount_task.h b/mount_task.h
index e5efdb3..675a7fb 100644
--- a/mount_task.h
+++ b/mount_task.h
@@ -37,6 +37,8 @@
#include "pkcs11_init.h"
#include "username_passkey.h"
+using chromeos::SecureBlob;
+
namespace cryptohome {
extern const char* kMountTaskResultEventType;
@@ -72,6 +74,7 @@
: sequence_id_(rhs.sequence_id_),
return_status_(rhs.return_status_),
return_code_(rhs.return_code_),
+ return_data_(rhs.return_data_),
event_name_(rhs.event_name_),
mount_(rhs.mount_),
pkcs11_init_(rhs.pkcs11_init_),
@@ -133,10 +136,21 @@
guest_ = value;
}
+ SecureBlob return_data() const {
+ return return_data_;
+ }
+
+ void set_return_data(const SecureBlob& data) {
+ return_data_.clear_contents();
+ return_data_ = data;
+ }
+
MountTaskResult& operator=(const MountTaskResult& rhs) {
sequence_id_ = rhs.sequence_id_;
return_status_ = rhs.return_status_;
return_code_ = rhs.return_code_;
+ return_data_.clear_contents();
+ return_data_ = rhs.return_data_;
event_name_ = rhs.event_name_;
mount_ = rhs.mount_;
pkcs11_init_ = rhs.pkcs11_init_;
@@ -152,6 +166,7 @@
int sequence_id_;
bool return_status_;
MountError return_code_;
+ SecureBlob return_data_;
const char* event_name_;
Mount* mount_;
bool pkcs11_init_;
diff --git a/service.cc b/service.cc
index abb3cc3..7aba369 100644
--- a/service.cc
+++ b/service.cc
@@ -26,6 +26,7 @@
#include <string>
#include <vector>
+#include "attestation_task.h"
#include "cryptohome_event_source.h"
#include "crypto.h"
#include "install_attributes.h"
@@ -430,8 +431,26 @@
void Service::NotifyEvent(CryptohomeEventBase* event) {
if (!strcmp(event->GetEventName(), kMountTaskResultEventType)) {
MountTaskResult* result = static_cast<MountTaskResult*>(event);
- g_signal_emit(cryptohome_, async_complete_signal_, 0, result->sequence_id(),
- result->return_status(), result->return_code());
+ if (result->return_data().size() == 0) {
+ g_signal_emit(cryptohome_,
+ async_complete_signal_,
+ 0,
+ result->sequence_id(),
+ result->return_status(),
+ result->return_code());
+ } else {
+ chromeos::glib::ScopedArray tmp_array(g_array_new(FALSE, FALSE, 1));
+ g_array_append_vals(tmp_array.get(),
+ result->return_data().data(),
+ result->return_data().size());
+ g_signal_emit(cryptohome_,
+ async_data_complete_signal_,
+ 0,
+ result->sequence_id(),
+ result->return_status(),
+ tmp_array.get());
+ chromeos::SecureMemset(tmp_array.get()->data, 0, tmp_array.get()->len);
+ }
if (result->pkcs11_init()) {
LOG(INFO) << "An asynchronous mount request with sequence id: "
<< result->sequence_id()
@@ -1036,9 +1055,15 @@
gboolean Service::AsyncTpmAttestationCreateEnrollRequest(gint* OUT_async_id,
GError** error) {
- // TODO(dkrahn): Implement.
- g_set_error(error, 0, 0, "Not implemented");
- return FALSE;
+ AttestationTaskObserver* observer =
+ new MountTaskObserverBridge(NULL, &event_source_);
+ scoped_refptr<CreateEnrollRequestTask> task =
+ new CreateEnrollRequestTask(observer, tpm_init_->get_attestation());
+ *OUT_async_id = task->sequence_id();
+ mount_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&CreateEnrollRequestTask::Run, task.get()));
+ return TRUE;
}
gboolean Service::TpmAttestationEnroll(GArray* pca_response,
@@ -1058,9 +1083,16 @@
gboolean Service::AsyncTpmAttestationEnroll(GArray* pca_response,
gint* OUT_async_id,
GError** error) {
- // TODO(dkrahn): Implement.
- g_set_error(error, 0, 0, "Not implemented");
- return FALSE;
+ chromeos::SecureBlob blob(pca_response->data, pca_response->len);
+ AttestationTaskObserver* observer =
+ new MountTaskObserverBridge(NULL, &event_source_);
+ scoped_refptr<EnrollTask> task =
+ new EnrollTask(observer, tpm_init_->get_attestation(), blob);
+ *OUT_async_id = task->sequence_id();
+ mount_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&EnrollTask::Run, task.get()));
+ return TRUE;
}
gboolean Service::TpmAttestationCreateCertRequest(gboolean is_cert_for_owner,
@@ -1082,9 +1114,17 @@
gboolean is_cert_for_owner,
gint* OUT_async_id,
GError** error) {
- // TODO(dkrahn): Implement.
- g_set_error(error, 0, 0, "Not implemented");
- return FALSE;
+ AttestationTaskObserver* observer =
+ new MountTaskObserverBridge(NULL, &event_source_);
+ scoped_refptr<CreateCertRequestTask> task =
+ new CreateCertRequestTask(observer,
+ tpm_init_->get_attestation(),
+ is_cert_for_owner);
+ *OUT_async_id = task->sequence_id();
+ mount_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&CreateCertRequestTask::Run, task.get()));
+ return TRUE;
}
gboolean Service::TpmAttestationFinishCertRequest(GArray* pca_response,
@@ -1109,9 +1149,16 @@
gboolean Service::AsyncTpmAttestationFinishCertRequest(GArray* pca_response,
gint* OUT_async_id,
GError** error) {
- // TODO(dkrahn): Implement.
- g_set_error(error, 0, 0, "Not implemented");
- return FALSE;
+ chromeos::SecureBlob blob(pca_response->data, pca_response->len);
+ AttestationTaskObserver* observer =
+ new MountTaskObserverBridge(NULL, &event_source_);
+ scoped_refptr<FinishCertRequestTask> task =
+ new FinishCertRequestTask(observer, tpm_init_->get_attestation(), blob);
+ *OUT_async_id = task->sequence_id();
+ mount_thread_.message_loop()->PostTask(
+ FROM_HERE,
+ base::Bind(&FinishCertRequestTask::Run, task.get()));
+ return TRUE;
}
gboolean Service::TpmIsAttestationEnrolled(gboolean* OUT_is_enrolled,