Refactor ecryptfs engine 32/109532/7
authorSungbae Yoo <sungbae.yoo@samsung.com>
Tue, 10 Jan 2017 08:05:25 +0000 (17:05 +0900)
committerSungbae Yoo <sungbae.yoo@samsung.com>
Fri, 20 Jan 2017 07:52:25 +0000 (16:52 +0900)
Signed-off-by: Sungbae Yoo <sungbae.yoo@samsung.com>
Change-Id: I1420497da64043e2391d0be8a1b2896976e519b7

server/CMakeLists.txt
server/engine/ecryptfs-engine.cpp
server/engine/ecryptfs-engine.h
server/external-encryption.cpp
server/kernel-keyring.cpp [new file with mode: 0644]
server/kernel-keyring.h [new file with mode: 0644]
tests/CMakeLists.txt

index 20748885ac102a3427450719746f841858c43cd6..2b55873b9996ffec44015deff4c11f90c20d1060 100644 (file)
@@ -23,6 +23,7 @@ SET(SERVER_SRCS       main.cpp
                                progress-bar.cpp
                                progress-vconf-backend.cpp
                                block-device.cpp
+                               kernel-keyring.cpp
                                internal-encryption.cpp
                                external-encryption.cpp
                                engine/ext4-engine.cpp
index 21c567788991b82b34bc6483b55e7a7c7c89c1aa..64f4eac18b66ca7ae048cd42380fb41717914ef6 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
+#include <iomanip>
+
+#include <klay/error.h>
+#include <klay/exception.h>
 #include <klay/filesystem.h>
 #include <klay/audit/logger.h>
-#include <klay/exception.h>
 
+#include "../kernel-keyring.h"
 #include "../file-footer.h"
 
 #include "ecryptfs-engine.h"
 
-namespace ode {
-
-EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) :
-       mSource(src), mDestination(dest), progressBar(prgsBar)
-{
-}
-
-EcryptfsEngine::~EcryptfsEngine()
-{
-}
-
-key_serial_t EcryptfsEngine::add_key(const char *type,
-                                                                        const char *description,
-                                                                        const void *payload,
-                                                                        size_t plen,
-                                                                        key_serial_t ringid)
-{
-       return ::syscall(__NR_add_key, type, description, payload, plen, ringid);
-}
-
-long EcryptfsEngine::keyctl_search(key_serial_t ringid,
-                                                                  const char *type,
-                                                                  const char *description,
-                                                                  key_serial_t destringid)
-{
-       return ::syscall(__NR_keyctl, KEYCTL_SEARCH, ringid, type, description, destringid);
-}
-
-void EcryptfsEngine::hexConvert(char *dest, unsigned char *src, int srcLen)
-{
-       for (int i = 0; i < srcLen; i++)
-               ::sprintf(&dest[i * 2], "%.2x", (unsigned char)src[i]);
-       dest[srcLen * 2] = '\0';
-}
-
-int EcryptfsEngine::add_user_auth_token_to_keyring(ecryptfs_payload *payload)
-{
-       int result = ERR_NO;
-
-       if (keyctl_search(KEY_SPEC_USER_KEYRING, AUTH_TOKEN_TYPE,
-                                         (const char *)payload->token.password.signature, 0) <= 0) {
-               if (add_key(AUTH_TOKEN_TYPE, (const char *)payload->token.password.signature,
-                                       (void *)payload, sizeof(ecryptfs_payload), KEY_SPEC_USER_KEYRING) <= 0) {
-                       result = ERR_FAILED_AUTH;
-               } else {
-                       INFO("Token added = " + std::string((const char *)payload->token.password.signature));
-               }
-       }
-
-       return result;
-}
+#if 0
+#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"
+#endif
 
-int EcryptfsEngine::smack_check(void)
-{
-       struct statfs sfs;
-       int ret;
-       int checksmack = 0;
+#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
 
-       do {
-               ret = ::statfs(SMACKFS_MNT, &sfs);
-       } while (ret < 0 && errno == EINTR);
+#define ECRYPTFS_AUTH_TOKEN_TYPE "user"
 
-       if (ret == 0 && sfs.f_type == SMACKFS_MAGIC)
-               checksmack = 1;
-       return checksmack;
-}
+namespace ode {
 
-void EcryptfsEngine::build_ecryptfs_options(char *ecryptfs_opts, char *sig, int excludeMediaTypes)
-{
-       ::sprintf(ecryptfs_opts,    ECRYPTFS_PLAINTEXT_PASSTHOUGH","
-                         ECRYPTFS_SIGNATURE"%s,"
-                         ECRYPTFS_CIPHERA"%s,"
-                         ECRYPTFS_KEY_BYTES"%d", sig, ECRYPTFS_FEK_CIPHER, MAX_KEY_BYTES);
-
-       if (excludeMediaTypes == EXCL_MEDIA_ON) {
-               INFO("building options with media files filtering.");
-               ::strcat(ecryptfs_opts, ",");
-               ::strcat(ecryptfs_opts, ECRYPTFS_ENABLE_FILTERING);
-               ::strcat(ecryptfs_opts, ECRYPTFS_MEDIA_EXCLUSION_LIST);
-       } else if (excludeMediaTypes == EXCL_ALL_NEW_ON) {
-               INFO("building options with all new files filtering.");
-               ::strcat(ecryptfs_opts, ",");
-               ::strcat(ecryptfs_opts, ECRYPTFS_ENABLE_FILTERING);
-               ::strcat(ecryptfs_opts, ECRYPTFS_GLOBAL_EXCLUSION_LIST);
-       } else {
-               INFO("building options without file encryption filtering.");
-       }
-       if (smack_check()) {
-               INFO("smack fs was enabled, add smack labeling");
-               ::strcat(ecryptfs_opts, ",");
-               ::strcat(ecryptfs_opts, SMACKFS_MOUNT_OPT);
-       }
-}
+namespace {
 
-void EcryptfsEngine::mount(const data &key)
+unsigned long long getAvailableSpace(const std::string& mountPoint)
 {
-       int result = ERR_NO;
-       unsigned char master_key[MAX_KEY_BYTES] = {0};
-       char ecryptfs_opts[ECRYPTFS_MAX_OPTIONS] = {0};
-       INFO("Source: " + mSource);
-       INFO("Destination: " + mDestination);
-       INFO("EcryptfsMount: ");
-       if (key.size() == 0)
-               throw runtime::Exception("Key size is zero.");
-
-       for (unsigned int iter = 0; iter < key.size(); iter++) {
-               master_key[iter] = key[iter];
-       }
-
-       if (isEcryptfsMountpointMounted(mDestination) == 0) {
-               INFO("Already Mounted");
-               throw runtime::Exception("Already Mounted.");
+       struct statfs statbuf;
+       if (::statfs(mountPoint.c_str(), &statbuf)) {
+               throw runtime::Exception("Failed to access " + mountPoint);
        }
 
-       //MOUNT_ECRYPTFS_DRIVE
-       memset(&(sde_payload), 0, sizeof(ecryptfs_payload));
-
-       sde_payload.version = ECRYPTFS_VERSION;
-       sde_payload.token_type = ECRYPTFS_PWD_PAYLOAD_TYPE;
-       sde_payload.token.password.session_key_encryption_key_bytes = MAX_KEY_BYTES;
-       sde_payload.token.password.flags = ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET;
-       memcpy(sde_payload.token.password.session_key_encryption_key, master_key, MAX_KEY_BYTES);
-
-       hexConvert((char *)sde_payload.token.password.signature, master_key, SIG_SIZE);
-
-       result = add_user_auth_token_to_keyring(&sde_payload);
-       if (result == ERR_NO) {
-               build_ecryptfs_options(ecryptfs_opts, (char *)sde_payload.token.password.signature, mExcludeMedia);
-               INFO("encrypted fs option : " + std::string(ecryptfs_opts) + ", source : " + mSource + ", dest : " + mDestination);
-               if (::mount(mSource.c_str(), mDestination.c_str(), ECRYPTFS_MOUNT_DEVICE, MS_NODEV, ecryptfs_opts) != 0) {
-                       INFO("Unable to mount drive: " + std::string(strerror(errno)));
-                       throw runtime::Exception("Unable to mount drive.");
-               } else {
-                       INFO("Mount is completed.");
-               }
-       } else {
-               INFO("Unable to add token to keyring");
-               throw runtime::Exception("Unable to add token to keyring.");
-       }
+       return (unsigned long long)statbuf.f_bfree * statbuf.f_bsize;
 }
 
-void EcryptfsEngine::umount()
+bool wasEncrypted(const std::string &path)
 {
-       int result = ERR_NO;
-
-       INFO("EcryptfsUmount");
-       if (isEcryptfsMountpointMounted(mDestination) == 0) {
-               if (::umount(mDestination.c_str()) != 0) {
-                       if (::umount2(mDestination.c_str(), MNT_EXPIRE) != 0) {
-                               INFO("Unmount failed for drive " + mDestination + "err(" + std::to_string(errno) + std::string(strerror(errno)) + ")");
-                               if (errno == EAGAIN) {
-                                       INFO("Trying Unmount again");
-                                       if (::umount2(mDestination.c_str(), MNT_EXPIRE) != 0) {
-                                               INFO("Unmount failed for drive" + mDestination + "err(" + std::to_string(errno) + std::string(strerror(errno)) + ")");
-                                               throw runtime::Exception("Unmount failed for drive.");
-                                       }
-                               } else {
-                                       INFO("Drive " + mDestination + "unmounted failed ");
-                                       throw runtime::Exception("Unmount failed for drive.");
-                               }
-                       }
-               }
+#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES
+       unsigned int attrs = 0;
+       bool ret = false;
+       int fd = 0;
 
-               if (result == ERR_NO)
-                       INFO("Drive " + mDestination + " unmounted successfully");
-               else {
-                       INFO("Drive " + mDestination + " unmounted failed");
-                       throw runtime::Exception("Unmount failed for drive.");
-               }
+       fd = ::open(path.c_str(), O_RDWR);
+       if (fd < 0) {
+               throw runtime::Exception("Failed to open " + path);
        }
-}
 
-void EcryptfsEngine::encrypt(const data &key)
-{
-       int result = ERR_NO;
-
-       INFO("EcryptfsEncrypt");
-       if (!isMountpointMounted(mSource)) {
-               INFO("SD Card not inserted!");
-               throw runtime::Exception("SD Card not inserted.");
+       if (::ioctl(fd, ECRYPTFS_IOCTL_GET_ATTRIBUTES, &attrs) == 0 &&
+               (attrs & ECRYPTFS_WAS_ENCRYPTED)) {
+               ret = true;
        }
+       ::close(fd);
 
-       result = DoCrypt(key, mDestination.c_str(), 1, EXCL_MEDIA_ON);
-       if (result != ERR_NO) {
-               INFO("Encrypt failed!");
-               throw runtime::Exception("Encrypt failed.");
-       }
+       return ret;
+#else
+       return true;
+#endif
 }
 
-void EcryptfsEngine::decrypt(const data &key)
-{
-       int result = ERR_NO;
+unsigned long long getEncryptedSize(const runtime::File &file) {
+       unsigned long long originalSize = file.size();
+       unsigned long long result = 0;
 
-       INFO("EcryptfsDecrypt");
-       if (!isMountpointMounted(mSource)) {
-               INFO("SD Card not inserted!");
-               throw runtime::Exception("SD Card not inserted.");
+       if (originalSize % 4096) {
+               originalSize = (1 + originalSize / 4096) * 4096;
        }
 
-       result = DoCrypt(key, mDestination.c_str(), 0, EXCL_ALL_NEW_ON);
-       if (result != ERR_NO) {
-               INFO("Decrypt failed!");
-               throw runtime::Exception("Decrypt failed.");
+#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES
+       if (wasEncrypted(file.getPath())) {
+               result = originalSize;
+       } else {
+#endif
+               result = originalSize + 2 * 4096;
+#ifdef ECRYPTFS_IOCTL_GET_ATTRIBUTES
        }
-}
+#endif
 
-int EcryptfsEngine::DoCrypt(const data &key, const char *path, int reqEnc, int excludeMedia)
-{
-       int result = ERR_NO;
-       const char *cryptTempFile = CRYPT_META_FILE;
-       INFO("DoCrypt: reqEnc: " + std::to_string(reqEnc) + ", excludeMedia: " + std::to_string(excludeMedia));
-
-       mPath = path;
-       mReqEnc = reqEnc;
-       mExcludeMedia = excludeMedia;
-       mMetaDataFile = new char[::strlen(mPath) +::strlen(cryptTempFile) + 2];
-       if (mMetaDataFile) {
-               ::sprintf(mMetaDataFile, "%s%s%s", mPath, "/", cryptTempFile);
+       //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;
        }
 
-       if (reqEnc)
-               result = DoEncrypt(key);
-       else
-               result = DoDecrypt(key);
-
        return result;
 }
 
-int EcryptfsEngine::DoEncrypt(const data &key)
-{
-       INFO("DoEncrypt()");
-
-       try {
-               mount(key);
-       } catch (runtime::Exception &e) {
-               INFO("EcryptfsEngine: Error mounting " + std::string(mPath));
-               goto error;
-       }
-
-       if (createEncryptMetaData(mMetaDataFile) != 0) {
-               goto error;
-       }
-
-       if (preScanForEncrypt(mPath) != 0) {
-               goto error;
-       }
+unsigned long long getDecryptedSize(const runtime::File &file) {
+       unsigned long long originalSize = file.size();
+       unsigned long long result = originalSize;
 
-       if (mTotalFileCt) {
-               mTotalCopied = 0;
-               mLastProg = 0;
-               progressBar.update(mLastProg);
-               INFO("calling the recursive function EncryptFile (" + std::string(mPath) + ")");
-               if (cryptInplace(mPath, "", false) != 0) {
-                       INFO("Ecryptfs: Full Encryption couldn't complete");
-                       goto error;
+       if (wasEncrypted(file.getPath())) {
+               if (originalSize > 2 * 4096) {
+                       result = originalSize - 2 * 4096;
                }
-               progressBar.done();
-       }
-
-       return 0;
-error:
-       deleteEncryptMetaData(mMetaDataFile);
-       umount();
-       return -1;
-}
-
-int EcryptfsEngine::DoDecrypt(const data &key)
-{
-       INFO("DoDecrypt()");
-
-       if (checkEncryptMetaData(ORIG_META_FILE_PATH) != 0) {
-               goto success;
-       }
-
-       try {
-               mount(key);
-       } catch (runtime::Exception &e) {
-               INFO("EcryptfsEngine: Error mounting " + std::string(mPath));
-               goto error;
        }
 
-       if (preScanForDecrypt(mPath) != 0) {
-               goto error;
-       }
+       result = originalSize;
 
-       if (mTotalFileCt) {
-               mTotalCopied = 0;
-               mLastProg = 0;
-               progressBar.update(mLastProg);
-               INFO("calling the recursive function EncryptFile (" + std::string(mPath) + ")");
-               if (cryptInplace(mPath, "", true) != 0) {
-                       INFO("Ecryptfs: Full Decryption couldn't complete");
-                       goto error;
-               }
-               progressBar.done();
+       //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;
        }
 
-       deleteEncryptMetaData(mMetaDataFile);
-success:
-       INFO("Decryption Completed !!!");
-       umount();
-       return 0;
-error:
-       umount();
-       return -1;
-}
-
-void EcryptfsEngine::progress(long long size)
-{
-       int complPercentage = 0;
-
-       if (mTotalStSz != 0) {
-               complPercentage = (size * 100) / mTotalStSz;
-               if ((complPercentage - mLastProg) >= DELTA_PROGRESS) {
-                       INFO("Progress: " + std::to_string(complPercentage) + "%, Total Size: " + std::to_string(mTotalStSz));
-                       mLastProg = complPercentage;
-                       progressBar.update(mLastProg);
-               }
-       }
+       return result;
 }
 
-long long EcryptfsEngine::CopyImpl(int sfd, int dfd, long long fullsz, bool enctype)
+bool isEnoughToCopyInPlace(const std::string& path,
+       const std::function<unsigned long long(const runtime::File&)> getSizeFunc)
 {
-       long long ret = -1;
-       long long total = 0;
-
-       char buffer [ECRYPTFS_BUFFER_SIZE];
-
-       INFO("CopyImpl");
-       while (1) {
-               ssize_t rdsz = 0;
+       unsigned long long availableSpace = getAvailableSpace(path);
 
-               rdsz = FullRead(sfd, buffer, ECRYPTFS_BUFFER_SIZE);
-               if (!rdsz) {
-                       ret = 0;
-                       break;
-               }
-
-               if (rdsz < 0) {
-                       INFO("Error reading src file");
-                       break;
-               }
-
-               if (dfd >= 0) {
-                       ssize_t wrsz = FullWrite(dfd, buffer, rdsz);
-                       if (wrsz < rdsz) {
-                               INFO("Write Error");
-                               break;
+       std::function<bool(const std::string &path)> 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;
                        }
                }
-               total += rdsz;
-               mTotalCopied += rdsz;
-
-               progress(mTotalCopied);
-       }
+               return true;
+       };
 
-       return ret ? -1 : total;
+       return check(path);
 }
 
-ssize_t EcryptfsEngine::FullRead(int fd, void *buf, size_t count)
-{
-       ssize_t n;
-
-       do {
-               n = ::read(fd, buf, count);
-       } while (n < 0 && errno == EINTR);
-
-       return n;
-}
-ssize_t EcryptfsEngine::FullWrite(int fd, const void *buf, size_t len)
+void copyInPlace(const std::string& source, const std::string& destination,
+                                       const std::string& temp,
+                                       const std::function<bool(const std::string&)> &isTarget,
+                                       const std::function<void(unsigned long long)> &addProgress)
 {
-       ssize_t total = 0;
-
-       while (len) {
-               ssize_t n;
+       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();
 
-               do {
-                       n = ::write(fd, buf, len);
-               } while (n < 0 && errno == EINTR);
+                       iter->copyTo(tempFilePath);
+                       iter->remove();
+                       if (::rename(tempFilePath.c_str(), destFilePath.c_str()) != 0) {
+                               throw runtime::Exception("Failed to rename from " + tempFilePath + " to " + destFilePath);
+                       }
 
-               if (n < 0) {
-                       if (total)
-                               return total;
-                       return n;
+                       addProgress(iter->size());
                }
-
-               total += n;
-               buf = ((const char *)buf) + n;
-               len -= n;
        }
-
-       return total;
 }
 
-int EcryptfsEngine::CopyFile(const char *src, const char *dest, struct stat *src_stat, bool enctype)
+void ecryptfsMount(const std::string &source, const std::string &destination, const std::vector<unsigned char> &key)
 {
-       int sfd, dfd;
-       struct utimbuf times;
-       long long retval = 0;
+       ecryptfs_auth_tok payload;
+       std::string mountOption;
 
-       INFO("Copy start " + std::string(src) + " => " + std::string(dest));
+       ::memset(&(payload), 0, sizeof(ecryptfs_auth_tok));
 
-       sfd = ::open(src, O_RDONLY, 0666);
+       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);
 
-       if (sfd < 0) {
-               INFO("Cann't open " + std::string(src));
-               return -1;
+    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);
 
-       dfd = ::open(dest, O_WRONLY | O_CREAT | O_TRUNC, src_stat->st_mode);
-       if (dfd < 0) {
-               INFO("Error opening the destination file " + std::string(dest));
-               ::close(sfd);
-               return -1;
-       }
-
-       retval = CopyImpl(sfd, dfd, src_stat->st_size, enctype);
-
-       if (retval < 0) {
-               INFO("Encryption Error CopyData returned <" + std::to_string(retval) + "> : <" + std::string(src) + "> errno " + std::to_string(errno) + " " + std::string(strerror(errno)));
-               ::close(sfd);
-               ::close(dfd);
-               return retval;
+       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.");
+               }
        }
 
-       times.actime = src_stat->st_atime;
-       times.modtime = src_stat->st_mtime;
-
-       if (::utime(dest, &times) < 0)
-               INFO("can't preserve times of '" + std::string(src) + "'");
+       mountOption = "ecryptfs_passthrough"
+               ",ecryptfs_sig=" + std::string((char *)payload.token.password.signature) +
+               ",ecryptfs_cipher=" CIPHER_MODE
+               ",ecryptfs_key_bytes=" + std::to_string(payload.token.password.session_key_encryption_key_bytes);
 
-       INFO("Copy Completed");
-
-       if (::fsync(dfd) != 0)
-               INFO("can't fsync of '" + std::string(src) + "'");
-       if (::posix_fadvise(dfd, 0, src_stat->st_size, POSIX_FADV_DONTNEED) < 0)
-               INFO("can't fadvise of '" + std::string(dest) + "'");
-
-       ::close(sfd);
-       ::close(dfd);
+#ifdef MEDIA_EXCLUSION_LIST
+       mountOption += ",ecryptfs_enable_filtering=" MEDIA_EXCLUSION_LIST;
+#endif
 
-       return 0;
-}
+       INFO("option = " + mountOption);
+       INFO("source = " + source);
+       INFO("dest = " + destination);
 
-void EcryptfsEngine::syncdatafile(const char *src)
-{
-       int sfd;
-       sfd = ::open(src, O_WRONLY);
-       if (sfd < 0) {
-               INFO("Cann't open " + std::string(src));
-               return;
+       if (::mount(source.c_str(), destination.c_str(), "ecryptfs", MS_NODEV,
+                               mountOption.c_str()) != 0) {
+               throw runtime::Exception(runtime::GetSystemErrorMessage());
        }
-       if (::fsync(sfd) != 0)
-               INFO("can't fsync of '" + std::string(src) + "'");
-       /* just open and close for flushing file to ecryptfs */
-       ::close(sfd);
 }
-int EcryptfsEngine::cryptInplace(const char *src, const char *tmpdest, bool dec_fl)
-{
-       struct stat src_stat;
-       int retval = 0;
-       int enc_fl = 0;
-
-       if (::lstat(src, & src_stat) < 0)
-               INFO("source : < " + std::string(src) + "> is a dangling link");
-
-       if (S_ISDIR(src_stat.st_mode)) {
-               /* dir call recursively */
-               DIR *dp;
-               struct dirent *d;
-
-               dp = ::opendir(src);
-               if (NULL == dp) {
-                       retval = -1;
-                       return retval;
-               }
-
-               while ((d = ::readdir(dp)) != NULL) {
-                       char *nsrc = NULL;
-                       char *ntmpdest = NULL;
 
-                       nsrc = catSubpathFile(src, d->d_name, &ntmpdest);
-                       if (nsrc == NULL) {
-                               if (ntmpdest != NULL) delete [] ntmpdest;
-                               continue;
-                       }
-
-                       if (cryptInplace(nsrc, ntmpdest, dec_fl) < 0) {
-                               INFO("Encryptfile returned error for nsrc <" + std::string(nsrc) + ">");
-                               retval = -1;
-                               delete [] ntmpdest;
-                               delete [] nsrc;
-                               break;
-                       }
-                       delete [] ntmpdest;
-                       delete [] nsrc;
-               }
-               ::closedir(dp);
-       } else if (S_ISREG(src_stat.st_mode)) {
-               enc_fl = fn_was_encrypted(src);
-
-               if (enc_fl == WAS_ECRYPTED_ERROR)
-                       return enc_fl;
-
-               if ((!dec_fl && enc_fl == WAS_NOT_ENCRYPTED) ||
-                               (dec_fl && enc_fl == WAS_ENCRYPTED)) {
-                       INFO("ENC/DEC " + std::string(src));
-
-                       retval = CopyFile(src, tmpdest, &src_stat, dec_fl);
-                       if (retval) {
-                               INFO("CopyFileImpl returned error <" + std::to_string(retval) + "> errno " + std::to_string(errno) + std::string(strerror(errno)));
-                               return retval;
-                       }
-                       ::unlink(src);
-                       retval = ::rename(tmpdest, src);
-                       syncdatafile(src);
-                       if (retval) {
-                               INFO("rename returned error <" + std::to_string(retval) + "> errno " + std::to_string(errno) + std::string(strerror(errno)));
-                               return retval;
-                       }
-               } else
-                       INFO("File already encrpyted/Decrypted : <" + std::string(src) + ">");
+void ecryptfsUmount(const std::string &destination)
+{
+       if (::umount(destination.c_str()) != 0) {
+               throw runtime::Exception(runtime::GetSystemErrorMessage());
        }
 
-       return retval;
+       //TODO : remove key from keyring
 }
 
-int EcryptfsEngine::preScanForEncrypt(const char *src)
-{
-       sizeinfo_type szinfo;
-       struct statfs statbuf;
-       int result = ERR_NO;
-
-       INFO("preScanForEncrypt");
-       do {
-               ::memset(&szinfo, 0, sizeof(sizeinfo_type));
-               if (!::statfs(src, &statbuf)) {
-                       szinfo.availsz = (long long)statbuf.f_bfree * statbuf.f_bsize;
-                       szinfo.blocksz = (int)statbuf.f_bsize;
-                       INFO("Free size available from statfs : <" + std::to_string(szinfo.availsz) + ">");
-               } else {
-                       INFO("can't access " + std::string(src));
-                       return PRESCAN_ERR;
-               }
-
-               mPreScanEncryptErr = 0;
-               result = getEncryptedSize(src, &szinfo);
-
-               INFO("Prescan Free <" + std::to_string(szinfo.availsz) + ">, source size <" + std::to_string(szinfo.cursz) + ">, Source Encrypted size <" + std::to_string(szinfo.encsz) + "> largeFileSz <"
-                        + std::to_string(szinfo.largesz) + "> filecount <" + std::to_string(szinfo.filecount) + "> for <" + std::string(src) + ">");
-               INFO("retval <" + std::to_string(result) + "> PrescanencryptErr <" + std::to_string(mPreScanEncryptErr) + ">");
-
-               mTotalFileCt = szinfo.filecount;
-               mTotalStSz = szinfo.totalstsz;
-
-               if (mPreScanEncryptErr == PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR) {
-                       result = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-               } else if ((mPreScanEncryptErr == PRESCAN_ERR) || (result == PRESCAN_ERR)) {
-#if !defined(NDEBUG)
-                       int total = (szinfo.encsz + szinfo.largesz - szinfo.cursz + 12 * 1024) / 1024;
-                       int needed  = total - szinfo.availsz / 1024;
-#endif
-                       if (isEcryptfsMountpointMounted(mPath)) {
-                               umount();
-                               INFO("Unmounting mpath <" + std::string(mPath) + ">");
-                       }
-
-                       INFO("Prescan failed with Too full error, need more space, " + std::to_string(needed) + " extra, total " + std::to_string(total));
-                       result = PRESCAN_ERR;
-               }
-
-               if (result == PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR) {
-                       INFO("EcryptfsEngine: Need to run Prescan Again");
-                       continue;
-               }
-
-               if (result == 0) {
-                       INFO("EcryptfsEngine: Prescan completed successfully");
-                       return result;
-               }
-
-               INFO("EcryptfsEngine: Cannot encrypt, Disk Space is not enough");
-               return PRESCAN_ERR;
-       } while (1);
-}
+} // namespace
 
-int EcryptfsEngine::preScanForDecrypt(const char *src)
+EcryptfsEngine::EcryptfsEngine(const std::string &src, const std::string &dest, const ProgressBar &prg) :
+       source(src), destination(dest), progress(prg)
 {
-       sizeinfo_type szinfo;
-       struct statfs statbuf;
-       int result = ERR_NO;
-
-       INFO("preScanForDecrypt");
-       do {
-               ::memset(&szinfo, 0, sizeof(EcryptfsEngine::sizeinfo_type));
-               if (!::statfs(src, &statbuf)) {
-                       szinfo.availsz = (long long)statbuf.f_bfree * statbuf.f_bsize;
-                       szinfo.blocksz = (int)statbuf.f_bsize;
-                       INFO("Free size available from statfs : <" + std::to_string(szinfo.availsz) + ">");
-               } else {
-                       INFO("can't access " + std::string(src));
-                       return PRESCAN_ERR;
-               }
-
-               mPreScanEncryptErr = 0;
-               result = getDecryptedSize(src, &szinfo);
-
-               INFO("Prescan Decrypt Free <" + std::to_string(szinfo.availsz) + ">, source size <" + std::to_string(szinfo.cursz) + ">, Source Decrypted size <" + std::to_string(szinfo.decsz) + "> largeFileSz <"
-                        + std::to_string(szinfo.largesz) + "> filecount <" + std::to_string(szinfo.filecount) + "> for <" + std::string(src) + ">");
-               INFO("retval <" + std::to_string(result) + "> PrescanencryptErr <" + std::to_string(mPreScanEncryptErr) + ">");
-
-               mTotalFileCt = szinfo.filecount;
-               mTotalStSz = szinfo.totalstsz;
-
-               if (mPreScanEncryptErr == PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR) {
-                       result = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-               } else if ((mPreScanEncryptErr == PRESCAN_ERR) || (result == PRESCAN_ERR)) {
-#if !defined(NDEBUG)
-                       int total = (szinfo.encsz + szinfo.largesz - szinfo.cursz + 12 * 1024) / 1024;
-                       int needed  = total - szinfo.availsz / 1024;
-#endif
-                       if (isEcryptfsMountpointMounted(mPath)) {
-                               umount();
-                               INFO("Unmounting mpath <" + std::string(mPath) + ">");
-                       }
-
-                       INFO("Prescan failed with Too full error, need more space, " + std::to_string(needed) + " extra, total " + std::to_string(total));
-                       result = PRESCAN_ERR;
-               }
-
-               if (result == PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR) {
-                       INFO("EcryptfsEngine: Need to run Prescan Again");
-                       continue;
-               }
-
-               if (result == 0) {
-                       INFO("EcryptfsEngine: Prescan completed successfully");
-                       return 0;
-               }
-
-               INFO("EcryptfsEngine: Cannot encrypt, Disk Space is not enough");
-               return PRESCAN_ERR;
-       } while (1);
 }
 
-int EcryptfsEngine::getEncryptedSize(const char *src, EcryptfsEngine::sizeinfo_type *szinfo)
+EcryptfsEngine::~EcryptfsEngine()
 {
-       struct stat src_stat;
-       int result = ERR_NO;
-       INFO("getEncryptedSize: " + std::string(src));
-       if (::lstat(src, &src_stat) < 0)
-               INFO("getEncryptedSize: source : <" + std::string(src) + "> is a dangling link");
-       if (S_ISDIR(src_stat.st_mode)) {
-               /* dir call recursively */
-               DIR *dp;
-               struct dirent *d;
-
-               /* TODO check for recursion
-                * no need to Create dir
-                * */
-               dp = ::opendir(src);
-               if (NULL == dp) {
-                       result = -1;
-                       INFO("getEncryptedSize: opendir return null <" + std::string(src) + ">");
-                       return result;
-               }
-
-               while ((d = ::readdir(dp)) != NULL) {
-                       char *nsrc = NULL;
-                       char *ntmpdest = NULL;
-
-                       nsrc = catSubpathFile(src, d->d_name, &ntmpdest);
-
-                       if (nsrc == NULL) {
-                               if (ntmpdest) delete [] ntmpdest;
-                               continue;
-                       }
-
-                       if ((result = getEncryptedSize(nsrc, szinfo)) < 0) {
-                               INFO("getEncryptedSize() reutnred error for nsrc <" + std::string(nsrc) + "> result < " + std::to_string(result) + ">");
-                               if (result == PRESCAN_ERR)
-                                       mPreScanEncryptErr = result;
-                       }
-                       delete [] ntmpdest;
-                       delete [] nsrc;
-               }
-               ::closedir(dp);
-       } else if (S_ISREG(src_stat.st_mode)) {
-               long long padded_sz = src_stat.st_size;
-               long long new_enc_sz = 0;
-               int enc_fl = fn_was_encrypted(src);
-
-               INFO("fn_was_encrypted returned: " + std::to_string(enc_fl));
-
-               if (padded_sz % 4096)
-                       padded_sz = (1 + padded_sz / 4096) * 4096;
-
-               if (enc_fl != WAS_NOT_ENCRYPTED) {
-                       INFO("Skipping " + std::string(src));
-                       new_enc_sz = padded_sz;
-               } else {
-                       INFO("PRE ENC " + std::string(src));
-                       INFO("fn_was_encrypted returned: " + std::to_string(enc_fl));
-                       new_enc_sz = padded_sz + 2 * 4096;
-
-                       if (szinfo->largesz < src_stat.st_size)
-                               szinfo->largesz = src_stat.st_size;
-
-                       szinfo->filecount += 1;
-                       szinfo->totalstsz += src_stat.st_size;
-               }
-
-               // Pad it to block size
-               if (new_enc_sz % szinfo->blocksz)
-                       new_enc_sz = (1 + new_enc_sz / szinfo->blocksz) * szinfo->blocksz;
-
-               szinfo->encsz += new_enc_sz;
-
-               if ((enc_fl == WAS_NOT_ENCRYPTED) && ((szinfo->encsz - szinfo->cursz) > szinfo->availsz)) {
-                       if (mPreScanEncryptErr == PRESCAN_TEMP_FILE_EXIST_ERR) {
-                               result = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-                       } else
-                               result = PRESCAN_ERR;
-               }
-
-               {
-                       long long padded_cursz = src_stat.st_size;
-
-                       if (padded_cursz % szinfo->blocksz)
-                               padded_cursz = (1 + padded_cursz / szinfo->blocksz) * szinfo->blocksz;
-
-                       szinfo->cursz += padded_cursz;
-               }
-       }
-
-       return result;
 }
 
-int EcryptfsEngine::getDecryptedSize(const char *src, EcryptfsEngine::sizeinfo_type *szinfo)
+void EcryptfsEngine::mount(const data &key)
 {
-       struct stat src_stat;
-       int result = ERR_NO;
-       INFO("getDecryptedSize: " + std::string(src));
-       if (::lstat(src, & src_stat) < 0)
-               INFO("getDecryptedSize: source : <" + std::string(src) + "> is a dangling link");
-
-       if (S_ISDIR(src_stat.st_mode)) {
-               /* dir call recursively */
-               DIR *dp;
-               struct dirent *d;
-
-               /* TODO check for recursion
-                * no need to Create dir
-                * */
-               dp = ::opendir(src);
-               if (NULL == dp) {
-                       result = -1;
-                       INFO("getDecryptedSize: opendir return null <" + std::string(src) + ">");
-                       return result;
-               }
-
-               while ((d = ::readdir(dp)) != NULL) {
-                       char *nsrc = NULL;
-                       char *ntmpdest = NULL;
-
-                       nsrc = catSubpathFile(src, d->d_name, &ntmpdest);
-
-                       if (nsrc == NULL) {
-                               if (ntmpdest != NULL) delete [] ntmpdest;
-                               continue;
-                       }
-
-                       if ((result = getDecryptedSize(nsrc, szinfo)) < 0) {
-                               INFO("getDecryptedSize() reutnred error for nsrc <" + std::string(nsrc) + "> result < " + std::to_string(result) + ">");
-                               if (result == PRESCAN_ERR) {
-                                       mPreScanDecryptErr = result;
-                               }
-                       }
-                       delete [] ntmpdest;
-                       delete [] nsrc;
-               }
-               ::closedir(dp);
-       } else if (S_ISREG(src_stat.st_mode)) {
-               long long decsize = 0;
-               long long paddedsize = 0;
-               long long paddedstsz = 0;
-               int enc_fl = fn_was_encrypted(src);
-
-               INFO("fn_was_encrypted returned: " + std::to_string(enc_fl));
-
-               if (src_stat.st_size > 2 * 4096)
-                       decsize = src_stat.st_size - 2 * 4096;
-
-               paddedsize = decsize;
-               if (decsize % szinfo->blocksz)
-                       paddedsize = (1 + decsize / szinfo->blocksz) * szinfo->blocksz;
-
-               paddedstsz = src_stat.st_size;
-               if (paddedstsz % szinfo->blocksz)
-                       paddedstsz = (1 + paddedstsz / szinfo->blocksz) * szinfo->blocksz;
-
-               if (enc_fl == WAS_ENCRYPTED) {
-                       INFO("PRE ENC " + std::string(src));
-                       szinfo->filecount += 1;
-                       szinfo->totalstsz += src_stat.st_size;
-
-                       if (szinfo->largesz < src_stat.st_size)
-                               szinfo->largesz = src_stat.st_size;
-
-                       if ((decsize > szinfo->availsz) ||
-                                       (!decsize && (paddedstsz > szinfo->availsz))) {
-                               int tmpneeded;
-                               INFO("Runtime Error source: " + std::string(src) + ", decsz <" + std::to_string(szinfo->decsz) + "> cursz <" + std::to_string(szinfo->cursz) + ">, largesz <" +
-                                        std::to_string(szinfo->largesz) + "> st_size <" + std::to_string(src_stat.st_size) + "> availsz <" + std::to_string(szinfo->availsz) + ">");
-                               if (mPreScanDecryptErr == PRESCAN_TEMP_FILE_EXIST_ERR)
-                                       result = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-                               else
-                                       result = PRESCAN_ERR;
-
-                               if (decsize)
-                                       tmpneeded = decsize - szinfo->availsz;
-                               else
-                                       tmpneeded = paddedstsz - szinfo->availsz;
-
-                               if (szinfo->neededsz < tmpneeded) {
-                                       szinfo->neededsz = tmpneeded;
-                                       if (decsize)
-                                               szinfo->totalneedsz = decsize;
-                                       else
-                                               szinfo->totalneedsz = paddedstsz;
-                               }
-                       } else {
-                               if (decsize) {
-                                       long long delta = paddedsize - decsize - 2 * 4096;
-
-                                       szinfo->decsz += paddedsize;
-                                       if (delta > 0)
-                                               szinfo->availsz += delta;
-                               } else
-                                       szinfo->decsz += paddedstsz;
-
-                               szinfo->cursz += paddedstsz;
-                       }
-               } else {
-                       INFO("in decrypting case fn_was_encrypted returned: " + std::to_string(enc_fl));
-                       INFO("Skipping " << std::string(src));
-                       szinfo->decsz += paddedstsz;
-                       szinfo->cursz += paddedstsz;
-               }
-       }
-
-       return result;
+       ecryptfsMount(source, destination, key);
 }
 
-char *EcryptfsEngine::catSubpathFile(const char *src, const char *filename, char **prefixtmp)
+void EcryptfsEngine::umount()
 {
-       if (src == NULL || filename == NULL || prefixtmp == NULL)
-               return NULL;
-
-       char *catstr = new char[::strlen(src) + ::strlen(filename) + 2];
-       int len = ::strlen(src);
-       const char *prefix = ".tmp_eCfs";
-
-       if (filename && check_dots(filename)) {
-               delete [] catstr;
-               return NULL;
-       }
-
-       *prefixtmp = new char[::strlen(src) + ::strlen(filename) + ::strlen(prefix) + 2];
-
-       while (*filename == '/')
-               filename++;
-
-       if (src [len - 1] == '/') {
-               ::sprintf(catstr, "%s%s", src, filename);
-               ::sprintf(*prefixtmp, "%s%s%s", src, prefix, filename);
-       } else {
-               ::sprintf(catstr, "%s%s%s", src, "/", filename);
-               ::sprintf(*prefixtmp, "%s%s%s%s", src, "/", prefix, filename);
-       }
-
-       if (!::strncmp(filename, prefix, ::strlen(prefix))) {
-               INFO("Deleting Existing Temp file " + std::string(filename));
-               if (!mPreScanEncryptErr)
-                       mPreScanEncryptErr = PRESCAN_TEMP_FILE_EXIST_ERR;
-               else
-                       mPreScanEncryptErr = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-               if (!mPreScanDecryptErr)
-                       mPreScanDecryptErr = PRESCAN_TEMP_FILE_EXIST_ERR;
-               else
-                       mPreScanDecryptErr = PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR;
-               ::unlink(catstr);
-               delete [] * prefixtmp;
-               delete [] catstr;
-               *prefixtmp = NULL;
-               return NULL;
-       }
-
-       return catstr;
+       ecryptfsUmount(destination);
 }
 
-int EcryptfsEngine::fn_was_encrypted(const char *filePath)
+void EcryptfsEngine::encrypt(const data &key)
 {
-       int fd = 0;
-       int ret = WAS_NOT_ENCRYPTED;
-       __u32 attrs = 0;
-
-       if (filePath == NULL) {
-               INFO("Ecryptfs: fn_was_encrypted:  source file path is null");
-               return WAS_ECRYPTED_ERROR;
+       if (!isEnoughToCopyInPlace(source, getDecryptedSize)) {
+               throw runtime::Exception("No space to encryption");
        }
 
-       fd = ::open(filePath, O_RDWR);
-       if (fd < 0) {
-               INFO("Ecryptfs: fn_was_encrypted:  cannot open file " + std::string(strerror(errno)));
-               return WAS_ECRYPTED_ERROR;
-       }
+       progress.update(0);
 
-       if (::ioctl(fd, ECRYPTFS_IOCTL_GET_ATTRIBUTES, &attrs)) {
-               INFO("Ecryptfs: fn_was_encrypted: ioctl fail " + std::string(strerror(errno)));
-               ::close(fd);
-               return WAS_ECRYPTED_ERROR;
-       }
-
-       INFO("Ecryptfs: IOCT_GET_ATTRIBUTE = " + std::to_string(attrs));
-       if ((attrs & ECRYPTFS_WAS_ENCRYPTED) == ECRYPTFS_WAS_ENCRYPTED)
-               ret = WAS_ENCRYPTED;
-       else if ((attrs & ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE) == ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE)
-               ret = WAS_ENCRYPTED_OTHER_DEVICE;
-
-       ::close(fd);
-
-       return ret;
-}
-
-int EcryptfsEngine::createEncryptMetaData(const char *filename)
-{
-       int fd = -1;
-       INFO("createEncryptMetaData");
-
-       fd = ::open(filename, O_RDWR | O_CREAT | O_TRUNC, 0600);
-       if (fd < 0)     {
-               INFO("Cann't open " + std::string(filename));
-               return -1;
+       try {
+               ecryptfsMount(source, destination, key);
+       } catch (runtime::Exception &e) {
+               throw runtime::Exception("Failed to mount - " + std::string(e.what()));
        }
-       if (::fsync(fd) != 0)
-               INFO("Cann't fsync of '" + std::string(filename) + "'");
-       ::close(fd);
-       return 0;
-}
 
-int EcryptfsEngine::checkEncryptMetaData(const char *path)
-{
-       struct stat src_stat;
-       int retval = 0;
-
-       if (path == NULL) {
-               if (mMetaDataFile) {
-                       if (::lstat(mMetaDataFile, &src_stat) < 0)
-                               if (errno == ENOENT)
-                                       retval = -1;
-               }
-       } else {
-               std::cout << path << std::endl;
-               if (::stat(path, &src_stat) < 0)
-                       if (errno == ENOENT)
-                               retval = -1;
+       try {
+               unsigned long long totalSize = getAvailableSpace(source), current;
+           runtime::File tempDir(destination + "/" ENCRYPTION_CHECKER_NAME);
+
+               tempDir.makeDirectory();
+               copyInPlace(destination, destination, tempDir.getPath(),
+                                       [](const std::string &file) {
+                                               return true;
+                                       },
+                                       [&current, &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()));
        }
 
-       return retval;
-}
+       sync();
 
-void EcryptfsEngine::deleteEncryptMetaData(const char *filename)
-{
-       if (checkEncryptMetaData(filename) == 0)
-               ::unlink(filename);
+       progress.done();
 }
 
-int EcryptfsEngine::isMountpointMounted(const std::string &path)
+void EcryptfsEngine::decrypt(const data &key)
 {
-       char device[256];
-       char mount_path[256];
-       char rest[256];
-       FILE *fp;
-       char line[1024];
-
-       if (!(fp = ::fopen("/proc/mounts", "r"))) {
-               INFO("Error opening /proc/mounts (" + std::string(strerror(errno)) + ")");
-               return 0;
+       if (!isEnoughToCopyInPlace(destination, getEncryptedSize)) {
+               throw runtime::Exception("No space to encryption");
        }
 
-       while (::fgets(line, sizeof(line), fp)) {
-               line[::strlen(line) - 1] = '\0';
-               ::sscanf(line, "%255s %255s %255s\n", device, mount_path, rest);
-               if (!::strcmp(mount_path, path.c_str())) {
-                       ::fclose(fp);
-                       return 1;
-               }
-       }
+       progress.update(0);
 
-       ::fclose(fp);
-       return 0;
-}
-
-int EcryptfsEngine::isEcryptfsMountpointMounted(const std::string &path)
-{
-       char device[256];
-       char mount_path[256];
-       char dev_path[256];
-       char rest[256];
-       FILE *fp;
-       char line[1024];
-
-       if (!(fp = ::fopen("/proc/mounts", "r"))) {
-               INFO("Error opening /proc/mounts (" + std::string(strerror(errno)) + ")");
-               return -1;
+       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);
+
+               copyInPlace(tempMountpoint.getPath(), source,
+                                       tempDir.getPath(), wasEncrypted,
+                                       [&current, &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()));
        }
 
-       while (::fgets(line, sizeof(line), fp)) {
-               line[strlen(line) - 1] = '\0';
-               ::sscanf(line, "%255s %255s %255s %255s\n", dev_path, mount_path, device, rest);
-               if (!::strcmp(mount_path, path.c_str()) && !strcmp(device, "ecryptfs")) {
-                       ::fclose(fp);
-                       INFO("Returning True mount_path<" + std::string(mount_path) + ">,path <" + path + ">, device <" + std::string(device) + ">");
-                       return 0;
-               }
-       }
+       sync();
 
-       fclose(fp);
-       return -1;
+       progress.done();
 }
 
 const EcryptfsEngine::data EcryptfsEngine::getKeyMeta()
 {
-    return FileFooter::read(mSource);
+    return FileFooter::read(source);
 }
 
 void EcryptfsEngine::setKeyMeta(const data &meta)
 {
-       FileFooter::write(mSource, meta);
+       FileFooter::write(source, meta);
 }
 
 } // namespace ode
index 9fb7c8620a5f1d61611a94073f50514f9d1dfb5b..4e5ebb5d6e9c6622dde4cdfbb8eec90d242a05d4 100644 (file)
 
 #include "../progress-bar.h"
 
-#define __u32 unsigned int
-
-#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_MAX_KEY_BYTES              64
-#define ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES    512
-#define ECRYPTFS_MAX_PKI_NAME_BYTES         16
-#define ECRYPTFS_SALT_SIZE                  8
-#define ECRYPTFS_BUFFER_SIZE 4096
-
-#define ECRYPTFS_MAJOR_VERSION 0x00
-#define ECRYPTFS_MINOR_VERSION 0x04
-#define ECRYPTFS_VERSION ((ECRYPTFS_MAJOR_VERSION << 8) | ECRYPTFS_MINOR_VERSION)
-#define ECRYPTFS_PWD_PAYLOAD_TYPE      0
-#define ECRYPTFS_SESSION_KEY_ENCRYPTION_KEY_SET 0x02
-
-#define MAX_KEY_BYTES 32
-#define SIG_SIZE 8
-#define ECRYPTFS_MAX_OPTIONS   1024
-
-#define ECRYPTFS_PLAINTEXT_PASSTHOUGH  "ecryptfs_passthrough"
-#define ECRYPTFS_SIGNATURE             "ecryptfs_sig="
-#define ECRYPTFS_CIPHERA               "ecryptfs_cipher="
-#define ECRYPTFS_KEY_BYTES             "ecryptfs_key_bytes="
-#define ECRYPTFS_UNLINK_SIGNATURE      "ecryptfs_unlink_sig"
-#define ECRYPTFS_FEK_CIPHER            "aes"
-#define ECRYPTFS_ENABLE_FILTERING      "ecryptfs_enable_filtering="
-#define ECRYPTFS_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 ECRYPTFS_GLOBAL_EXCLUSION_LIST "*"
-
-#define SMACKFS_MAGIC  0x43415d53
-#define SMACKFS_MNT            "/smack"
-#define SMACKFS_MOUNT_OPT              "smackfsroot=*,smackfsdef=*"
-
-#define EXCL_ALL_NEW_ON   2
-#define EXCL_MEDIA_ON   1
-#define EXCL_MEDIA_OFF  0
-
-typedef int32_t key_serial_t;
-
-#define KEY_SPEC_USER_KEYRING           -4      /* - key ID for UID-specific keyring */
-#define KEYCTL_SEARCH                   10      /* search for a key in a keyring */
-#define AUTH_TOKEN_TYPE                "user"
-#define ECRYPTFS_MOUNT_DEVICE  "ecryptfs"
-
-#define CRYPT_META_FILE ".MetaEcfsFile"
-#define ORIG_META_FILE_PATH "/opt/media/SDCardA1/.MetaEcfsFile"
-
-#define ERR_NO                         0
-#define ERR_FAILED_AUTH                1
-#define ERR_MOUNT              5
-#define ERR_UNMOUNT            6
-
-#define ECRYPTFS_IOCTL_GET_ATTRIBUTES  _IOR('l', 0x10, __u32)
-#define ECRYPTFS_WAS_ENCRYPTED 0x0080
-#define ECRYPTFS_WAS_ENCRYPTED_OTHER_DEVICE 0x0100
-
-#define PRESCAN_ERR   (-2)
-#define PRESCAN_TEMP_FILE_EXIST_ERR   (-3)
-#define PRESCAN_TEMP_FILE_EXIST_AND_SIZE_ERR   (-4)
-
-#define WAS_ECRYPTED_ERROR (-2)
-#define WAS_NOT_ENCRYPTED (-1)
-#define WAS_ENCRYPTED 0
-#define WAS_ENCRYPTED_OTHER_DEVICE 1
-
-#define DELTA_PROGRESS 1
-
-#define check_dots(p) ((p)[0] == '.' && (!(p)[1] || ((p)[1] =='.'&& !(p)[2])))
-
 namespace ode {
 
 class EcryptfsEngine final {
 public:
-       EcryptfsEngine(const std::string& src, const std::string& dest, const ProgressBar& prgsBar);
+       EcryptfsEngine(const std::string& src, const std::string& dest, const ProgressBar& prgs);
        EcryptfsEngine(const EcryptfsEngine&) = delete;
        EcryptfsEngine(EcryptfsEngine&&) = delete;
        ~EcryptfsEngine();
@@ -116,87 +45,16 @@ public:
 
        const std::string& getSource()
        {
-               return mSource;
+               return source;
        }
 
        const std::string& getDestination()
        {
-               return mDestination;
-       }
-
-       void setSource(const std::string& src)
-       {
-               mSource = src;
-       }
-
-       void setDestination(const std::string& dest)
-       {
-               mDestination = dest;
+               return destination;
        }
 
        typedef std::vector<unsigned char> data;
 
-       typedef struct {
-               int blocksz;
-               int filecount;
-               long long availsz;
-               long long decsz;
-               long long encsz;
-               long long cursz;
-               long long largesz;
-               long long neededsz;
-               long long totalneedsz;
-               long long totalstsz;
-       } sizeinfo_type;
-
-       struct ecryptfs_session_key {
-               u_int32_t flags;
-               u_int32_t encrypted_key_size;
-               u_int32_t decrypted_key_size;
-               u_int8_t encrypted_key[ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES];
-               u_int8_t decrypted_key[ECRYPTFS_MAX_KEY_BYTES];
-       };
-
-       struct ecryptfs_password {
-               u_int32_t password_bytes;
-               int32_t hash_algo;
-               u_int32_t hash_iterations;
-               u_int32_t session_key_encryption_key_bytes;
-               u_int32_t flags;
-               u_int8_t session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES];
-               u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
-               u_int8_t salt[ECRYPTFS_SALT_SIZE];
-       };
-
-       struct ecryptfs_private_key {
-               u_int32_t key_size;
-               u_int32_t data_len;
-               u_int8_t signature[ECRYPTFS_PASSWORD_SIG_SIZE + 1];
-               char pki_type[ECRYPTFS_MAX_PKI_NAME_BYTES + 1];
-               u_int8_t data[];
-       };
-
-       struct ecryptfs_auth_tok {
-               u_int16_t version;
-               u_int16_t token_type;
-               u_int32_t flags;
-               struct ecryptfs_session_key session_key;
-               u_int8_t reserved[32];
-               union {
-                       struct ecryptfs_password password;
-                       struct ecryptfs_private_key private_key;
-               } token;
-       } __attribute__ ((packed));
-
-       typedef struct ecryptfs_auth_tok ecryptfs_payload;
-
-       key_serial_t add_key(const char *type, const char *description, const void *payload, size_t plen, key_serial_t ringid);
-       long keyctl_search(key_serial_t ringid, const char *type, const char *description, key_serial_t destringid);
-       void hexConvert(char *dest, unsigned char *src, int srcLen);
-       int add_user_auth_token_to_keyring(ecryptfs_payload *payload) ;
-       int smack_check(void);
-       void build_ecryptfs_options(char *ecryptfs_opts, char *sig, int excludeMediaTypes);
-
        void mount(const data& key);
        void umount();
 
@@ -206,42 +64,9 @@ public:
        const data getKeyMeta();
        void setKeyMeta(const data &data);
 
-       int DoCrypt(const data &key, const char *path, int reqEnc, int excludeMedia);
-       int DoEncrypt(const data &key);
-       int DoDecrypt(const data &key);
-       void progress(long long size);
-       long long CopyImpl(int sfd, int dfd, long long fullsz, bool enctype);
-       ssize_t FullRead (int fd, void * buf, size_t count);
-       ssize_t FullWrite (int fd, const void * buf, size_t len);
-       int CopyFile (const char * src, const char * dest, struct stat * src_stat, bool enctype);
-       void syncdatafile (const char * src);
-       int cryptInplace(const char * src, const char * tmpdest, bool dec_fl);
-       int preScanForEncrypt(const char *src);
-       int preScanForDecrypt(const char * src);
-       int getEncryptedSize(const char * src, sizeinfo_type * szinfo);
-       int getDecryptedSize(const char * src, sizeinfo_type * szinfo);
-       char * catSubpathFile(const char * src, const char * filename, char ** prefixtmp);
-       int fn_was_encrypted(const char *filePath);
-       int createEncryptMetaData(const char *filename);
-       int checkEncryptMetaData(const char *path);
-       void deleteEncryptMetaData (const char *filename);
-       int isMountpointMounted(const std::string& path);
-       int isEcryptfsMountpointMounted(const std::string& path);
-
 private:
-       std::string mSource, mDestination;
-       ecryptfs_payload sde_payload;
-       const char *mPath;
-       char *mMetaDataFile;
-       int mReqEnc;
-       int mExcludeMedia;
-       int mPreScanEncryptErr;
-       int mPreScanDecryptErr;
-       int mLastProg;
-       int mTotalFileCt;
-       long long  mTotalStSz;
-       long long mTotalCopied;
-       ProgressBar progressBar;
+       std::string source, destination;
+       ProgressBar progress;
 };
 
 } // namespace ode
index bd3b98b136b283dc791cccbd8ccc93e8506c364d..2601a353a97ee3a0b5c63f3a9e4d7719449ec97a 100644 (file)
@@ -13,6 +13,9 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
+#include <fstream>
+#include <sstream>
+
 #include <signal.h>
 #include <unistd.h>
 #include <sys/mount.h>
@@ -78,8 +81,7 @@ void externalCallback(dbus::Variant parameters)
                     &intparams[5]); // strage id
        if(intparams[2] == 0) {
                INFO("Unmounted!!!");
-       }
-       else {
+       } else {
                INFO("Mounted!!!");
                // TODO
                // Password Popup
@@ -100,32 +102,7 @@ void externalAddEventReceiver()
                                                            externalCallback);
 }
 
-void externalCheckMount()
-{
-       INFO("EcryptfsEncrypt");
-       if (!engine.isMountpointMounted(EXTERNAL_STORAGE_PATH)) {
-               INFO("SD Card not inserted!");
-       }
-       else {
-               INFO("SD Card inserted!");
-               if (engine.checkEncryptMetaData(ORIG_META_FILE_PATH) == 0) {
-                       INFO("SD Card encrypted!");
-                       if (engine.isEcryptfsMountpointMounted(EXTERNAL_STORAGE_PATH) == 0) {
-                               INFO("Already Ecryptfs Mounted");
-                       }
-                       else {
-//                             std::string pw = "tizen";
-//                             KeyManager::data pwData(pw.begin(), pw.end());
-//                             engine.mount(keyManager.getDEK(pwData));
-                       }
-               }
-               else {
-                       INFO("SD Card not encrypted!");
-               }
-       }
-}
-
-}
+} // namsepace
 
 ExternalEncryption::ExternalEncryption(ODEControlContext &ctx) :
        context(ctx)
@@ -138,7 +115,6 @@ ExternalEncryption::ExternalEncryption(ODEControlContext &ctx) :
        context.registerNonparametricMethod(this, "", (int)(ExternalEncryption::getState));
 
        externalAddEventReceiver();
-       externalCheckMount();
 }
 
 
diff --git a/server/kernel-keyring.cpp b/server/kernel-keyring.cpp
new file mode 100644 (file)
index 0000000..98f1e8e
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ *  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 <unistd.h>
+#include <sys/mount.h>
+#include <sys/syscall.h>
+#include <linux/limits.h>
+
+#include "kernel-keyring.h"
+
+#ifndef KEYCTL_SEARCH
+#define KEYCTL_SEARCH   10
+#endif
+
+int32_t KernelKeyRing::add(const std::string& type, const std::string& description, const void* payload, size_t plen, int32_t ringid)
+{
+       return ::syscall(__NR_add_key, type.c_str(), description.c_str(), payload, plen, ringid);
+}
+
+long KernelKeyRing::search(int32_t ringid, const std::string& type, const std::string& description, int32_t destringid)
+{
+       return ::syscall(__NR_keyctl, KEYCTL_SEARCH, ringid, type.c_str(), description.c_str(), destringid);
+}
+
+long KernelKeyRing::link(int32_t keyid, int32_t ringid)
+{
+       return ::syscall(__NR_keyctl, KEYCTL_LINK, keyid, ringid);
+}
+
+long KernelKeyRing::unlink(int32_t keyid, int32_t ringid)
+{
+       return ::syscall(__NR_keyctl, KEYCTL_UNLINK, keyid, ringid);
+}
diff --git a/server/kernel-keyring.h b/server/kernel-keyring.h
new file mode 100644 (file)
index 0000000..786b069
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ *  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 __KERNEL_KEY_RING_H__
+#define __KERNEL_KEY_RING_H__
+
+#include <sys/types.h>
+#include <linux/keyctl.h>
+
+#include <string>
+
+/* 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
+
+class KernelKeyRing final {
+public:
+       KernelKeyRing() = delete;
+       KernelKeyRing(const KernelKeyRing&) = delete;
+       KernelKeyRing(KernelKeyRing&&) = delete;
+
+       KernelKeyRing& operator=(const KernelKeyRing&) = delete;
+       KernelKeyRing& operator=(KernelKeyRing&&) = delete;
+
+       static int32_t add(const std::string& type, const std::string& description, const void* payload, size_t plen, int32_t ringid);
+
+       static long search(int32_t ringid, const std::string& type, const std::string& description, int32_t destringid);
+
+       static long link(int32_t keyid, int32_t ringid);
+       static long unlink(int32_t keyid, int32_t ringid);
+};
+
+#endif //!__KERNEL_KEY_RING_H__
index a8c97736289985ac561e9ef81a19e7df1f704d1e..fc3ca056c5a32137e95a0b39b228bd8444127d9b 100755 (executable)
@@ -21,6 +21,7 @@ SET(TEST_SRC  main.cpp
                                ecryptfs-engine.cpp
                                af.cpp
                                ../server/file-footer.cpp
+                               ../server/kernel-keyring.cpp
                                ../server/engine/ext4-engine.cpp
                                ../server/engine/ecryptfs-engine.cpp
                                ../server/key-manager/key-generator.cpp