| // 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/cryptohome_vault_factory.h" |
| |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include <base/files/file_path.h> |
| |
| #include "cryptohome/filesystem_layout.h" |
| #include "cryptohome/platform.h" |
| #include "cryptohome/storage/cryptohome_vault.h" |
| #include "cryptohome/storage/encrypted_container/encrypted_container.h" |
| #include "cryptohome/storage/encrypted_container/encrypted_container_factory.h" |
| #include "cryptohome/storage/encrypted_container/filesystem_key.h" |
| |
| namespace { |
| // Size of logical volumes to use for the dm-crypt cryptohomes. |
| constexpr uint64_t kLogicalVolumeSizePercent = 90; |
| } // namespace |
| |
| namespace cryptohome { |
| |
| CryptohomeVaultFactory::CryptohomeVaultFactory( |
| Platform* platform, |
| std::unique_ptr<EncryptedContainerFactory> encrypted_container_factory) |
| : platform_(platform), |
| encrypted_container_factory_(std::move(encrypted_container_factory)) {} |
| |
| CryptohomeVaultFactory::CryptohomeVaultFactory(Platform* platform) |
| : CryptohomeVaultFactory( |
| platform, std::make_unique<EncryptedContainerFactory>(platform)) {} |
| |
| CryptohomeVaultFactory::~CryptohomeVaultFactory() {} |
| |
| std::unique_ptr<EncryptedContainer> |
| CryptohomeVaultFactory::GenerateEncryptedContainer( |
| EncryptedContainerType type, |
| const std::string& obfuscated_username, |
| const FileSystemKeyReference& key_reference, |
| const std::string& container_identifier) { |
| EncryptedContainerConfig config; |
| base::FilePath stateful_device; |
| uint64_t stateful_size; |
| |
| switch (type) { |
| case EncryptedContainerType::kEcryptfs: |
| config.backing_dir = GetEcryptfsUserVaultPath(obfuscated_username); |
| config.type = EncryptedContainerType::kEcryptfs; |
| break; |
| case EncryptedContainerType::kFscrypt: |
| config.backing_dir = GetUserMountDirectory(obfuscated_username); |
| config.type = EncryptedContainerType::kFscrypt; |
| break; |
| case EncryptedContainerType::kDmcrypt: |
| // Calculate size for dm-crypt partition. |
| stateful_device = platform_->GetStatefulDevice(); |
| if (stateful_device.empty()) |
| return nullptr; |
| |
| if (!platform_->GetBlkSize(stateful_device, &stateful_size)) |
| return nullptr; |
| |
| config.type = EncryptedContainerType::kDmcrypt; |
| config.dmcrypt_config = { |
| .backing_device_config = |
| {.type = BackingDeviceType::kLogicalVolumeBackingDevice, |
| .name = LogicalVolumePrefix(obfuscated_username) + |
| container_identifier, |
| .size = static_cast<int64_t>( |
| (stateful_size * kLogicalVolumeSizePercent) / |
| (100 * 1024 * 1024)), |
| .logical_volume = {.thinpool_name = "thinpool", |
| .physical_volume = stateful_device}}, |
| .dmcrypt_device_name = |
| DmcryptVolumePrefix(obfuscated_username) + container_identifier, |
| .dmcrypt_cipher = "aes-xts-plain64", |
| // TODO(sarthakkukreti): Add more dynamic checks for filesystem |
| // features once dm-crypt cryptohomes are stable. |
| .mkfs_opts = {"-O", "^huge_file,^flex_bg,", "-E", |
| "discard,lazy_itable_init"}, |
| .tune2fs_opts = {"-O", "verity,quota", "-Q", "usrquota,grpquota"}}; |
| break; |
| default: |
| return nullptr; |
| } |
| |
| return encrypted_container_factory_->Generate(config, key_reference); |
| } |
| |
| std::unique_ptr<CryptohomeVault> CryptohomeVaultFactory::Generate( |
| const std::string& obfuscated_username, |
| const FileSystemKeyReference& key_reference, |
| EncryptedContainerType container_type, |
| EncryptedContainerType migrating_container_type) { |
| // Generate containers for the vault. |
| std::unique_ptr<EncryptedContainer> container = |
| GenerateEncryptedContainer(container_type, obfuscated_username, |
| key_reference, kDmcryptDataContainerSuffix); |
| std::unique_ptr<EncryptedContainer> migrating_container = |
| GenerateEncryptedContainer(migrating_container_type, obfuscated_username, |
| key_reference, kDmcryptDataContainerSuffix); |
| |
| std::unique_ptr<EncryptedContainer> cache_container; |
| if (container_type == EncryptedContainerType::kDmcrypt) { |
| cache_container = |
| GenerateEncryptedContainer(container_type, obfuscated_username, |
| key_reference, kDmcryptCacheContainerSuffix); |
| } |
| return std::make_unique<CryptohomeVault>( |
| obfuscated_username, std::move(container), std::move(migrating_container), |
| std::move(cache_container), platform_); |
| } |
| |
| } // namespace cryptohome |