attestation: Make the attestation interface asynchronous.
Also moves to the D-Bus asynchronous methods for proxy / object.
BUG=brillo:737
TEST=build, unit tests, manually ran 'attestation_client'
Change-Id: I7cf60edcb5bf7fa112592e5f129a2dcd6334ae22
Reviewed-on: https://chromium-review.googlesource.com/264932
Reviewed-by: Alex Vakulenko <[email protected]>
Commit-Queue: Darren Krahn <[email protected]>
Tested-by: Darren Krahn <[email protected]>
diff --git a/attestation.gyp b/attestation.gyp
index 84a1916..b37cdee 100644
--- a/attestation.gyp
+++ b/attestation.gyp
@@ -103,6 +103,7 @@
'sources': [
'attestation_testrunner.cc',
'client/dbus_proxy_test.cc',
+ 'server/dbus_service_test.cc',
],
'dependencies': [
'client_library',
diff --git a/client/dbus_proxy.cc b/client/dbus_proxy.cc
index 5a4d64a..9f507a2 100644
--- a/client/dbus_proxy.cc
+++ b/client/dbus_proxy.cc
@@ -4,10 +4,19 @@
#include "attestation/client/dbus_proxy.h"
+#include <chromeos/bind_lambda.h>
#include <chromeos/dbus/dbus_method_invoker.h>
#include "attestation/common/dbus_interface.h"
+namespace {
+
+// Use a two minute timeout because TPM operations can take a long time and
+// there may be a few of them queued up.
+const int kDBusTimeoutMS = 120000;
+
+} // namespace
+
namespace attestation {
DBusProxy::DBusProxy() {}
@@ -27,37 +36,34 @@
return (object_proxy_ != nullptr);
}
-AttestationStatus DBusProxy::CreateGoogleAttestedKey(
+void DBusProxy::CreateGoogleAttestedKey(
const std::string& key_label,
KeyType key_type,
KeyUsage key_usage,
CertificateProfile certificate_profile,
- std::string* server_error_details,
- std::string* certificate) {
+ const base::Callback<CreateGoogleAttestedKeyCallback>& callback) {
attestation::CreateGoogleAttestedKeyRequest request;
request.set_key_label(key_label);
request.set_key_type(key_type);
request.set_key_usage(key_usage);
request.set_certificate_profile(certificate_profile);
- auto response = chromeos::dbus_utils::CallMethodAndBlock(
+ auto on_success = [callback](
+ const attestation::CreateGoogleAttestedKeyReply& reply) {
+ callback.Run(reply.status(),
+ reply.certificate_chain(),
+ reply.server_error());
+ };
+ auto on_error = [callback](chromeos::Error* error) {
+ callback.Run(NOT_AVAILABLE, std::string(), std::string());
+ };
+ chromeos::dbus_utils::CallMethodWithTimeout(
+ kDBusTimeoutMS,
object_proxy_,
attestation::kAttestationInterface,
attestation::kCreateGoogleAttestedKey,
- nullptr /* error */,
+ base::Bind(on_success),
+ base::Bind(on_error),
request);
- if (!response) {
- return NOT_AVAILABLE;
- }
- attestation::CreateGoogleAttestedKeyReply reply;
- if (!chromeos::dbus_utils::ExtractMethodCallResults(
- response.get(),
- nullptr /* error */,
- &reply)) {
- return UNEXPECTED_DEVICE_ERROR;
- }
- *certificate = reply.certificate();
- *server_error_details = reply.server_error();
- return reply.status();
}
} // namespace attestation
diff --git a/client/dbus_proxy.h b/client/dbus_proxy.h
index 1847273..7d3d135 100644
--- a/client/dbus_proxy.h
+++ b/client/dbus_proxy.h
@@ -28,13 +28,12 @@
// AttestationInterface methods.
bool Initialize() override;
- AttestationStatus CreateGoogleAttestedKey(
+ void CreateGoogleAttestedKey(
const std::string& key_label,
KeyType key_type,
KeyUsage key_usage,
CertificateProfile certificate_profile,
- std::string* server_error_details,
- std::string* certificate) override;
+ const base::Callback<CreateGoogleAttestedKeyCallback>& callback) override;
// Useful for testing.
void set_object_proxy(dbus::ObjectProxy* object_proxy) {
diff --git a/client/dbus_proxy_test.cc b/client/dbus_proxy_test.cc
index c86862e..bc1920a 100644
--- a/client/dbus_proxy_test.cc
+++ b/client/dbus_proxy_test.cc
@@ -4,6 +4,7 @@
#include <string>
+#include <chromeos/bind_lambda.h>
#include <dbus/mock_object_proxy.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
@@ -31,7 +32,9 @@
};
TEST_F(DBusProxyTest, CreateGoogleAttestedKeySuccess) {
- auto fake_dbus_call = [](dbus::MethodCall* method_call) -> dbus::Response* {
+ auto fake_dbus_call = [](
+ dbus::MethodCall* method_call,
+ const dbus::MockObjectProxy::ResponseCallback& response_callback) {
// Verify request protobuf.
dbus::MessageReader reader(method_call);
CreateGoogleAttestedKeyRequest request_proto;
@@ -47,21 +50,26 @@
dbus::MessageWriter writer(response.get());
CreateGoogleAttestedKeyReply reply_proto;
reply_proto.set_status(SUCCESS);
- reply_proto.set_certificate("certificate");
+ reply_proto.set_certificate_chain("certificate");
reply_proto.set_server_error("server_error");
writer.AppendProtoAsArrayOfBytes(reply_proto);
- return response.release();
+ response_callback.Run(response.release());
};
EXPECT_CALL(*mock_object_proxy_,
- MockCallMethodAndBlockWithErrorDetails(_, _, _))
- .WillOnce(WithArgs<0>(Invoke(fake_dbus_call)));
- std::string certificate;
- std::string server_error;
- EXPECT_EQ(SUCCESS, proxy_.CreateGoogleAttestedKey(
- "label", KEY_TYPE_ECC, KEY_USAGE_SIGN, ENTERPRISE_MACHINE_CERTIFICATE,
- &server_error, &certificate));
- EXPECT_EQ("certificate", certificate);
- EXPECT_EQ("server_error", server_error);
+ CallMethodWithErrorCallback(_, _, _, _))
+ .WillOnce(WithArgs<0, 2>(Invoke(fake_dbus_call)));
+
+ // Set expectations on the outputs.
+ auto callback = [](AttestationStatus status,
+ const std::string& certificate,
+ const std::string& server_error) {
+ EXPECT_EQ(SUCCESS, status);
+ EXPECT_EQ("certificate", certificate);
+ EXPECT_EQ("server_error", server_error);
+ };
+ proxy_.CreateGoogleAttestedKey("label", KEY_TYPE_ECC, KEY_USAGE_SIGN,
+ ENTERPRISE_MACHINE_CERTIFICATE,
+ base::Bind(callback));
}
} // namespace attestation
diff --git a/client/main.cc b/client/main.cc
index 1fae5a1..b97e9a6 100644
--- a/client/main.cc
+++ b/client/main.cc
@@ -2,35 +2,114 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <stdio.h>
+#include <sysexits.h>
+
#include <memory>
#include <string>
+#include <base/command_line.h>
+#include <base/message_loop/message_loop.h>
+#include <chromeos/bind_lambda.h>
+#include <chromeos/daemons/daemon.h>
+#include <chromeos/syslog_logging.h>
+
#include "attestation/client/dbus_proxy.h"
#include "attestation/common/attestation_ca.pb.h"
#include "attestation/common/interface.pb.h"
-int main(int argc, char* argv[]) {
- std::unique_ptr<attestation::AttestationInterface> attestation(
- new attestation::DBusProxy());
- if (!attestation->Initialize()) {
- printf("Failed to initialize.\n");
- }
- std::string certificate;
- std::string server_error_details;
- attestation::AttestationStatus status = attestation->CreateGoogleAttestedKey(
- "test_key",
- attestation::KEY_TYPE_RSA,
- attestation::KEY_USAGE_SIGN,
- attestation::ENTERPRISE_MACHINE_CERTIFICATE,
- &certificate,
- &server_error_details);
- if (status == attestation::SUCCESS) {
- printf("Success!\n");
- } else {
- printf("Error occurred: %d.\n", status);
- if (!server_error_details.empty()) {
- printf("Server error details: %s\n", server_error_details.c_str());
+namespace attestation {
+
+const char kCreateCommand[] = "create";
+const char kUsage[] = R"(
+Usage: attestation_client <command> [<args>]
+Commands:
+ create - Creates a Google-attested key (this is the default command).
+)";
+
+// The Daemon class works well as a client loop as well.
+using ClientLoopBase = chromeos::Daemon;
+
+class ClientLoop : public ClientLoopBase {
+ public:
+ ClientLoop() = default;
+ ~ClientLoop() override = default;
+
+ protected:
+ int OnInit() override {
+ int exit_code = ClientLoopBase::OnInit();
+ if (exit_code != EX_OK) {
+ return exit_code;
}
+ attestation_.reset(new attestation::DBusProxy());
+ if (!attestation_->Initialize()) {
+ return EX_UNAVAILABLE;
+ }
+ exit_code = ScheduleCommand();
+ if (exit_code == EX_USAGE) {
+ printf("%s", kUsage);
+ }
+ return exit_code;
}
- return status;
+
+ void OnShutdown(int* exit_code) override {
+ attestation_.reset();
+ ClientLoopBase::OnShutdown(exit_code);
+ }
+
+ private:
+ // Posts tasks according to the command line options.
+ int ScheduleCommand() {
+ base::Closure task;
+ auto args = base::CommandLine::ForCurrentProcess()->GetArgs();
+ if (args.empty() || args.front() == kCreateCommand) {
+ task = base::Bind(&ClientLoop::CallCreateGoogleAttestedKey,
+ weak_factory_.GetWeakPtr());
+ } else {
+ return EX_USAGE;
+ }
+ base::MessageLoop::current()->PostTask(FROM_HERE, task);
+ return EX_OK;
+ }
+
+ void HandleCreateGoogleAttestedKeyReply(
+ attestation::AttestationStatus status,
+ const std::string& certificate,
+ const std::string& server_error_details) {
+ if (status == attestation::SUCCESS) {
+ printf("Success!\n");
+ } else {
+ printf("Error occurred: %d.\n", status);
+ if (!server_error_details.empty()) {
+ printf("Server error details: %s\n", server_error_details.c_str());
+ }
+ }
+ Quit();
+ }
+
+ void CallCreateGoogleAttestedKey() {
+ attestation_->CreateGoogleAttestedKey(
+ "test_key",
+ attestation::KEY_TYPE_RSA,
+ attestation::KEY_USAGE_SIGN,
+ attestation::ENTERPRISE_MACHINE_CERTIFICATE,
+ base::Bind(&ClientLoop::HandleCreateGoogleAttestedKeyReply,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ std::unique_ptr<attestation::AttestationInterface> attestation_;
+
+ // Declare this last so weak pointers will be destroyed first.
+ base::WeakPtrFactory<ClientLoop> weak_factory_{this};
+
+ DISALLOW_COPY_AND_ASSIGN(ClientLoop);
+};
+
+} // namespace attestation
+
+int main(int argc, char* argv[]) {
+ base::CommandLine::Init(argc, argv);
+ chromeos::InitLog(chromeos::kLogToSyslog | chromeos::kLogToStderr);
+ attestation::ClientLoop loop;
+ return loop.Run();
}
diff --git a/common/attestation_interface.h b/common/attestation_interface.h
index b153899..89b6d87 100644
--- a/common/attestation_interface.h
+++ b/common/attestation_interface.h
@@ -7,6 +7,8 @@
#include <string>
+#include <base/callback_forward.h>
+
#include "attestation/common/attestation_ca.pb.h"
#include "attestation/common/export.h"
#include "attestation/common/interface.pb.h"
@@ -18,7 +20,7 @@
// [APP] -> AttestationInterface -> [IPC] -> AttestationInterface
class ATTESTATION_EXPORT AttestationInterface {
public:
- virtual ~AttestationInterface() {}
+ virtual ~AttestationInterface() = default;
// Performs initialization tasks that may take a long time. This method must
// be successfully called before calling any other method. Returns true on
@@ -26,18 +28,25 @@
virtual bool Initialize() = 0;
// Creates a key certified by the Google Attestation CA which corresponds to
- // the give |key_label|, |key_type|, and |key_usage|. The certificate issued
- // by the CA will correspond to |certificate_profile|. On success,
- // |certificate| will contain the DER-encoded X.509 certificate issued by the
- // CA. If the CA refuses to issue a certificate, REQUEST_DENIED_BY_CA is
- // returned and |server_error_details| contains a message from the CA.
- virtual AttestationStatus CreateGoogleAttestedKey(
+ // the given |key_label|, |key_type|, and |key_usage|. The certificate issued
+ // by the CA will correspond to |certificate_profile|. On success, |status|
+ // will be SUCCESS and |certificate_chain| will contain a PEM-encoded list of
+ // X.509 certificates starting with the requested certificate issued by the CA
+ // and followed by certificates for any intermediate authorities, in order.
+ // The Google Attestation CA root certificate is well-known and not included.
+ // If the CA refuses to issue a certificate, |status| will be
+ // REQUEST_DENIED_BY_CA and |server_error_details| will contain an error
+ // message from the CA.
+ using CreateGoogleAttestedKeyCallback =
+ void(AttestationStatus status,
+ const std::string& certificate_chain,
+ const std::string& server_error_details);
+ virtual void CreateGoogleAttestedKey(
const std::string& key_label,
KeyType key_type,
KeyUsage key_usage,
CertificateProfile certificate_profile,
- std::string* certificate,
- std::string* server_error_details) = 0;
+ const base::Callback<CreateGoogleAttestedKeyCallback>& callback) = 0;
};
} // namespace attestation
diff --git a/common/interface.proto b/common/interface.proto
index f81e3ff..ef7af4e 100644
--- a/common/interface.proto
+++ b/common/interface.proto
@@ -44,6 +44,9 @@
// More information about a server-side error. This only exists
// if status=REQUEST_DENIED_BY_CA.
optional string server_error = 2;
- // The X.509/DER certificate issued by the Google Attestation CA.
- optional bytes certificate = 3;
+ // A PEM-encoded list of X.509 certificates starting with the requested
+ // certificate issued by the CA and followed by certificates for any
+ // intermediate authorities, in order. The Google Attestation CA root
+ // certificate is well-known and not included.
+ optional string certificate_chain = 3;
}
diff --git a/common/mock_attestation_interface.h b/common/mock_attestation_interface.h
new file mode 100644
index 0000000..2dcca1f
--- /dev/null
+++ b/common/mock_attestation_interface.h
@@ -0,0 +1,33 @@
+// Copyright 2015 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.
+
+#ifndef ATTESTATION_COMMON_MOCK_ATTESTATION_INTERFACE_H_
+#define ATTESTATION_COMMON_MOCK_ATTESTATION_INTERFACE_H_
+
+#include <string>
+
+#include <gmock/gmock.h>
+
+#include "attestation/common/attestation_interface.h"
+
+namespace attestation {
+
+class MockAttestationInterface : public AttestationInterface {
+ public:
+ MockAttestationInterface() = default;
+ virtual ~MockAttestationInterface() = default;
+
+ MOCK_METHOD0(Initialize, bool());
+ MOCK_METHOD5(CreateGoogleAttestedKey, void(
+ const std::string&,
+ KeyType,
+ KeyUsage,
+ CertificateProfile,
+ const base::Callback<CreateGoogleAttestedKeyCallback>&));
+};
+
+} // namespace attestation
+
+#endif // ATTESTATION_COMMON_MOCK_ATTESTATION_INTERFACE_H_
+
diff --git a/server/attestation_service.cc b/server/attestation_service.cc
index 9565a13..dfddea8 100644
--- a/server/attestation_service.cc
+++ b/server/attestation_service.cc
@@ -4,20 +4,22 @@
#include "attestation/server/attestation_service.h"
+#include <base/callback.h>
+
namespace attestation {
bool AttestationService::Initialize() {
+ LOG(INFO) << "Attestation service started.";
return true;
}
-AttestationStatus AttestationService::CreateGoogleAttestedKey(
+void AttestationService::CreateGoogleAttestedKey(
const std::string& key_label,
KeyType key_type,
KeyUsage key_usage,
CertificateProfile certificate_profile,
- std::string* server_error_details,
- std::string* certificate) {
- return NOT_AVAILABLE;
+ const base::Callback<CreateGoogleAttestedKeyCallback>& callback) {
+ callback.Run(NOT_AVAILABLE, std::string(), std::string());
}
} // namespace attestation
diff --git a/server/attestation_service.h b/server/attestation_service.h
index a869db2..0e835b8 100644
--- a/server/attestation_service.h
+++ b/server/attestation_service.h
@@ -11,7 +11,7 @@
namespace attestation {
-// An implementation of AttestationInterface that actually implements it.
+// An implementation of AttestationInterface for the core attestation service.
// Usage:
// std::unique_ptr<AttestationInterface> attestation =
// new AttestationService();
@@ -24,13 +24,12 @@
// AttestationInterface methods.
bool Initialize() override;
- AttestationStatus CreateGoogleAttestedKey(
+ void CreateGoogleAttestedKey(
const std::string& key_label,
KeyType key_type,
KeyUsage key_usage,
CertificateProfile certificate_profile,
- std::string* server_error_details,
- std::string* certificate) override;
+ const base::Callback<CreateGoogleAttestedKeyCallback>& callback) override;
};
} // namespace attestation
diff --git a/server/dbus_service.cc b/server/dbus_service.cc
index 29e8e82..919ac7b 100644
--- a/server/dbus_service.cc
+++ b/server/dbus_service.cc
@@ -6,11 +6,14 @@
#include <string>
+#include <chromeos/bind_lambda.h>
#include <dbus/bus.h>
#include <dbus/object_path.h>
#include "attestation/common/dbus_interface.h"
+using chromeos::dbus_utils::DBusMethodResponse;
+
namespace attestation {
DBusService::DBusService(const scoped_refptr<dbus::Bus>& bus,
@@ -23,7 +26,7 @@
chromeos::dbus_utils::DBusInterface* dbus_interface =
dbus_object_.AddOrGetInterface(kAttestationInterface);
- dbus_interface->AddSimpleMethodHandler(
+ dbus_interface->AddMethodHandler(
kCreateGoogleAttestedKey,
base::Unretained(this),
&DBusService::HandleCreateGoogleAttestedKey);
@@ -31,26 +34,34 @@
dbus_object_.RegisterAsync(callback);
}
-CreateGoogleAttestedKeyReply DBusService::HandleCreateGoogleAttestedKey(
- CreateGoogleAttestedKeyRequest request) {
+void DBusService::HandleCreateGoogleAttestedKey(
+ scoped_ptr<DBusMethodResponse<const CreateGoogleAttestedKeyReply&>>
+ response,
+ const CreateGoogleAttestedKeyRequest& request) {
VLOG(1) << __func__;
- std::string certificate;
- std::string server_error_details;
- AttestationStatus status = service_->CreateGoogleAttestedKey(
- request.key_label(),
- request.key_type(),
- request.key_usage(),
- request.certificate_profile(),
- &certificate,
- &server_error_details);
- CreateGoogleAttestedKeyReply reply;
- reply.set_status(status);
- if (status == SUCCESS) {
- reply.set_certificate(certificate);
- } else if (status == REQUEST_DENIED_BY_CA) {
- reply.set_server_error(server_error_details);
- }
- return reply;
+ // A callback that fills the reply protobuf and sends it.
+ // CAUTION: This callback takes ownership of |response|.
+ auto callback = [](
+ scoped_ptr<DBusMethodResponse<const CreateGoogleAttestedKeyReply&>>
+ response,
+ AttestationStatus status,
+ const std::string& certificate_chain,
+ const std::string& server_error_details) {
+ CreateGoogleAttestedKeyReply reply;
+ reply.set_status(status);
+ if (status == SUCCESS) {
+ reply.set_certificate_chain(certificate_chain);
+ } else if (status == REQUEST_DENIED_BY_CA) {
+ reply.set_server_error(server_error_details);
+ }
+ response->Return(reply);
+ };
+ service_->CreateGoogleAttestedKey(request.key_label(),
+ request.key_type(),
+ request.key_usage(),
+ request.certificate_profile(),
+ base::Bind(callback,
+ base::Passed(&response)));
}
} // namespace attestation
diff --git a/server/dbus_service.h b/server/dbus_service.h
index 12c8ab5..e880c16 100644
--- a/server/dbus_service.h
+++ b/server/dbus_service.h
@@ -6,6 +6,7 @@
#define ATTESTATION_SERVER_DBUS_SERVICE_H_
#include <base/memory/scoped_ptr.h>
+#include <chromeos/dbus/dbus_method_response.h>
#include <chromeos/dbus/dbus_object.h>
#include <dbus/bus.h>
@@ -16,7 +17,7 @@
using CompletionAction =
chromeos::dbus_utils::AsyncEventSequencer::CompletionAction;
-// Main class within the attestation daemon that ties other classes together.
+// Handles D-Bus calls to the attestation daemon.
class DBusService {
public:
// DBusService does not take ownership of |service|; it must remain valid for
@@ -28,10 +29,19 @@
// Connects to D-Bus system bus and exports methods.
void Register(const CompletionAction& callback);
+ // Useful for testing.
+ void set_service(AttestationInterface* service) {
+ service_ = service;
+ }
+
private:
+ friend class DBusServiceTest;
+
// Handles a CreateGoogleAttestedKey D-Bus call.
- CreateGoogleAttestedKeyReply HandleCreateGoogleAttestedKey(
- CreateGoogleAttestedKeyRequest request);
+ void HandleCreateGoogleAttestedKey(
+ scoped_ptr<chromeos::dbus_utils::DBusMethodResponse<
+ const CreateGoogleAttestedKeyReply&>> response,
+ const CreateGoogleAttestedKeyRequest& request);
chromeos::dbus_utils::DBusObject dbus_object_;
AttestationInterface* service_;
diff --git a/server/dbus_service_test.cc b/server/dbus_service_test.cc
new file mode 100644
index 0000000..c440f5a
--- /dev/null
+++ b/server/dbus_service_test.cc
@@ -0,0 +1,108 @@
+// Copyright 2014 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 <chromeos/bind_lambda.h>
+#include <chromeos/dbus/dbus_object_test_helpers.h>
+#include <dbus/mock_bus.h>
+#include <dbus/mock_exported_object.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "attestation/common/dbus_interface.h"
+#include "attestation/common/mock_attestation_interface.h"
+#include "attestation/server/dbus_service.h"
+
+using testing::_;
+using testing::Invoke;
+using testing::NiceMock;
+using testing::Return;
+using testing::StrictMock;
+using testing::WithArgs;
+
+namespace attestation {
+
+class DBusServiceTest : public testing::Test {
+ public:
+ ~DBusServiceTest() override = default;
+ void SetUp() override {
+ dbus::Bus::Options options;
+ mock_bus_ = new NiceMock<dbus::MockBus>(options);
+ dbus::ObjectPath path(kAttestationServicePath);
+ mock_exported_object_ = new NiceMock<dbus::MockExportedObject>(
+ mock_bus_.get(), path);
+ ON_CALL(*mock_bus_, GetExportedObject(path))
+ .WillByDefault(Return(mock_exported_object_.get()));
+ dbus_service_.reset(new DBusService(mock_bus_, &mock_service_));
+ dbus_service_->Register(chromeos::dbus_utils::AsyncEventSequencer::
+ GetDefaultCompletionAction());
+ }
+
+ std::unique_ptr<dbus::Response> CallMethod(dbus::MethodCall* method_call) {
+ return chromeos::dbus_utils::testing::CallMethod(
+ dbus_service_->dbus_object_, method_call);
+ }
+
+ std::unique_ptr<dbus::MethodCall> CreateMethodCall(
+ const std::string& method_name) {
+ std::unique_ptr<dbus::MethodCall> call(new dbus::MethodCall(
+ kAttestationInterface, method_name));
+ call->SetSerial(1);
+ return call;
+ }
+
+ protected:
+ scoped_refptr<dbus::MockBus> mock_bus_;
+ scoped_refptr<dbus::MockExportedObject> mock_exported_object_;
+ StrictMock<MockAttestationInterface> mock_service_;
+ std::unique_ptr<DBusService> dbus_service_;
+};
+
+TEST_F(DBusServiceTest, CreateGoogleAttestedKeySuccess) {
+ EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(
+ "label", KEY_TYPE_ECC, KEY_USAGE_SIGN, ENTERPRISE_MACHINE_CERTIFICATE, _))
+ .WillOnce(WithArgs<4>(Invoke([](const base::Callback<
+ AttestationInterface::CreateGoogleAttestedKeyCallback>& callback) {
+ callback.Run(SUCCESS, "certificate", "server_error");
+ })));
+ std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
+ kCreateGoogleAttestedKey);
+ CreateGoogleAttestedKeyRequest request_proto;
+ request_proto.set_key_label("label");
+ request_proto.set_key_type(KEY_TYPE_ECC);
+ request_proto.set_key_usage(KEY_USAGE_SIGN);
+ request_proto.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE);
+ dbus::MessageWriter writer(call.get());
+ writer.AppendProtoAsArrayOfBytes(request_proto);
+ auto response = CallMethod(call.get());
+ dbus::MessageReader reader(response.get());
+ CreateGoogleAttestedKeyReply reply_proto;
+ EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply_proto));
+ EXPECT_EQ(SUCCESS, reply_proto.status());
+ EXPECT_EQ("certificate", reply_proto.certificate_chain());
+ EXPECT_EQ("", reply_proto.server_error());
+}
+
+TEST_F(DBusServiceTest, CreateGoogleAttestedKeyServerError) {
+ EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _, _, _, _))
+ .WillOnce(WithArgs<4>(Invoke([](const base::Callback<
+ AttestationInterface::CreateGoogleAttestedKeyCallback>& callback) {
+ callback.Run(REQUEST_DENIED_BY_CA, "certificate", "server_error");
+ })));
+ std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(
+ kCreateGoogleAttestedKey);
+ CreateGoogleAttestedKeyRequest request_proto;
+ dbus::MessageWriter writer(call.get());
+ writer.AppendProtoAsArrayOfBytes(request_proto);
+ auto response = CallMethod(call.get());
+ dbus::MessageReader reader(response.get());
+ CreateGoogleAttestedKeyReply reply_proto;
+ EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply_proto));
+ EXPECT_EQ(REQUEST_DENIED_BY_CA, reply_proto.status());
+ EXPECT_EQ("", reply_proto.certificate_chain());
+ EXPECT_EQ("server_error", reply_proto.server_error());
+}
+
+} // namespace attestation