diff options
author | Paul Lawrence <paullawrence@google.com> | 2016-05-23 22:03:40 +0000 |
---|---|---|
committer | Paul Lawrence <paullawrence@google.com> | 2016-05-27 08:23:09 -0700 |
commit | 4818b73cf845e05c6b14afb07e38da0b6720865a (patch) | |
tree | 0e9747080c3739307def3c7b56bdf9a9e76c3fdb | |
parent | aedf28f07cc4a8082816667ac3c175ea43e1edad (diff) | |
download | extras-4818b73cf845e05c6b14afb07e38da0b6720865a.tar.gz |
Revert "Add fileencrypted=software/ice to fstab options"
This reverts commit e8299d81a18d16b006019f37ec9d84921d5ff845.
Bug: 28905864
Change-Id: I077f1ce7337c7ff42be67fb7acbb80ce5ee9b9ba
-rw-r--r-- | ext4_utils/Android.mk | 1 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt.cpp | 171 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt.h | 6 | ||||
-rw-r--r-- | ext4_utils/ext4_crypt_init_extensions.cpp | 29 |
4 files changed, 191 insertions, 16 deletions
diff --git a/ext4_utils/Android.mk b/ext4_utils/Android.mk index e5431dd8..a8362b22 100644 --- a/ext4_utils/Android.mk +++ b/ext4_utils/Android.mk @@ -87,7 +87,6 @@ include $(CLEAR_VARS) LOCAL_SRC_FILES := $(libext4_utils_src_files) \ ext4_crypt_init_extensions.cpp LOCAL_MODULE := libext4_utils_static -LOCAL_C_INCLUDES += system/core/init # Various instances of dereferencing a type-punned pointer in extent.c LOCAL_CFLAGS += -fno-strict-aliasing LOCAL_STATIC_LIBRARIES := \ diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp index 72ce104d..be77b791 100644 --- a/ext4_utils/ext4_crypt.cpp +++ b/ext4_utils/ext4_crypt.cpp @@ -16,11 +16,182 @@ #include "ext4_crypt.h" +#include <dirent.h> +#include <errno.h> #include <string.h> +#include <unistd.h> + +#include <fcntl.h> +#include <asm/ioctl.h> +#include <sys/syscall.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <android-base/logging.h> #include <cutils/properties.h> +#define XATTR_NAME_ENCRYPTION_POLICY "encryption.policy" +#define EXT4_KEYREF_DELIMITER ((char)'.') + +// ext4enc:TODO Include structure from somewhere sensible +// MUST be in sync with ext4_crypto.c in kernel +#define EXT4_KEY_DESCRIPTOR_SIZE 8 +#define EXT4_KEY_DESCRIPTOR_SIZE_HEX 17 + +struct ext4_encryption_policy { + char version; + char contents_encryption_mode; + char filenames_encryption_mode; + char flags; + 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) +#define EXT4_IOC_GET_ENCRYPTION_POLICY _IOW('f', 21, struct ext4_encryption_policy) + +#define HEX_LOOKUP "0123456789abcdef" + bool e4crypt_is_native() { char value[PROPERTY_VALUE_MAX]; property_get("ro.crypto.type", value, "none"); return !strcmp(value, "file"); } + +static void policy_to_hex(const char* policy, char* hex) { + for (size_t i = 0, j = 0; i < EXT4_KEY_DESCRIPTOR_SIZE; i++) { + hex[j++] = HEX_LOOKUP[(policy[i] & 0xF0) >> 4]; + hex[j++] = HEX_LOOKUP[policy[i] & 0x0F]; + } + hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX - 1] = '\0'; +} + +static bool is_dir_empty(const char *dirname, bool *is_empty) +{ + int n = 0; + auto dirp = std::unique_ptr<DIR, int (*)(DIR*)>(opendir(dirname), closedir); + if (!dirp) { + PLOG(ERROR) << "Unable to read directory: " << dirname; + return false; + } + for (;;) { + errno = 0; + auto entry = readdir(dirp.get()); + if (!entry) { + if (errno) { + PLOG(ERROR) << "Unable to read directory: " << dirname; + return false; + } + break; + } + if (strcmp(entry->d_name, "lost+found") != 0) { // Skip lost+found + ++n; + if (n > 2) { + *is_empty = false; + return true; + } + } + } + *is_empty = true; + return true; +} + +static bool e4crypt_policy_set(const char *directory, const char *policy, size_t policy_length) { + if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { + LOG(ERROR) << "Policy wrong length: " << policy_length; + return false; + } + int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); + if (fd == -1) { + PLOG(ERROR) << "Failed to open directory " << directory; + return false; + } + + 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; + eep.flags = 0; + memcpy(eep.master_key_descriptor, policy, EXT4_KEY_DESCRIPTOR_SIZE); + if (ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &eep)) { + PLOG(ERROR) << "Failed to set encryption policy for " << directory; + close(fd); + return false; + } + close(fd); + + char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; + policy_to_hex(policy, policy_hex); + LOG(INFO) << "Policy for " << directory << " set to " << policy_hex; + return true; +} + +static bool e4crypt_policy_get(const char *directory, char *policy, size_t policy_length) { + if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { + LOG(ERROR) << "Policy wrong length: " << policy_length; + return false; + } + + int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC); + if (fd == -1) { + PLOG(ERROR) << "Failed to open directory " << directory; + return false; + } + + ext4_encryption_policy eep; + memset(&eep, 0, sizeof(ext4_encryption_policy)); + if (ioctl(fd, EXT4_IOC_GET_ENCRYPTION_POLICY, &eep) != 0) { + PLOG(ERROR) << "Failed to get encryption policy for " << directory; + close(fd); + return -1; + } + close(fd); + + if ((eep.version != 0) + || (eep.contents_encryption_mode != EXT4_ENCRYPTION_MODE_AES_256_XTS) + || (eep.filenames_encryption_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) + || (eep.flags != 0)) { + LOG(ERROR) << "Failed to find matching encryption policy for " << directory; + return false; + } + memcpy(policy, eep.master_key_descriptor, EXT4_KEY_DESCRIPTOR_SIZE); + + return true; +} + +static bool e4crypt_policy_check(const char *directory, const char *policy, size_t policy_length) { + if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { + LOG(ERROR) << "Policy wrong length: " << policy_length; + return false; + } + char existing_policy[EXT4_KEY_DESCRIPTOR_SIZE]; + if (!e4crypt_policy_get(directory, existing_policy, EXT4_KEY_DESCRIPTOR_SIZE)) return false; + char existing_policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; + + policy_to_hex(existing_policy, existing_policy_hex); + + if (memcmp(policy, existing_policy, EXT4_KEY_DESCRIPTOR_SIZE) != 0) { + char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; + policy_to_hex(policy, policy_hex); + LOG(ERROR) << "Found policy " << existing_policy_hex << " at " << directory + << " which doesn't match expected value " << policy_hex; + return false; + } + LOG(INFO) << "Found policy " << existing_policy_hex << " at " << directory + << " which matches expected value"; + return true; +} + +int e4crypt_policy_ensure(const char *directory, const char *policy, size_t policy_length) { + bool is_empty; + if (!is_dir_empty(directory, &is_empty)) return -1; + if (is_empty) { + if (!e4crypt_policy_set(directory, policy, policy_length)) return -1; + } else { + if (!e4crypt_policy_check(directory, policy, policy_length)) return -1; + } + return 0; +} diff --git a/ext4_utils/ext4_crypt.h b/ext4_utils/ext4_crypt.h index 8a83da19..ddc09a71 100644 --- a/ext4_utils/ext4_crypt.h +++ b/ext4_utils/ext4_crypt.h @@ -20,9 +20,11 @@ __BEGIN_DECLS +bool e4crypt_is_native(); + +int e4crypt_policy_ensure(const char *directory, const char* policy, size_t policy_length); + static const char* e4crypt_unencrypted_folder = "/unencrypted"; static const char* e4crypt_key_ref = "/unencrypted/ref"; -bool e4crypt_is_native(); - __END_DECLS diff --git a/ext4_utils/ext4_crypt_init_extensions.cpp b/ext4_utils/ext4_crypt_init_extensions.cpp index 0298b116..c6baea74 100644 --- a/ext4_utils/ext4_crypt_init_extensions.cpp +++ b/ext4_utils/ext4_crypt_init_extensions.cpp @@ -24,11 +24,18 @@ #include <string> #include <vector> +#include <dirent.h> +#include <errno.h> +#include <sys/mount.h> +#include <sys/stat.h> +#include <unistd.h> + #include <android-base/file.h> #include <cutils/klog.h> +#include <cutils/properties.h> +#include <cutils/sockets.h> #include <logwrap/logwrap.h> -#include <util.h> #include "key_control.h" @@ -110,6 +117,9 @@ int e4crypt_set_directory_policy(const char* dir) return 0; } + // Special case various directories that must not be encrypted, + // often because their subdirectories must be encrypted. + // This isn't a nice way to do this, see b/26641735 std::vector<std::string> directories_to_exclude = { "lost+found", "system_ce", "system_de", @@ -131,19 +141,12 @@ int e4crypt_set_directory_policy(const char* dir) KLOG_ERROR(TAG, "Unable to read system policy to set on %s\n", dir); return -1; } - - std::string hex_policy = bytes_to_hex((const uint8_t*)policy.c_str(), - policy.length()); - - const char* argv[] = { "/system/bin/vdc", "--wait", "cryptfs", - "ensure_policy", dir, hex_policy.c_str()}; - KLOG_INFO(TAG, "Setting policy on %s\n", dir); - int rc = android_fork_execvp(6, (char**) argv, NULL, false, true); - if (rc) { - KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n", - hex_policy.c_str(), dir); - return rc; + int result = e4crypt_policy_ensure(dir, policy.c_str(), policy.size()); + if (result) { + KLOG_ERROR(TAG, "Setting %02x%02x%02x%02x policy on %s failed!\n", + policy[0], policy[1], policy[2], policy[3], dir); + return -1; } return 0; |