blob: 4661249c7f8044095c004425aa7458e514e3da71 [file] [log] [blame]
// Copyright 2021 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/storage/encrypted_container/dmcrypt_container.h"
#include <memory>
#include <string>
#include <utility>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <base/bind.h>
#include <base/files/file_path.h>
#include <brillo/blkdev_utils/device_mapper_fake.h>
#include <brillo/secure_blob.h>
#include "cryptohome/mock_platform.h"
#include "cryptohome/storage/encrypted_container/encrypted_container.h"
#include "cryptohome/storage/encrypted_container/fake_backing_device.h"
#include "cryptohome/storage/encrypted_container/filesystem_key.h"
using ::testing::_;
using ::testing::DoAll;
using ::testing::Return;
using ::testing::SetArgPointee;
namespace cryptohome {
class DmcryptContainerTest : public ::testing::Test {
public:
DmcryptContainerTest()
: config_({.dmcrypt_device_name = "crypt_device",
.dmcrypt_cipher = "aes-xts-plain64",
.mkfs_opts = {"-O", "encrypt,verity"},
.tune2fs_opts = {"-Q", "project"}}),
key_({.fek = brillo::SecureBlob("random key")}),
device_mapper_(base::Bind(&brillo::fake::CreateDevmapperTask)),
backing_device_(std::make_unique<FakeBackingDevice>(
BackingDeviceType::kLogicalVolumeBackingDevice,
base::FilePath("/dev/VG/LV"))) {}
~DmcryptContainerTest() override = default;
void GenerateContainer() {
container_ = std::make_unique<DmcryptContainer>(
config_, std::move(backing_device_), key_reference_, &platform_,
std::make_unique<brillo::DeviceMapper>(
base::Bind(&brillo::fake::CreateDevmapperTask)));
}
protected:
DmcryptConfig config_;
FileSystemKeyReference key_reference_;
FileSystemKey key_;
MockPlatform platform_;
brillo::DeviceMapper device_mapper_;
std::unique_ptr<BackingDevice> backing_device_;
std::unique_ptr<DmcryptContainer> container_;
};
// Tests the creation path for the dm-crypt container.
TEST_F(DmcryptContainerTest, SetupCreateCheck) {
EXPECT_CALL(platform_, GetBlkSize(_, _))
.WillOnce(DoAll(SetArgPointee<1>(1024 * 1024 * 1024), Return(true)));
EXPECT_CALL(platform_, UdevAdmSettle(_, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, FormatExt4(_, _, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, Tune2Fs(_, _)).WillOnce(Return(true));
GenerateContainer();
EXPECT_TRUE(container_->Setup(key_, /*create=*/true));
// Check that the device mapper target exists.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
key_.fek);
EXPECT_TRUE(device_mapper_.Remove(config_.dmcrypt_device_name));
}
// Tests the setup path with an existing container.
TEST_F(DmcryptContainerTest, SetupNoCreateCheck) {
EXPECT_CALL(platform_, GetBlkSize(_, _))
.WillOnce(DoAll(SetArgPointee<1>(1024 * 1024 * 1024), Return(true)));
EXPECT_CALL(platform_, UdevAdmSettle(_, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, Tune2Fs(_, _)).WillOnce(Return(true));
backing_device_->Create();
GenerateContainer();
EXPECT_TRUE(container_->Setup(key_, /*create=*/false));
// Check that the device mapper target exists.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
key_.fek);
EXPECT_TRUE(device_mapper_.Remove(config_.dmcrypt_device_name));
}
// Tests failure path if the backing device fails to setup.
TEST_F(DmcryptContainerTest, SetupFailedBackingDeviceSetup) {
GenerateContainer();
EXPECT_FALSE(container_->Setup(key_, /*create=*/false));
// Check that the device mapper target doesn't exist.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
brillo::SecureBlob());
}
// Tests failure path if the filesystem setup fails.
TEST_F(DmcryptContainerTest, SetupFailedFormatExt4) {
EXPECT_CALL(platform_, GetBlkSize(_, _))
.WillOnce(DoAll(SetArgPointee<1>(1024 * 1024 * 1024), Return(true)));
EXPECT_CALL(platform_, UdevAdmSettle(_, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, FormatExt4(_, _, _)).WillOnce(Return(false));
GenerateContainer();
EXPECT_FALSE(container_->Setup(key_, /*create=*/true));
// Check that the device mapper target doesn't exist.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
brillo::SecureBlob());
}
// Tests the failure path on setting new filesystem features.
TEST_F(DmcryptContainerTest, SetupFailedTune2fs) {
EXPECT_CALL(platform_, GetBlkSize(_, _))
.WillOnce(DoAll(SetArgPointee<1>(1024 * 1024 * 1024), Return(true)));
EXPECT_CALL(platform_, UdevAdmSettle(_, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, Tune2Fs(_, _)).WillOnce(Return(false));
backing_device_->Create();
GenerateContainer();
EXPECT_FALSE(container_->Setup(key_, /*create=*/false));
// Check that the device mapper target doesn't exist.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
brillo::SecureBlob());
}
// Tests that teardown doesn't leave an active dm-crypt device or an attached
// backing device.
TEST_F(DmcryptContainerTest, TeardownCheck) {
EXPECT_CALL(platform_, GetBlkSize(_, _))
.WillOnce(DoAll(SetArgPointee<1>(1024 * 1024 * 1024), Return(true)));
EXPECT_CALL(platform_, UdevAdmSettle(_, _)).WillOnce(Return(true));
EXPECT_CALL(platform_, Tune2Fs(_, _)).WillOnce(Return(true));
backing_device_->Create();
GenerateContainer();
EXPECT_TRUE(container_->Setup(key_, /*create=*/false));
// Now, attempt teardown of the device.
EXPECT_TRUE(container_->Teardown());
// Check that the device mapper target doesn't exist.
EXPECT_EQ(device_mapper_.GetTable(config_.dmcrypt_device_name).CryptGetKey(),
brillo::SecureBlob());
}
} // namespace cryptohome