From db1d49c70eec489cf3d60a4ec70a8e7c0f3f2b76 Mon Sep 17 00:00:00 2001 From: Paul Lawrence Date: Fri, 10 Apr 2015 07:47:30 -0700 Subject: [PATCH] DO NOT MERGE New ext4enc kernel switching from xattrs to ioctl (cherry-picked from commit 9f53fb4abca1ee3af7b537c95445161db4b81f86) This is one of three changes to enable this functionality: https://android-review.googlesource.com/#/c/146259/ https://android-review.googlesource.com/#/c/146264/ https://android-review.googlesource.com/#/c/146265/ Bug: 18151196 Change-Id: I05b96f49b8848e82484a500e4536bdb4d2cdd635 --- ext4_utils/ext4_crypt.cpp | 74 +++++++++++++++---------------- ext4_utils/ext4_crypt_init_extensions.cpp | 7 ++- ext4_utils/ext4_crypt_init_extensions.h | 2 +- 3 files changed, 41 insertions(+), 42 deletions(-) diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp index 7d3dc91e..69358ba8 100644 --- a/ext4_utils/ext4_crypt.cpp +++ b/ext4_utils/ext4_crypt.cpp @@ -11,9 +11,11 @@ #include #include -#include +#include +#include #include #include +#include #include @@ -24,12 +26,20 @@ // ext4enc:TODO Include structure from somewhere sensible // MUST be in sync with ext4_crypto.c in kernel -#define EXT4_MAX_KEY_SIZE 76 -struct ext4_encryption_key { - uint32_t mode; - char raw[EXT4_MAX_KEY_SIZE]; - uint32_t size; -}; +#define EXT4_KEY_DESCRIPTOR_SIZE 8 +struct ext4_encryption_policy { + char version; + char contents_encryption_mode; + char filenames_encryption_mode; + char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE]; +} __attribute__((__packed__)); + +#define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 +#define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 + +// ext4enc:TODO Get value from somewhere sensible +#define EXT4_IOC_SET_ENCRYPTION_POLICY \ + _IOR('f', 19, struct ext4_encryption_policy) /* Validate that all path items are available and accessible. */ static int is_path_valid(const char *path) @@ -42,32 +52,6 @@ static int is_path_valid(const char *path) return 1; } -/* Checks whether the policy provided is valid */ -static int is_keyref_valid(const char *keyref) -{ - char *period = 0; - size_t key_location_len = 0; - - /* Key ref must have a key and location delimiter character. */ - period = strchr(keyref, EXT4_KEYREF_DELIMITER); - if (!period) { - return 0; - } - - /* period must be >= keyref. */ - key_location_len = period - keyref; - - if (strncmp(keyref, "@t", key_location_len) == 0 || - strncmp(keyref, "@p", key_location_len) == 0 || - strncmp(keyref, "@s", key_location_len) == 0 || - strncmp(keyref, "@u", key_location_len) == 0 || - strncmp(keyref, "@g", key_location_len) == 0 || - strncmp(keyref, "@us", key_location_len) == 0) - return 1; - - return 0; -} - static int is_dir_empty(const char *dirname) { int n = 0; @@ -86,13 +70,13 @@ static int is_dir_empty(const char *dirname) return n <= 2; } -int do_policy_set(const char *directory, const char *policy) +int do_policy_set(const char *directory, const char *policy, int policy_length) { struct stat st; ssize_t ret; - if (!is_keyref_valid(policy)) { - KLOG_ERROR(TAG, "Policy has invalid format.\n"); + if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { + KLOG_ERROR("Policy wrong length\n"); return -EINVAL; } @@ -112,12 +96,24 @@ int do_policy_set(const char *directory, const char *policy) return -EINVAL; } - ret = lsetxattr(directory, XATTR_NAME_ENCRYPTION_POLICY, policy, - strlen(policy), 0); + int fd = open(directory, O_DIRECTORY); + if (fd == -1) { + KLOG_ERROR(TAG, "Failed to open directory (%s)\n", directory); + return -EINVAL; + } + + ext4_encryption_policy eep; + eep.version = 0; + eep.contents_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; + eep.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; + memcpy(eep.master_key_descriptor, policy, EXT4_KEY_DESCRIPTOR_SIZE); + ret = ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &eep); + auto preserve_errno = errno; + close(fd); if (ret) { KLOG_ERROR(TAG, "Failed to set encryption policy for %s: %s\n", - directory, strerror(errno)); + directory, strerror(preserve_errno)); return -EINVAL; } diff --git a/ext4_utils/ext4_crypt_init_extensions.cpp b/ext4_utils/ext4_crypt_init_extensions.cpp index 3b7df6dd..cd0a02ac 100644 --- a/ext4_utils/ext4_crypt_init_extensions.cpp +++ b/ext4_utils/ext4_crypt_init_extensions.cpp @@ -101,7 +101,6 @@ int e4crypt_create_device_key(const char* dir, } // Make sure folder exists. Use make_dir to set selinux permissions. - KLOG_INFO(TAG, "Creating test device key\n"); if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) { KLOG_ERROR(TAG, "Failed to create %s with error %s\n", UnencryptedProperties::GetPath(dir).c_str(), @@ -152,8 +151,12 @@ int e4crypt_set_directory_policy(const char* dir) UnencryptedProperties props("/data"); std::string policy = props.Get(properties::ref); + if (policy.empty()) { + return 0; + } + KLOG_INFO(TAG, "Setting policy %s\n", policy.c_str()); - int result = do_policy_set(dir, policy.c_str()); + int result = do_policy_set(dir, policy.c_str(), policy.size()); if (result) { KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n", policy.c_str(), dir); diff --git a/ext4_utils/ext4_crypt_init_extensions.h b/ext4_utils/ext4_crypt_init_extensions.h index 17f5b2e0..79311246 100644 --- a/ext4_utils/ext4_crypt_init_extensions.h +++ b/ext4_utils/ext4_crypt_init_extensions.h @@ -10,6 +10,6 @@ int e4crypt_create_device_key(const char* path, int ensure_dir_exists(const char* dir)); int e4crypt_set_directory_policy(const char* path); bool e4crypt_non_default_key(const char* path); -int do_policy_set(const char *directory, const char *policy); +int do_policy_set(const char *directory, const char *policy, int policy_length); __END_DECLS -- 2.11.0