blob: 679508cce40a4ecca9fc50155da9d15e7afc8780 [file] [log] [blame]
// Copyright 2019 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/proxy/legacy_cryptohome_interface_adaptor.h"
#include <attestation-client-test/attestation/dbus-proxy-mocks.h>
#include <base/files/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <brillo/dbus/mock_dbus_method_response.h>
#include <chromeos/constants/cryptohome.h>
#include <tpm_manager-client-test/tpm_manager/dbus-proxy-mocks.h>
#include "cryptohome/mock_platform.h"
#include "user_data_auth/dbus-proxy-mocks.h"
namespace cryptohome {
namespace {
using ::brillo::dbus_utils::MockDBusMethodResponse;
using ::testing::_;
using ::testing::DoAll;
using ::testing::Invoke;
using ::testing::InvokeArgument;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SaveArg;
// A mock adaptor that is used for testing. This is added so that we can capture
// the Send*() functions used for sending signals.
class LegacyCryptohomeInterfaceAdaptorForTesting
: public LegacyCryptohomeInterfaceAdaptor {
public:
LegacyCryptohomeInterfaceAdaptorForTesting(
org::chromium::AttestationProxyInterface* attestation_proxy,
org::chromium::TpmManagerProxyInterface* tpm_ownership_proxy,
org::chromium::TpmNvramProxyInterface* tpm_nvram_proxy,
org::chromium::UserDataAuthInterfaceProxyInterface* userdataauth_proxy,
org::chromium::ArcQuotaProxyInterface* arc_quota_proxy,
org::chromium::CryptohomePkcs11InterfaceProxyInterface* pkcs11_proxy,
org::chromium::InstallAttributesInterfaceProxyInterface*
install_attributes_proxy,
org::chromium::CryptohomeMiscInterfaceProxyInterface* misc_proxy,
cryptohome::Platform* platform)
: LegacyCryptohomeInterfaceAdaptor(attestation_proxy,
tpm_ownership_proxy,
tpm_nvram_proxy,
userdataauth_proxy,
arc_quota_proxy,
pkcs11_proxy,
install_attributes_proxy,
misc_proxy,
platform) {}
MOCK_METHOD(void,
VirtualSendAsyncCallStatusSignal,
(int32_t, bool, int32_t),
(override));
MOCK_METHOD(void,
VirtualSendAsyncCallStatusWithDataSignal,
(int32_t, bool, const std::vector<uint8_t>&),
(override));
MOCK_METHOD(void,
VirtualSendDircryptoMigrationProgressSignal,
(int32_t, uint64_t, uint64_t),
(override));
MOCK_METHOD(void, VirtualSendLowDiskSpaceSignal, (uint64_t), (override));
};
// Some common constants used for testing.
constexpr char kUsername1[] = "foo@gmail.com";
constexpr char kKeyLabel[] = "somelabel";
constexpr char kSecret[] = "blah";
constexpr char kSanitizedUsername1[] = "baadf00ddeadbeeffeedcafe";
constexpr char kPCARequest[] = "PCA\0Request\xFFMay\x80Have\0None.ASCII";
constexpr char kRequestOrigin[] = "SomeOrigin";
class LegacyCryptohomeInterfaceAdaptorTest : public ::testing::Test {
public:
LegacyCryptohomeInterfaceAdaptorTest() = default;
LegacyCryptohomeInterfaceAdaptorTest(
const LegacyCryptohomeInterfaceAdaptorTest&) = delete;
LegacyCryptohomeInterfaceAdaptorTest& operator=(
const LegacyCryptohomeInterfaceAdaptorTest&) = delete;
~LegacyCryptohomeInterfaceAdaptorTest() override = default;
void SetUp() override {
adaptor_.reset(new LegacyCryptohomeInterfaceAdaptorForTesting(
&attestation_, &ownership_, &nvram_, &userdataauth_, &arc_quota_,
&pkcs11_, &install_attributes_, &misc_, &platform_));
account_.set_account_id(kUsername1);
auth_.mutable_key()->set_secret(kSecret);
}
protected:
// Mocks that will be passed into |adaptor_| for its internal use.
NiceMock<org::chromium::AttestationProxyMock> attestation_;
NiceMock<org::chromium::TpmManagerProxyMock> ownership_;
NiceMock<org::chromium::TpmNvramProxyMock> nvram_;
NiceMock<org::chromium::UserDataAuthInterfaceProxyMock> userdataauth_;
NiceMock<org::chromium::ArcQuotaProxyMock> arc_quota_;
NiceMock<org::chromium::CryptohomePkcs11InterfaceProxyMock> pkcs11_;
NiceMock<org::chromium::InstallAttributesInterfaceProxyMock>
install_attributes_;
NiceMock<org::chromium::CryptohomeMiscInterfaceProxyMock> misc_;
NiceMock<MockPlatform> platform_;
// The adaptor that we'll be testing.
std::unique_ptr<LegacyCryptohomeInterfaceAdaptorForTesting> adaptor_;
// Default account identifier and authentication request set up with valid
// value to avoid repeating the same pattern in many test.
cryptohome::AccountIdentifier account_;
cryptohome::AuthorizationRequest auth_;
};
// -------------------------- MountEx Related Tests --------------------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, MountExSuccess) {
cryptohome::MountRequest req;
user_data_auth::MountRequest proxied_request;
req.set_require_ephemeral(false);
req.set_force_dircrypto_if_available(true);
req.set_to_migrate_from_ecryptfs(false);
req.set_public_mount(false);
req.set_hidden_mount(false);
EXPECT_CALL(userdataauth_, MountAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const user_data_auth::MountRequest& in_request,
const base::Callback<void(
const user_data_auth::MountReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
user_data_auth::MountReply proxied_reply;
proxied_reply.set_recreated(true);
proxied_reply.set_sanitized_username(kSanitizedUsername1);
success_callback.Run(proxied_reply);
})));
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->save_return_args(&final_reply);
adaptor_->MountEx(std::move(response), account_, auth_, req);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(final_reply.has_value());
// Verify its content
EXPECT_EQ(cryptohome::CRYPTOHOME_ERROR_NOT_SET, final_reply->error());
EXPECT_TRUE(final_reply->HasExtension(cryptohome::MountReply::reply));
auto ext = final_reply->GetExtension(cryptohome::MountReply::reply);
EXPECT_TRUE(ext.recreated());
EXPECT_EQ(ext.sanitized_username(), kSanitizedUsername1);
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.account().account_id(), kUsername1);
EXPECT_EQ(proxied_request.authorization().key().secret(), kSecret);
EXPECT_FALSE(proxied_request.require_ephemeral());
EXPECT_TRUE(proxied_request.force_dircrypto_if_available());
EXPECT_FALSE(proxied_request.to_migrate_from_ecryptfs());
EXPECT_FALSE(proxied_request.public_mount());
EXPECT_FALSE(proxied_request.hidden_mount());
EXPECT_FALSE(proxied_request.guest_mount());
EXPECT_FALSE(proxied_request.has_create());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, MountExSuccessWithCreate) {
cryptohome::MountRequest req;
user_data_auth::MountRequest proxied_request;
req.set_require_ephemeral(false);
req.set_force_dircrypto_if_available(true);
req.set_to_migrate_from_ecryptfs(false);
req.set_public_mount(false);
req.set_hidden_mount(false);
req.mutable_create()->set_force_ecryptfs(true);
req.mutable_create()->set_copy_authorization_key(true);
auto key = req.mutable_create()->add_keys();
key->set_secret(kSecret);
EXPECT_CALL(userdataauth_, MountAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const user_data_auth::MountRequest& in_request,
const base::Callback<void(
const user_data_auth::MountReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
user_data_auth::MountReply proxied_reply;
proxied_reply.set_recreated(true);
proxied_reply.set_sanitized_username(kSanitizedUsername1);
success_callback.Run(proxied_reply);
})));
int respond_count = 0;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->set_return_callback(base::Bind(
[](int* respond_count_ptr, const cryptohome::BaseReply& reply) {
EXPECT_EQ(cryptohome::CRYPTOHOME_ERROR_NOT_SET, reply.error());
EXPECT_TRUE(reply.HasExtension(cryptohome::MountReply::reply));
auto ext = reply.GetExtension(cryptohome::MountReply::reply);
EXPECT_TRUE(ext.recreated());
EXPECT_EQ(ext.sanitized_username(), kSanitizedUsername1);
(*respond_count_ptr)++;
},
&respond_count));
adaptor_->MountEx(std::move(response), account_, auth_, req);
// Verify that Return() is indeed called.
EXPECT_EQ(respond_count, 1);
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.account().account_id(), kUsername1);
EXPECT_EQ(proxied_request.authorization().key().secret(), kSecret);
EXPECT_FALSE(proxied_request.require_ephemeral());
EXPECT_TRUE(proxied_request.force_dircrypto_if_available());
EXPECT_FALSE(proxied_request.to_migrate_from_ecryptfs());
EXPECT_FALSE(proxied_request.public_mount());
EXPECT_FALSE(proxied_request.hidden_mount());
EXPECT_FALSE(proxied_request.guest_mount());
EXPECT_TRUE(proxied_request.has_create());
EXPECT_TRUE(proxied_request.create().force_ecryptfs());
EXPECT_TRUE(proxied_request.create().copy_authorization_key());
EXPECT_EQ(proxied_request.create().keys_size(), 1);
EXPECT_EQ(proxied_request.create().keys(0).secret(), kSecret);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, MountExFail) {
cryptohome::MountRequest req;
user_data_auth::MountRequest proxied_request;
req.set_require_ephemeral(true);
req.set_force_dircrypto_if_available(false);
req.set_to_migrate_from_ecryptfs(true);
req.set_public_mount(true);
req.set_hidden_mount(true);
EXPECT_CALL(userdataauth_, MountAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const user_data_auth::MountRequest& in_request,
const base::Callback<void(
const user_data_auth::MountReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
user_data_auth::MountReply proxied_reply;
proxied_reply.set_error(
user_data_auth::CRYPTOHOME_ERROR_MOUNT_FATAL);
proxied_reply.set_recreated(false);
success_callback.Run(proxied_reply);
})));
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->save_return_args(&final_reply);
adaptor_->MountEx(std::move(response), account_, auth_, req);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(final_reply.has_value());
// Verify its content
EXPECT_EQ(cryptohome::CRYPTOHOME_ERROR_MOUNT_FATAL, final_reply->error());
EXPECT_TRUE(final_reply->HasExtension(cryptohome::MountReply::reply));
auto ext = final_reply->GetExtension(cryptohome::MountReply::reply);
EXPECT_FALSE(ext.recreated());
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.account().account_id(), kUsername1);
EXPECT_EQ(proxied_request.authorization().key().secret(), kSecret);
EXPECT_TRUE(proxied_request.require_ephemeral());
EXPECT_FALSE(proxied_request.force_dircrypto_if_available());
EXPECT_TRUE(proxied_request.to_migrate_from_ecryptfs());
EXPECT_TRUE(proxied_request.public_mount());
EXPECT_TRUE(proxied_request.hidden_mount());
EXPECT_FALSE(proxied_request.guest_mount());
}
// ------------- TpmIsAttestationPrepared Related Tests -------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmIsAttestationPreparedSuccessResultTrue) {
attestation::GetEnrollmentPreparationsRequest proxied_request;
EXPECT_CALL(attestation_, GetEnrollmentPreparationsAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::GetEnrollmentPreparationsRequest&
in_request,
const base::Callback<void(
const attestation::GetEnrollmentPreparationsReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::GetEnrollmentPreparationsReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
(*proxied_reply.mutable_enrollment_preparations())[0] = true;
(*proxied_reply.mutable_enrollment_preparations())[1] = false;
success_callback.Run(proxied_reply);
})));
base::Optional<bool> result;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result);
adaptor_->TpmIsAttestationPrepared(std::move(response));
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_TRUE(result.value());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmIsAttestationPreparedSuccessResultFalse) {
attestation::GetEnrollmentPreparationsRequest proxied_request;
EXPECT_CALL(attestation_, GetEnrollmentPreparationsAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::GetEnrollmentPreparationsRequest&
in_request,
const base::Callback<void(
const attestation::GetEnrollmentPreparationsReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::GetEnrollmentPreparationsReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
(*proxied_reply.mutable_enrollment_preparations())[0] = false;
(*proxied_reply.mutable_enrollment_preparations())[1] = false;
success_callback.Run(proxied_reply);
})));
base::Optional<bool> result;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result);
adaptor_->TpmIsAttestationPrepared(std::move(response));
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_FALSE(result.value());
}
// --------- TpmAttestationGetEnrollmentPreparationsEx Related Tests ---------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationGetEnrollmentPreparationsExSuccess) {
attestation::GetEnrollmentPreparationsRequest proxied_request;
EXPECT_CALL(attestation_, GetEnrollmentPreparationsAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::GetEnrollmentPreparationsRequest&
in_request,
const base::Callback<void(
const attestation::GetEnrollmentPreparationsReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::GetEnrollmentPreparationsReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
(*proxied_reply.mutable_enrollment_preparations())[0] = true;
(*proxied_reply.mutable_enrollment_preparations())[1] = false;
success_callback.Run(proxied_reply);
})));
base::Optional<cryptohome::BaseReply> result;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->save_return_args(&result);
cryptohome::AttestationGetEnrollmentPreparationsRequest in_request;
in_request.set_pca_type(1);
adaptor_->TpmAttestationGetEnrollmentPreparationsEx(std::move(response),
in_request);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_EQ(result->error(), cryptohome::CRYPTOHOME_ERROR_NOT_SET);
EXPECT_TRUE(
result->HasExtension(AttestationGetEnrollmentPreparationsReply::reply));
auto& ext =
result->GetExtension(AttestationGetEnrollmentPreparationsReply::reply);
EXPECT_EQ(ext.enrollment_preparations().size(), 2);
ASSERT_TRUE(ext.enrollment_preparations().contains(0));
EXPECT_TRUE(ext.enrollment_preparations().at(0));
ASSERT_TRUE(ext.enrollment_preparations().contains(1));
EXPECT_FALSE(ext.enrollment_preparations().at(1));
// Check that the proxied request have the right ACA
EXPECT_EQ(proxied_request.aca_type(), attestation::ACAType::TEST_ACA);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationGetEnrollmentPreparationsExInvalidACA) {
// GetEnrollmentPreparationsAsync() shouldn't get called because the ACA
// specified is invalid.
EXPECT_CALL(attestation_, GetEnrollmentPreparationsAsync(_, _, _, _))
.Times(0);
base::Optional<cryptohome::BaseReply> result;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->save_return_args(&result);
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_NOT_SUPPORTED,
"Requested ACA type 99999 is not supported in "
"TpmAttestationGetEnrollmentPreparationsEx()"))
.WillOnce(Return());
cryptohome::AttestationGetEnrollmentPreparationsRequest in_request;
in_request.set_pca_type(99999);
adaptor_->TpmAttestationGetEnrollmentPreparationsEx(std::move(response),
in_request);
// Verify that Return() is not called
ASSERT_FALSE(result.has_value());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationGetEnrollmentPreparationsExFailure) {
attestation::GetEnrollmentPreparationsRequest proxied_request;
EXPECT_CALL(attestation_, GetEnrollmentPreparationsAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::GetEnrollmentPreparationsRequest&
in_request,
const base::Callback<void(
const attestation::GetEnrollmentPreparationsReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::GetEnrollmentPreparationsReply proxied_reply;
proxied_reply.set_status(
attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
success_callback.Run(proxied_reply);
})));
base::Optional<cryptohome::BaseReply> result;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
response->save_return_args(&result);
cryptohome::AttestationGetEnrollmentPreparationsRequest in_request;
in_request.set_pca_type(1);
adaptor_->TpmAttestationGetEnrollmentPreparationsEx(std::move(response),
in_request);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_EQ(result->error(),
cryptohome::CRYPTOHOME_ERROR_INTERNAL_ATTESTATION_ERROR);
// Check that the proxied request have the right ACA
EXPECT_EQ(proxied_request.aca_type(), attestation::ACAType::TEST_ACA);
}
// ------------- TpmAttestationCreateEnrollRequest Related Tests -------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateEnrollRequestSuccess) {
attestation::CreateEnrollRequestRequest proxied_request;
EXPECT_CALL(attestation_, CreateEnrollRequestAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::CreateEnrollRequestRequest& in_request,
const base::Callback<void(
const attestation::CreateEnrollRequestReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::CreateEnrollRequestReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
proxied_reply.set_pca_request(
std::string(kPCARequest, sizeof(kPCARequest)));
success_callback.Run(proxied_reply);
})));
base::Optional<std::vector<uint8_t>> result_pca_request;
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
response->save_return_args(&result_pca_request);
adaptor_->TpmAttestationCreateEnrollRequest(
std::move(response), static_cast<int>(attestation::TEST_ACA));
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result_pca_request.has_value());
// Verify response content.
EXPECT_EQ(
result_pca_request.value(),
std::vector<uint8_t>(kPCARequest, kPCARequest + sizeof(kPCARequest)));
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::TEST_ACA);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateEnrollRequestInvalidACA) {
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_NOT_SUPPORTED,
"Requested ACA type 99999 is not supported"))
.WillOnce(Return());
// 99999 is an invalid ACA
adaptor_->TpmAttestationCreateEnrollRequest(std::move(response), 99999);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateEnrollRequestFailed) {
attestation::CreateEnrollRequestRequest proxied_request;
EXPECT_CALL(attestation_, CreateEnrollRequestAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::CreateEnrollRequestRequest& in_request,
const base::Callback<void(
const attestation::CreateEnrollRequestReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::CreateEnrollRequestReply reply;
reply.set_status(attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
success_callback.Run(reply);
})));
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_FAILED,
"Attestation daemon returned status " +
std::to_string(static_cast<int>(
attestation::STATUS_UNEXPECTED_DEVICE_ERROR))))
.WillOnce(Return());
adaptor_->TpmAttestationCreateEnrollRequest(
std::move(response), static_cast<int>(attestation::DEFAULT_ACA));
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::DEFAULT_ACA);
}
// ------------------- TpmAttestationEnroll Related Tests -------------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, TpmAttestationEnrollSuccess) {
attestation::FinishEnrollRequest proxied_request;
EXPECT_CALL(attestation_, FinishEnrollAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke(
[](const attestation::FinishEnrollRequest& in_request,
const base::Callback<void(
const attestation::FinishEnrollReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) {
attestation::FinishEnrollReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
success_callback.Run(proxied_reply);
})));
base::Optional<bool> result_success;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result_success);
std::vector<uint8_t> pca_request(kPCARequest,
kPCARequest + sizeof(kPCARequest));
adaptor_->TpmAttestationEnroll(std::move(response),
static_cast<int>(attestation::TEST_ACA),
pca_request);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result_success.has_value());
// Verify the response.
EXPECT_TRUE(result_success.value());
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::TEST_ACA);
EXPECT_EQ(proxied_request.pca_response(),
std::string(kPCARequest, kPCARequest + sizeof(kPCARequest)));
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, TpmAttestationEnrollInvalidACA) {
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_NOT_SUPPORTED,
"Requested ACA type 99999 is not supported"))
.WillOnce(Return());
std::vector<uint8_t> pca_request(kPCARequest,
kPCARequest + sizeof(kPCARequest));
// 99999 is an invalid ACA
adaptor_->TpmAttestationEnroll(std::move(response), 99999, pca_request);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, TpmAttestationEnrollFailed) {
attestation::FinishEnrollRequest proxied_request;
EXPECT_CALL(attestation_, FinishEnrollAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke(
[](const attestation::FinishEnrollRequest& in_request,
const base::Callback<void(
const attestation::FinishEnrollReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) {
attestation::FinishEnrollReply reply;
reply.set_status(attestation::STATUS_NOT_READY);
success_callback.Run(reply);
})));
base::Optional<bool> result_success;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result_success);
std::vector<uint8_t> pca_request(kPCARequest,
kPCARequest + sizeof(kPCARequest));
adaptor_->TpmAttestationEnroll(std::move(response),
static_cast<int>(attestation::DEFAULT_ACA),
pca_request);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result_success.has_value());
// Verify the response.
EXPECT_FALSE(result_success.value());
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::DEFAULT_ACA);
EXPECT_EQ(proxied_request.pca_response(),
std::string(kPCARequest, kPCARequest + sizeof(kPCARequest)));
}
// ------------- TpmAttestationCreateCertRequest Related Tests -------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateCertRequestSuccess) {
attestation::CreateCertificateRequestRequest proxied_request;
EXPECT_CALL(attestation_, CreateCertificateRequestAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke(
[](const attestation::CreateCertificateRequestRequest& in_request,
const base::Callback<void(
const attestation::CreateCertificateRequestReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::CreateCertificateRequestReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
proxied_reply.set_pca_request(
std::string(kPCARequest, sizeof(kPCARequest)));
success_callback.Run(proxied_reply);
})));
base::Optional<std::vector<uint8_t>> result_pca_request;
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
response->save_return_args(&result_pca_request);
adaptor_->TpmAttestationCreateCertRequest(
std::move(response), static_cast<int>(attestation::TEST_ACA),
static_cast<int>(attestation::CONTENT_PROTECTION_CERTIFICATE), kUsername1,
kRequestOrigin);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result_pca_request.has_value());
// Verify response content.
EXPECT_EQ(
result_pca_request.value(),
std::vector<uint8_t>(kPCARequest, kPCARequest + sizeof(kPCARequest)));
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::TEST_ACA);
EXPECT_EQ(proxied_request.username(), kUsername1);
EXPECT_EQ(proxied_request.request_origin(), kRequestOrigin);
EXPECT_EQ(proxied_request.certificate_profile(),
attestation::CONTENT_PROTECTION_CERTIFICATE);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateCertRequestInvalidACA) {
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_NOT_SUPPORTED,
"Requested ACA type 99999 is not supported"))
.WillOnce(Return());
// 99999 is an invalid ACA
adaptor_->TpmAttestationCreateCertRequest(std::move(response), 99999, 2,
kUsername1, kRequestOrigin);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
TpmAttestationCreateCertRequestFailed) {
attestation::CreateCertificateRequestRequest proxied_request;
EXPECT_CALL(attestation_, CreateCertificateRequestAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke(
[](const attestation::CreateCertificateRequestRequest& in_request,
const base::Callback<void(
const attestation::CreateCertificateRequestReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::CreateCertificateRequestReply reply;
reply.set_status(attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
success_callback.Run(reply);
})));
std::unique_ptr<MockDBusMethodResponse<std::vector<uint8_t>>> response(
new MockDBusMethodResponse<std::vector<uint8_t>>(nullptr));
EXPECT_CALL(
*response,
ReplyWithError(_, brillo::errors::dbus::kDomain, DBUS_ERROR_FAILED,
"Attestation daemon returned status " +
std::to_string(static_cast<int>(
attestation::STATUS_UNEXPECTED_DEVICE_ERROR))))
.WillOnce(Return());
// 12345 is an invalid certificate profile and should result in
// ENTERPRISE_USER_CERTIFICATE.
adaptor_->TpmAttestationCreateCertRequest(
std::move(response), static_cast<int>(attestation::DEFAULT_ACA), 12345,
kUsername1, kRequestOrigin);
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_EQ(proxied_request.aca_type(), attestation::DEFAULT_ACA);
EXPECT_EQ(proxied_request.username(), kUsername1);
EXPECT_EQ(proxied_request.request_origin(), kRequestOrigin);
EXPECT_EQ(proxied_request.certificate_profile(),
attestation::ENTERPRISE_USER_CERTIFICATE);
}
// ------------- TpmAttestationDeleteKey(s) Related Tests -------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, TpmAttestationDeleteKeysSuccess) {
attestation::DeleteKeysRequest proxied_request;
EXPECT_CALL(attestation_, DeleteKeysAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::DeleteKeysRequest& in_request,
const base::Callback<void(
const attestation::DeleteKeysReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::DeleteKeysReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
success_callback.Run(proxied_reply);
})));
base::Optional<bool> result;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result);
adaptor_->TpmAttestationDeleteKeys(std::move(response),
/*is_user_specific=*/true, kUsername1,
kKeyLabel);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_TRUE(result.value());
// Verify that the parameters passed to DBus Proxy (New interface) are
// correct.
EXPECT_EQ(proxied_request.username(), kUsername1);
EXPECT_EQ(proxied_request.key_label_match(), kKeyLabel);
EXPECT_EQ(proxied_request.match_behavior(),
attestation::DeleteKeysRequest::MATCH_BEHAVIOR_PREFIX);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, TpmAttestationDeleteKeySuccess) {
attestation::DeleteKeysRequest proxied_request;
EXPECT_CALL(attestation_, DeleteKeysAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const attestation::DeleteKeysRequest& in_request,
const base::Callback<void(
const attestation::DeleteKeysReply&)>& success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
attestation::DeleteKeysReply proxied_reply;
proxied_reply.set_status(attestation::STATUS_SUCCESS);
success_callback.Run(proxied_reply);
})));
base::Optional<bool> result;
std::unique_ptr<MockDBusMethodResponse<bool>> response(
new MockDBusMethodResponse<bool>(nullptr));
response->save_return_args(&result);
adaptor_->TpmAttestationDeleteKey(std::move(response),
/*is_user_specific=*/true, kUsername1,
kKeyLabel);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(result.has_value());
// Verify response content.
EXPECT_TRUE(result.value());
// Verify that the parameters passed to DBus Proxy (New interface) are
// correct.
EXPECT_EQ(proxied_request.username(), kUsername1);
EXPECT_EQ(proxied_request.key_label_match(), kKeyLabel);
EXPECT_EQ(proxied_request.match_behavior(),
attestation::DeleteKeysRequest::MATCH_BEHAVIOR_EXACT);
}
// -------------------- MigrateToDircrypto Related Tests --------------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, MigrateToDircryptoSuccess) {
// Note that failure case is NOT tested because this method does not return
// anything so the failure case is no different from the success case.
user_data_auth::StartMigrateToDircryptoRequest proxied_request;
EXPECT_CALL(userdataauth_, StartMigrateToDircryptoAsync(_, _, _, _))
.WillOnce(DoAll(
SaveArg<0>(&proxied_request),
Invoke([](const user_data_auth::StartMigrateToDircryptoRequest&
in_request,
const base::Callback<void(
const user_data_auth::StartMigrateToDircryptoReply&)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms = dbus::ObjectProxy::TIMEOUT_USE_DEFAULT) {
user_data_auth::StartMigrateToDircryptoReply proxied_reply;
proxied_reply.set_error(user_data_auth::CRYPTOHOME_ERROR_NOT_SET);
success_callback.Run(proxied_reply);
})));
bool called = false;
std::unique_ptr<MockDBusMethodResponse<>> response(
new MockDBusMethodResponse<>(nullptr));
response->set_return_callback(base::Bind(
[](bool* called_ptr) {
// Return can only be called once
ASSERT_FALSE(*called_ptr);
*called_ptr = true;
},
&called));
MigrateToDircryptoRequest request;
request.set_minimal_migration(true);
adaptor_->MigrateToDircrypto(std::move(response), account_, request);
// Verify that Return() is indeed called at least once.
ASSERT_TRUE(called);
// Verify that the parameters passed to DBus Proxy (New interface) is correct.
EXPECT_TRUE(proxied_request.minimal_migration());
EXPECT_EQ(proxied_request.account_id().account_id(), kUsername1);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTest,
DircryptoMigrationProgressSignalValidity) {
constexpr uint64_t kCurrentBytes = 1234567890123ULL;
constexpr uint64_t kTotalBytes = 9876543210987ULL;
static_assert(kTotalBytes > kCurrentBytes,
"Incorrect constant test values in "
"DircryptoMigrationProgressSignalValidity");
user_data_auth::DircryptoMigrationProgress progress;
progress.set_status(user_data_auth::DIRCRYPTO_MIGRATION_SUCCESS);
progress.set_current_bytes(kCurrentBytes);
progress.set_total_bytes(kTotalBytes);
EXPECT_CALL(*adaptor_,
VirtualSendDircryptoMigrationProgressSignal(
DIRCRYPTO_MIGRATION_SUCCESS, kCurrentBytes, kTotalBytes))
.WillOnce(Return());
adaptor_->OnDircryptoMigrationProgressSignalForTestingOnly(progress);
}
// -------------------- LowDiskSpace Signal Related Tests --------------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, LowDiskSpaceSignalValidity) {
constexpr uint64_t kFreeDiskSpace = 998877665544ULL;
user_data_auth::LowDiskSpace payload;
payload.set_disk_free_bytes(kFreeDiskSpace);
EXPECT_CALL(*adaptor_, VirtualSendLowDiskSpaceSignal(kFreeDiskSpace))
.WillOnce(Return());
adaptor_->OnLowDiskSpaceSignalForTestingOnly(payload);
}
// --------------- TPM Ownership Interface Related Tests ---------------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, GetVersionInfo) {
EXPECT_CALL(ownership_, GetVersionInfoAsync(_, _, _, _))
.WillOnce(
Invoke([](const tpm_manager::GetVersionInfoRequest& in_request,
const base::Callback<void(
const tpm_manager::GetVersionInfoReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>&
/* error_callback */,
int /* timeout_ms */) {
tpm_manager::GetVersionInfoReply info;
info.set_family(1);
info.set_spec_level(2);
info.set_manufacturer(3);
info.set_tpm_model(4);
info.set_firmware_version(5);
info.set_vendor_specific("ab");
success_callback.Run(info);
}));
using VersionInfoResponse =
MockDBusMethodResponse<uint32_t, uint64_t, uint32_t, uint32_t, uint64_t,
std::string>;
std::unique_ptr<VersionInfoResponse> response =
std::make_unique<VersionInfoResponse>(nullptr);
base::Optional<uint32_t> family;
base::Optional<uint64_t> spec_level;
base::Optional<uint32_t> manufacture;
base::Optional<uint32_t> tpm_model;
base::Optional<uint64_t> firmware_version;
base::Optional<std::string> vendor_specific;
response->save_return_args(&family, &spec_level, &manufacture, &tpm_model,
&firmware_version, &vendor_specific);
adaptor_->TpmGetVersionStructured(std::move(response));
EXPECT_TRUE(family.has_value());
EXPECT_EQ(*family, 1);
EXPECT_TRUE(spec_level.has_value());
EXPECT_EQ(*spec_level, 2);
EXPECT_TRUE(manufacture.has_value());
EXPECT_EQ(*manufacture, 3);
EXPECT_TRUE(tpm_model.has_value());
EXPECT_EQ(*tpm_model, 4);
EXPECT_TRUE(firmware_version.has_value());
EXPECT_EQ(*firmware_version, 5);
EXPECT_TRUE(vendor_specific.has_value());
EXPECT_EQ(*vendor_specific, base::HexEncode("ab", 2));
}
// --------- CryptohomeMiscInterfaceProxyInterface Related Tests ---------------
TEST_F(LegacyCryptohomeInterfaceAdaptorTest, GetLoginStatus) {
EXPECT_CALL(misc_, GetLoginStatusAsync(_, _, _, _))
.WillOnce(
Invoke([](const user_data_auth::GetLoginStatusRequest& request,
const base::Callback<void(
const user_data_auth::GetLoginStatusReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>&
/* error_callback */,
int /* timeout_ms */) {
user_data_auth::GetLoginStatusReply reply;
reply.set_owner_user_exists(true);
reply.set_is_locked_to_single_user(true);
success_callback.Run(reply);
}));
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_)).Times(0);
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).Times(0);
response->save_return_args(&final_reply);
const cryptohome::GetLoginStatusRequest in_request;
adaptor_->GetLoginStatus(std::move(response), in_request);
ASSERT_TRUE(final_reply.has_value());
ASSERT_TRUE(
final_reply->HasExtension(cryptohome::GetLoginStatusReply::reply));
const auto& ext =
final_reply->GetExtension(cryptohome::GetLoginStatusReply::reply);
// These are the default values when call to retrieve attestation status
// failed.
EXPECT_TRUE(ext.owner_user_exists());
EXPECT_TRUE(ext.is_locked_to_single_user());
EXPECT_FALSE(ext.boot_lockbox_finalized());
}
// This class holds the various extra setups to facilitate testing GetTpmStatus
class LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus
: public LegacyCryptohomeInterfaceAdaptorTest {
public:
LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus() = default;
LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus(
const LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus&) = delete;
LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus& operator=(
const LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus&) = delete;
~LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus() override = default;
protected:
void SetUp() override {
LegacyCryptohomeInterfaceAdaptorTest::SetUp();
status_reply_.set_enabled(true);
status_reply_.set_owned(true);
status_reply_.mutable_local_data()->set_owner_password(kPassword);
da_reply_.set_dictionary_attack_counter(kDACounter);
da_reply_.set_dictionary_attack_threshold(kDAThreshold);
da_reply_.set_dictionary_attack_lockout_in_effect(false);
da_reply_.set_dictionary_attack_lockout_seconds_remaining(kDALockoutRem);
install_attr_reply_.set_state(
user_data_auth::InstallAttributesState::VALID);
attestation_reply_.set_prepared_for_enrollment(true);
attestation_reply_.set_enrolled(true);
attestation_reply_.set_verified_boot(true);
auto* identity1 = attestation_reply_.mutable_identities()->Add();
identity1->set_features(kFeature1);
auto* identity2 = attestation_reply_.mutable_identities()->Add();
identity2->set_features(kFeature2);
attestation::GetStatusReply::IdentityCertificate identity_cert1;
identity_cert1.set_identity(kFeature1);
identity_cert1.set_aca(kACA1);
attestation_reply_.mutable_identity_certificates()->insert(
google::protobuf::Map<
int, attestation::GetStatusReply::IdentityCertificate>::
value_type(kACA1, identity_cert1));
attestation::GetStatusReply::IdentityCertificate identity_cert2;
identity_cert2.set_identity(kFeature2);
identity_cert2.set_aca(kACA2);
attestation_reply_.mutable_identity_certificates()->insert(
google::protobuf::Map<
int, attestation::GetStatusReply::IdentityCertificate>::
value_type(kACA2, identity_cert2));
}
void ExpectGetTpmStatus(
const base::Optional<tpm_manager::GetTpmStatusReply>& reply) {
EXPECT_CALL(ownership_, GetTpmStatusAsync(_, _, _, _))
.WillOnce(Invoke(
[reply](const tpm_manager::GetTpmStatusRequest& in_request,
const base::Callback<void(
const tpm_manager::GetTpmStatusReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
if (reply.has_value()) {
// If |reply| has value, then the method will be successful and
// |reply| will be returned.
success_callback.Run(reply.value());
} else {
// If not, the method will return an error.
error_callback.Run(CreateDefaultError(FROM_HERE).get());
}
}));
}
void ExpectGetDictionaryAttackInfo(
const base::Optional<tpm_manager::GetDictionaryAttackInfoReply>& reply) {
EXPECT_CALL(ownership_, GetDictionaryAttackInfoAsync(_, _, _, _))
.WillOnce(Invoke(
[reply](
const tpm_manager::GetDictionaryAttackInfoRequest& in_request,
const base::Callback<void(
const tpm_manager::
GetDictionaryAttackInfoReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
if (reply.has_value()) {
success_callback.Run(reply.value());
} else {
error_callback.Run(CreateDefaultError(FROM_HERE).get());
}
}));
}
void ExpectInstallAttributesGetStatus(
const base::Optional<user_data_auth::InstallAttributesGetStatusReply>&
reply) {
EXPECT_CALL(install_attributes_,
InstallAttributesGetStatusAsync(_, _, _, _))
.WillOnce(Invoke(
[reply](const user_data_auth::InstallAttributesGetStatusRequest&
in_request,
const base::Callback<void(
const user_data_auth::
InstallAttributesGetStatusReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
if (reply.has_value()) {
success_callback.Run(reply.value());
} else {
error_callback.Run(CreateDefaultError(FROM_HERE).get());
}
}));
}
void ExpectAttestationGetStatus(
const base::Optional<attestation::GetStatusReply>& reply) {
EXPECT_CALL(attestation_, GetStatusAsync(_, _, _, _))
.WillOnce(Invoke(
[reply](const attestation::GetStatusRequest& in_request,
const base::Callback<void(
const attestation::GetStatusReply& /*reply*/)>&
success_callback,
const base::Callback<void(brillo::Error*)>& error_callback,
int timeout_ms) {
if (reply.has_value()) {
success_callback.Run(reply.value());
} else {
error_callback.Run(CreateDefaultError(FROM_HERE).get());
}
}));
}
// The reply we'll get from various proxies.
tpm_manager::GetTpmStatusReply status_reply_;
tpm_manager::GetDictionaryAttackInfoReply da_reply_;
user_data_auth::InstallAttributesGetStatusReply install_attr_reply_;
attestation::GetStatusReply attestation_reply_;
// The request we send to GetTpmStatus()
cryptohome::GetTpmStatusRequest in_request_;
// Constants used during testing
static constexpr char kPassword[] = "YetAnotherPassword";
static constexpr int kDACounter = 42; // The answer
static constexpr int kDAThreshold = 4200; // 100x The answer!!
static constexpr int kDALockoutRem = 0;
static constexpr int kFeature1 = 0xDEADBEEF;
static constexpr int kFeature2 = 0xBAADF00D;
static constexpr int kACA1 = 1;
static constexpr int kACA2 = 2;
private:
static brillo::ErrorPtr CreateDefaultError(const base::Location& from_here) {
brillo::ErrorPtr error;
brillo::Error::AddTo(&error, from_here, brillo::errors::dbus::kDomain,
DBUS_ERROR_FAILED, "Here's a fake error");
return error;
}
};
constexpr char LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kPassword[];
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kDACounter;
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kDAThreshold;
constexpr int
LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kDALockoutRem;
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kFeature1;
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kFeature2;
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kACA1;
constexpr int LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus::kACA2;
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusValidity) {
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
// Setup GetDictionaryAttackInfo in tpm_manager to successfully return
// |da_reply_|
ExpectGetDictionaryAttackInfo(da_reply_);
// Setup GetStatus in cryptohome/install attributes interface to sucessfully
// return |install_attr_reply_|
ExpectInstallAttributesGetStatus(install_attr_reply_);
// Setup GetStatus in attestation to successfully return |attestation_reply_|
ExpectAttestationGetStatus(attestation_reply_);
EXPECT_CALL(platform_,
FileExists(base::FilePath(cryptohome::kLockedToSingleUserFile)))
.WillOnce(Return(true));
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_)).Times(0);
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).Times(0);
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_TRUE(final_reply.has_value());
ASSERT_TRUE(final_reply->HasExtension(cryptohome::GetTpmStatusReply::reply));
const auto& ext =
final_reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
EXPECT_EQ(ext.enabled(), status_reply_.enabled());
EXPECT_EQ(ext.owned(), status_reply_.owned());
// |initialized| should be false because the owner password is supplied in
// |status_reply_|.
EXPECT_FALSE(ext.initialized());
EXPECT_EQ(ext.owner_password(), status_reply_.local_data().owner_password());
EXPECT_EQ(ext.dictionary_attack_counter(),
da_reply_.dictionary_attack_counter());
EXPECT_EQ(ext.dictionary_attack_threshold(),
da_reply_.dictionary_attack_threshold());
EXPECT_EQ(ext.dictionary_attack_lockout_in_effect(),
da_reply_.dictionary_attack_lockout_in_effect());
EXPECT_EQ(ext.dictionary_attack_lockout_seconds_remaining(),
da_reply_.dictionary_attack_lockout_seconds_remaining());
// |install_lockbox_finalized| is true because |install_attr_reply_.state()|
// is VALID.
EXPECT_TRUE(ext.install_lockbox_finalized());
// |ext.boot_lockbox_finalized| is deprecated and always set to false.
EXPECT_FALSE(ext.boot_lockbox_finalized());
// |ext.is_locked_to_single_user| is set according to the flag file specified
// in kLockedToSingleUserFile.
EXPECT_TRUE(ext.is_locked_to_single_user());
EXPECT_EQ(ext.attestation_prepared(),
attestation_reply_.prepared_for_enrollment());
EXPECT_EQ(ext.attestation_enrolled(), attestation_reply_.enrolled());
EXPECT_EQ(ext.verified_boot_measured(), attestation_reply_.verified_boot());
EXPECT_EQ(ext.identities().size(), attestation_reply_.identities().size());
EXPECT_EQ(ext.identities().Get(0).features(),
attestation_reply_.identities().Get(0).features());
EXPECT_EQ(ext.identities().Get(1).features(),
attestation_reply_.identities().Get(1).features());
EXPECT_EQ(ext.identity_certificates().size(),
attestation_reply_.identity_certificates().size());
EXPECT_EQ(ext.identity_certificates().count(kACA1), 1);
EXPECT_EQ(ext.identity_certificates().at(kACA1).identity(),
attestation_reply_.identity_certificates().at(kACA1).identity());
EXPECT_EQ(ext.identity_certificates().at(kACA1).aca(),
attestation_reply_.identity_certificates().at(kACA1).aca());
EXPECT_EQ(ext.identity_certificates().count(kACA2), 1);
EXPECT_EQ(ext.identity_certificates().at(kACA2).identity(),
attestation_reply_.identity_certificates().at(kACA2).identity());
EXPECT_EQ(ext.identity_certificates().at(kACA2).aca(),
attestation_reply_.identity_certificates().at(kACA2).aca());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusInitialized) {
// If it's owned and no there's no owner_password, then it's initialized.
status_reply_.mutable_local_data()->clear_owner_password();
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
// Setup GetDictionaryAttackInfo in tpm_manager to successfully return
// |da_reply_|
ExpectGetDictionaryAttackInfo(da_reply_);
// Setup GetStatus in cryptohome/install attributes interface to sucessfully
// return |install_attr_reply_|
ExpectInstallAttributesGetStatus(install_attr_reply_);
// Setup GetStatus in attestation to successfully return |attestation_reply_|
ExpectAttestationGetStatus(attestation_reply_);
EXPECT_CALL(platform_,
FileExists(base::FilePath(cryptohome::kLockedToSingleUserFile)))
.WillOnce(Return(false));
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_)).Times(0);
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).Times(0);
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_TRUE(final_reply.has_value());
ASSERT_TRUE(final_reply->HasExtension(cryptohome::GetTpmStatusReply::reply));
const auto& ext =
final_reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
// |initialized| is set to true because owner_password is cleared but owned is
// true.
EXPECT_TRUE(ext.initialized());
EXPECT_EQ(ext.owner_password(), status_reply_.local_data().owner_password());
EXPECT_FALSE(ext.is_locked_to_single_user());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusStageOwnershipStatusFail) {
status_reply_.set_status(tpm_manager::STATUS_DEVICE_ERROR);
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).WillOnce(Return());
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_FALSE(final_reply.has_value());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusStageDictionaryAttackFail) {
da_reply_.set_status(tpm_manager::STATUS_DEVICE_ERROR);
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
// Setup GetDictionaryAttackInfo in tpm_manager to successfully return
// |da_reply_|
ExpectGetDictionaryAttackInfo(da_reply_);
// Setup GetStatus in cryptohome/install attributes interface to sucessfully
// return |install_attr_reply_|
ExpectInstallAttributesGetStatus(install_attr_reply_);
// Setup GetStatus in attestation to successfully return |attestation_reply_|
ExpectAttestationGetStatus(attestation_reply_);
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_)).Times(0);
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).Times(0);
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_TRUE(final_reply.has_value());
ASSERT_TRUE(final_reply->HasExtension(cryptohome::GetTpmStatusReply::reply));
const auto& ext =
final_reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
// These are the default values when call to retrieve DictionaryAttack info
// failed.
EXPECT_EQ(ext.dictionary_attack_counter(), 0);
EXPECT_EQ(ext.dictionary_attack_threshold(), 0);
EXPECT_FALSE(ext.dictionary_attack_lockout_in_effect());
EXPECT_EQ(ext.dictionary_attack_lockout_seconds_remaining(), 0);
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusStageInstallAttributesFail) {
install_attr_reply_.set_error(
user_data_auth::CRYPTOHOME_ERROR_INVALID_ARGUMENT);
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
// Setup GetDictionaryAttackInfo in tpm_manager to successfully return
// |da_reply_|
ExpectGetDictionaryAttackInfo(da_reply_);
// Setup GetStatus in cryptohome/install attributes interface to sucessfully
// return |install_attr_reply_|
ExpectInstallAttributesGetStatus(install_attr_reply_);
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).WillOnce(Return());
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_FALSE(final_reply.has_value());
}
TEST_F(LegacyCryptohomeInterfaceAdaptorTestForGetTpmStatus,
GetTpmStatusStageAttestationFail) {
attestation_reply_.set_status(attestation::STATUS_NOT_AVAILABLE);
// Setup GetTpmStatus in tpm_manager to successfully return |status_reply_|
ExpectGetTpmStatus(status_reply_);
// Setup GetDictionaryAttackInfo in tpm_manager to successfully return
// |da_reply_|
ExpectGetDictionaryAttackInfo(da_reply_);
// Setup GetStatus in cryptohome/install attributes interface to sucessfully
// return |install_attr_reply_|
ExpectInstallAttributesGetStatus(install_attr_reply_);
// Setup GetStatus in attestation to successfully return |attestation_reply_|
ExpectAttestationGetStatus(attestation_reply_);
base::Optional<cryptohome::BaseReply> final_reply;
std::unique_ptr<MockDBusMethodResponse<cryptohome::BaseReply>> response(
new MockDBusMethodResponse<cryptohome::BaseReply>(nullptr));
EXPECT_CALL(*response, ReplyWithError(_)).Times(0);
EXPECT_CALL(*response, ReplyWithError(_, _, _, _)).Times(0);
response->save_return_args(&final_reply);
adaptor_->GetTpmStatus(std::move(response), in_request_);
ASSERT_TRUE(final_reply.has_value());
ASSERT_TRUE(final_reply->HasExtension(cryptohome::GetTpmStatusReply::reply));
const auto& ext =
final_reply->GetExtension(cryptohome::GetTpmStatusReply::reply);
// These are the default values when call to retrieve attestation status
// failed.
EXPECT_FALSE(ext.attestation_prepared());
EXPECT_FALSE(ext.attestation_enrolled());
EXPECT_FALSE(ext.verified_boot_measured());
}
} // namespace
} // namespace cryptohome