From: seolheui,kim Date: Fri, 10 Feb 2017 08:26:35 +0000 (+0900) Subject: Refactor secure erase and add MMC erase engine X-Git-Tag: submit/tizen/20170214.101511~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=d92e8dee95eae202f9e45d41a2a6281ecf29bf82;p=platform%2Fcore%2Fsecurity%2Fode.git Refactor secure erase and add MMC erase engine Change-Id: Ibfd5df003e1ec10ee2e1a34107eb341a7501f7c7 Signed-off-by: seolheui,kim --- diff --git a/rmi/secure-erase.h b/rmi/secure-erase.h index 48facda..2eb4735 100644 --- a/rmi/secure-erase.h +++ b/rmi/secure-erase.h @@ -33,13 +33,8 @@ public: int erase(const std::string& name); int clean(const std::string& name); -private: - int fileErase(const std::string& name); - int directoryErase(const std::string& name); - void dropCachePage(); private: ODEControlContext& context; - std::string devicePath; }; } // namespace ode diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 6ec742a..c07f9e1 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -25,9 +25,10 @@ SET(SERVER_SRCS main.cpp kernel-keyring.cpp internal-encryption.cpp external-encryption.cpp - engine/ext4-engine.cpp - engine/dmcrypt-engine.cpp - engine/ecryptfs-engine.cpp + engine/encryption/ext4-engine.cpp + engine/encryption/dmcrypt-engine.cpp + engine/encryption/ecryptfs-engine.cpp + engine/erase/mmc-engine.cpp key-manager/key-store.cpp key-manager/key-manager.cpp key-manager/key-generator.cpp diff --git a/server/engine/dmcrypt-engine.cpp b/server/engine/dmcrypt-engine.cpp deleted file mode 100644 index 8152d76..0000000 --- a/server/engine/dmcrypt-engine.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include - -#include - -#include -#include -#include - -#include "../file-footer.h" -#include "../ext4-tool.h" - -#include "dmcrypt-engine.h" - -#define OPTION_INCLUDE_UNUSED_REGION (1 << 0) - -namespace ode { - -void CryptInfo::init(const std::string &src, const std::string &crypto_name) -{ - crypto_type_name = crypto_name; - fs_size = getBlkdevSize(src); -} - -long CryptInfo::getFileSystemSize() -{ - return fs_size; -} - -std::string CryptInfo::getCryptoTypeName() const -{ - return crypto_type_name; -} - -long CryptInfo::getBlkdevSize(const std::string &src) -{ - int fd = open(src.c_str(), O_RDONLY); - if (fd < 0) - return 0; - - long fs_size = 0; - if ((ioctl(fd, BLKGETSIZE, &fs_size)) == -1) - fs_size = 0; - close(fd); - - return fs_size; -} - - -static void convertKeyToHexASCII(const DMCryptEngine::data &key, - DMCryptEngine::data &key_ascii) -{ - unsigned int i, a; - unsigned char nibble; - - for (i = 0, a = 0; i < key.size(); i++, a += 2) { - // For each byte, write out two ascii hex digits - nibble = (key[i] >> 4) & 0xf; - key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30); - - nibble = key[i] & 0xf; - key_ascii[a + 1] = nibble + (nibble > 9 ? 0x37 : 0x30); - } - - // Add the null termination - key_ascii[a] = '\0'; -} - -DMCryptEngine::DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) : - source(src), destination(dest), progressBar(prgsBar) -{ - // 1. Get Real Block device(src)'s infomation - cryptInfo.init(src, "aes-cbc-essiv:sha256"); -} - -DMCryptEngine::~DMCryptEngine() -{ -} - -static void ioctlInit(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) -{ - memset(io, 0, dataSize); - io->data_size = dataSize; - io->data_start = sizeof(struct dm_ioctl); - io->version[0] = 4; - io->version[1] = 0; - io->version[2] = 0; - io->flags = flags; - if (name) { - memset(io->name, 0, sizeof(io->name)); - strncpy(io->name, name, sizeof(io->name) - 1); - } -} - -#define DM_CRYPT_BUF_SIZE 4096 -#define DM_LABEL "userdata" - -static const std::string createCryptoBlkDev(const std::string &real_blkdev, const std::string &mount_name, const DMCryptEngine::data &key, long fileSystemSize, std::string cryptoTypeName) -{ - int fd = -1; - - std::string crypto_blkdev; - ode::DMCryptEngine::data key_ascii(512); - - /* - * dm_buffer |-------------------------------------------------| 4096 - * dm_io |----------| size of dm_ioctl - * dm_ts |--------------| size of dm_Target_spec - * crypt_params |---------------------| - */ - char dm_buffer[DM_CRYPT_BUF_SIZE]; // first: for dm_io, dm_ts - struct dm_ioctl *dm_io; - struct dm_target_spec *dm_ts; - unsigned int dm_minor; - - char *crypt_params; // protocol for dm-crypt - - // Open dm control IOCTL - if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) - throw runtime::Exception("Cannot open device-mapper"); - - /* - * dm_buffer |-------------------------------------------------| 4096 - * dm_io |----------| size of dm_ioctl - */ - dm_io = (struct dm_ioctl *)dm_buffer; - - // Clean-up dm_ioctl - // Create Device (mount_name) - ioctlInit(dm_io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); - if (ioctl(fd, DM_DEV_CREATE, dm_io)) { - close(fd); - throw runtime::Exception("Cannot create dm-crypt device"); - } - - // Clean-up dm_ioctl - // Get the device status, in particular, the mount_name of it's device file - ioctlInit(dm_io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); - if (ioctl(fd, DM_DEV_STATUS, dm_io)) { - close(fd); - throw runtime::Exception("Cannot retrieve dm-crypt device status"); - } - - // Store created device into crypto_blkdev - dm_minor = (dm_io->dev & 0xff) | ((dm_io->dev >> 12) & 0xfff00); - crypto_blkdev = "/dev/dm-" + std::to_string(dm_minor); - - // Load the mapping table for this device - dm_ts = (struct dm_target_spec *)&dm_buffer[sizeof(struct dm_ioctl)]; - - /* - * dm_buffer |-------------------------------------------------| 4096 - * dm_io |----------| size of dm_ioctl - * dm_ts |--------------| size of dm_Target_spec - */ - - // Force clean-up whole dm_buffer - ioctlInit(dm_io, 4096, mount_name.c_str(), 0); - dm_io->target_count = 1; - dm_ts->status = 0; - dm_ts->sector_start = 0; - dm_ts->length = fileSystemSize; - strcpy(dm_ts->target_type, "crypt"); - - // Prepare crypt_params - /* - * dm_buffer |-------------------------------------------------| 4096 - * dm_io |----------| size of dm_ioctl - * dm_ts |--------------| size of dm_Target_spec - * crypt_params |---------------------| - */ - - crypt_params = dm_buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); - - ode::convertKeyToHexASCII(key, key_ascii); - - // Store crypt_params - sprintf(crypt_params, "%s %s 0 %s 0", cryptoTypeName.c_str(), key_ascii.data(), real_blkdev.c_str()); - - crypt_params += strlen(crypt_params) + 1; - // Align to an 8 byte boundary - crypt_params = (char *)(((unsigned long)crypt_params + 7) & ~8); - dm_ts->next = crypt_params - dm_buffer; - - // Table load - if (ioctl(fd, DM_TABLE_LOAD, dm_io) < 0) { - close(fd); - throw runtime::Exception("Cannot load dm-crypt mapping table."); - } - - // Force clean-up whole dm_buffer - // Resume this device to activate it - ioctlInit(dm_io, 4096, mount_name.c_str(), 0); - if (ioctl(fd, DM_DEV_SUSPEND, dm_io)) { - close(fd); - throw runtime::Exception("Cannot resume the dm-crypt device"); - } - - // If fd is <0 from a failed open call, - // it's safe to just ignore the close error - if (fd >= 0) - close(fd); - - return crypto_blkdev; -} - -static void destroyCryptoBlkDev(const std::string &mount_name) -{ - int fd; - char buffer[DM_CRYPT_BUF_SIZE]; - struct dm_ioctl *io; - - if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) - throw runtime::Exception("Cannot open device-mapper"); - - io = (struct dm_ioctl *)buffer; - - ioctlInit(io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); - if (ioctl(fd, DM_DEV_REMOVE, io)) { - close(fd); - throw runtime::Exception("Cannot remove dm-crypt device"); - } - - if (fd >= 0) - close(fd); -} - -#define DMCRYPT_KEY_MIN_LEN_BYTE (32) -#define DMCRYPT_KEY_MIN_LEN_BIT (DMCRYPT_KEY_MIN_LEN_BYTE*8) - -static ode::DMCryptEngine::data sanitizeKey(const ode::DMCryptEngine::data &key) -{ - if (key.size() < DMCRYPT_KEY_MIN_LEN_BYTE) - throw runtime::Exception("Key length isn't enough to be used for dmcrypt"); - else if (key.size() > DMCRYPT_KEY_MIN_LEN_BYTE) - return ode::DMCryptEngine::data(key.begin(), key.begin() + DMCRYPT_KEY_MIN_LEN_BYTE); - else - return key; -} - -void DMCryptEngine::mount(const DMCryptEngine::data &key, unsigned int options) -{ - DMCryptEngine::data sanitized_key = sanitizeKey(key); - - // create crypto type device mapping layer to mount the encrypted partition. - const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); - - if (::mount(crypto_blkdev.c_str(), destination.c_str(), "ext4", 0, 0) < 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); -} - -void DMCryptEngine::umount() -{ - if (::umount(destination.c_str())) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - - destroyCryptoBlkDev(DM_LABEL); -} - -void DMCryptEngine::encryptInPlace(const std::string &src_blkdev, - const std::string &dst_blkdev, - const bool isFastEncEnabled) -{ - Ext4Tool ext4tool(src_blkdev); - ext4tool.forceCleanUp(); - - const unsigned int SRC_BLOCK_SIZE = ext4tool.getBlockSize(); - const unsigned int SRC_TOTAL_BLOCK_COUNT = ext4tool.getTotalBlockCount(); - char buff[SRC_BLOCK_SIZE] = {0, }; - - runtime::File dst(dst_blkdev, O_WRONLY); - runtime::File src(src_blkdev, O_RDONLY); - - for (unsigned int n = 0; n < SRC_TOTAL_BLOCK_COUNT; n++) { - if (isFastEncEnabled && ext4tool.isUsedBlock(n) == false) - continue; - - src.lseek(n * SRC_BLOCK_SIZE, SEEK_SET); - dst.lseek(n * SRC_BLOCK_SIZE, SEEK_SET); - - src.read(buff, SRC_BLOCK_SIZE); - dst.write(buff, SRC_BLOCK_SIZE); - - progressBar.update(n, SRC_TOTAL_BLOCK_COUNT, 1); - } - progressBar.done(); -} - -void DMCryptEngine::encrypt(const DMCryptEngine::data &key, unsigned int options) -{ - DMCryptEngine::data sanitized_key = sanitizeKey(key); - - // create crypto type device mapping layer to mount the plain partition - // should be encrypted here. - const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); - - bool isFastEncEnabled = true; - if (options == OPTION_INCLUDE_UNUSED_REGION) - isFastEncEnabled = false; - - INFO("FastEncryption: " + std::string(isFastEncEnabled ? "Enabled" : "Disabled")); - - // We always do In-place encryption - encryptInPlace(source, crypto_blkdev, isFastEncEnabled); - - // remove crypto type device mapper - destroyCryptoBlkDev(DM_LABEL); -} - -void DMCryptEngine::decrypt(const DMCryptEngine::data &key, unsigned int options) -{ - DMCryptEngine::data sanitized_key = sanitizeKey(key); - - // create crypto type device mapping layer to mount the plain partition - // should be encrypted here. - const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); - - bool isFastEncEnabled = true; - if (options == OPTION_INCLUDE_UNUSED_REGION) - isFastEncEnabled = false; - - INFO("FastEncryption: " + std::string(isFastEncEnabled ? "Enabled" : "Disabled")); - - // We always do In-place encryption - encryptInPlace(crypto_blkdev, source, isFastEncEnabled); - - // remove crypto type device mapper - destroyCryptoBlkDev(DM_LABEL); -} - -bool DMCryptEngine::isKeyMetaSet() -{ - return FileFooter::exist(source); -} - -const DMCryptEngine::data DMCryptEngine::getKeyMeta() -{ - return FileFooter::read(source); -} - -void DMCryptEngine::setKeyMeta(const data &meta) -{ - FileFooter::write(source, meta); -} - -void DMCryptEngine::clearKeyMeta() -{ - FileFooter::clear(source); -} - -unsigned int DMCryptEngine::getSupportedOptions() -{ - return OPTION_INCLUDE_UNUSED_REGION; -} - -} // namespace ode diff --git a/server/engine/dmcrypt-engine.h b/server/engine/dmcrypt-engine.h deleted file mode 100644 index 8f71f44..0000000 --- a/server/engine/dmcrypt-engine.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 - */ - -#ifndef __DMCRYPT_ENGINE_H__ -#define __DMCRYPT_ENGINE_H__ - -#include -#include - -#include "progress-bar.h" - -namespace ode { - -class CryptInfo { -public: - void init(const std::string &src, const std::string &crypto_name); - long getFileSystemSize(); - std::string getCryptoTypeName() const; - -private: - long getBlkdevSize(const std::string &src); - -private: - // TODO(seok85.hong): support fast-encryption - long fs_size; - std::string crypto_type_name; -}; - - -class DMCryptEngine final { -public: - DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar); - DMCryptEngine(const DMCryptEngine &) = delete; - DMCryptEngine(DMCryptEngine &&) = delete; - ~DMCryptEngine(); - - DMCryptEngine &operator=(const DMCryptEngine &) = delete; - DMCryptEngine &operator=(DMCryptEngine &&) = delete; - - const std::string &getSource() - { - return source; - } - - const std::string &getDestination() - { - return destination; - } - - typedef std::vector data; - - void mount(const data &key, unsigned int options); - void umount(); - - void encrypt(const data &key, unsigned int options); - void decrypt(const data &key, unsigned int options); - - bool isKeyMetaSet(); - const data getKeyMeta(); - void setKeyMeta(const data &data); - void clearKeyMeta(); - - unsigned int getSupportedOptions(); - -private: - void encryptInPlace(const std::string &src_blkdev, - const std::string &dst_blkdev, - const bool isFastEncEnabled); - -private: - std::string source, destination; - CryptInfo cryptInfo; - ProgressBar progressBar; -}; - -} // namespace ode -#endif // __DMCRYPT_ENGINE_H__ diff --git a/server/engine/ecryptfs-engine.cpp b/server/engine/ecryptfs-engine.cpp deleted file mode 100644 index cea2716..0000000 --- a/server/engine/ecryptfs-engine.cpp +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 - -#include -#include -#include - -#include -#include -#include -#include - -#include "../kernel-keyring.h" -#include "../file-footer.h" - -#include "ecryptfs-engine.h" - -#define OPTION_ONLY_NEW_FILE (1 << 0) -#define OPTION_EXCEPT_FOR_MEDIA_FILE (1 << 1) - -#define SUPPORTED_OPTIONS OPTION_ONLY_NEW_FILE - -#define MEDIA_EXCLUSION_LIST "temp_video/Camera/DCIM:mp3|mpga|m4a|mp4|wav|amr|awb|wma|ogg|oga|aac|mka|flac|3gp|3ga|mid|midi|xmf|rtttl|rtx|ota|smf|spm|imy|mpeg|m4v|3gp|3gpp|3g2|3gpp2|wmv|asf|mkv|webm|ts|avi|jpg|jpeg|gif|png|bmp|wbmp|divx|flv|ac3|mov|tiff|f4v|mpeg3|voice" - -#define CIPHER_MODE "aes" -#define ENCRYPTION_CHECKER_NAME ".ecryptfs_encrypted" - - -#define ECRYPTFS_VERSION_MAJOR 0x00 -#define ECRYPTFS_VERSION_MINOR 0x04 -#define ECRYPTFS_VERSION ((ECRYPTFS_VERSION_MAJOR << 8) | ECRYPTFS_VERSION_MINOR) - -#define ECRYPTFS_MAX_KEY_BYTES 64 -#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 -#define ECRYPTFS_SIG_SIZE 8 -#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2) -#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX -#define ECRYPTFS_SALT_SIZE 8 -#define ECRYPTFS_MAX_KEY_MOD_NAME_BYTES 16 - -struct ecryptfs_session_key { -#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001 -#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002 -#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004 -#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008 - int32_t flags; - int32_t encrypted_key_size; - int32_t decrypted_key_size; - uint8_t encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; - uint8_t decrypted_key[ECRYPTFS_MAX_KEY_BYTES]; -}; - -struct ecryptfs_password { - int32_t password_bytes; - int32_t hash_algo; - int32_t hash_iterations; - int32_t session_key_encryption_key_bytes; -#define ECRYPTFS_PERSISTENT_PASSWORD 0x01 -#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 - uint32_t flags; - uint8_t session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; - uint8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; - uint8_t salt[ECRYPTFS_SALT_SIZE]; -}; - -struct ecryptfs_private_key { - uint32_t key_size; - uint32_t data_len; - uint8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; - char key_mod_alias[ECRYPTFS_MAX_KEY_MOD_NAME_BYTES + 1]; - uint8_t data[]; -}; - -enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; - -struct ecryptfs_auth_tok { - uint16_t version; - uint16_t token_type; -#define ECRYPTFS_ENCRYPT_ONLY 0x00000001 - uint32_t flags; - struct ecryptfs_session_key session_key; - uint8_t reserved[32]; - union { - struct ecryptfs_password password; - struct ecryptfs_private_key private_key; - } token; -} __attribute__((packed)); - -#if 0 -#define ECRYPTFS_IOCTL_GET_ATTRIBUTES _IOR('l', 0x10, unsigned int) -#define ECRYPTFS_WAS_ENCRYPTED 0x0080 -#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100 -#endif - -#define ECRYPTFS_AUTH_TOKEN_TYPE "user" - -namespace ode { - -namespace { - -unsigned long long getAvailableSpace(const std::string& mountPoint) -{ - struct statfs statbuf; - if (::statfs(mountPoint.c_str(), &statbuf)) { - throw runtime::Exception("Failed to access " + mountPoint); - } - - return (unsigned long long)statbuf.f_bfree * statbuf.f_bsize; -} - -bool wasEncrypted(const std::string &path) -{ -#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES - unsigned int attrs = 0; - bool ret = false; - int fd = 0; - - fd = ::open(path.c_str(), O_RDWR); - if (fd < 0) { - throw runtime::Exception("Failed to open " + path); - } - - if (::ioctl(fd, ECRYPTFS_IOCTL_GET_ATTRIBUTES, &attrs) == 0 && - (attrs & ECRYPTFS_WAS_ENCRYPTED)) { - ret = true; - } - ::close(fd); - - return ret; -#else - return true; -#endif -} - -unsigned long long getEncryptedSize(const runtime::File &file) { - unsigned long long originalSize = file.size(); - unsigned long long result = 0; - - if (originalSize % 4096) { - originalSize = (1 + originalSize / 4096) * 4096; - } - -#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES - if (wasEncrypted(file.getPath())) { - result = originalSize; - } else { -#endif - result = originalSize + 2 * 4096; -#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES - } -#endif - - //TODO : block size have to not hard-coded. - // If there is a better way, the followings have to be changed. - unsigned int blockSize = 4096; - if (result % blockSize) { - result = (1 + result / blockSize) * blockSize; - } - - return result; -} - -unsigned long long getDecryptedSize(const runtime::File &file) { - unsigned long long originalSize = file.size(); - unsigned long long result = originalSize; - - if (wasEncrypted(file.getPath())) { - if (originalSize > 2 * 4096) { - result = originalSize - 2 * 4096; - } - } - - result = originalSize; - - //TODO : block size have to not hard-coded. - // If there is a better way, the followings have to be changed. - unsigned int blockSize = 4096; - if (result % blockSize) { - result = (1 + result / blockSize) * blockSize; - } - - return result; -} - -bool isEnoughToCopyInPlace(const std::string& path, - const std::function getSizeFunc) -{ - unsigned long long availableSpace = getAvailableSpace(path); - - std::function check; - check = [&check, &getSizeFunc, availableSpace](const std::string &path) { - for (runtime::DirectoryIterator iter(path), end; - iter != end; ++iter) { - if (iter->isDirectory()) { - if (!check(iter->getPath())) { - return false; - } - } else if (getSizeFunc(*iter) > availableSpace) { - //TODO : have to consider changing file size - // when encrypt/decrypt - return false; - } - } - return true; - }; - - return check(path); -} - -void copyInPlace(const std::string& source, const std::string& destination, - const std::string& temp, - const std::function &isTarget, - const std::function &addProgress) -{ - for (runtime::DirectoryIterator iter(source), end; - iter != end; ++iter) { - if (iter->isDirectory()) { - copyInPlace(iter->getPath(), destination + "/" + iter->getName(), - temp, isTarget, addProgress); - } else if (isTarget(iter->getPath())) { - std::string tempFilePath = temp + "/" + iter->getName(); - std::string destFilePath = destination + "/" + iter->getName(); - - iter->copyTo(tempFilePath); - iter->remove(); - if (::rename(tempFilePath.c_str(), destFilePath.c_str()) != 0) { - throw runtime::Exception("Failed to rename from " + tempFilePath + " to " + destFilePath); - } - - addProgress(iter->size()); - } - } -} - -void ecryptfsMount(const std::string &source, const std::string &destination, const std::vector &key, unsigned int options) -{ - ecryptfs_auth_tok payload; - std::string mountOption; - - ::memset(&(payload), 0, sizeof(ecryptfs_auth_tok)); - - payload.version = ECRYPTFS_VERSION; - payload.token_type = ECRYPTFS_PASSWORD; - payload.token.password.flags = ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; - payload.token.password.session_key_encryption_key_bytes = - (ECRYPTFS_MAX_KEY_BYTES > key.size())? key.size() : - ECRYPTFS_MAX_KEY_BYTES; - ::memcpy(payload.token.password.session_key_encryption_key, key.data(), - payload.token.password.session_key_encryption_key_bytes); - - std::stringstream signature; - signature<< std::hex << std::setfill('0') << std::setw(2); - for (unsigned int byte : key) { - signature << byte; - } - for (int i = key.size(); i < ECRYPTFS_SIG_SIZE; i++) { - signature << (unsigned int) 0; - } - ::memcpy((char *)payload.token.password.signature, - signature.str().c_str(), ECRYPTFS_PASSWORD_SIG_SIZE); - - if (KernelKeyRing::search(KEY_SPEC_USER_KEYRING, ECRYPTFS_AUTH_TOKEN_TYPE, - (char *)payload.token.password.signature, 0) < 0) { - if (KernelKeyRing::add(ECRYPTFS_AUTH_TOKEN_TYPE, - (char *)payload.token.password.signature, - (void *)&payload, sizeof(payload), - KEY_SPEC_USER_KEYRING) < 0) { - throw runtime::Exception("Unable to add token to keyring."); - } - } - - mountOption = "ecryptfs_passthrough" - ",ecryptfs_cipher=" CIPHER_MODE - ",ecryptfs_sig=" + std::string((char *)payload.token.password.signature) + - ",ecryptfs_key_bytes=" + std::to_string(payload.token.password.session_key_encryption_key_bytes); - - if (options & OPTION_EXCEPT_FOR_MEDIA_FILE) { - mountOption += ",ecryptfs_enable_filtering=" MEDIA_EXCLUSION_LIST; - } - - INFO("option = " + mountOption); - INFO("source = " + source); - INFO("dest = " + destination); - - if (::mount(source.c_str(), destination.c_str(), "ecryptfs", MS_NODEV, - mountOption.c_str()) != 0) { - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } -} - -void ecryptfsUmount(const std::string &destination) -{ - if (::umount(destination.c_str()) != 0) { - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } - - //TODO : remove key from keyring -} - -} // namespace - -EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest, const ProgressBar &prg) : - source(src), destination(dest), progress(prg) -{ -} - -EcryptfsEngine::~EcryptfsEngine() -{ -} - -void EcryptfsEngine::mount(const data &key, unsigned int options) -{ - ecryptfsMount(source, destination, key, options); -} - -void EcryptfsEngine::umount() -{ - ecryptfsUmount(destination); -} - -void EcryptfsEngine::encrypt(const data &key, unsigned int options) -{ - if (!isEnoughToCopyInPlace(source, getDecryptedSize)) { - throw runtime::Exception("No space to encryption"); - } - - progress.update(0); - - try { - ecryptfsMount(source, destination, key, options); - } catch (runtime::Exception &e) { - throw runtime::Exception("Failed to mount - " + std::string(e.what())); - } - - try { - unsigned long long totalSize = getAvailableSpace(source), current; - runtime::File tempDir(destination + "/" ENCRYPTION_CHECKER_NAME); - - tempDir.makeDirectory(); - if (!(options & OPTION_ONLY_NEW_FILE)) { - copyInPlace(destination, destination, tempDir.getPath(), - [](const std::string &file) { - return true; - }, - [¤t, &totalSize, this](unsigned long long size) { - current += size; - this->progress.update(current * 100 / totalSize); - }); - } - } catch (runtime::Exception &e) { - try { - ecryptfsUmount(destination); - } catch (runtime::Exception &e) {} - throw runtime::Exception("Failed to encrypt file - " + std::string(e.what())); - } - - sync(); - - progress.done(); -} - -void EcryptfsEngine::decrypt(const data &key, unsigned int options) -{ - if (!isEnoughToCopyInPlace(destination, getEncryptedSize)) { - throw runtime::Exception("No space to encryption"); - } - - progress.update(0); - - try { - unsigned long long totalSize = getAvailableSpace(source), current; - runtime::File tempDir(source + "/" ENCRYPTION_CHECKER_NAME); - runtime::File tempMountpoint(tempDir.getPath() + "/mount"); - - tempMountpoint.makeDirectory(); - ecryptfsMount(source, tempMountpoint.getPath(), key, 0); - - copyInPlace(tempMountpoint.getPath(), source, - tempDir.getPath(), wasEncrypted, - [¤t, &totalSize, this](unsigned long long size) { - current += size; - this->progress.update(current * 100 / totalSize); - }); - ecryptfsUmount(tempMountpoint.getPath()); - - tempDir.remove(true); - } catch (runtime::Exception &e) { - throw runtime::Exception("Failed to decrypt file - " + std::string(e.what())); - } - - sync(); - - progress.done(); -} - -bool EcryptfsEngine::isKeyMetaSet() -{ - return FileFooter::exist(source); -} - -const EcryptfsEngine::data EcryptfsEngine::getKeyMeta() -{ - return FileFooter::read(source); -} - -void EcryptfsEngine::setKeyMeta(const data &meta) -{ - FileFooter::write(source, meta); -} - -void EcryptfsEngine::clearKeyMeta() -{ - FileFooter::clear(source); -} - -unsigned int EcryptfsEngine::getSupportedOptions() -{ - return SUPPORTED_OPTIONS; -} - -} // namespace ode diff --git a/server/engine/ecryptfs-engine.h b/server/engine/ecryptfs-engine.h deleted file mode 100644 index 4a57f1f..0000000 --- a/server/engine/ecryptfs-engine.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 - */ - -#ifndef __ECRYPTFS_ENGINE_H__ -#define __ECRYPTFS_ENGINE_H__ - -#include -#include - -#include "../progress-bar.h" - -namespace ode { - -class EcryptfsEngine final { -public: - EcryptfsEngine(const std::string& src, const std::string& dest, const ProgressBar& prgs); - EcryptfsEngine(const EcryptfsEngine&) = delete; - EcryptfsEngine(EcryptfsEngine&&) = delete; - ~EcryptfsEngine(); - - EcryptfsEngine& operator=(const EcryptfsEngine&) = delete; - EcryptfsEngine& operator=(EcryptfsEngine&&) = delete; - - const std::string& getSource() - { - return source; - } - - const std::string& getDestination() - { - return destination; - } - - typedef std::vector data; - - void mount(const data& key, unsigned int); - void umount(); - - void encrypt(const data& key, unsigned int); - void decrypt(const data& key, unsigned int); - - bool isKeyMetaSet(); - const data getKeyMeta(); - void setKeyMeta(const data &data); - void clearKeyMeta(); - - unsigned int getSupportedOptions(); - -private: - std::string source, destination; - ProgressBar progress; -}; - -} // namespace ode -#endif // __ECRYPTFS_ENGINE_H__ - diff --git a/server/engine/encryption/dmcrypt-engine.cpp b/server/engine/encryption/dmcrypt-engine.cpp new file mode 100644 index 0000000..ce97023 --- /dev/null +++ b/server/engine/encryption/dmcrypt-engine.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include + +#include + +#include +#include +#include + +#include "../../file-footer.h" +#include "../../ext4-tool.h" + +#include "dmcrypt-engine.h" + +#define OPTION_INCLUDE_UNUSED_REGION (1 << 0) + +namespace ode { + +void CryptInfo::init(const std::string &src, const std::string &crypto_name) +{ + crypto_type_name = crypto_name; + fs_size = getBlkdevSize(src); +} + +long CryptInfo::getFileSystemSize() +{ + return fs_size; +} + +std::string CryptInfo::getCryptoTypeName() const +{ + return crypto_type_name; +} + +long CryptInfo::getBlkdevSize(const std::string &src) +{ + int fd = open(src.c_str(), O_RDONLY); + if (fd < 0) + return 0; + + long fs_size = 0; + if ((ioctl(fd, BLKGETSIZE, &fs_size)) == -1) + fs_size = 0; + close(fd); + + return fs_size; +} + + +static void convertKeyToHexASCII(const DMCryptEngine::data &key, + DMCryptEngine::data &key_ascii) +{ + unsigned int i, a; + unsigned char nibble; + + for (i = 0, a = 0; i < key.size(); i++, a += 2) { + // For each byte, write out two ascii hex digits + nibble = (key[i] >> 4) & 0xf; + key_ascii[a] = nibble + (nibble > 9 ? 0x37 : 0x30); + + nibble = key[i] & 0xf; + key_ascii[a + 1] = nibble + (nibble > 9 ? 0x37 : 0x30); + } + + // Add the null termination + key_ascii[a] = '\0'; +} + +DMCryptEngine::DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) : + source(src), destination(dest), progressBar(prgsBar) +{ + // 1. Get Real Block device(src)'s infomation + cryptInfo.init(src, "aes-cbc-essiv:sha256"); +} + +DMCryptEngine::~DMCryptEngine() +{ +} + +static void ioctlInit(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags) +{ + memset(io, 0, dataSize); + io->data_size = dataSize; + io->data_start = sizeof(struct dm_ioctl); + io->version[0] = 4; + io->version[1] = 0; + io->version[2] = 0; + io->flags = flags; + if (name) { + memset(io->name, 0, sizeof(io->name)); + strncpy(io->name, name, sizeof(io->name) - 1); + } +} + +#define DM_CRYPT_BUF_SIZE 4096 +#define DM_LABEL "userdata" + +static const std::string createCryptoBlkDev(const std::string &real_blkdev, const std::string &mount_name, const DMCryptEngine::data &key, long fileSystemSize, std::string cryptoTypeName) +{ + int fd = -1; + + std::string crypto_blkdev; + ode::DMCryptEngine::data key_ascii(512); + + /* + * dm_buffer |-------------------------------------------------| 4096 + * dm_io |----------| size of dm_ioctl + * dm_ts |--------------| size of dm_Target_spec + * crypt_params |---------------------| + */ + char dm_buffer[DM_CRYPT_BUF_SIZE]; // first: for dm_io, dm_ts + struct dm_ioctl *dm_io; + struct dm_target_spec *dm_ts; + unsigned int dm_minor; + + char *crypt_params; // protocol for dm-crypt + + // Open dm control IOCTL + if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) + throw runtime::Exception("Cannot open device-mapper"); + + /* + * dm_buffer |-------------------------------------------------| 4096 + * dm_io |----------| size of dm_ioctl + */ + dm_io = (struct dm_ioctl *)dm_buffer; + + // Clean-up dm_ioctl + // Create Device (mount_name) + ioctlInit(dm_io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); + if (ioctl(fd, DM_DEV_CREATE, dm_io)) { + close(fd); + throw runtime::Exception("Cannot create dm-crypt device"); + } + + // Clean-up dm_ioctl + // Get the device status, in particular, the mount_name of it's device file + ioctlInit(dm_io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); + if (ioctl(fd, DM_DEV_STATUS, dm_io)) { + close(fd); + throw runtime::Exception("Cannot retrieve dm-crypt device status"); + } + + // Store created device into crypto_blkdev + dm_minor = (dm_io->dev & 0xff) | ((dm_io->dev >> 12) & 0xfff00); + crypto_blkdev = "/dev/dm-" + std::to_string(dm_minor); + + // Load the mapping table for this device + dm_ts = (struct dm_target_spec *)&dm_buffer[sizeof(struct dm_ioctl)]; + + /* + * dm_buffer |-------------------------------------------------| 4096 + * dm_io |----------| size of dm_ioctl + * dm_ts |--------------| size of dm_Target_spec + */ + + // Force clean-up whole dm_buffer + ioctlInit(dm_io, 4096, mount_name.c_str(), 0); + dm_io->target_count = 1; + dm_ts->status = 0; + dm_ts->sector_start = 0; + dm_ts->length = fileSystemSize; + strcpy(dm_ts->target_type, "crypt"); + + // Prepare crypt_params + /* + * dm_buffer |-------------------------------------------------| 4096 + * dm_io |----------| size of dm_ioctl + * dm_ts |--------------| size of dm_Target_spec + * crypt_params |---------------------| + */ + + crypt_params = dm_buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); + + ode::convertKeyToHexASCII(key, key_ascii); + + // Store crypt_params + sprintf(crypt_params, "%s %s 0 %s 0", cryptoTypeName.c_str(), key_ascii.data(), real_blkdev.c_str()); + + crypt_params += strlen(crypt_params) + 1; + // Align to an 8 byte boundary + crypt_params = (char *)(((unsigned long)crypt_params + 7) & ~8); + dm_ts->next = crypt_params - dm_buffer; + + // Table load + if (ioctl(fd, DM_TABLE_LOAD, dm_io) < 0) { + close(fd); + throw runtime::Exception("Cannot load dm-crypt mapping table."); + } + + // Force clean-up whole dm_buffer + // Resume this device to activate it + ioctlInit(dm_io, 4096, mount_name.c_str(), 0); + if (ioctl(fd, DM_DEV_SUSPEND, dm_io)) { + close(fd); + throw runtime::Exception("Cannot resume the dm-crypt device"); + } + + // If fd is <0 from a failed open call, + // it's safe to just ignore the close error + if (fd >= 0) + close(fd); + + return crypto_blkdev; +} + +static void destroyCryptoBlkDev(const std::string &mount_name) +{ + int fd; + char buffer[DM_CRYPT_BUF_SIZE]; + struct dm_ioctl *io; + + if ((fd = open("/dev/mapper/control", O_RDWR)) < 0) + throw runtime::Exception("Cannot open device-mapper"); + + io = (struct dm_ioctl *)buffer; + + ioctlInit(io, DM_CRYPT_BUF_SIZE, mount_name.c_str(), 0); + if (ioctl(fd, DM_DEV_REMOVE, io)) { + close(fd); + throw runtime::Exception("Cannot remove dm-crypt device"); + } + + if (fd >= 0) + close(fd); +} + +#define DMCRYPT_KEY_MIN_LEN_BYTE (32) +#define DMCRYPT_KEY_MIN_LEN_BIT (DMCRYPT_KEY_MIN_LEN_BYTE*8) + +static ode::DMCryptEngine::data sanitizeKey(const ode::DMCryptEngine::data &key) +{ + if (key.size() < DMCRYPT_KEY_MIN_LEN_BYTE) + throw runtime::Exception("Key length isn't enough to be used for dmcrypt"); + else if (key.size() > DMCRYPT_KEY_MIN_LEN_BYTE) + return ode::DMCryptEngine::data(key.begin(), key.begin() + DMCRYPT_KEY_MIN_LEN_BYTE); + else + return key; +} + +void DMCryptEngine::mount(const DMCryptEngine::data &key, unsigned int options) +{ + DMCryptEngine::data sanitized_key = sanitizeKey(key); + + // create crypto type device mapping layer to mount the encrypted partition. + const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); + + if (::mount(crypto_blkdev.c_str(), destination.c_str(), "ext4", 0, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +void DMCryptEngine::umount() +{ + if (::umount(destination.c_str())) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + destroyCryptoBlkDev(DM_LABEL); +} + +void DMCryptEngine::encryptInPlace(const std::string &src_blkdev, + const std::string &dst_blkdev, + const bool isFastEncEnabled) +{ + Ext4Tool ext4tool(src_blkdev); + ext4tool.forceCleanUp(); + + const unsigned int SRC_BLOCK_SIZE = ext4tool.getBlockSize(); + const unsigned int SRC_TOTAL_BLOCK_COUNT = ext4tool.getTotalBlockCount(); + char buff[SRC_BLOCK_SIZE] = {0, }; + + runtime::File dst(dst_blkdev, O_WRONLY); + runtime::File src(src_blkdev, O_RDONLY); + + for (unsigned int n = 0; n < SRC_TOTAL_BLOCK_COUNT; n++) { + if (isFastEncEnabled && ext4tool.isUsedBlock(n) == false) + continue; + + src.lseek(n * SRC_BLOCK_SIZE, SEEK_SET); + dst.lseek(n * SRC_BLOCK_SIZE, SEEK_SET); + + src.read(buff, SRC_BLOCK_SIZE); + dst.write(buff, SRC_BLOCK_SIZE); + + progressBar.update(n, SRC_TOTAL_BLOCK_COUNT, 1); + } + progressBar.done(); +} + +void DMCryptEngine::encrypt(const DMCryptEngine::data &key, unsigned int options) +{ + DMCryptEngine::data sanitized_key = sanitizeKey(key); + + // create crypto type device mapping layer to mount the plain partition + // should be encrypted here. + const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); + + bool isFastEncEnabled = true; + if (options == OPTION_INCLUDE_UNUSED_REGION) + isFastEncEnabled = false; + + INFO("FastEncryption: " + std::string(isFastEncEnabled ? "Enabled" : "Disabled")); + + // We always do In-place encryption + encryptInPlace(source, crypto_blkdev, isFastEncEnabled); + + // remove crypto type device mapper + destroyCryptoBlkDev(DM_LABEL); +} + +void DMCryptEngine::decrypt(const DMCryptEngine::data &key, unsigned int options) +{ + DMCryptEngine::data sanitized_key = sanitizeKey(key); + + // create crypto type device mapping layer to mount the plain partition + // should be encrypted here. + const std::string crypto_blkdev = createCryptoBlkDev(source, DM_LABEL, sanitized_key, cryptInfo.getFileSystemSize(), cryptInfo.getCryptoTypeName()); + + bool isFastEncEnabled = true; + if (options == OPTION_INCLUDE_UNUSED_REGION) + isFastEncEnabled = false; + + INFO("FastEncryption: " + std::string(isFastEncEnabled ? "Enabled" : "Disabled")); + + // We always do In-place encryption + encryptInPlace(crypto_blkdev, source, isFastEncEnabled); + + // remove crypto type device mapper + destroyCryptoBlkDev(DM_LABEL); +} + +bool DMCryptEngine::isKeyMetaSet() +{ + return FileFooter::exist(source); +} + +const DMCryptEngine::data DMCryptEngine::getKeyMeta() +{ + return FileFooter::read(source); +} + +void DMCryptEngine::setKeyMeta(const data &meta) +{ + FileFooter::write(source, meta); +} + +void DMCryptEngine::clearKeyMeta() +{ + FileFooter::clear(source); +} + +unsigned int DMCryptEngine::getSupportedOptions() +{ + return OPTION_INCLUDE_UNUSED_REGION; +} + +} // namespace ode diff --git a/server/engine/encryption/dmcrypt-engine.h b/server/engine/encryption/dmcrypt-engine.h new file mode 100644 index 0000000..8f71f44 --- /dev/null +++ b/server/engine/encryption/dmcrypt-engine.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ + +#ifndef __DMCRYPT_ENGINE_H__ +#define __DMCRYPT_ENGINE_H__ + +#include +#include + +#include "progress-bar.h" + +namespace ode { + +class CryptInfo { +public: + void init(const std::string &src, const std::string &crypto_name); + long getFileSystemSize(); + std::string getCryptoTypeName() const; + +private: + long getBlkdevSize(const std::string &src); + +private: + // TODO(seok85.hong): support fast-encryption + long fs_size; + std::string crypto_type_name; +}; + + +class DMCryptEngine final { +public: + DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar); + DMCryptEngine(const DMCryptEngine &) = delete; + DMCryptEngine(DMCryptEngine &&) = delete; + ~DMCryptEngine(); + + DMCryptEngine &operator=(const DMCryptEngine &) = delete; + DMCryptEngine &operator=(DMCryptEngine &&) = delete; + + const std::string &getSource() + { + return source; + } + + const std::string &getDestination() + { + return destination; + } + + typedef std::vector data; + + void mount(const data &key, unsigned int options); + void umount(); + + void encrypt(const data &key, unsigned int options); + void decrypt(const data &key, unsigned int options); + + bool isKeyMetaSet(); + const data getKeyMeta(); + void setKeyMeta(const data &data); + void clearKeyMeta(); + + unsigned int getSupportedOptions(); + +private: + void encryptInPlace(const std::string &src_blkdev, + const std::string &dst_blkdev, + const bool isFastEncEnabled); + +private: + std::string source, destination; + CryptInfo cryptInfo; + ProgressBar progressBar; +}; + +} // namespace ode +#endif // __DMCRYPT_ENGINE_H__ diff --git a/server/engine/encryption/ecryptfs-engine.cpp b/server/engine/encryption/ecryptfs-engine.cpp new file mode 100644 index 0000000..ece06ad --- /dev/null +++ b/server/engine/encryption/ecryptfs-engine.cpp @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include +#include +#include + +#include +#include +#include +#include + +#include "../../kernel-keyring.h" +#include "../../file-footer.h" + +#include "ecryptfs-engine.h" + +#define OPTION_ONLY_NEW_FILE (1 << 0) +#define OPTION_EXCEPT_FOR_MEDIA_FILE (1 << 1) + +#define SUPPORTED_OPTIONS OPTION_ONLY_NEW_FILE + +#define MEDIA_EXCLUSION_LIST "temp_video/Camera/DCIM:mp3|mpga|m4a|mp4|wav|amr|awb|wma|ogg|oga|aac|mka|flac|3gp|3ga|mid|midi|xmf|rtttl|rtx|ota|smf|spm|imy|mpeg|m4v|3gp|3gpp|3g2|3gpp2|wmv|asf|mkv|webm|ts|avi|jpg|jpeg|gif|png|bmp|wbmp|divx|flv|ac3|mov|tiff|f4v|mpeg3|voice" + +#define CIPHER_MODE "aes" +#define ENCRYPTION_CHECKER_NAME ".ecryptfs_encrypted" + + +#define ECRYPTFS_VERSION_MAJOR 0x00 +#define ECRYPTFS_VERSION_MINOR 0x04 +#define ECRYPTFS_VERSION ((ECRYPTFS_VERSION_MAJOR << 8) | ECRYPTFS_VERSION_MINOR) + +#define ECRYPTFS_MAX_KEY_BYTES 64 +#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES 512 +#define ECRYPTFS_SIG_SIZE 8 +#define ECRYPTFS_SIG_SIZE_HEX (ECRYPTFS_SIG_SIZE*2) +#define ECRYPTFS_PASSWORD_SIG_SIZE ECRYPTFS_SIG_SIZE_HEX +#define ECRYPTFS_SALT_SIZE 8 +#define ECRYPTFS_MAX_KEY_MOD_NAME_BYTES 16 + +struct ecryptfs_session_key { +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_DECRYPT 0x00000001 +#define ECRYPTFS_USERSPACE_SHOULD_TRY_TO_ENCRYPT 0x00000002 +#define ECRYPTFS_CONTAINS_DECRYPTED_KEY 0x00000004 +#define ECRYPTFS_CONTAINS_ENCRYPTED_KEY 0x00000008 + int32_t flags; + int32_t encrypted_key_size; + int32_t decrypted_key_size; + uint8_t encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES]; + uint8_t decrypted_key[ECRYPTFS_MAX_KEY_BYTES]; +}; + +struct ecryptfs_password { + int32_t password_bytes; + int32_t hash_algo; + int32_t hash_iterations; + int32_t session_key_encryption_key_bytes; +#define ECRYPTFS_PERSISTENT_PASSWORD 0x01 +#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02 + uint32_t flags; + uint8_t session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; + uint8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + uint8_t salt[ECRYPTFS_SALT_SIZE]; +}; + +struct ecryptfs_private_key { + uint32_t key_size; + uint32_t data_len; + uint8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1]; + char key_mod_alias[ECRYPTFS_MAX_KEY_MOD_NAME_BYTES + 1]; + uint8_t data[]; +}; + +enum ecryptfs_token_types {ECRYPTFS_PASSWORD, ECRYPTFS_PRIVATE_KEY}; + +struct ecryptfs_auth_tok { + uint16_t version; + uint16_t token_type; +#define ECRYPTFS_ENCRYPT_ONLY 0x00000001 + uint32_t flags; + struct ecryptfs_session_key session_key; + uint8_t reserved[32]; + union { + struct ecryptfs_password password; + struct ecryptfs_private_key private_key; + } token; +} __attribute__((packed)); + +#if 0 +#define ECRYPTFS_IOCTL_GET_ATTRIBUTES _IOR('l', 0x10, unsigned int) +#define ECRYPTFS_WAS_ENCRYPTED 0x0080 +#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100 +#endif + +#define ECRYPTFS_AUTH_TOKEN_TYPE "user" + +namespace ode { + +namespace { + +unsigned long long getAvailableSpace(const std::string& mountPoint) +{ + struct statfs statbuf; + if (::statfs(mountPoint.c_str(), &statbuf)) { + throw runtime::Exception("Failed to access " + mountPoint); + } + + return (unsigned long long)statbuf.f_bfree * statbuf.f_bsize; +} + +bool wasEncrypted(const std::string &path) +{ +#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES + unsigned int attrs = 0; + bool ret = false; + int fd = 0; + + fd = ::open(path.c_str(), O_RDWR); + if (fd < 0) { + throw runtime::Exception("Failed to open " + path); + } + + if (::ioctl(fd, ECRYPTFS_IOCTL_GET_ATTRIBUTES, &attrs) == 0 && + (attrs & ECRYPTFS_WAS_ENCRYPTED)) { + ret = true; + } + ::close(fd); + + return ret; +#else + return true; +#endif +} + +unsigned long long getEncryptedSize(const runtime::File &file) { + unsigned long long originalSize = file.size(); + unsigned long long result = 0; + + if (originalSize % 4096) { + originalSize = (1 + originalSize / 4096) * 4096; + } + +#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES + if (wasEncrypted(file.getPath())) { + result = originalSize; + } else { +#endif + result = originalSize + 2 * 4096; +#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES + } +#endif + + //TODO : block size have to not hard-coded. + // If there is a better way, the followings have to be changed. + unsigned int blockSize = 4096; + if (result % blockSize) { + result = (1 + result / blockSize) * blockSize; + } + + return result; +} + +unsigned long long getDecryptedSize(const runtime::File &file) { + unsigned long long originalSize = file.size(); + unsigned long long result = originalSize; + + if (wasEncrypted(file.getPath())) { + if (originalSize > 2 * 4096) { + result = originalSize - 2 * 4096; + } + } + + result = originalSize; + + //TODO : block size have to not hard-coded. + // If there is a better way, the followings have to be changed. + unsigned int blockSize = 4096; + if (result % blockSize) { + result = (1 + result / blockSize) * blockSize; + } + + return result; +} + +bool isEnoughToCopyInPlace(const std::string& path, + const std::function getSizeFunc) +{ + unsigned long long availableSpace = getAvailableSpace(path); + + std::function check; + check = [&check, &getSizeFunc, availableSpace](const std::string &path) { + for (runtime::DirectoryIterator iter(path), end; + iter != end; ++iter) { + if (iter->isDirectory()) { + if (!check(iter->getPath())) { + return false; + } + } else if (getSizeFunc(*iter) > availableSpace) { + //TODO : have to consider changing file size + // when encrypt/decrypt + return false; + } + } + return true; + }; + + return check(path); +} + +void copyInPlace(const std::string& source, const std::string& destination, + const std::string& temp, + const std::function &isTarget, + const std::function &addProgress) +{ + for (runtime::DirectoryIterator iter(source), end; + iter != end; ++iter) { + if (iter->isDirectory()) { + copyInPlace(iter->getPath(), destination + "/" + iter->getName(), + temp, isTarget, addProgress); + } else if (isTarget(iter->getPath())) { + std::string tempFilePath = temp + "/" + iter->getName(); + std::string destFilePath = destination + "/" + iter->getName(); + + iter->copyTo(tempFilePath); + iter->remove(); + if (::rename(tempFilePath.c_str(), destFilePath.c_str()) != 0) { + throw runtime::Exception("Failed to rename from " + tempFilePath + " to " + destFilePath); + } + + addProgress(iter->size()); + } + } +} + +void ecryptfsMount(const std::string &source, const std::string &destination, const std::vector &key, unsigned int options) +{ + ecryptfs_auth_tok payload; + std::string mountOption; + + ::memset(&(payload), 0, sizeof(ecryptfs_auth_tok)); + + payload.version = ECRYPTFS_VERSION; + payload.token_type = ECRYPTFS_PASSWORD; + payload.token.password.flags = ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET; + payload.token.password.session_key_encryption_key_bytes = + (ECRYPTFS_MAX_KEY_BYTES > key.size())? key.size() : + ECRYPTFS_MAX_KEY_BYTES; + ::memcpy(payload.token.password.session_key_encryption_key, key.data(), + payload.token.password.session_key_encryption_key_bytes); + + std::stringstream signature; + signature<< std::hex << std::setfill('0') << std::setw(2); + for (unsigned int byte : key) { + signature << byte; + } + for (int i = key.size(); i < ECRYPTFS_SIG_SIZE; i++) { + signature << (unsigned int) 0; + } + ::memcpy((char *)payload.token.password.signature, + signature.str().c_str(), ECRYPTFS_PASSWORD_SIG_SIZE); + + if (KernelKeyRing::search(KEY_SPEC_USER_KEYRING, ECRYPTFS_AUTH_TOKEN_TYPE, + (char *)payload.token.password.signature, 0) < 0) { + if (KernelKeyRing::add(ECRYPTFS_AUTH_TOKEN_TYPE, + (char *)payload.token.password.signature, + (void *)&payload, sizeof(payload), + KEY_SPEC_USER_KEYRING) < 0) { + throw runtime::Exception("Unable to add token to keyring."); + } + } + + mountOption = "ecryptfs_passthrough" + ",ecryptfs_cipher=" CIPHER_MODE + ",ecryptfs_sig=" + std::string((char *)payload.token.password.signature) + + ",ecryptfs_key_bytes=" + std::to_string(payload.token.password.session_key_encryption_key_bytes); + + if (options & OPTION_EXCEPT_FOR_MEDIA_FILE) { + mountOption += ",ecryptfs_enable_filtering=" MEDIA_EXCLUSION_LIST; + } + + INFO("option = " + mountOption); + INFO("source = " + source); + INFO("dest = " + destination); + + if (::mount(source.c_str(), destination.c_str(), "ecryptfs", MS_NODEV, + mountOption.c_str()) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +void ecryptfsUmount(const std::string &destination) +{ + if (::umount(destination.c_str()) != 0) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + //TODO : remove key from keyring +} + +} // namespace + +EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest, const ProgressBar &prg) : + source(src), destination(dest), progress(prg) +{ +} + +EcryptfsEngine::~EcryptfsEngine() +{ +} + +void EcryptfsEngine::mount(const data &key, unsigned int options) +{ + ecryptfsMount(source, destination, key, options); +} + +void EcryptfsEngine::umount() +{ + ecryptfsUmount(destination); +} + +void EcryptfsEngine::encrypt(const data &key, unsigned int options) +{ + if (!isEnoughToCopyInPlace(source, getDecryptedSize)) { + throw runtime::Exception("No space to encryption"); + } + + progress.update(0); + + try { + ecryptfsMount(source, destination, key, options); + } catch (runtime::Exception &e) { + throw runtime::Exception("Failed to mount - " + std::string(e.what())); + } + + try { + unsigned long long totalSize = getAvailableSpace(source), current; + runtime::File tempDir(destination + "/" ENCRYPTION_CHECKER_NAME); + + tempDir.makeDirectory(); + if (!(options & OPTION_ONLY_NEW_FILE)) { + copyInPlace(destination, destination, tempDir.getPath(), + [](const std::string &file) { + return true; + }, + [¤t, &totalSize, this](unsigned long long size) { + current += size; + this->progress.update(current * 100 / totalSize); + }); + } + } catch (runtime::Exception &e) { + try { + ecryptfsUmount(destination); + } catch (runtime::Exception &e) {} + throw runtime::Exception("Failed to encrypt file - " + std::string(e.what())); + } + + sync(); + + progress.done(); +} + +void EcryptfsEngine::decrypt(const data &key, unsigned int options) +{ + if (!isEnoughToCopyInPlace(destination, getEncryptedSize)) { + throw runtime::Exception("No space to encryption"); + } + + progress.update(0); + + try { + unsigned long long totalSize = getAvailableSpace(source), current; + runtime::File tempDir(source + "/" ENCRYPTION_CHECKER_NAME); + runtime::File tempMountpoint(tempDir.getPath() + "/mount"); + + tempMountpoint.makeDirectory(); + ecryptfsMount(source, tempMountpoint.getPath(), key, 0); + + copyInPlace(tempMountpoint.getPath(), source, + tempDir.getPath(), wasEncrypted, + [¤t, &totalSize, this](unsigned long long size) { + current += size; + this->progress.update(current * 100 / totalSize); + }); + ecryptfsUmount(tempMountpoint.getPath()); + + tempDir.remove(true); + } catch (runtime::Exception &e) { + throw runtime::Exception("Failed to decrypt file - " + std::string(e.what())); + } + + sync(); + + progress.done(); +} + +bool EcryptfsEngine::isKeyMetaSet() +{ + return FileFooter::exist(source); +} + +const EcryptfsEngine::data EcryptfsEngine::getKeyMeta() +{ + return FileFooter::read(source); +} + +void EcryptfsEngine::setKeyMeta(const data &meta) +{ + FileFooter::write(source, meta); +} + +void EcryptfsEngine::clearKeyMeta() +{ + FileFooter::clear(source); +} + +unsigned int EcryptfsEngine::getSupportedOptions() +{ + return SUPPORTED_OPTIONS; +} + +} // namespace ode diff --git a/server/engine/encryption/ecryptfs-engine.h b/server/engine/encryption/ecryptfs-engine.h new file mode 100644 index 0000000..983ed6d --- /dev/null +++ b/server/engine/encryption/ecryptfs-engine.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ + +#ifndef __ECRYPTFS_ENGINE_H__ +#define __ECRYPTFS_ENGINE_H__ + +#include +#include + +#include "progress-bar.h" + +namespace ode { + +class EcryptfsEngine final { +public: + EcryptfsEngine(const std::string& src, const std::string& dest, const ProgressBar& prgs); + EcryptfsEngine(const EcryptfsEngine&) = delete; + EcryptfsEngine(EcryptfsEngine&&) = delete; + ~EcryptfsEngine(); + + EcryptfsEngine& operator=(const EcryptfsEngine&) = delete; + EcryptfsEngine& operator=(EcryptfsEngine&&) = delete; + + const std::string& getSource() + { + return source; + } + + const std::string& getDestination() + { + return destination; + } + + typedef std::vector data; + + void mount(const data& key, unsigned int); + void umount(); + + void encrypt(const data& key, unsigned int); + void decrypt(const data& key, unsigned int); + + bool isKeyMetaSet(); + const data getKeyMeta(); + void setKeyMeta(const data &data); + void clearKeyMeta(); + + unsigned int getSupportedOptions(); + +private: + std::string source, destination; + ProgressBar progress; +}; + +} // namespace ode +#endif // __ECRYPTFS_ENGINE_H__ + diff --git a/server/engine/encryption/ext4-engine.cpp b/server/engine/encryption/ext4-engine.cpp new file mode 100644 index 0000000..0abd19c --- /dev/null +++ b/server/engine/encryption/ext4-engine.cpp @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../../file-footer.h" +#include "../../key-manager/key-generator.h" + +#include "ext4-engine.h" + +namespace ode { + +#define EXT4_MAX_KEY_SIZE 64 +#define EXT4_KEY_DESCRIPTOR_SIZE 8 +#define EXT4_KEY_DESC_PREFIX_SIZE 5 +#define EXT4_KEY_REF_STR_BUF_SIZE ((EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1) +#define EXT4_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct ext4_encryption_policy) +#define EXT4_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct ext4_encryption_policy) + +/* special process keyring shortcut IDs */ +#define KEY_SPEC_THREAD_KEYRING -1 +#define KEY_SPEC_PROCESS_KEYRING -2 +#define KEY_SPEC_SESSION_KEYRING -3 +#define KEY_SPEC_USER_KEYRING -4 +#define KEY_SPEC_USER_SESSION_KEYRING -5 +#define KEY_SPEC_GROUP_KEYRING -6 + +#define KEYCTL_GET_KEYRING_ID 0 +#define KEYCTL_SEARCH 10 + + /* Encryption algorithms */ +#define EXT4_ENCRYPTION_MODE_INVALID 0 +#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 +#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2 +#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3 +#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 + +#define SMACK_LABEL_LEN_MAX 255 +struct ext4_encryption_policy { + char version; + char contents_encryption_mode; + char filenames_encryption_mode; + char flags; + char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; +}__attribute__((__packed__)); + +struct ext4_encryption_key { + unsigned int mode; + char raw[EXT4_MAX_KEY_SIZE]; + unsigned int size; +} __attribute__((__packed__)); + +/* for now, It only suits for "/opt/usr" */ +namespace { + std::string secondMountPoint("/opt/usr_encrypt"); + std::string bindMountPoint("/opt/usr_encrypt/secure"); + std::string ext4KeyringType("logon"); + std::string smackAccessLabel("security.SMACK64"); + long long totalSize = 0; + long long curSize = 0; +} + +const Ext4Engine::data generateKeyDesc(const ode::Ext4Engine::data& key) +{ + Ext4Engine::data keyRef1 = ode::KeyGenerator::SHA512(key); + Ext4Engine::data keyRef2 = ode::KeyGenerator::SHA512(keyRef1); + Ext4Engine::data ret(keyRef2.begin(), keyRef2.begin()+EXT4_KEY_DESCRIPTOR_SIZE); + + return ret; +} + +const Ext4Engine::data generateKeyRefStr(const Ext4Engine::data& key) +{ + Ext4Engine::data ret(EXT4_KEY_REF_STR_BUF_SIZE); + Ext4Engine::data keyDesc = generateKeyDesc(key); + + int i, a; + unsigned char nibble; + for (i=0, a=0; i < EXT4_KEY_DESCRIPTOR_SIZE; i++, a+=2) { + nibble = (keyDesc[i] >> 4) & 0xf; + if (nibble <= 9) ret[a] = '0' + nibble; + else ret[a] = 'a' + nibble - 10; + nibble = keyDesc[i] & 0xf; + if (nibble <= 9) ret[a+1] = '0' + nibble; + else ret[a+1] = 'a' + nibble - 10; + } + + ret[a] = '\0'; + + return ret; +} + +void addKeyToKeyring(const Ext4Engine::data& key) +{ + struct ext4_encryption_key ext4Key; + Ext4Engine::data keyRefStr(EXT4_KEY_REF_STR_BUF_SIZE); + keyRefStr = generateKeyRefStr(key); + std::string keyRef(keyRefStr.begin(), keyRefStr.end()), keyRefFull; + int keyringId, ret; + + keyringId = ::syscall(__NR_keyctl, KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 0); + if (keyringId == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + keyRefFull = "ext4:" + keyRef; + ret = ::syscall(__NR_keyctl, KEYCTL_SEARCH, keyringId, ext4KeyringType.c_str(), keyRefFull.c_str(), 0); + if (ret != -1) { + INFO("Key with descriptor already exist"); + return; + } + ext4Key.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; + ::memcpy(ext4Key.raw, key.data(), EXT4_MAX_KEY_SIZE); + std::string ext4KeyRaw = ext4Key.raw; + ext4Key.size = EXT4_MAX_KEY_SIZE; + + ret = ::syscall(__NR_add_key, ext4KeyringType.c_str(), keyRefFull.c_str(), + (void *)&ext4Key, sizeof(ext4Key), keyringId); + + if (ret == -1) { + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } +} + +static void copySmackLabel(std::string& srcPath, std::string& destPath) +{ + Ext4Engine::data smackLabel(SMACK_LABEL_LEN_MAX + 1); + + if (::getxattr(srcPath.c_str(), smackAccessLabel.c_str(), (unsigned char*)smackLabel.data(), SMACK_LABEL_LEN_MAX + 1) == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + if (::setxattr(destPath.c_str(), smackAccessLabel.c_str(), smackLabel.data(), smackLabel.size(), 0) == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +int Ext4Engine::copy(std::string& src, std::string& dest) +{ + int readFd, writeFd, ret; + struct stat st; + + ret = ::stat(src.c_str(), &st); + if (ret != 0) { + throw runtime::Exception(src + runtime::GetSystemErrorMessage()); + } + + readFd = ::open(src.c_str(), O_RDONLY); + if (readFd < 0) + throw runtime::Exception(src + runtime::GetSystemErrorMessage()); + + writeFd = ::open(dest.c_str(), O_WRONLY | O_CREAT, st.st_mode); + if (writeFd < 0) + throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); + copySmackLabel(src, dest); + if (::chown(dest.c_str(), st.st_uid, st.st_gid) == -1) + throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); + if (::sendfile(writeFd, readFd, 0, st.st_size) == -1) + return 1; + + /* progress bar update */ + curSize += st.st_size; + INFO("curSize is " + std::to_string(curSize)); + progressBar.update(curSize, totalSize, 1); + + if (::fsync(writeFd) != 0) + throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); + + if (::posix_fadvise(writeFd, 0, st.st_size, POSIX_FADV_DONTNEED) < 0) + throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); + + ::close(readFd); + ::close(writeFd); + return 0; +} + +static void preScanDir(std::string& dir) +{ + DIR* d; + + d = ::opendir(dir.c_str()); + + if (!d) + throw runtime::Exception(dir + runtime::GetSystemErrorMessage()); + + while(1) { + struct dirent* entry; + std::string dName; + + entry = ::readdir(d); + if (!entry) { + break; + } + dName = entry->d_name; + if (!(entry->d_type & DT_DIR)) { + std::string file = dir + "/" + dName; + struct stat st; + int statRet; + + statRet = ::stat(file.c_str(), &st); + if (statRet != 0) + throw runtime::Exception(file + runtime::GetSystemErrorMessage()); + INFO("[preListDir] " + file + " totalSize = " + std::to_string(totalSize) + " " +std::to_string(st.st_size)); + totalSize += st.st_size; + } + + if (entry->d_type & DT_DIR) { + if (dName.compare(".") != 0 && dName.compare("..") != 0) { + std::string path; + + path = dir + "/" + dName; + + + if (path.size() >= PATH_MAX) + throw runtime::Exception(path + " :path length has got too long"); + + preScanDir(path); + } + } + } + + if (::closedir(d)) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + +} + +void Ext4Engine::listDir(std::string& source, std::string& dest, bool excludeFlag) +{ + DIR* d; + + if (excludeFlag && source.compare(0, bindMountPoint.size(), bindMountPoint) == 0) + return; + + d = ::opendir(source.c_str()); + + if (!d) + throw runtime::Exception(source + runtime::GetSystemErrorMessage()); + + while(1) { + struct dirent* entry; + std::string dName; + + entry = ::readdir(d); + if (!entry) { + break; + } + dName = entry->d_name; + if (!(entry->d_type & DT_DIR)) { + std::string srcFile = source + "/" + dName; + std::string destFile = dest + "/" +dName; + copy(srcFile, destFile); + + if (::remove(srcFile.c_str()) != 0) + ERROR("file remove failed"); + } + + if (entry->d_type & DT_DIR) { + if (dName.compare(".") != 0 && dName.compare("..") != 0) { + std::string pathS, pathD; + + pathS = source + "/" + dName; + pathD = dest + "/" +dName; + + /* make new directory */ + int mkdirRet, statRet; + struct stat st; + statRet = ::stat(pathS.c_str(), &st); + if (statRet != 0) + throw runtime::Exception(pathS + runtime::GetSystemErrorMessage()); + + if (excludeFlag) { + if (pathS.compare(bindMountPoint) != 0) { + mkdirRet = ::mkdir(pathD.c_str(), st.st_mode); + if (mkdirRet != 0) + throw runtime::Exception(pathS + runtime::GetSystemErrorMessage()); + copySmackLabel(pathS, pathD); + if (::chown(pathD.c_str(), st.st_uid, st.st_gid) == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + } else { + mkdirRet = ::mkdir(pathD.c_str(), st.st_mode); + if (mkdirRet != 0) + throw runtime::Exception(pathD + runtime::GetSystemErrorMessage()); + copySmackLabel(pathS, pathD); + if (::chown(pathD.c_str(), st.st_uid, st.st_gid) == -1) + throw runtime::Exception(pathD + runtime::GetSystemErrorMessage()); + } + if (pathS.size() >= PATH_MAX) + throw runtime::Exception(pathS + " :path length has got too long"); + + listDir(pathS, pathD, excludeFlag); + } + } + } + + if (::closedir(d)) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + if (source.compare(secondMountPoint) != 0) { + if (::remove(source.c_str()) != 0) + throw runtime::Exception(source + runtime::GetSystemErrorMessage()); + } +} + +static int intLog2(int arg) +{ + int l = 0; + + arg >>= 1; + while(arg) { + l++; + arg >>= 1; + } + + return l; +} + +static void setPolicy(const std::string& source, const Ext4Engine::data& key) +{ + struct ext4_encryption_policy policy; + int pad = 4; + int fd, rc; + Ext4Engine::data descriptor(EXT4_KEY_DESCRIPTOR_SIZE); + + descriptor = generateKeyDesc(key); + std::string descStr(descriptor.begin(), descriptor.end()); + + fd = ::open(source.c_str(), O_DIRECTORY); + if (fd == -1) + throw runtime::Exception("invalid path"); + + policy.version = 0; + policy.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; + policy.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; + policy.flags = intLog2(pad >> 2); + ::memcpy(policy.master_key_descriptor, descriptor.data(), EXT4_KEY_DESCRIPTOR_SIZE); + + rc = ::ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &policy); + ::close(fd); + + if (rc) + throw runtime::Exception("set policy failed :" + runtime::GetSystemErrorMessage()); +} + +static bool prepareEncryptDir(std::string& sourceName, std::string& destName) +{ + struct stat dirStat; + ::stat(destName.c_str(), &dirStat); + + if (::mkdir(secondMountPoint.c_str(), dirStat.st_mode) != 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + copySmackLabel(destName, secondMountPoint); + if (::chown(secondMountPoint.c_str(), dirStat.st_uid, dirStat.st_gid) == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + if (::mount(sourceName.c_str(), secondMountPoint.c_str(), "ext4", 0, 0) < 0) { + ::remove(secondMountPoint.c_str()); + throw runtime::Exception(runtime::GetSystemErrorMessage()); + } + + if (::mkdir(bindMountPoint.c_str(), dirStat.st_mode) != 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + copySmackLabel(secondMountPoint, bindMountPoint); + if (::chown(bindMountPoint.c_str(), dirStat.st_uid, dirStat.st_gid) == -1) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + return true; +} + +static bool getPolicy(const std::string& dirName) +{ + struct ext4_encryption_policy policy; + int fd, rc; + + fd = ::open(dirName.c_str(), O_DIRECTORY); + if (fd == -1) + return false; + + rc = ::ioctl(fd, EXT4_IOC_GET_ENCRYPTION_POLICY, &policy); + close(fd); + if (rc) { + ERROR("ioctl error"); + return false; + } + return true; +} + +Ext4Engine::Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar) : + source(src), destination(dest), progressBar(prgsBar) +{ +} + +Ext4Engine::~Ext4Engine() +{ +} + +void Ext4Engine::mount(const Ext4Engine::data& key, unsigned int options) +{ + addKey(key); + /* mount : /dev/mmcblk0p21 /opt/usr_encrypt */ + if (::mount(source.c_str(), secondMountPoint.c_str(), "ext4", 0, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + /* bind mount :/opt/usr_encrypt/secure /opt/usr */ + if (::mount(bindMountPoint.c_str(), destination.c_str(), "ext4", MS_BIND, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +void Ext4Engine::umount() +{ + /* for decrypt, umount /opt/usr */ + if (::umount(destination.c_str())) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +void Ext4Engine::addKey(const Ext4Engine::data& key) +{ + addKeyToKeyring(key); +} + +void Ext4Engine::encrypt(const Ext4Engine::data& key, unsigned int options) +{ + std::string sourceDir = getSource(); + std::string destDir = getDestination(); + bool copyFlag = false; + + if (!(copyFlag = prepareEncryptDir(sourceDir, destDir))) + throw runtime::Exception("prepareEncryptDir failed"); + + preScanDir(secondMountPoint); + /* key add to keyring */ + addKeyToKeyring(key); + /* set policy */ + setPolicy(bindMountPoint, key); + + if (copyFlag) + listDir(secondMountPoint, bindMountPoint, true); + INFO("[ext4 encrypt] copy done"); + + progressBar.done(); + if (::mount(bindMountPoint.c_str(), destDir.c_str(), "ext4", MS_BIND, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); +} + +void Ext4Engine::decrypt(const Ext4Engine::data& key, unsigned int options) +{ + std::string destDir = getDestination(); + + if (!getPolicy(bindMountPoint)) + throw runtime::Exception("directory isn't encrypted"); + addKeyToKeyring(key); + + preScanDir(bindMountPoint); + + listDir(bindMountPoint, secondMountPoint, false); + INFO("[ext4 decrypt] copy done"); + progressBar.done(); + + if (::open(bindMountPoint.c_str(), O_RDONLY) != -1) + ::remove(bindMountPoint.c_str()); + + /* umount /opt/usr_encrypt */ + if (::umount(secondMountPoint.c_str())) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + /* mount /dev/mmcblk0p21 /opt/usr */ + if (::mount(source.c_str(), destination.c_str(), "ext4", 0, 0) < 0) + throw runtime::Exception(runtime::GetSystemErrorMessage()); + + if (::open(secondMountPoint.c_str(), O_RDONLY) != -1) + ::remove(secondMountPoint.c_str()); +} + +bool Ext4Engine::isKeyMetaSet() +{ + return FileFooter::exist(source); +} + +const Ext4Engine::data Ext4Engine::getKeyMeta() +{ + return FileFooter::read(source); +} + +void Ext4Engine::setKeyMeta(const data &data) +{ + FileFooter::write(source, data); +} + +void Ext4Engine::clearKeyMeta() +{ + FileFooter::clear(source); +} + +unsigned int Ext4Engine::getSupportedOptions() +{ + return 0; +} + +} // namespace ode diff --git a/server/engine/encryption/ext4-engine.h b/server/engine/encryption/ext4-engine.h new file mode 100644 index 0000000..eb233f4 --- /dev/null +++ b/server/engine/encryption/ext4-engine.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ + +#ifndef __EXT4_ENGINE_H__ +#define __EXT4_ENGINE_H__ + +#include +#include + +#include "progress-bar.h" + +namespace ode { + +class Ext4Engine final { +public: + Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar); + Ext4Engine(const Ext4Engine&) = delete; + Ext4Engine(Ext4Engine&&) = delete; + ~Ext4Engine(); + + Ext4Engine& operator=(const Ext4Engine&) = delete; + Ext4Engine& operator=(Ext4Engine&&) = delete; + + const std::string& getSource() + { + return source; + } + + const std::string& getDestination() + { + return destination; + } + + typedef std::vector data; + + void mount(const data &key, unsigned int options); + void umount(); + + void addKey(const data &key); + void encrypt(const data &key, unsigned int options); + void decrypt(const data &key, unsigned int options); + + bool isKeyMetaSet(); + const data getKeyMeta(); + void setKeyMeta(const data &data); + void clearKeyMeta(); + + unsigned int getSupportedOptions(); + + int copy(std::string& src, std::string& dest); + void listDir(std::string& source, std::string& dest, bool excludeFlag); + +private: + std::string source, destination; + ProgressBar progressBar; +}; + +} // namespace ode +#endif // __EXT4_ENGINE_H__ diff --git a/server/engine/erase/mmc-engine.cpp b/server/engine/erase/mmc-engine.cpp new file mode 100644 index 0000000..f9d84c6 --- /dev/null +++ b/server/engine/erase/mmc-engine.cpp @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "ext4-tool.h" +#include "block-device.h" +#include "mmc-engine.h" + +namespace ode { + +namespace { + +int getTotalFileCount(const std::string &path) +{ + int total = 0; + runtime::DirectoryIterator iter(path), end; + + while (iter != end) { + std::string next = path + "/" + iter->getName(); + runtime::File file(next); + if (!file.exists()) { + return -1; + } + + if (file.isFile()) { + total++; + } else if (file.isDirectory()) { + int subTotal = getTotalFileCount(next); + if (subTotal != -1) + total += subTotal; + } + ++iter; + } + return total; +} + +} /* namespace */ + +MMCEraseEngine::MMCEraseEngine(const ProgressBar &prgsBar) : + progressBar(prgsBar) +{ +} + +MMCEraseEngine::~MMCEraseEngine() +{ +} + +int MMCEraseEngine::cleanDevice(const std::string &path) +{ + runtime::File file(path, O_WRONLY); + if (!file.exists() || !file.isDevice()) { + throw runtime::Exception("Target doesn't exist"); + } + + BlockDevice blockDevice(path); + unsigned totalBlock, blockSize; + + Ext4Tool ext4Tool(path); + totalBlock = ext4Tool.getTotalBlockCount(); + blockSize = (unsigned int)blockDevice.getSize(); + + for (unsigned int i = 0; i < totalBlock; i++) { + if (!ext4Tool.isUsedBlock(i)) { + Block block(i * blockSize, blockSize); + blockDevice.discard(block); + } + progressBar.update(i, totalBlock, 1); + } + + progressBar.done(); + return 0; +} + +int MMCEraseEngine::eraseDevice(const std::string &path) +{ + runtime::File file(path, O_WRONLY); + if (!file.exists()) { + throw runtime::Exception("Target doesn't exist"); + } + + BlockDevice blockDevice(path); + Ext4Tool ext4Tool(blockDevice.getName()); + + unsigned int totalBlock = ext4Tool.getTotalBlockCount(); + unsigned int blockSize = (unsigned int)blockDevice.getSize(); + + for (unsigned int i = 0; i < totalBlock; i++) { + Block block(i * blockSize, blockSize); + blockDevice.discard(block); + progressBar.update(i, totalBlock, 1); + } + + progressBar.done(); + return 0; +} + +int MMCEraseEngine::eraseFile(const std::string &path) +{ + int ret = 0, fd = 0; + int extentBlockCount = 0; + char buf[4096] = ""; + struct fiemap *fmap = (struct fiemap *)buf; + struct fiemap_extent *fm_ext = NULL; + int count = (sizeof(buf) - sizeof(*fmap)) / sizeof(struct fiemap_extent); + + ::memset(fmap, 0, sizeof(struct fiemap)); + + fd = ::open(path.c_str(), O_RDONLY); + if (fd < 0) { + throw runtime::Exception("cannot open the file"); + } + + fmap->fm_length = ~0ULL; + fmap->fm_flags = 0; + fmap->fm_extent_count = count; + + ret = ::ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fmap); + if (ret < 0) { + ::close(fd); + throw runtime::Exception("failed to get a fiemap"); + } + + ::close(fd); + + fm_ext = &fmap->fm_extents[0]; + extentBlockCount = (int)fmap->fm_mapped_extents; + + BlockDevice blockDevice(path); + for (int i = 0; i < extentBlockCount; i++) { + Block block(fm_ext[i].fe_physical, fm_ext[i].fe_length); + ret = blockDevice.secDiscard(block); + if (ret < 0) { + throw runtime::Exception("failed to erase the device"); + } + } + + if (totalFileCount == 1) { + progressBar.update(1, extentBlockCount, 1); + } + + return ret; +} + +int MMCEraseEngine::eraseDirectory(const std::string &path) +{ + runtime::DirectoryIterator iter(path), end; + + while (iter != end) { + std::string next = path + "/" + iter->getName(); + runtime::File file(next); + if (!file.exists()) { + throw runtime::Exception("Target doesn't exist"); + } + + if (file.isFile()) { + eraseFile(next); + ::remove(next.c_str()); + erasedFileCount++; + progressBar.update(erasedFileCount, totalFileCount, 1); + } else if (file.isDirectory()) { + eraseDirectory(next); + } + ++iter; + } + + eraseFile(path); + ::rmdir(path.c_str()); + return 0; +} + +int MMCEraseEngine::eraseFiles(const std::string &path) +{ + runtime::File file(path); + + if (!file.exists()) { + throw runtime::Exception("Target doesn't exist"); + } + + if (file.isFile()) { + totalFileCount = 1; + eraseFile(path); + ::remove(path.c_str()); + } else { + totalFileCount = getTotalFileCount(path); + erasedFileCount = 0; + eraseDirectory(path); + } + + progressBar.done(); + return 0; +} + +} /* namespace ode */ diff --git a/server/engine/erase/mmc-engine.h b/server/engine/erase/mmc-engine.h new file mode 100644 index 0000000..31990a0 --- /dev/null +++ b/server/engine/erase/mmc-engine.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 + */ + +#ifndef __MMC_ERASE_ENGINE_H__ +#define __MMC_ERASE_ENGINE_H__ + +#include "progress-bar.h" + +namespace ode { + +class MMCEraseEngine final { +public: + MMCEraseEngine(const ProgressBar &prgsBar); + MMCEraseEngine(const MMCEraseEngine &) = delete; + MMCEraseEngine(MMCEraseEngine &&) = delete; + ~MMCEraseEngine(); + + MMCEraseEngine &operator=(const MMCEraseEngine &) = delete; + MMCEraseEngine &operator=(MMCEraseEngine &&) = delete; + + int eraseDevice(const std::string &path); + int cleanDevice(const std::string &path); + int eraseFiles(const std::string &path); + +private: + int eraseFile(const std::string &path); + int eraseDirectory(const std::string &path); +private: + ProgressBar progressBar; + int totalFileCount; + int erasedFileCount; +}; + +} /* namespace ode */ + +#endif /*__MMC_ERASE_ENGINE_H__*/ diff --git a/server/engine/ext4-engine.cpp b/server/engine/ext4-engine.cpp deleted file mode 100644 index e04801a..0000000 --- a/server/engine/ext4-engine.cpp +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../file-footer.h" -#include "../key-manager/key-generator.h" - -#include "ext4-engine.h" - -namespace ode { - -#define EXT4_MAX_KEY_SIZE 64 -#define EXT4_KEY_DESCRIPTOR_SIZE 8 -#define EXT4_KEY_DESC_PREFIX_SIZE 5 -#define EXT4_KEY_REF_STR_BUF_SIZE ((EXT4_KEY_DESCRIPTOR_SIZE * 2) + 1) -#define EXT4_IOC_SET_ENCRYPTION_POLICY _IOR('f', 19, struct ext4_encryption_policy) -#define EXT4_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct ext4_encryption_policy) - -/* special process keyring shortcut IDs */ -#define KEY_SPEC_THREAD_KEYRING -1 -#define KEY_SPEC_PROCESS_KEYRING -2 -#define KEY_SPEC_SESSION_KEYRING -3 -#define KEY_SPEC_USER_KEYRING -4 -#define KEY_SPEC_USER_SESSION_KEYRING -5 -#define KEY_SPEC_GROUP_KEYRING -6 - -#define KEYCTL_GET_KEYRING_ID 0 -#define KEYCTL_SEARCH 10 - - /* Encryption algorithms */ -#define EXT4_ENCRYPTION_MODE_INVALID 0 -#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 -#define EXT4_ENCRYPTION_MODE_AES_256_GCM 2 -#define EXT4_ENCRYPTION_MODE_AES_256_CBC 3 -#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 - -#define SMACK_LABEL_LEN_MAX 255 -struct ext4_encryption_policy { - char version; - char contents_encryption_mode; - char filenames_encryption_mode; - char flags; - char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; -}__attribute__((__packed__)); - -struct ext4_encryption_key { - unsigned int mode; - char raw[EXT4_MAX_KEY_SIZE]; - unsigned int size; -} __attribute__((__packed__)); - -/* for now, It only suits for "/opt/usr" */ -namespace { - std::string secondMountPoint("/opt/usr_encrypt"); - std::string bindMountPoint("/opt/usr_encrypt/secure"); - std::string ext4KeyringType("logon"); - std::string smackAccessLabel("security.SMACK64"); - long long totalSize = 0; - long long curSize = 0; -} - -const Ext4Engine::data generateKeyDesc(const ode::Ext4Engine::data& key) -{ - Ext4Engine::data keyRef1 = ode::KeyGenerator::SHA512(key); - Ext4Engine::data keyRef2 = ode::KeyGenerator::SHA512(keyRef1); - Ext4Engine::data ret(keyRef2.begin(), keyRef2.begin()+EXT4_KEY_DESCRIPTOR_SIZE); - - return ret; -} - -const Ext4Engine::data generateKeyRefStr(const Ext4Engine::data& key) -{ - Ext4Engine::data ret(EXT4_KEY_REF_STR_BUF_SIZE); - Ext4Engine::data keyDesc = generateKeyDesc(key); - - int i, a; - unsigned char nibble; - for (i=0, a=0; i < EXT4_KEY_DESCRIPTOR_SIZE; i++, a+=2) { - nibble = (keyDesc[i] >> 4) & 0xf; - if (nibble <= 9) ret[a] = '0' + nibble; - else ret[a] = 'a' + nibble - 10; - nibble = keyDesc[i] & 0xf; - if (nibble <= 9) ret[a+1] = '0' + nibble; - else ret[a+1] = 'a' + nibble - 10; - } - - ret[a] = '\0'; - - return ret; -} - -void addKeyToKeyring(const Ext4Engine::data& key) -{ - struct ext4_encryption_key ext4Key; - Ext4Engine::data keyRefStr(EXT4_KEY_REF_STR_BUF_SIZE); - keyRefStr = generateKeyRefStr(key); - std::string keyRef(keyRefStr.begin(), keyRefStr.end()), keyRefFull; - int keyringId, ret; - - keyringId = ::syscall(__NR_keyctl, KEYCTL_GET_KEYRING_ID, KEY_SPEC_SESSION_KEYRING, 0); - if (keyringId == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - - keyRefFull = "ext4:" + keyRef; - ret = ::syscall(__NR_keyctl, KEYCTL_SEARCH, keyringId, ext4KeyringType.c_str(), keyRefFull.c_str(), 0); - if (ret != -1) { - INFO("Key with descriptor already exist"); - return; - } - ext4Key.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; - ::memcpy(ext4Key.raw, key.data(), EXT4_MAX_KEY_SIZE); - std::string ext4KeyRaw = ext4Key.raw; - ext4Key.size = EXT4_MAX_KEY_SIZE; - - ret = ::syscall(__NR_add_key, ext4KeyringType.c_str(), keyRefFull.c_str(), - (void *)&ext4Key, sizeof(ext4Key), keyringId); - - if (ret == -1) { - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } -} - -static void copySmackLabel(std::string& srcPath, std::string& destPath) -{ - Ext4Engine::data smackLabel(SMACK_LABEL_LEN_MAX + 1); - - if (::getxattr(srcPath.c_str(), smackAccessLabel.c_str(), (unsigned char*)smackLabel.data(), SMACK_LABEL_LEN_MAX + 1) == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - - if (::setxattr(destPath.c_str(), smackAccessLabel.c_str(), smackLabel.data(), smackLabel.size(), 0) == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); -} - -int Ext4Engine::copy(std::string& src, std::string& dest) -{ - int readFd, writeFd, ret; - struct stat st; - - ret = ::stat(src.c_str(), &st); - if (ret != 0) { - throw runtime::Exception(src + runtime::GetSystemErrorMessage()); - } - - readFd = ::open(src.c_str(), O_RDONLY); - if (readFd < 0) - throw runtime::Exception(src + runtime::GetSystemErrorMessage()); - - writeFd = ::open(dest.c_str(), O_WRONLY | O_CREAT, st.st_mode); - if (writeFd < 0) - throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); - copySmackLabel(src, dest); - if (::chown(dest.c_str(), st.st_uid, st.st_gid) == -1) - throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); - if (::sendfile(writeFd, readFd, 0, st.st_size) == -1) - return 1; - - /* progress bar update */ - curSize += st.st_size; - INFO("curSize is " + std::to_string(curSize)); - progressBar.update(curSize, totalSize, 1); - - if (::fsync(writeFd) != 0) - throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); - - if (::posix_fadvise(writeFd, 0, st.st_size, POSIX_FADV_DONTNEED) < 0) - throw runtime::Exception(dest + runtime::GetSystemErrorMessage()); - - ::close(readFd); - ::close(writeFd); - return 0; -} - -static void preScanDir(std::string& dir) -{ - DIR* d; - - d = ::opendir(dir.c_str()); - - if (!d) - throw runtime::Exception(dir + runtime::GetSystemErrorMessage()); - - while(1) { - struct dirent* entry; - std::string dName; - - entry = ::readdir(d); - if (!entry) { - break; - } - dName = entry->d_name; - if (!(entry->d_type & DT_DIR)) { - std::string file = dir + "/" + dName; - struct stat st; - int statRet; - - statRet = ::stat(file.c_str(), &st); - if (statRet != 0) - throw runtime::Exception(file + runtime::GetSystemErrorMessage()); - INFO("[preListDir] " + file + " totalSize = " + std::to_string(totalSize) + " " +std::to_string(st.st_size)); - totalSize += st.st_size; - } - - if (entry->d_type & DT_DIR) { - if (dName.compare(".") != 0 && dName.compare("..") != 0) { - std::string path; - - path = dir + "/" + dName; - - - if (path.size() >= PATH_MAX) - throw runtime::Exception(path + " :path length has got too long"); - - preScanDir(path); - } - } - } - - if (::closedir(d)) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - -} - -void Ext4Engine::listDir(std::string& source, std::string& dest, bool excludeFlag) -{ - DIR* d; - - if (excludeFlag && source.compare(0, bindMountPoint.size(), bindMountPoint) == 0) - return; - - d = ::opendir(source.c_str()); - - if (!d) - throw runtime::Exception(source + runtime::GetSystemErrorMessage()); - - while(1) { - struct dirent* entry; - std::string dName; - - entry = ::readdir(d); - if (!entry) { - break; - } - dName = entry->d_name; - if (!(entry->d_type & DT_DIR)) { - std::string srcFile = source + "/" + dName; - std::string destFile = dest + "/" +dName; - copy(srcFile, destFile); - - if (::remove(srcFile.c_str()) != 0) - ERROR("file remove failed"); - } - - if (entry->d_type & DT_DIR) { - if (dName.compare(".") != 0 && dName.compare("..") != 0) { - std::string pathS, pathD; - - pathS = source + "/" + dName; - pathD = dest + "/" +dName; - - /* make new directory */ - int mkdirRet, statRet; - struct stat st; - statRet = ::stat(pathS.c_str(), &st); - if (statRet != 0) - throw runtime::Exception(pathS + runtime::GetSystemErrorMessage()); - - if (excludeFlag) { - if (pathS.compare(bindMountPoint) != 0) { - mkdirRet = ::mkdir(pathD.c_str(), st.st_mode); - if (mkdirRet != 0) - throw runtime::Exception(pathS + runtime::GetSystemErrorMessage()); - copySmackLabel(pathS, pathD); - if (::chown(pathD.c_str(), st.st_uid, st.st_gid) == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } - } else { - mkdirRet = ::mkdir(pathD.c_str(), st.st_mode); - if (mkdirRet != 0) - throw runtime::Exception(pathD + runtime::GetSystemErrorMessage()); - copySmackLabel(pathS, pathD); - if (::chown(pathD.c_str(), st.st_uid, st.st_gid) == -1) - throw runtime::Exception(pathD + runtime::GetSystemErrorMessage()); - } - if (pathS.size() >= PATH_MAX) - throw runtime::Exception(pathS + " :path length has got too long"); - - listDir(pathS, pathD, excludeFlag); - } - } - } - - if (::closedir(d)) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - - if (source.compare(secondMountPoint) != 0) { - if (::remove(source.c_str()) != 0) - throw runtime::Exception(source + runtime::GetSystemErrorMessage()); - } -} - -static int intLog2(int arg) -{ - int l = 0; - - arg >>= 1; - while(arg) { - l++; - arg >>= 1; - } - - return l; -} - -static void setPolicy(const std::string& source, const Ext4Engine::data& key) -{ - struct ext4_encryption_policy policy; - int pad = 4; - int fd, rc; - Ext4Engine::data descriptor(EXT4_KEY_DESCRIPTOR_SIZE); - - descriptor = generateKeyDesc(key); - std::string descStr(descriptor.begin(), descriptor.end()); - - fd = ::open(source.c_str(), O_DIRECTORY); - if (fd == -1) - throw runtime::Exception("invalid path"); - - policy.version = 0; - policy.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; - policy.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; - policy.flags = intLog2(pad >> 2); - ::memcpy(policy.master_key_descriptor, descriptor.data(), EXT4_KEY_DESCRIPTOR_SIZE); - - rc = ::ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &policy); - ::close(fd); - - if (rc) - throw runtime::Exception("set policy failed :" + runtime::GetSystemErrorMessage()); -} - -static bool prepareEncryptDir(std::string& sourceName, std::string& destName) -{ - struct stat dirStat; - ::stat(destName.c_str(), &dirStat); - - if (::mkdir(secondMountPoint.c_str(), dirStat.st_mode) != 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - copySmackLabel(destName, secondMountPoint); - if (::chown(secondMountPoint.c_str(), dirStat.st_uid, dirStat.st_gid) == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - if (::mount(sourceName.c_str(), secondMountPoint.c_str(), "ext4", 0, 0) < 0) { - ::remove(secondMountPoint.c_str()); - throw runtime::Exception(runtime::GetSystemErrorMessage()); - } - - if (::mkdir(bindMountPoint.c_str(), dirStat.st_mode) != 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - copySmackLabel(secondMountPoint, bindMountPoint); - if (::chown(bindMountPoint.c_str(), dirStat.st_uid, dirStat.st_gid) == -1) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - return true; -} - -static bool getPolicy(const std::string& dirName) -{ - struct ext4_encryption_policy policy; - int fd, rc; - - fd = ::open(dirName.c_str(), O_DIRECTORY); - if (fd == -1) - return false; - - rc = ::ioctl(fd, EXT4_IOC_GET_ENCRYPTION_POLICY, &policy); - close(fd); - if (rc) { - ERROR("ioctl error"); - return false; - } - return true; -} - -Ext4Engine::Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar) : - source(src), destination(dest), progressBar(prgsBar) -{ -} - -Ext4Engine::~Ext4Engine() -{ -} - -void Ext4Engine::mount(const Ext4Engine::data& key, unsigned int options) -{ - addKey(key); - /* mount : /dev/mmcblk0p21 /opt/usr_encrypt */ - if (::mount(source.c_str(), secondMountPoint.c_str(), "ext4", 0, 0) < 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - /* bind mount :/opt/usr_encrypt/secure /opt/usr */ - if (::mount(bindMountPoint.c_str(), destination.c_str(), "ext4", MS_BIND, 0) < 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); -} - -void Ext4Engine::umount() -{ - /* for decrypt, umount /opt/usr */ - if (::umount(destination.c_str())) - throw runtime::Exception(runtime::GetSystemErrorMessage()); -} - -void Ext4Engine::addKey(const Ext4Engine::data& key) -{ - addKeyToKeyring(key); -} - -void Ext4Engine::encrypt(const Ext4Engine::data& key, unsigned int options) -{ - std::string sourceDir = getSource(); - std::string destDir = getDestination(); - bool copyFlag = false; - - if (!(copyFlag = prepareEncryptDir(sourceDir, destDir))) - throw runtime::Exception("prepareEncryptDir failed"); - - preScanDir(secondMountPoint); - /* key add to keyring */ - addKeyToKeyring(key); - /* set policy */ - setPolicy(bindMountPoint, key); - - if (copyFlag) - listDir(secondMountPoint, bindMountPoint, true); - INFO("[ext4 encrypt] copy done"); - - progressBar.done(); - if (::mount(bindMountPoint.c_str(), destDir.c_str(), "ext4", MS_BIND, 0) < 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); -} - -void Ext4Engine::decrypt(const Ext4Engine::data& key, unsigned int options) -{ - std::string destDir = getDestination(); - - if (!getPolicy(bindMountPoint)) - throw runtime::Exception("directory isn't encrypted"); - addKeyToKeyring(key); - - preScanDir(bindMountPoint); - - listDir(bindMountPoint, secondMountPoint, false); - INFO("[ext4 decrypt] copy done"); - progressBar.done(); - - if (::open(bindMountPoint.c_str(), O_RDONLY) != -1) - ::remove(bindMountPoint.c_str()); - - /* umount /opt/usr_encrypt */ - if (::umount(secondMountPoint.c_str())) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - /* mount /dev/mmcblk0p21 /opt/usr */ - if (::mount(source.c_str(), destination.c_str(), "ext4", 0, 0) < 0) - throw runtime::Exception(runtime::GetSystemErrorMessage()); - - if (::open(secondMountPoint.c_str(), O_RDONLY) != -1) - ::remove(secondMountPoint.c_str()); -} - -bool Ext4Engine::isKeyMetaSet() -{ - return FileFooter::exist(source); -} - -const Ext4Engine::data Ext4Engine::getKeyMeta() -{ - return FileFooter::read(source); -} - -void Ext4Engine::setKeyMeta(const data &data) -{ - FileFooter::write(source, data); -} - -void Ext4Engine::clearKeyMeta() -{ - FileFooter::clear(source); -} - -unsigned int Ext4Engine::getSupportedOptions() -{ - return 0; -} - -} // namespace ode diff --git a/server/engine/ext4-engine.h b/server/engine/ext4-engine.h deleted file mode 100644 index eb233f4..0000000 --- a/server/engine/ext4-engine.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved - * - * 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 - */ - -#ifndef __EXT4_ENGINE_H__ -#define __EXT4_ENGINE_H__ - -#include -#include - -#include "progress-bar.h" - -namespace ode { - -class Ext4Engine final { -public: - Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar); - Ext4Engine(const Ext4Engine&) = delete; - Ext4Engine(Ext4Engine&&) = delete; - ~Ext4Engine(); - - Ext4Engine& operator=(const Ext4Engine&) = delete; - Ext4Engine& operator=(Ext4Engine&&) = delete; - - const std::string& getSource() - { - return source; - } - - const std::string& getDestination() - { - return destination; - } - - typedef std::vector data; - - void mount(const data &key, unsigned int options); - void umount(); - - void addKey(const data &key); - void encrypt(const data &key, unsigned int options); - void decrypt(const data &key, unsigned int options); - - bool isKeyMetaSet(); - const data getKeyMeta(); - void setKeyMeta(const data &data); - void clearKeyMeta(); - - unsigned int getSupportedOptions(); - - int copy(std::string& src, std::string& dest); - void listDir(std::string& source, std::string& dest, bool excludeFlag); - -private: - std::string source, destination; - ProgressBar progressBar; -}; - -} // namespace ode -#endif // __EXT4_ENGINE_H__ diff --git a/server/external-encryption.cpp b/server/external-encryption.cpp index 79001d3..173323a 100644 --- a/server/external-encryption.cpp +++ b/server/external-encryption.cpp @@ -33,7 +33,7 @@ #include "launchpad.h" #include "app-bundle.h" #include "progress-bar.h" -#include "engine/ecryptfs-engine.h" +#include "engine/encryption/ecryptfs-engine.h" #include "key-manager/key-manager.h" #include "rmi/external-encryption.h" diff --git a/server/internal-encryption.cpp b/server/internal-encryption.cpp index 284e436..f294f20 100644 --- a/server/internal-encryption.cpp +++ b/server/internal-encryption.cpp @@ -29,7 +29,7 @@ #include "vconf.h" #include "progress-bar.h" -#include "engine/dmcrypt-engine.h" +#include "engine/encryption/dmcrypt-engine.h" #include "key-manager/key-manager.h" #include "rmi/internal-encryption.h" diff --git a/server/secure-erase.cpp b/server/secure-erase.cpp index e8b66ad..2a46a25 100644 --- a/server/secure-erase.cpp +++ b/server/secure-erase.cpp @@ -14,69 +14,48 @@ * limitations under the License */ #include - -#include -#include -#include -#include - #include -#include -#include -#include +#include -#include "ext4-tool.h" -#include "block-device.h" -#include "progress-bar.h" +#include "engine/erase/mmc-engine.h" #include "rmi/secure-erase.h" +#define ERASE_ENGINE MMCEraseEngine #define PRIVILEGE_PLATFORM "http://tizen.org/privilege/internal/default/platform" namespace ode { namespace { -std::unique_ptr progressBar; +std::unique_ptr engine; -static int totalFileCount = 0; -static int erasedFileCount = 0; - -static int getTotalFileCount(const std::string &name) +void dropCachePage(void) { - int total = 0; - runtime::DirectoryIterator iter(name), end; - - while (iter != end) { - std::string next = name + "/" + iter->getName(); - runtime::File file(next); - if (!file.exists()) { - return -1; - } - - if (file.isFile()) { - total++; - } else if (file.isDirectory()) { - int subTotal = getTotalFileCount(next); - if (subTotal != -1) - total += subTotal; - } - ++iter; + std::ofstream file; + + file.open("/proc/sys/vm/drop_caches"); + if (file.fail()) { + throw runtime::Exception("failed to access drop_caches file"); } - return total; + file << "3\n"; + file.close(); + ::sync(); + return; } } /* namespace */ SecureErase::SecureErase(ODEControlContext &ctx) : - context(ctx), devicePath("") + context(ctx) { context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::erase)(std::string)); context.expose(this, PRIVILEGE_PLATFORM, (int)(SecureErase::clean)(std::string)); - progressBar.reset(new ProgressBar([](int v) { - ::vconf_set_str(VCONFKEY_ODE_ERASE_PROGRESS, std::to_string(v).c_str()); - })); + engine.reset(new ERASE_ENGINE(ProgressBar([](int v) { + ::vconf_set_str(VCONFKEY_ODE_ERASE_PROGRESS, std::to_string(v).c_str()); + })) + ); } SecureErase::~SecureErase() @@ -88,30 +67,12 @@ int SecureErase::erase(const std::string &name) auto eraseWorker = [name, this]() { try { runtime::File file(name); - - BlockDevice blockDevice(name); - devicePath = blockDevice.getName(); - - if (file.isFile()) { - totalFileCount = 1; - fileErase(name); - } else if (file.isDirectory()) { - totalFileCount = getTotalFileCount(name); - erasedFileCount = 0; - directoryErase(name); - } else if (file.isDevice()) { - Ext4Tool ext4Tool(name); - unsigned int totalBlock = ext4Tool.getTotalBlockCount(); - unsigned int blockSize = (unsigned int)blockDevice.getSize(); - - for (unsigned int i = 0; i < totalBlock; i++) { - Block block(i * blockSize, blockSize); - blockDevice.discard(block); - progressBar->update(i, totalBlock, 1); - } + if (file.isDevice()) { + engine->eraseDevice(name); + } else { + engine->eraseFiles(name); } dropCachePage(); - progressBar->done(); } catch (runtime::Exception &e) {} }; @@ -123,129 +84,16 @@ int SecureErase::erase(const std::string &name) int SecureErase::clean(const std::string &name) { - try { - runtime::File file(name, O_WRONLY); - if (!file.exists() || !file.isDevice()) - return -1; - } catch (runtime::Exception &e) {} - auto cleanWorker = [name, this]() { try { - BlockDevice blockDevice(name); - unsigned totalBlock, blockSize; - - Ext4Tool ext4Tool(name); - totalBlock = ext4Tool.getTotalBlockCount(); - blockSize = (unsigned int) blockDevice.getSize(); - - for (unsigned int i = 0; i < totalBlock; i++) { - if (!ext4Tool.isUsedBlock(i)) { - Block block(i * blockSize, blockSize); - blockDevice.discard(block); - } - - progressBar->update(i, totalBlock, 1); - } + engine->cleanDevice(name); dropCachePage(); - progressBar->done(); } catch (runtime::Exception &e) {} }; std::thread asyncWork(cleanWorker); asyncWork.detach(); - - return 0; -} - -int SecureErase::fileErase(const std::string &name) -{ - int ret = 0, fd = 0; - int extentBlockCount = 0; - char buf[4096] = ""; - struct fiemap *fmap = (struct fiemap *)buf; - struct fiemap_extent *fm_ext = NULL; - int count = (sizeof(buf) - sizeof(*fmap)) / sizeof(struct fiemap_extent); - - /* [TBD] stop the related process */ - - BlockDevice blockDevice(devicePath); - - ::memset(fmap, 0, sizeof(struct fiemap)); - - fd = ::open(name.c_str(), O_RDONLY); - if (fd < 0) { - return -1; - } - - fmap->fm_length = ~0ULL; - fmap->fm_flags = 0; - fmap->fm_extent_count = count; - - ret = ::ioctl(fd, FS_IOC_FIEMAP, (unsigned long)fmap); - if (ret < 0) { - ::close(fd); - return -1; - } - - ::close(fd); - - fm_ext = &fmap->fm_extents[0]; - extentBlockCount = (int)fmap->fm_mapped_extents; - - for (int i = 0; i < extentBlockCount; i++) { - Block block(fm_ext[i].fe_physical, fm_ext[i].fe_length); - ret = blockDevice.secDiscard(block); - if (ret < 0) { - return -1; - } - - if (totalFileCount == 1) { - progressBar->update(i, extentBlockCount, 1); - } - } - - return ret; -} - -int SecureErase::directoryErase(const std::string &name) -{ - runtime::DirectoryIterator iter(name), end; - while (iter != end) { - std::string next = name + "/" + iter->getName(); - runtime::File file(next); - if (!file.exists()) { - return -1; - } - - if (file.isFile()) { - fileErase(next); - ::remove(next.c_str()); - erasedFileCount++; - progressBar->update(erasedFileCount, totalFileCount, 1); - } else if (file.isDirectory()) { - directoryErase(next); - } - ++iter; - } - - fileErase(name); - ::rmdir(name.c_str()); return 0; } -void SecureErase::dropCachePage() -{ - std::ofstream file; - - file.open("/proc/sys/vm/drop_caches"); - if (file.fail()) { - throw runtime::Exception("Failed to access drop_caches file"); - } - file << "3\n"; - file.close(); - ::sync(); - - return; -} - } // namespace ode diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b7b8bc5..a9d1c08 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -22,8 +22,8 @@ SET(TEST_SRC main.cpp af.cpp ../server/file-footer.cpp ../server/kernel-keyring.cpp - ../server/engine/ext4-engine.cpp - ../server/engine/ecryptfs-engine.cpp + ../server/engine/encryption/ext4-engine.cpp + ../server/engine/encryption/ecryptfs-engine.cpp ../server/key-manager/key-generator.cpp ../server/key-manager/anti-forensics.cpp ../server/ext4-tool.cpp diff --git a/tests/dmcrypt-engine.cpp b/tests/dmcrypt-engine.cpp index 7fecded..e5ff644 100644 --- a/tests/dmcrypt-engine.cpp +++ b/tests/dmcrypt-engine.cpp @@ -29,7 +29,7 @@ #include #include -#include "../server/engine/dmcrypt-engine.cpp" +#include "../server/engine/encryption/dmcrypt-engine.cpp" #define TEST_USERDATA_NAME "userdata" #define TEST_USERDATA_PATH "/opt/usr" diff --git a/tests/ecryptfs-engine.cpp b/tests/ecryptfs-engine.cpp index a35f83e..6d13631 100644 --- a/tests/ecryptfs-engine.cpp +++ b/tests/ecryptfs-engine.cpp @@ -18,7 +18,7 @@ #include #include -#include "../server/engine/ecryptfs-engine.h" +#include "../server/engine/encryption/ecryptfs-engine.h" #define TEST_PATH "/opt/usr" diff --git a/tests/ext4-engine.cpp b/tests/ext4-engine.cpp index 9e89612..d0efba5 100755 --- a/tests/ext4-engine.cpp +++ b/tests/ext4-engine.cpp @@ -18,7 +18,7 @@ #include #include -#include "../server/engine/ext4-engine.h" +#include "../server/engine/encryption/ext4-engine.h" #define TEST_PATH "/opt/usr"