From: Seok Hong Date: Tue, 17 Jan 2017 06:05:03 +0000 (+0900) Subject: Support FastEncryption for DMCryptEngine X-Git-Tag: submit/tizen/20170213.020148~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a2afe66c2b29da572eb545d80ad76b4b1e8583c3;p=platform%2Fcore%2Fsecurity%2Fode.git Support FastEncryption for DMCryptEngine NOTE: - Won't support filesystem what uses 1K block size Change-Id: I63bc8d9dc5ebc50390267a87d5babbf5e0364b50 Signed-off-by: Seok Hong --- diff --git a/server/engine/dmcrypt-engine.cpp b/server/engine/dmcrypt-engine.cpp index eae9c16..02fefe9 100644 --- a/server/engine/dmcrypt-engine.cpp +++ b/server/engine/dmcrypt-engine.cpp @@ -25,6 +25,7 @@ #include #include "../file-footer.h" +#include "../ext4-tool.h" #include "dmcrypt-engine.h" @@ -273,29 +274,30 @@ void DMCryptEngine::umount() destroyCryptoBlkDev(DM_LABEL); } - -#define CRYPT_INPLACE_BUFSIZE 4096 -#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / 512) - -void DMCryptEngine::encryptInPlace(const std::string &dst_blkdev, - const std::string &src_blkdev, - const long src_blkdev_size) +void DMCryptEngine::encryptInPlace(const std::string &src_blkdev, + const std::string &dst_blkdev, + const bool isFastEncEnabled) { - // TODO(seok85.hong): support fast-encryption - - char buff[CRYPT_INPLACE_BUFSIZE]; + Ext4Tool ext4tool(src_blkdev); - off64_t numblocks = src_blkdev_size / CRYPT_SECTORS_PER_BUFSIZE; - off64_t remainder = src_blkdev_size % CRYPT_SECTORS_PER_BUFSIZE; - off64_t total = numblocks + remainder; + 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 (off64_t n = 0; n < total; n++) { - src.read(buff, CRYPT_INPLACE_BUFSIZE); - dst.write(buff, CRYPT_INPLACE_BUFSIZE); - progressBar.update(n, total, 1); + 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(); } @@ -308,8 +310,14 @@ void DMCryptEngine::encrypt(const DMCryptEngine::data &key, unsigned int options // 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, cryptInfo.getFileSystemSize()); + encryptInPlace(source, crypto_blkdev, isFastEncEnabled); // remove crypto type device mapper destroyCryptoBlkDev(DM_LABEL); @@ -323,8 +331,14 @@ void DMCryptEngine::decrypt(const DMCryptEngine::data &key, unsigned int options // 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, cryptInfo.getFileSystemSize()); + encryptInPlace(crypto_blkdev, source, isFastEncEnabled); // remove crypto type device mapper destroyCryptoBlkDev(DM_LABEL); diff --git a/server/engine/dmcrypt-engine.h b/server/engine/dmcrypt-engine.h index 65472e4..3a0876c 100644 --- a/server/engine/dmcrypt-engine.h +++ b/server/engine/dmcrypt-engine.h @@ -74,9 +74,9 @@ public: unsigned int getSupportedOptions(); private: - void encryptInPlace(const std::string &dst_blkdev, - const std::string &src_blkdev, - const long src_blkdev_size); + void encryptInPlace(const std::string &src_blkdev, + const std::string &dst_blkdev, + const bool isFastEncEnabled); private: std::string source, destination; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index fc3ca05..926687d 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,6 +26,7 @@ SET(TEST_SRC main.cpp ../server/engine/ecryptfs-engine.cpp ../server/key-manager/key-generator.cpp ../server/key-manager/anti-forensics.cpp + ../server/ext4-tool.cpp ../server/progress-bar.cpp ../server/progress-vconf-backend.cpp ) diff --git a/tests/dmcrypt-engine.cpp b/tests/dmcrypt-engine.cpp index c790bc8..6c926d4 100644 --- a/tests/dmcrypt-engine.cpp +++ b/tests/dmcrypt-engine.cpp @@ -94,7 +94,9 @@ TESTCASE(DMCryptTestInit) if (system(cmd.c_str())) {} // make filesystem(ext4) and write test file - cmd = "/usr/sbin/mkfs.ext4 -j "; + cmd = "/usr/sbin/mkfs.ext4 -j -b 4096 "; + // cmd = "/usr/sbin/mkfs.ext4 -j -b 2048 "; + // cmd = "/usr/sbin/mkfs.ext4 -j -b 1024 "; // has problem now cmd += test_real_blkdev; // "/dev/loop0" if (system(cmd.c_str())) {} @@ -429,47 +431,49 @@ TESTCASE(DMCryptEncryptMountUnmountDecrypt) } } -// TODO(seok85.hong): is numblocks + remainder less than fast-encryption enabled count? - -// When we try to dcrypt using wrong key, our encrypted partition will be broken. -// so, we should do this test at last test case -TESTCASE(DMCryptEncryptButDecryptWithWrongKey) +TESTCASE(DMCryptFastEncryptMountUnmountFastDecrypt) { try { // ode::cryptInfo.init(test_real_blkdev, "aes-cbc-essiv:sha256"); const std::string keystring = "01020304050607080910111213141516"; const ode::DMCryptEngine::data key32bit(keystring.begin(), keystring.end()); - const std::string wrongkeystring = "SIZE_IS_SAME_BUT_WRONG_DECKEY___"; - const ode::DMCryptEngine::data wrongkey32bit(wrongkeystring.begin(), wrongkeystring.end()); ode::DMCryptEngine engine(test_real_blkdev, test_real_mntpoint, progressBar); - engine.encrypt(key32bit, OPTION_INCLUDE_UNUSED_REGION); - - // check the encryption result of test_real_blkdev(/dev/loop0) - // at this time, if we mount /dev/loop0 forcely, we can't mount them... + engine.encrypt(key32bit, (~OPTION_INCLUDE_UNUSED_REGION)); // disable fast-encryption + engine.mount(key32bit, 0); { - int ret = ::mount(test_real_blkdev.c_str(), test_real_mntpoint.c_str(), "ext4", 0, 0); - if ((ret != -1) || (runtime::Error::lastErrorCode() != EINVAL)) { - // we expected ret value is EINVAL (mount failure in man page of mount) - std::cout << "expected: EINVAL" << "\n"; - std::cout << "real : " << runtime::GetSystemErrorMessage() << "\n"; - TEST_FAIL("Unexpected result from cryptsetup status"); - } - } - // decrypt with WRONG KEY - engine.decrypt(wrongkey32bit, OPTION_INCLUDE_UNUSED_REGION); + // we should find test file (file name: ABC, body: DEF) in mount-point + std::string cmd = "cat " + test_real_mntpoint + "/ABC"; + FILE *fp = popen(cmd.c_str(), "r"); + if (!fp) + TEST_FAIL("Can't get test file body"); - // check the decryption result of test_Real_Blkdev(/dev/loop0) - // at this time, if we mount /dev/loop0 forcely, we can't mount them... - { - int ret = ::mount(test_real_blkdev.c_str(), test_real_mntpoint.c_str(), "ext4", 0, 0); - if ((ret != -1) || (runtime::Error::lastErrorCode() != EINVAL)) { - // we expected ret value is EINVAL (mount failure in man page of mount) - std::cout << "expected: EINVAL" << "\n"; - std::cout << "real : " << runtime::GetSystemErrorMessage() << "\n"; - TEST_FAIL("Unexpected result from cryptsetup status"); + std::vector answer = { + "DEF", + }; + + char buff[128] = {0, }; + for (auto &a : answer) { + if (fgets(buff, 128, fp) == nullptr) { + pclose(fp); + TEST_FAIL("Can't read test file body from buffer"); + } + + std::string ret = buff; + ret.erase(std::remove(ret.begin(), ret.end(), '\n'), ret.end()); + + if (ret.compare(a)) { + pclose(fp); + std::cout << "expected: " << a << "\n"; + std::cout << "real : " << ret << "\n"; + TEST_FAIL("Unexpected result from test file body"); + } } + pclose(fp); } + engine.umount(); + engine.decrypt(key32bit, (~OPTION_INCLUDE_UNUSED_REGION)); // disable fast-encryption + // } catch (runtime::Exception &e) { TEST_FAIL(e.what()); }