You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
381 lines
15 KiB
381 lines
15 KiB
// |
|
// Copyright (C) 2014 The Android Open Source Project |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
// |
|
|
|
#include <string> |
|
|
|
#include <brillo/bind_lambda.h> |
|
#include <brillo/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( |
|
brillo::dbus_utils::AsyncEventSequencer::GetDefaultCompletionAction()); |
|
} |
|
|
|
std::unique_ptr<dbus::Response> CallMethod(dbus::MethodCall* method_call) { |
|
return brillo::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, CreateGoogleAttestedKey) { |
|
CreateGoogleAttestedKeyRequest request; |
|
request.set_key_label("label"); |
|
request.set_key_type(KEY_TYPE_ECC); |
|
request.set_key_usage(KEY_USAGE_SIGN); |
|
request.set_certificate_profile(ENTERPRISE_MACHINE_CERTIFICATE); |
|
request.set_username("username"); |
|
request.set_origin("origin"); |
|
EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _)) |
|
.WillOnce( |
|
Invoke([](const CreateGoogleAttestedKeyRequest& request, |
|
const AttestationInterface::CreateGoogleAttestedKeyCallback& |
|
callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ(KEY_TYPE_ECC, request.key_type()); |
|
EXPECT_EQ(KEY_USAGE_SIGN, request.key_usage()); |
|
EXPECT_EQ(ENTERPRISE_MACHINE_CERTIFICATE, |
|
request.certificate_profile()); |
|
EXPECT_EQ("username", request.username()); |
|
EXPECT_EQ("origin", request.origin()); |
|
CreateGoogleAttestedKeyReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_certificate_chain("certificate"); |
|
reply.set_server_error("server_error"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kCreateGoogleAttestedKey); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
CreateGoogleAttestedKeyReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("certificate", reply.certificate_chain()); |
|
EXPECT_EQ("server_error", reply.server_error()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, CopyableCallback) { |
|
EXPECT_CALL(mock_service_, CreateGoogleAttestedKey(_, _)) |
|
.WillOnce(WithArgs<1>( |
|
Invoke([](const AttestationInterface::CreateGoogleAttestedKeyCallback& |
|
callback) { |
|
// Copy the callback, then call the original. |
|
CreateGoogleAttestedKeyReply reply; |
|
base::Closure copy = base::Bind(callback, reply); |
|
callback.Run(reply); |
|
}))); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kCreateGoogleAttestedKey); |
|
CreateGoogleAttestedKeyRequest request; |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
CreateGoogleAttestedKeyReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
} |
|
|
|
TEST_F(DBusServiceTest, GetKeyInfo) { |
|
GetKeyInfoRequest request; |
|
request.set_key_label("label"); |
|
request.set_username("username"); |
|
EXPECT_CALL(mock_service_, GetKeyInfo(_, _)) |
|
.WillOnce( |
|
Invoke([](const GetKeyInfoRequest& request, |
|
const AttestationInterface::GetKeyInfoCallback& callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ("username", request.username()); |
|
GetKeyInfoReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_key_type(KEY_TYPE_ECC); |
|
reply.set_key_usage(KEY_USAGE_SIGN); |
|
reply.set_public_key("public_key"); |
|
reply.set_certify_info("certify"); |
|
reply.set_certify_info_signature("signature"); |
|
reply.set_certificate("certificate"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kGetKeyInfo); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
GetKeyInfoReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ(KEY_TYPE_ECC, reply.key_type()); |
|
EXPECT_EQ(KEY_USAGE_SIGN, reply.key_usage()); |
|
EXPECT_EQ("public_key", reply.public_key()); |
|
EXPECT_EQ("certify", reply.certify_info()); |
|
EXPECT_EQ("signature", reply.certify_info_signature()); |
|
EXPECT_EQ("certificate", reply.certificate()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, GetEndorsementInfo) { |
|
GetEndorsementInfoRequest request; |
|
request.set_key_type(KEY_TYPE_ECC); |
|
EXPECT_CALL(mock_service_, GetEndorsementInfo(_, _)) |
|
.WillOnce(Invoke( |
|
[](const GetEndorsementInfoRequest& request, |
|
const AttestationInterface::GetEndorsementInfoCallback& callback) { |
|
EXPECT_EQ(KEY_TYPE_ECC, request.key_type()); |
|
GetEndorsementInfoReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_ek_public_key("public_key"); |
|
reply.set_ek_certificate("certificate"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kGetEndorsementInfo); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
GetEndorsementInfoReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("public_key", reply.ek_public_key()); |
|
EXPECT_EQ("certificate", reply.ek_certificate()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, GetAttestationKeyInfo) { |
|
GetAttestationKeyInfoRequest request; |
|
request.set_key_type(KEY_TYPE_ECC); |
|
EXPECT_CALL(mock_service_, GetAttestationKeyInfo(_, _)) |
|
.WillOnce(Invoke([]( |
|
const GetAttestationKeyInfoRequest& request, |
|
const AttestationInterface::GetAttestationKeyInfoCallback& callback) { |
|
EXPECT_EQ(KEY_TYPE_ECC, request.key_type()); |
|
GetAttestationKeyInfoReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_public_key("public_key"); |
|
reply.set_public_key_tpm_format("public_key_tpm_format"); |
|
reply.set_certificate("certificate"); |
|
reply.mutable_pcr0_quote()->set_quote("pcr0"); |
|
reply.mutable_pcr1_quote()->set_quote("pcr1"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kGetAttestationKeyInfo); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
GetAttestationKeyInfoReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("public_key", reply.public_key()); |
|
EXPECT_EQ("public_key_tpm_format", reply.public_key_tpm_format()); |
|
EXPECT_EQ("certificate", reply.certificate()); |
|
EXPECT_EQ("pcr0", reply.pcr0_quote().quote()); |
|
EXPECT_EQ("pcr1", reply.pcr1_quote().quote()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, ActivateAttestationKey) { |
|
ActivateAttestationKeyRequest request; |
|
request.set_key_type(KEY_TYPE_ECC); |
|
request.mutable_encrypted_certificate()->set_asym_ca_contents("encrypted1"); |
|
request.mutable_encrypted_certificate()->set_sym_ca_attestation("encrypted2"); |
|
request.set_save_certificate(true); |
|
EXPECT_CALL(mock_service_, ActivateAttestationKey(_, _)) |
|
.WillOnce( |
|
Invoke([](const ActivateAttestationKeyRequest& request, |
|
const AttestationInterface::ActivateAttestationKeyCallback& |
|
callback) { |
|
EXPECT_EQ(KEY_TYPE_ECC, request.key_type()); |
|
EXPECT_EQ("encrypted1", |
|
request.encrypted_certificate().asym_ca_contents()); |
|
EXPECT_EQ("encrypted2", |
|
request.encrypted_certificate().sym_ca_attestation()); |
|
EXPECT_TRUE(request.save_certificate()); |
|
ActivateAttestationKeyReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_certificate("certificate"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kActivateAttestationKey); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
ActivateAttestationKeyReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("certificate", reply.certificate()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, CreateCertifiableKey) { |
|
CreateCertifiableKeyRequest request; |
|
request.set_key_label("label"); |
|
request.set_key_type(KEY_TYPE_ECC); |
|
request.set_key_usage(KEY_USAGE_SIGN); |
|
request.set_username("user"); |
|
EXPECT_CALL(mock_service_, CreateCertifiableKey(_, _)) |
|
.WillOnce(Invoke([]( |
|
const CreateCertifiableKeyRequest& request, |
|
const AttestationInterface::CreateCertifiableKeyCallback& callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ(KEY_TYPE_ECC, request.key_type()); |
|
EXPECT_EQ(KEY_USAGE_SIGN, request.key_usage()); |
|
EXPECT_EQ("user", request.username()); |
|
CreateCertifiableKeyReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_public_key("public_key"); |
|
reply.set_certify_info("certify_info"); |
|
reply.set_certify_info_signature("signature"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kCreateCertifiableKey); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
CreateCertifiableKeyReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("public_key", reply.public_key()); |
|
EXPECT_EQ("certify_info", reply.certify_info()); |
|
EXPECT_EQ("signature", reply.certify_info_signature()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, Decrypt) { |
|
DecryptRequest request; |
|
request.set_key_label("label"); |
|
request.set_username("user"); |
|
request.set_encrypted_data("data"); |
|
EXPECT_CALL(mock_service_, Decrypt(_, _)) |
|
.WillOnce( |
|
Invoke([](const DecryptRequest& request, |
|
const AttestationInterface::DecryptCallback& callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ("user", request.username()); |
|
EXPECT_EQ("data", request.encrypted_data()); |
|
DecryptReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_decrypted_data("data"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kDecrypt); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
DecryptReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("data", reply.decrypted_data()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, Sign) { |
|
SignRequest request; |
|
request.set_key_label("label"); |
|
request.set_username("user"); |
|
request.set_data_to_sign("data"); |
|
EXPECT_CALL(mock_service_, Sign(_, _)) |
|
.WillOnce(Invoke([](const SignRequest& request, |
|
const AttestationInterface::SignCallback& callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ("user", request.username()); |
|
EXPECT_EQ("data", request.data_to_sign()); |
|
SignReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
reply.set_signature("signature"); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = CreateMethodCall(kSign); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
SignReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
EXPECT_EQ("signature", reply.signature()); |
|
} |
|
|
|
TEST_F(DBusServiceTest, RegisterKeyWithChapsToken) { |
|
RegisterKeyWithChapsTokenRequest request; |
|
request.set_key_label("label"); |
|
request.set_username("user"); |
|
EXPECT_CALL(mock_service_, RegisterKeyWithChapsToken(_, _)) |
|
.WillOnce(Invoke( |
|
[](const RegisterKeyWithChapsTokenRequest& request, |
|
const AttestationInterface::RegisterKeyWithChapsTokenCallback& |
|
callback) { |
|
EXPECT_EQ("label", request.key_label()); |
|
EXPECT_EQ("user", request.username()); |
|
RegisterKeyWithChapsTokenReply reply; |
|
reply.set_status(STATUS_SUCCESS); |
|
callback.Run(reply); |
|
})); |
|
std::unique_ptr<dbus::MethodCall> call = |
|
CreateMethodCall(kRegisterKeyWithChapsToken); |
|
dbus::MessageWriter writer(call.get()); |
|
writer.AppendProtoAsArrayOfBytes(request); |
|
auto response = CallMethod(call.get()); |
|
dbus::MessageReader reader(response.get()); |
|
RegisterKeyWithChapsTokenReply reply; |
|
EXPECT_TRUE(reader.PopArrayOfBytesAsProto(&reply)); |
|
EXPECT_EQ(STATUS_SUCCESS, reply.status()); |
|
} |
|
|
|
} // namespace attestation
|
|
|