diff options
Diffstat (limited to 'ext4_utils/ext4_crypt_init_extensions.cpp')
-rw-r--r-- | ext4_utils/ext4_crypt_init_extensions.cpp | 165 |
1 files changed, 33 insertions, 132 deletions
diff --git a/ext4_utils/ext4_crypt_init_extensions.cpp b/ext4_utils/ext4_crypt_init_extensions.cpp index 284437f9..3b7df6dd 100644 --- a/ext4_utils/ext4_crypt_init_extensions.cpp +++ b/ext4_utils/ext4_crypt_init_extensions.cpp @@ -1,12 +1,10 @@ #define TAG "ext4_utils" -#include "ext4_crypt.h" +#include "ext4_crypt_init_extensions.h" #include <string> -#include <fstream> -#include <iomanip> -#include <sstream> +#include <dirent.h> #include <errno.h> #include <sys/mount.h> #include <sys/stat.h> @@ -16,29 +14,26 @@ #include <cutils/sockets.h> #include <poll.h> +#include "key_control.h" #include "unencrypted_properties.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; -}; - -static const std::string keyring = "@s"; static const std::string arbitrary_sequence_number = "42"; -static const int vold_command_timeout_ms = 10 * 1000; - -static key_serial_t device_keyring = -1; +static const int vold_command_timeout_ms = 60 * 1000; static std::string vold_command(std::string const& command) { KLOG_INFO(TAG, "Running command %s\n", command.c_str()); - int sock = socket_local_client("vold", + int sock = -1; + + while (true) { + sock = socket_local_client("vold", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM); + if (sock >= 0) { + break; + } + usleep(10000); + } if (sock < 0) { KLOG_INFO(TAG, "Cannot open vold, failing command\n"); @@ -97,52 +92,35 @@ static std::string vold_command(std::string const& command) int e4crypt_create_device_key(const char* dir, int ensure_dir_exists(const char*)) { + // Already encrypted with password? If so bail + std::string temp_folder = std::string() + dir + "/tmp_mnt"; + DIR* temp_dir = opendir(temp_folder.c_str()); + if (temp_dir) { + closedir(temp_dir); + return 0; + } + // Make sure folder exists. Use make_dir to set selinux permissions. KLOG_INFO(TAG, "Creating test device key\n"); - UnencryptedProperties props(dir); - if (ensure_dir_exists(props.GetPath().c_str())) { + if (ensure_dir_exists(UnencryptedProperties::GetPath(dir).c_str())) { KLOG_ERROR(TAG, "Failed to create %s with error %s\n", - props.GetPath().c_str(), strerror(errno)); + UnencryptedProperties::GetPath(dir).c_str(), + strerror(errno)); return -1; } - if (props.Get<std::string>(properties::key).empty()) { - // Create new key since it doesn't already exist - std::ifstream urandom("/dev/urandom", std::ifstream::binary); - if (!urandom) { - KLOG_ERROR(TAG, "Failed to open /dev/urandom\n"); - return -1; - } - - // ext4enc:TODO Don't hardcode 32 - std::string key_material(32, '\0'); - urandom.read(&key_material[0], key_material.length()); - if (!urandom) { - KLOG_ERROR(TAG, "Failed to read random bytes\n"); - return -1; - } - - if (!props.Set(properties::key, key_material)) { - KLOG_ERROR(TAG, "Failed to write key material\n"); - return -1; - } - } - - if (!props.Remove(properties::ref)) { - KLOG_ERROR(TAG, "Failed to remove key ref\n"); - return -1; - } + auto result = vold_command("cryptfs enablefilecrypto"); + // ext4enc:TODO proper error handling + KLOG_INFO(TAG, "enablefilecrypto returned with result %s\n", + result.c_str()); return 0; } int e4crypt_install_keyring() { - device_keyring = add_key("keyring", - "e4crypt", - 0, - 0, - KEY_SPEC_SESSION_KEYRING); + key_serial_t device_keyring = add_key("keyring", "e4crypt", 0, 0, + KEY_SPEC_SESSION_KEYRING); if (device_keyring == -1) { KLOG_ERROR(TAG, "Failed to create keyring\n"); @@ -162,83 +140,6 @@ int e4crypt_install_keyring() return 0; } -int e4crypt_install_key(const char* dir) -{ - UnencryptedProperties props(dir); - auto key = props.Get<std::string>(properties::key); - - // Get password to decrypt as needed - if (e4crypt_non_default_key(dir)) { - std::string result = vold_command("cryptfs getpw"); - // result is either - // 200 0 -1 - // or - // 200 0 {{sensitive}} 0001020304 - // where 0001020304 is hex encoding of password - std::istringstream i(result); - std::string bit; - i >> bit; - if (bit != "200") { - KLOG_ERROR(TAG, "Expecting 200\n"); - return -1; - } - - i >> bit; - if (bit != arbitrary_sequence_number) { - KLOG_ERROR(TAG, "Expecting %s\n", arbitrary_sequence_number.c_str()); - return -1; - } - - i >> bit; - if (bit != "{{sensitive}}") { - KLOG_INFO(TAG, "Not encrypted\n"); - return -1; - } - - i >> bit; - } - - // Add key to keyring - ext4_encryption_key ext4_key = {0, {0}, 0}; - if (key.length() > sizeof(ext4_key.raw)) { - KLOG_ERROR(TAG, "Key too long\n"); - return -1; - } - - ext4_key.mode = 0; - memcpy(ext4_key.raw, &key[0], key.length()); - ext4_key.size = key.length(); - - // ext4enc:TODO Use better reference not 1234567890 - key_serial_t key_id = add_key("logon", "ext4-key:1234567890", - (void*)&ext4_key, sizeof(ext4_key), - device_keyring); - - if (key_id == -1) { - KLOG_ERROR(TAG, "Failed to insert key into keyring with error %s\n", - strerror(errno)); - return -1; - } - - KLOG_INFO(TAG, "Added key %d to keyring %d in process %d\n", - key_id, device_keyring, getpid()); - - // ext4enc:TODO set correct permissions - long result = keyctl_setperm(key_id, 0x3f3f3f3f); - if (result) { - KLOG_ERROR(TAG, "KEYCTL_SETPERM failed with error %ld\n", result); - return -1; - } - - // Save reference to key so we can set policy later - if (!props.Set(properties::ref, "ext4-key:1234567890")) { - KLOG_ERROR(TAG, "Cannot save key reference\n"); - return -1; - } - - return 0; -} - int e4crypt_set_directory_policy(const char* dir) { // Only set policy on first level /data directories @@ -250,12 +151,12 @@ int e4crypt_set_directory_policy(const char* dir) } UnencryptedProperties props("/data"); - std::string ref = props.Get<std::string>(properties::ref); - std::string policy = keyring + "." + ref; + std::string policy = props.Get<std::string>(properties::ref); KLOG_INFO(TAG, "Setting policy %s\n", policy.c_str()); int result = do_policy_set(dir, policy.c_str()); if (result) { - KLOG_ERROR(TAG, "Setting policy on %s failed!\n", dir); + KLOG_ERROR(TAG, "Setting %s policy on %s failed!\n", + policy.c_str(), dir); return -1; } |