From b37ba2656dbef3e82243f2c55345de6fec94158e Mon Sep 17 00:00:00 2001 From: Sungbae Yoo Date: Tue, 10 Jan 2017 17:05:25 +0900 Subject: [PATCH] Refactor ecryptfs engine Signed-off-by: Sungbae Yoo Change-Id: I1420497da64043e2391d0be8a1b2896976e519b7 --- server/CMakeLists.txt | 1 + server/engine/ecryptfs-engine.cpp | 1211 +++++++++---------------------------- server/engine/ecryptfs-engine.h | 185 +----- server/external-encryption.cpp | 34 +- server/kernel-keyring.cpp | 46 ++ server/kernel-keyring.h | 50 ++ tests/CMakeLists.txt | 1 + 7 files changed, 386 insertions(+), 1142 deletions(-) create mode 100644 server/kernel-keyring.cpp create mode 100644 server/kernel-keyring.h diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 2074888..2b55873 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -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 diff --git a/server/engine/ecryptfs-engine.cpp b/server/engine/ecryptfs-engine.cpp index 21c5677..64f4eac 100644 --- a/server/engine/ecryptfs-engine.cpp +++ b/server/engine/ecryptfs-engine.cpp @@ -13,1054 +13,399 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include + +#include +#include #include #include -#include +#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 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 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 &isTarget, + const std::function &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 &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, ×) < 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; + }, + [¤t, &totalSize, this](unsigned long long size) { + current += size; + this->progress.update(current * 100 / totalSize); + }); + } catch (runtime::Exception &e) { + try { + ecryptfsUmount(destination); + } catch (runtime::Exception &e) {} + throw runtime::Exception("Failed to encrypt file - " + std::string(e.what())); } - 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, + [¤t, &totalSize, this](unsigned long long size) { + current += size; + this->progress.update(current * 100 / totalSize); + }); + ecryptfsUmount(tempMountpoint.getPath()); + + tempDir.remove(true); + } catch (runtime::Exception &e) { + throw runtime::Exception("Failed to decrypt file - " + std::string(e.what())); } - 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 diff --git a/server/engine/ecryptfs-engine.h b/server/engine/ecryptfs-engine.h index 9fb7c86..4e5ebb5 100644 --- a/server/engine/ecryptfs-engine.h +++ b/server/engine/ecryptfs-engine.h @@ -31,82 +31,11 @@ #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 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 diff --git a/server/external-encryption.cpp b/server/external-encryption.cpp index bd3b98b..2601a35 100644 --- a/server/external-encryption.cpp +++ b/server/external-encryption.cpp @@ -13,6 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License */ +#include +#include + #include #include #include @@ -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 index 0000000..98f1e8e --- /dev/null +++ b/server/kernel-keyring.cpp @@ -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 +#include +#include +#include + +#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 index 0000000..786b069 --- /dev/null +++ b/server/kernel-keyring.h @@ -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 +#include + +#include + +/* 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__ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index a8c9773..fc3ca05 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 -- 2.7.4