* See the License for the specific language governing permissions and
* limitations under the License
*/
-#include <iostream>
+
#include <string>
-#include <string.h>
-#include <dirent.h>
+#include <iomanip>
+#include <iostream>
+
#include <fcntl.h>
#include <unistd.h>
-#include <stdlib.h>
-#include <linux/keyctl.h>
+#include <sys/vfs.h>
+#include <sys/stat.h>
#include <sys/mount.h>
-#include <sys/xattr.h>
-#include <sys/syscall.h>
#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/sendfile.h>
+#include <sys/types.h>
+#include <sys/xattr.h>
-#include <klay/filesystem.h>
-#include <klay/audit/logger.h>
#include <klay/error.h>
#include <klay/exception.h>
+#include <klay/filesystem.h>
+#include <klay/audit/logger.h>
+#include "../../kernel-keyring.h"
#include "../../file-footer.h"
#include "../../key-manager/key-generator.h"
#include "ext4-engine.h"
-namespace ode {
+#define ENCRYPTION_DIR ".encrypted"
+
+#define SMACK_LABEL_LEN_MAX 255
#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
+#define EXT4_KEYRING_TYPE "logon"
/* Encryption algorithms */
#define EXT4_ENCRYPTION_MODE_INVALID 0
#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;
unsigned int size;
} __attribute__((__packed__));
-/* for now, It only suits for "/opt/usr" */
+namespace ode {
+
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)
+const Ext4Engine::data generateKeyDescriptor(const 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;
+ auto hash = KeyGenerator::SHA512(KeyGenerator::SHA512(key));
+ hash.resize(EXT4_KEY_DESCRIPTOR_SIZE);
+ return hash;
}
-const Ext4Engine::data generateKeyRefStr(const Ext4Engine::data& key)
+const std::string convertToHex(const Ext4Engine::data &binary)
{
- 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;
- }
+ std::stringstream hex;
- ret[a] = '\0';
+ hex << std::hex << std::setfill('0');
+ for (unsigned int byte : binary) {
+ hex << std::setw(2) << byte;
+ }
+ return hex.str();
+}
- return ret;
+Ext4Engine::data sanitizeKey(const Ext4Engine::data &key)
+{
+ Ext4Engine::data sanitized(key);
+ sanitized.resize(EXT4_MAX_KEY_SIZE);
+ return sanitized;
}
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());
+ struct ext4_encryption_key payload;
+ std::string keyDescriptor;
+ int keyringId;
+
+ keyringId = KernelKeyRing::getKeyringId(KEY_SPEC_SESSION_KEYRING, 0);
+ if (keyringId == -1) {
+ throw runtime::Exception("Unable to get keyring id");
+ }
- keyRefFull = "ext4:" + keyRef;
- ret = ::syscall(__NR_keyctl, KEYCTL_SEARCH, keyringId, ext4KeyringType.c_str(), keyRefFull.c_str(), 0);
- if (ret != -1) {
+ keyDescriptor = "ext4:" + convertToHex(generateKeyDescriptor(key));
+ if (KernelKeyRing::search(keyringId, EXT4_KEYRING_TYPE,
+ keyDescriptor, 0) >= 0) {
INFO("Key with descriptor already exist");
return;
}
- ext4Key.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
- ::memset(ext4Key.raw, 0, EXT4_MAX_KEY_SIZE);
- ::memcpy(ext4Key.raw, key.data(), key.size());
- ext4Key.size = EXT4_MAX_KEY_SIZE;
- ret = ::syscall(__NR_add_key, ext4KeyringType.c_str(), keyRefFull.c_str(),
- (void *)&ext4Key, sizeof(ext4Key), keyringId);
+ payload.mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
+ payload.size = EXT4_MAX_KEY_SIZE;
+ ::memcpy(payload.raw, key.data(), key.size());
- if (ret == -1) {
- throw runtime::Exception(runtime::GetSystemErrorMessage());
+ if (KernelKeyRing::add(EXT4_KEYRING_TYPE, keyDescriptor,
+ (void *)&payload, sizeof(payload),
+ KEY_SPEC_USER_KEYRING) < 0) {
+ throw runtime::Exception("Unable to add key to keyring");
}
}
-static void copySmackLabel(std::string& srcPath, std::string& destPath)
+int intLog2(int arg)
{
- Ext4Engine::data smackLabel(SMACK_LABEL_LEN_MAX + 1);
+ int l = 0;
- if (::getxattr(srcPath.c_str(), smackAccessLabel.c_str(), (unsigned char*)smackLabel.data(), SMACK_LABEL_LEN_MAX + 1) == -1)
- throw runtime::Exception(runtime::GetSystemErrorMessage());
+ arg >>= 1;
+ while(arg) {
+ l++;
+ arg >>= 1;
+ }
- if (::setxattr(destPath.c_str(), smackAccessLabel.c_str(), smackLabel.data(), smackLabel.size(), 0) == -1)
- throw runtime::Exception(runtime::GetSystemErrorMessage());
+ return l;
}
-int Ext4Engine::copy(std::string& src, std::string& dest)
+void setPolicy(const std::string& path, const Ext4Engine::data& key)
{
- int readFd, writeFd, ret;
- struct stat st;
+ struct ext4_encryption_policy policy;
+ int pad = 4;
+ int fd, rc;
- ret = ::stat(src.c_str(), &st);
- if (ret != 0) {
- throw runtime::Exception(src + runtime::GetSystemErrorMessage());
+ fd = ::open(path.c_str(), O_DIRECTORY);
+ if (fd == -1) {
+ throw runtime::Exception("invalid path");
}
- 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)
- throw runtime::Exception(runtime::GetSystemErrorMessage());
+ Ext4Engine::data descriptor = generateKeyDescriptor(key);
- /* 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());
+ 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(), descriptor.size());
- if (::posix_fadvise(writeFd, 0, st.st_size, POSIX_FADV_DONTNEED) < 0)
- throw runtime::Exception(dest + runtime::GetSystemErrorMessage());
+ rc = ::ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &policy);
+ ::close(fd);
- ::close(readFd);
- ::close(writeFd);
- return 0;
+ if (rc) {
+ throw runtime::Exception("set policy failed :" + runtime::GetSystemErrorMessage());
+ }
}
-static void preScanDir(std::string& dir)
+bool hasPolicy(const 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;
+ struct ext4_encryption_policy policy;
+ int fd, rc;
+ fd = ::open(dir.c_str(), O_DIRECTORY);
+ if (fd == -1) {
+ return false;
+ }
- if (path.size() >= PATH_MAX)
- throw runtime::Exception(path + " :path length has got too long");
+ rc = ::ioctl(fd, EXT4_IOC_GET_ENCRYPTION_POLICY, &policy);
+ close(fd);
- preScanDir(path);
- }
- }
+ if (rc) {
+ return false;
}
- if (::closedir(d))
- throw runtime::Exception(runtime::GetSystemErrorMessage());
-
+ return true;
}
-void Ext4Engine::listDir(std::string& source, std::string& dest, bool excludeFlag)
+unsigned long long getUsedSpace(const std::string& mountPoint)
{
- 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);
- }
- }
+ struct statfs statbuf;
+ if (::statfs(mountPoint.c_str(), &statbuf)) {
+ throw runtime::Exception("Failed to access " + mountPoint);
}
- 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());
- }
+ return (unsigned long long)(statbuf.f_blocks - statbuf.f_bfree) * statbuf.f_bsize;
}
-static int intLog2(int arg)
+unsigned long long getAvailableSpace(const std::string& mountPoint)
{
- int l = 0;
-
- arg >>= 1;
- while(arg) {
- l++;
- arg >>= 1;
+ struct statfs statbuf;
+ if (::statfs(mountPoint.c_str(), &statbuf)) {
+ throw runtime::Exception("Failed to access " + mountPoint);
}
- return l;
+ return (unsigned long long)statbuf.f_bfree * statbuf.f_bsize;
}
-static void setPolicy(const std::string& source, const Ext4Engine::data& key)
+static void copyDac(const std::string& srcPath, const std::string& destPath)
{
- struct ext4_encryption_policy policy;
- int pad = 4;
- int fd, rc;
- Ext4Engine::data descriptor(EXT4_KEY_DESCRIPTOR_SIZE);
+ runtime::File src(srcPath), dest(destPath);
- descriptor = generateKeyDesc(key);
- std::string descStr(descriptor.begin(), descriptor.end());
+ try {
+ mode_t mode = src.getMode();
+ uid_t uid = src.getUid();
+ gid_t gid = src.getGid();
- 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);
+ try {
+ dest.chown(uid, gid);
+ } catch (runtime::Exception &e) {}
- rc = ::ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &policy);
- ::close(fd);
-
- if (rc)
- throw runtime::Exception("set policy failed :" + runtime::GetSystemErrorMessage());
+ try {
+ dest.chmod(mode);
+ } catch (runtime::Exception &e) {}
+ } catch (runtime::Exception &e) {}
}
-static bool prepareEncryptDir(std::string& sourceName, std::string& destName)
+static void copyMac(const std::string& srcPath, const std::string& destPath)
{
- struct stat dirStat;
- ::stat(destName.c_str(), &dirStat);
+ char smackLabel[SMACK_LABEL_LEN_MAX + 1];
+ ssize_t labelSize;
- 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());
+ labelSize = ::getxattr(srcPath.c_str(), "security.SMACK64", smackLabel, SMACK_LABEL_LEN_MAX + 1);
+
+ if (labelSize == -1) {
+ return;
}
- 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;
+ ::setxattr(destPath.c_str(), "security.SMACK64", smackLabel, labelSize, 0);
}
-static int getPolicy(const std::string& dirName)
+bool isEnoughToCopyInPlace(const std::string& path)
{
- struct ext4_encryption_policy policy;
- int fd, rc;
+ unsigned long long availableSpace = getAvailableSpace(path);
+
+ std::function<bool(const std::string &path)> check;
+ check = [&check, 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 (iter->size() > availableSpace) {
+ return false;
+ }
+ }
+ return true;
+ };
- fd = ::open(dirName.c_str(), O_DIRECTORY);
- if (fd == -1)
- return 0;
+ return check(path);
+}
- rc = ::ioctl(fd, EXT4_IOC_GET_ENCRYPTION_POLICY, &policy);
- close(fd);
- if (rc) {
- ERROR("ioctl error");
- return 0;
+void copyInPlace(const std::string& source, const std::string& destination,
+ const std::function<void(unsigned long long)> &addProgress)
+{
+ for (runtime::DirectoryIterator iter(source), end; iter != end; ++iter) {
+ if (iter->getPath() == destination) {
+ continue;
+ }
+
+ runtime::File destFile(destination + "/" + iter->getName());
+ if (iter->isDirectory()) {
+ destFile.makeDirectory();
+ copyInPlace(iter->getPath(), destFile.getPath(), addProgress);
+ } else {
+ iter->copyTo(destFile.getPath());
+ addProgress(iter->size());
+ }
+ copyDac(iter->getPath(), destFile.getPath());
+ copyMac(iter->getPath(), destFile.getPath());
+
+ iter->remove();
}
- return 1;
}
+} // namespace
+
Ext4Engine::Ext4Engine(const std::string& src, const std::string& dest, const ProgressBar &prgsBar) :
- source(src), destination(dest), progressBar(prgsBar)
+ source(src), destination(dest), progress(prgsBar)
{
}
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());
+ std::string encryptedPath(destination + "/" ENCRYPTION_DIR);
+
+ addKeyToKeyring(sanitizeKey(key));
+
+ if (::mount(source.c_str(), destination.c_str(), "ext4", 0, 0) < 0) {
+ throw runtime::Exception("Mount error - " + runtime::GetSystemErrorMessage());
+ }
+
+ if (::mount(encryptedPath.c_str(), destination.c_str(), NULL, MS_BIND, 0) < 0) {
+ throw runtime::Exception("Mount error - " + runtime::GetSystemErrorMessage());
+ }
}
void Ext4Engine::umount()
{
- /* for decrypt, umount /opt/usr */
- if (::umount(destination.c_str()))
- throw runtime::Exception(runtime::GetSystemErrorMessage());
-}
+ //TODO : remove Key
-void Ext4Engine::addKey(const Ext4Engine::data& key)
-{
- addKeyToKeyring(key);
+ if (::umount(destination.c_str())) {
+ throw runtime::Exception(runtime::GetSystemErrorMessage());
+ }
}
void Ext4Engine::encrypt(const Ext4Engine::data& key, unsigned int options)
{
- std::string sourceDir = getSource();
- std::string destDir = getDestination();
- bool copyFlag = false;
+ if (!isEnoughToCopyInPlace(destination)) {
+ throw runtime::Exception("No space to encryption");
+ }
- if (!(copyFlag = prepareEncryptDir(sourceDir, destDir)))
- throw runtime::Exception("prepareEncryptDir failed");
+ if (::mount(source.c_str(), destination.c_str(), "ext4", 0, 0) < 0) {
+ throw runtime::Exception("Mount error - " + runtime::GetSystemErrorMessage());
+ }
- preScanDir(secondMountPoint);
- /* key add to keyring */
- addKeyToKeyring(key);
- /* set policy */
- setPolicy(bindMountPoint, key);
+ Ext4Engine::data sanitizedKey = sanitizeKey(key);
+ addKeyToKeyring(sanitizedKey);
- if (copyFlag)
- listDir(secondMountPoint, bindMountPoint, true);
- INFO("[ext4 encrypt] copy done");
+ runtime::File encrypted(destination + "/" ENCRYPTION_DIR);
+ if (encrypted.exists()) {
+ encrypted.remove(true);
+ }
+ encrypted.makeDirectory();
+ setPolicy(encrypted.getPath(), sanitizedKey);
+
+ unsigned long long totalSize = getUsedSpace(source), current = 0;
+ copyInPlace(destination, encrypted.getPath(),
+ [¤t, &totalSize, this](unsigned long long size) {
+ current += size;
+ this->progress.update(current, totalSize, 1);
+ });
+
+ if (::mount(encrypted.getPath().c_str(), destination.c_str(), NULL, MS_BIND, 0) < 0) {
+ throw runtime::Exception("Mount error - " + runtime::GetSystemErrorMessage());
+ }
- progressBar.done();
- if (::mount(bindMountPoint.c_str(), destDir.c_str(), "ext4", MS_BIND, 0) < 0)
- throw runtime::Exception(runtime::GetSystemErrorMessage());
+ sync();
+
+ progress.done();
}
void Ext4Engine::decrypt(const Ext4Engine::data& key, unsigned int options)
{
- std::string destDir = getDestination();
+ if (!isEnoughToCopyInPlace(destination)) {
+ throw runtime::Exception("No space to encryption");
+ }
- if (getPolicy(bindMountPoint) != 1)
+ if (!hasPolicy(destination)) {
throw runtime::Exception("failed get policy");
- addKeyToKeyring(key);
+ }
- preScanDir(bindMountPoint);
+ if (::umount(destination.c_str())) {
+ throw runtime::Exception(runtime::GetSystemErrorMessage());
+ }
- listDir(bindMountPoint, secondMountPoint, false);
- INFO("[ext4 decrypt] copy done");
- progressBar.done();
+ runtime::File encrypted(destination + "/" ENCRYPTION_DIR);
- if (::open(bindMountPoint.c_str(), O_RDONLY) != -1)
- ::remove(bindMountPoint.c_str());
+ unsigned long long totalSize = getUsedSpace(source), current = 0;
+ copyInPlace(encrypted.getPath(), destination,
+ [¤t, &totalSize, this](unsigned long long size) {
+ current += size;
+ this->progress.update(current, totalSize, 1);
+ });
- /* 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());
+ encrypted.remove(true);
+
+ sync();
- if (::open(secondMountPoint.c_str(), O_RDONLY) != -1)
- ::remove(secondMountPoint.c_str());
+ progress.done();
}
bool Ext4Engine::isKeyMetaSet()