Support FastEncryption for DMCryptEngine 99/97299/12
authorSeok Hong <seok85.hong@samsung.com>
Tue, 17 Jan 2017 06:05:03 +0000 (15:05 +0900)
committerSeok Hong <seok85.hong@samsung.com>
Tue, 24 Jan 2017 08:08:41 +0000 (17:08 +0900)
NOTE:
  - Won't support filesystem what uses 1K block size

Change-Id: I63bc8d9dc5ebc50390267a87d5babbf5e0364b50
Signed-off-by: Seok Hong <seok85.hong@samsung.com>
server/engine/dmcrypt-engine.cpp
server/engine/dmcrypt-engine.h
tests/CMakeLists.txt
tests/dmcrypt-engine.cpp

index eae9c16..02fefe9 100644 (file)
@@ -25,6 +25,7 @@
 #include <klay/filesystem.h>
 
 #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);
index 65472e4..3a0876c 100644 (file)
@@ -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;
index fc3ca05..926687d 100755 (executable)
@@ -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
 )
index c790bc8..6c926d4 100644 (file)
@@ -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<std::string> 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());
        }