From a9fa60514da82a4bb2d420771b696b4a6d53c024 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 2 Feb 2017 14:37:05 -0800 Subject: [PATCH] ext4_utils: allow specifying HEH filenames encryption Make the ext4_utils changes needed to support specifying aes-256-heh filenames encryption. The previous mode, aes-256-cts, remains supported as well. The file /data/unencrypted/mode is updated to have the syntax contents_encryption_mode[:filenames_encryption_mode] instead of just contents_encryption_mode. This is consistent with the new fstab syntax. Bug: 34712722 Change-Id: Ia40f589ed46dd008ab2c65d28995b574c45bbac0 --- ext4_utils/ext4_crypt.cpp | 79 ++++++++++++++++++++++++------ ext4_utils/ext4_crypt_init_extensions.cpp | 16 ++++-- ext4_utils/include/ext4_utils/ext4_crypt.h | 7 +-- 3 files changed, 80 insertions(+), 22 deletions(-) diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp index 890082e1..de85f7e9 100644 --- a/ext4_utils/ext4_crypt.cpp +++ b/ext4_utils/ext4_crypt.cpp @@ -48,8 +48,16 @@ struct ext4_encryption_policy { #define EXT4_ENCRYPTION_MODE_AES_256_XTS 1 #define EXT4_ENCRYPTION_MODE_AES_256_CTS 4 +#define EXT4_ENCRYPTION_MODE_AES_256_HEH 126 #define EXT4_ENCRYPTION_MODE_PRIVATE 127 +#define EXT4_POLICY_FLAGS_PAD_4 0x00 +#define EXT4_POLICY_FLAGS_PAD_8 0x01 +#define EXT4_POLICY_FLAGS_PAD_16 0x02 +#define EXT4_POLICY_FLAGS_PAD_32 0x03 +#define EXT4_POLICY_FLAGS_PAD_MASK 0x03 +#define EXT4_POLICY_FLAGS_VALID 0x03 + // 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) @@ -100,8 +108,25 @@ static bool is_dir_empty(const char *dirname, bool *is_empty) return true; } +static uint8_t e4crypt_get_policy_flags(int filenames_encryption_mode) { + + // With HEH, pad filenames with zeroes to the next 16-byte boundary. This + // is not required, but it's more secure (helps hide the length of + // filenames), makes the inputs evenly divisible into blocks which is more + // efficient for encryption and decryption, and we had the opportunity to + // make a breaking change when introducing a new mode anyway. + if (filenames_encryption_mode == EXT4_ENCRYPTION_MODE_AES_256_HEH) { + return EXT4_POLICY_FLAGS_PAD_16; + } + + // Default flags (4-byte padding) for CTS + return EXT4_POLICY_FLAGS_PAD_4; +} + static bool e4crypt_policy_set(const char *directory, const char *policy, - size_t policy_length, int contents_encryption_mode) { + size_t policy_length, + int contents_encryption_mode, + int filenames_encryption_mode) { if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { LOG(ERROR) << "Policy wrong length: " << policy_length; return false; @@ -115,8 +140,8 @@ static bool e4crypt_policy_set(const char *directory, const char *policy, ext4_encryption_policy eep; eep.version = 0; eep.contents_encryption_mode = contents_encryption_mode; - eep.filenames_encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; - eep.flags = 0; + eep.filenames_encryption_mode = filenames_encryption_mode; + eep.flags = e4crypt_get_policy_flags(filenames_encryption_mode); 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; @@ -132,7 +157,9 @@ static bool e4crypt_policy_set(const char *directory, const char *policy, } static bool e4crypt_policy_get(const char *directory, char *policy, - size_t policy_length, int contents_encryption_mode) { + size_t policy_length, + int contents_encryption_mode, + int filenames_encryption_mode) { if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) { LOG(ERROR) << "Policy wrong length: " << policy_length; return false; @@ -155,8 +182,9 @@ static bool e4crypt_policy_get(const char *directory, char *policy, if ((eep.version != 0) || (eep.contents_encryption_mode != contents_encryption_mode) - || (eep.filenames_encryption_mode != EXT4_ENCRYPTION_MODE_AES_256_CTS) - || (eep.flags != 0)) { + || (eep.filenames_encryption_mode != filenames_encryption_mode) + || (eep.flags != + e4crypt_get_policy_flags(filenames_encryption_mode))) { LOG(ERROR) << "Failed to find matching encryption policy for " << directory; return false; } @@ -166,14 +194,17 @@ static bool e4crypt_policy_get(const char *directory, char *policy, } static bool e4crypt_policy_check(const char *directory, const char *policy, - size_t policy_length, int contents_encryption_mode) { + size_t policy_length, + int contents_encryption_mode, + int filenames_encryption_mode) { 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, - contents_encryption_mode)) return false; + contents_encryption_mode, + filenames_encryption_mode)) return false; char existing_policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX]; policy_to_hex(existing_policy, existing_policy_hex); @@ -191,14 +222,30 @@ static bool e4crypt_policy_check(const char *directory, const char *policy, } int e4crypt_policy_ensure(const char *directory, const char *policy, - size_t policy_length, const char* contents_encryption_mode) { - int mode = 0; - if (!strcmp(contents_encryption_mode, "software")) { - mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; + size_t policy_length, + const char *contents_encryption_mode, + const char *filenames_encryption_mode) { + int contents_mode = 0; + int filenames_mode = 0; + + if (!strcmp(contents_encryption_mode, "software") || + !strcmp(contents_encryption_mode, "aes-256-xts")) { + contents_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS; } else if (!strcmp(contents_encryption_mode, "ice")) { - mode = EXT4_ENCRYPTION_MODE_PRIVATE; + contents_mode = EXT4_ENCRYPTION_MODE_PRIVATE; + } else { + LOG(ERROR) << "Invalid file contents encryption mode: " + << contents_encryption_mode; + return -1; + } + + if (!strcmp(filenames_encryption_mode, "aes-256-cts")) { + filenames_mode = EXT4_ENCRYPTION_MODE_AES_256_CTS; + } else if (!strcmp(filenames_encryption_mode, "aes-256-heh")) { + filenames_mode = EXT4_ENCRYPTION_MODE_AES_256_HEH; } else { - LOG(ERROR) << "Invalid encryption mode"; + LOG(ERROR) << "Invalid file names encryption mode: " + << filenames_encryption_mode; return -1; } @@ -206,10 +253,10 @@ int e4crypt_policy_ensure(const char *directory, const char *policy, if (!is_dir_empty(directory, &is_empty)) return -1; if (is_empty) { if (!e4crypt_policy_set(directory, policy, policy_length, - mode)) return -1; + contents_mode, filenames_mode)) return -1; } else { if (!e4crypt_policy_check(directory, policy, policy_length, - mode)) return -1; + contents_mode, filenames_mode)) return -1; } return 0; } diff --git a/ext4_utils/ext4_crypt_init_extensions.cpp b/ext4_utils/ext4_crypt_init_extensions.cpp index e219d2f8..55a1c1cd 100644 --- a/ext4_utils/ext4_crypt_init_extensions.cpp +++ b/ext4_utils/ext4_crypt_init_extensions.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -117,14 +118,23 @@ int e4crypt_set_directory_policy(const char* dir) } auto type_filename = std::string("/data") + e4crypt_key_mode; - std::string contents_encryption_mode; - if (!android::base::ReadFileToString(type_filename, &contents_encryption_mode)) { + std::string modestring; + if (!android::base::ReadFileToString(type_filename, &modestring)) { LOG(ERROR) << "Cannot read mode"; } + std::vector modes = android::base::Split(modestring, ":"); + + if (modes.size() < 1 || modes.size() > 2) { + LOG(ERROR) << "Invalid encryption mode string: " << modestring; + return -1; + } + LOG(INFO) << "Setting policy on " << dir; int result = e4crypt_policy_ensure(dir, policy.c_str(), policy.length(), - contents_encryption_mode.c_str()); + modes[0].c_str(), + modes.size() >= 2 ? + modes[1].c_str() : "aes-256-cts"); if (result) { LOG(ERROR) << android::base::StringPrintf( "Setting %02x%02x%02x%02x policy on %s failed!", diff --git a/ext4_utils/include/ext4_utils/ext4_crypt.h b/ext4_utils/include/ext4_utils/ext4_crypt.h index 2be0bec5..d410ccfd 100644 --- a/ext4_utils/include/ext4_utils/ext4_crypt.h +++ b/ext4_utils/include/ext4_utils/ext4_crypt.h @@ -25,9 +25,10 @@ __BEGIN_DECLS bool e4crypt_is_native(); -int e4crypt_policy_ensure(const char *directory, - const char* policy, size_t policy_length, - const char* contents_encryption_mode); +int e4crypt_policy_ensure(const char *directory, const char *policy, + size_t policy_length, + const char *contents_encryption_mode, + const char *filenames_encryption_mode); static const char* e4crypt_unencrypted_folder = "/unencrypted"; static const char* e4crypt_key_ref = "/unencrypted/ref"; -- 2.11.0