diff options
author | Paul Lawrence <paullawrence@google.com> | 2015-02-25 15:11:13 -0800 |
---|---|---|
committer | Paul Lawrence <paullawrence@google.com> | 2015-03-27 13:24:06 -0700 |
commit | 92da49db65ffbe0bff1771ecef87ad49e94a0626 (patch) | |
tree | e748f4a0dcb6c572835d211a770be4d7355a8e50 /ext4_utils/e4crypt_static.c | |
parent | 99918d024a0b361f48162599c968fb100e1dcc3e (diff) | |
download | extras-92da49db65ffbe0bff1771ecef87ad49e94a0626.tar.gz |
[HACK] Adding e4crypt support
This is a dirty hack requiring a lot of clean up.
Needed to allow other parts to make progress.
Add e4crypt functions to libext4_utils
Add e4crypt command line tool
Change-Id: Iac5ae75e7f39cccc87701faf1f590e44f5209c0e
Diffstat (limited to 'ext4_utils/e4crypt_static.c')
-rw-r--r-- | ext4_utils/e4crypt_static.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/ext4_utils/e4crypt_static.c b/ext4_utils/e4crypt_static.c new file mode 100644 index 00000000..187a014f --- /dev/null +++ b/ext4_utils/e4crypt_static.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2015 Google, Inc. + */ + +#include <dirent.h> +#include <errno.h> +#include <string.h> +#include <unistd.h> + +#include <sys/xattr.h> +#include <sys/syscall.h> +#include <sys/stat.h> + +// ext4enc:TODO Use include paths +#include "../../core/init/log.h" + +#include "ext4_crypt.h" + +/* keyring keyctl commands */ +#define KEYCTL_SETPERM 5 /* set permissions for a key in a keyring */ +#define KEYCTL_UNLINK 9 /* unlink a key from a keyring */ +#define KEYCTL_SEARCH 10 /* search for a key in a keyring */ + +#define XATTR_NAME_ENCRYPTION_POLICY "encryption.policy" +#define EXT4_KEYREF_DELIMITER ((char)'.') + +/* Validate that all path items are available and accessible. */ +static int is_path_valid(const char *path) +{ + if (access(path, W_OK)) { + ERROR("Can't access %s: %s\n",strerror(errno), path); + return 0; + } + + 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; + struct dirent *d; + DIR *dir; + + dir = opendir(dirname); + while ((d = readdir(dir)) != NULL) { + if (strcmp(d->d_name, "lost+found") == 0) { + // Skip lost+found directory + } else if (++n > 2) { + break; + } + } + closedir(dir); + return n <= 2; +} + +int do_policy_set(const char *directory, const char *policy) +{ + struct stat st; + ssize_t ret; + + if (!is_keyref_valid(policy)) { + ERROR("Policy has invalid format.\n"); + return -EINVAL; + } + + if (!is_path_valid(directory)) { + return -EINVAL; + } + + stat(directory, &st); + if (!S_ISDIR(st.st_mode)) { + ERROR("Can only set policy on a directory (%s)\n", directory); + return -EINVAL; + } + + if (!is_dir_empty(directory)) { + ERROR("Can only set policy on an empty directory (%s)\n", directory); + return -EINVAL; + } + + ret = lsetxattr(directory, XATTR_NAME_ENCRYPTION_POLICY, policy, + strlen(policy), 0); + + if (ret) { + ERROR("Failed to set encryption policy for %s: %s\n", + directory, strerror(errno)); + return -EINVAL; + } + + INFO("Encryption policy for %s is set to %s\n", directory, policy); + return 0; +} + +static long keyctl(int cmd, ...) +{ + va_list va; + unsigned long arg2, arg3, arg4, arg5; + + va_start(va, cmd); + arg2 = va_arg(va, unsigned long); + arg3 = va_arg(va, unsigned long); + arg4 = va_arg(va, unsigned long); + arg5 = va_arg(va, unsigned long); + va_end(va); + return syscall(__NR_keyctl, cmd, arg2, arg3, arg4, arg5); +} + +key_serial_t add_key(const char *type, + const char *description, + const void *payload, + size_t plen, + key_serial_t ringid) +{ + return syscall(__NR_add_key, type, description, payload, plen, ringid); +} + +long keyctl_setperm(key_serial_t id, int permissions) +{ + return keyctl(KEYCTL_SETPERM, id, permissions); +} |