OSDN Git Service

DO NOT MERGE New ext4enc kernel switching from xattrs to ioctl
authorPaul Lawrence <paullawrence@google.com>
Fri, 10 Apr 2015 14:47:30 +0000 (07:47 -0700)
committerPaul Lawrence <paullawrence@google.com>
Fri, 29 May 2015 17:50:27 +0000 (17:50 +0000)
(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
ext4_utils/ext4_crypt_init_extensions.cpp
ext4_utils/ext4_crypt_init_extensions.h

index 7d3dc91..69358ba 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#include <sys/xattr.h>
+#include <fcntl.h>
+#include <asm/ioctl.h>
 #include <sys/syscall.h>
 #include <sys/stat.h>
+#include <sys/types.h>
 
 #include <cutils/klog.h>
 
 
 // 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;
     }
 
index 3b7df6d..cd0a02a 100644 (file)
@@ -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<std::string>(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);
index 17f5b2e..7931124 100644 (file)
@@ -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