summaryrefslogtreecommitdiff
path: root/ext4_utils/ext4_crypt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ext4_utils/ext4_crypt.cpp')
-rw-r--r--ext4_utils/ext4_crypt.cpp172
1 files changed, 92 insertions, 80 deletions
diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp
index bb573323..7d3dc91e 100644
--- a/ext4_utils/ext4_crypt.cpp
+++ b/ext4_utils/ext4_crypt.cpp
@@ -1,120 +1,132 @@
-#define TAG "ext4_utils"
+/*
+ * Copyright (c) 2015 Google, Inc.
+ */
-#include "ext4_crypt.h"
+#define TAG "ext4_utils"
-#include <string>
-#include <fstream>
-#include <map>
+#include "ext4_crypt_init_extensions.h"
+#include <dirent.h>
#include <errno.h>
-#include <sys/mount.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/xattr.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
#include <cutils/klog.h>
-#include <cutils/properties.h>
#include "unencrypted_properties.h"
-namespace {
- std::map<std::string, std::string> s_password_store;
-}
-
-bool e4crypt_non_default_key(const char* dir)
-{
- int type = e4crypt_get_password_type(dir);
+#define XATTR_NAME_ENCRYPTION_POLICY "encryption.policy"
+#define EXT4_KEYREF_DELIMITER ((char)'.')
- // ext4enc:TODO Use consts, not 1 here
- return type != -1 && type != 1;
-}
+// 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;
+};
-int e4crypt_get_password_type(const char* path)
+/* Validate that all path items are available and accessible. */
+static int is_path_valid(const char *path)
{
- UnencryptedProperties props(path);
- if (props.Get<std::string>(properties::key).empty()) {
- KLOG_INFO(TAG, "No master key, so not ext4enc\n");
- return -1;
+ if (access(path, W_OK)) {
+ KLOG_ERROR(TAG, "Can't access %s: %s\n",strerror(errno), path);
+ return 0;
}
- return props.Get<int>(properties::type, 1);
+ return 1;
}
-int e4crypt_change_password(const char* path, int crypt_type,
- const char* password)
+/* Checks whether the policy provided is valid */
+static int is_keyref_valid(const char *keyref)
{
- // ext4enc:TODO Encrypt master key with password securely. Store hash of
- // master key for validation
- UnencryptedProperties props(path);
- if ( props.Set(properties::password, password)
- && props.Set(properties::type, crypt_type))
- return 0;
- return -1;
-}
+ char *period = 0;
+ size_t key_location_len = 0;
-int e4crypt_crypto_complete(const char* path)
-{
- KLOG_INFO(TAG, "ext4 crypto complete called on %s\n", path);
- if (UnencryptedProperties(path).Get<std::string>(properties::key).empty()) {
- KLOG_INFO(TAG, "No master key, so not ext4enc\n");
- return -1;
+ /* 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;
}
-int e4crypt_check_passwd(const char* path, const char* password)
+static int is_dir_empty(const char *dirname)
{
- UnencryptedProperties props(path);
- if (props.Get<std::string>(properties::key).empty()) {
- KLOG_INFO(TAG, "No master key, so not ext4enc\n");
- return -1;
- }
-
- auto actual_password = props.Get<std::string>(properties::password);
-
- if (actual_password == password) {
- s_password_store[path] = password;
- return 0;
- } else {
- return -1;
+ 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 e4crypt_restart(const char* path)
+int do_policy_set(const char *directory, const char *policy)
{
- int rc = 0;
+ struct stat st;
+ ssize_t ret;
- KLOG_INFO(TAG, "ext4 restart called on %s\n", path);
- property_set("vold.decrypt", "trigger_reset_main");
- KLOG_INFO(TAG, "Just asked init to shut down class main\n");
- sleep(2);
+ if (!is_keyref_valid(policy)) {
+ KLOG_ERROR(TAG, "Policy has invalid format.\n");
+ return -EINVAL;
+ }
- std::string tmp_path = std::string() + path + "/tmp_mnt";
+ if (!is_path_valid(directory)) {
+ return -EINVAL;
+ }
- // ext4enc:TODO add retry logic
- rc = umount(tmp_path.c_str());
- if (rc) {
- KLOG_ERROR(TAG, "umount %s failed with rc %d, msg %s\n",
- tmp_path.c_str(), rc, strerror(errno));
- return rc;
+ stat(directory, &st);
+ if (!S_ISDIR(st.st_mode)) {
+ KLOG_ERROR(TAG, "Can only set policy on a directory (%s)\n", directory);
+ return -EINVAL;
}
- // ext4enc:TODO add retry logic
- rc = umount(path);
- if (rc) {
- KLOG_ERROR(TAG, "umount %s failed with rc %d, msg %s\n",
- path, rc, strerror(errno));
- return rc;
+ if (!is_dir_empty(directory)) {
+ KLOG_ERROR(TAG, "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) {
+ KLOG_ERROR(TAG, "Failed to set encryption policy for %s: %s\n",
+ directory, strerror(errno));
+ return -EINVAL;
+ }
+
+ KLOG_INFO(TAG, "Encryption policy for %s is set to %s\n", directory, policy);
return 0;
}
-const char* e4crypt_get_password(const char* path)
+bool e4crypt_non_default_key(const char* dir)
{
- // ext4enc:TODO scrub password after timeout
- auto i = s_password_store.find(path);
- if (i == s_password_store.end()) {
- return 0;
- } else {
- return i->second.c_str();
- }
+ UnencryptedProperties props(dir);
+ return props.Get<int>(properties::is_default, 1) != 1;
}