summaryrefslogtreecommitdiffstats
path: root/crypto/ext4crypt
diff options
context:
space:
mode:
authorEthan Yonker <dees_troy@teamw.in>2016-12-09 21:52:12 +0100
committerEthan Yonker <dees_troy@teamw.in>2016-12-13 21:25:04 +0100
commit79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5 (patch)
treefef98df68f755305fcbb4da7d5cfaf0a8409a400 /crypto/ext4crypt
parentSupport File Based Encryption (diff)
downloadandroid_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar.gz
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar.bz2
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar.lz
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar.xz
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.tar.zst
android_bootable_recovery-79f88bdf8d54a84b7bb727b0c28b2dfcdc3d14d5.zip
Diffstat (limited to 'crypto/ext4crypt')
-rw-r--r--crypto/ext4crypt/Android.mk13
-rw-r--r--crypto/ext4crypt/Decrypt.cpp62
-rw-r--r--crypto/ext4crypt/Ext4Crypt.cpp12
-rw-r--r--crypto/ext4crypt/Ext4Crypt.h4
-rw-r--r--crypto/ext4crypt/e4policyget.cpp44
-rw-r--r--crypto/ext4crypt/ext4_crypt.cpp180
-rw-r--r--crypto/ext4crypt/ext4crypt_tar.h38
7 files changed, 348 insertions, 5 deletions
diff --git a/crypto/ext4crypt/Android.mk b/crypto/ext4crypt/Android.mk
index 531aca199..bcbcccfa2 100644
--- a/crypto/ext4crypt/Android.mk
+++ b/crypto/ext4crypt/Android.mk
@@ -5,7 +5,7 @@ include $(CLEAR_VARS)
LOCAL_MODULE := libe4crypt
LOCAL_MODULE_TAGS := eng optional
LOCAL_CFLAGS :=
-LOCAL_SRC_FILES := Decrypt.cpp Ext4Crypt.cpp Keymaster.cpp KeyStorage.cpp ScryptParameters.cpp Utils.cpp HashPassword.cpp
+LOCAL_SRC_FILES := Decrypt.cpp Ext4Crypt.cpp Keymaster.cpp KeyStorage.cpp ScryptParameters.cpp Utils.cpp HashPassword.cpp ext4_crypt.cpp
LOCAL_SHARED_LIBRARIES := libselinux libc libc++ libext4_utils libsoftkeymaster libbase libcrypto libcutils libkeymaster_messages libhardware libprotobuf-cpp-lite
LOCAL_STATIC_LIBRARIES := libscrypt_static
LOCAL_C_INCLUDES := system/extras/ext4_utils external/scrypt/lib/crypto system/security/keystore hardware/libhardware/include/hardware system/security/softkeymaster/include/keymaster system/keymaster/include
@@ -30,4 +30,15 @@ LOCAL_SHARED_LIBRARIES := libe4crypt
include $(BUILD_EXECUTABLE)
+include $(CLEAR_VARS)
+LOCAL_MODULE := e4policyget
+LOCAL_MODULE_TAGS := optional
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+LOCAL_SRC_FILES := e4policyget.cpp
+LOCAL_SHARED_LIBRARIES := libe4crypt
+LOCAL_LDFLAGS += -Wl,-dynamic-linker,/sbin/linker64
+
+include $(BUILD_EXECUTABLE)
+
endif
diff --git a/crypto/ext4crypt/Decrypt.cpp b/crypto/ext4crypt/Decrypt.cpp
index 6c47add0c..3b69d4651 100644
--- a/crypto/ext4crypt/Decrypt.cpp
+++ b/crypto/ext4crypt/Decrypt.cpp
@@ -17,10 +17,12 @@
#include "Decrypt.h"
#include "Ext4Crypt.h"
+#include <map>
#include <string>
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -32,6 +34,66 @@
#include <android-base/file.h>
+// Store main DE raw ref / policy
+extern std::string de_raw_ref;
+extern std::map<userid_t, std::string> s_de_key_raw_refs;
+extern std::map<userid_t, std::string> s_ce_key_raw_refs;
+
+static bool lookup_ref_key_internal(std::map<userid_t, std::string>& key_map, const char* policy, userid_t* user_id) {
+ for (std::map<userid_t, std::string>::iterator it=key_map.begin(); it!=key_map.end(); ++it) {
+ if (strncmp(it->second.c_str(), policy, it->second.size()) == 0) {
+ *user_id = it->first;
+ return true;
+ }
+ }
+ return false;
+}
+
+extern "C" bool lookup_ref_key(const char* policy, char* policy_type) {
+ userid_t user_id = 0;
+ if (strncmp(de_raw_ref.c_str(), policy, de_raw_ref.size()) == 0) {
+ strcpy(policy_type, "1DK");
+ return true;
+ }
+ if (!lookup_ref_key_internal(s_de_key_raw_refs, policy, &user_id)) {
+ if (!lookup_ref_key_internal(s_ce_key_raw_refs, policy, &user_id)) {
+ return false;
+ } else
+ sprintf(policy_type, "1CE%d", user_id);
+ } else
+ sprintf(policy_type, "1DE%d", user_id);
+ return true;
+}
+
+extern "C" bool lookup_ref_tar(const char* policy_type, char* policy) {
+ if (strncmp(policy_type, "1", 1) != 0) {
+ printf("Unexpected version %c\n", policy_type);
+ return false;
+ }
+ const char* ptr = policy_type + 1; // skip past the version number
+ if (strncmp(ptr, "DK", 2) == 0) {
+ strncpy(policy, de_raw_ref.data(), de_raw_ref.size());
+ return true;
+ }
+ userid_t user_id = atoi(ptr + 2);
+ std::string raw_ref;
+ if (*ptr == 'D') {
+ if (lookup_key_ref(s_de_key_raw_refs, user_id, &raw_ref)) {
+ strncpy(policy, raw_ref.data(), raw_ref.size());
+ } else
+ return false;
+ } else if (*ptr == 'C') {
+ if (lookup_key_ref(s_ce_key_raw_refs, user_id, &raw_ref)) {
+ strncpy(policy, raw_ref.data(), raw_ref.size());
+ } else
+ return false;
+ } else {
+ printf("unknown policy type '%s'\n", policy_type);
+ return false;
+ }
+ return true;
+}
+
int gatekeeper_device_initialize(gatekeeper_device_t **dev) {
int ret;
const hw_module_t *mod;
diff --git a/crypto/ext4crypt/Ext4Crypt.cpp b/crypto/ext4crypt/Ext4Crypt.cpp
index 423147d66..8bc419992 100644
--- a/crypto/ext4crypt/Ext4Crypt.cpp
+++ b/crypto/ext4crypt/Ext4Crypt.cpp
@@ -67,6 +67,12 @@ using android::vold::kEmptyAuthentication;
//static constexpr int FLAG_STORAGE_DE = 1 << 0; // moved to Decrypt.h
//static constexpr int FLAG_STORAGE_CE = 1 << 1;
+// Store main DE raw ref / policy
+std::string de_raw_ref;
+// Map user ids to key references
+std::map<userid_t, std::string> s_de_key_raw_refs;
+std::map<userid_t, std::string> s_ce_key_raw_refs;
+
namespace {
const std::string device_key_dir = std::string() + DATA_MNT_POINT + e4crypt_unencrypted_folder;
const std::string device_key_path = device_key_dir + "/key";
@@ -80,9 +86,6 @@ bool s_global_de_initialized = false;
// Some users are ephemeral, don't try to wipe their keys from disk
std::set<userid_t> s_ephemeral_users;
-// Map user ids to key references
-std::map<userid_t, std::string> s_de_key_raw_refs;
-std::map<userid_t, std::string> s_ce_key_raw_refs;
// TODO abolish this map. Keys should not be long-lived in user memory, only kernel memory.
// See b/26948053
std::map<userid_t, std::string> s_ce_keys;
@@ -290,7 +293,7 @@ static bool path_exists(const std::string& path) {
return access(path.c_str(), F_OK) == 0;
}
-static bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
+bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
std::string* raw_ref) {
auto refi = key_map.find(user_id);
if (refi == key_map.end()) {
@@ -379,6 +382,7 @@ bool e4crypt_initialize_global_de() {
}
s_global_de_initialized = true;
+ de_raw_ref = device_key_ref;
return true;
}
diff --git a/crypto/ext4crypt/Ext4Crypt.h b/crypto/ext4crypt/Ext4Crypt.h
index b05ff4ddb..57623e35c 100644
--- a/crypto/ext4crypt/Ext4Crypt.h
+++ b/crypto/ext4crypt/Ext4Crypt.h
@@ -19,6 +19,7 @@
#include <cutils/multiuser.h>
+#include <map>
#include <string>
__BEGIN_DECLS
@@ -40,4 +41,7 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token, co
bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, int flags);
//bool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags);
+bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t user_id,
+ std::string* raw_ref);
+
__END_DECLS
diff --git a/crypto/ext4crypt/e4policyget.cpp b/crypto/ext4crypt/e4policyget.cpp
new file mode 100644
index 000000000..d217f18ee
--- /dev/null
+++ b/crypto/ext4crypt/e4policyget.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ext4crypt_tar.h"
+
+#define EXT4_KEY_DESCRIPTOR_SIZE 8
+#define EXT4_KEY_DESCRIPTOR_SIZE_HEX 17
+
+int main(int argc, char *argv[]) {
+ bool ret = false;
+ if (argc != 2) {
+ printf("Must specify a path\n");
+ return -1;
+ } else {
+ char e4crypt_policy[EXT4_KEY_DESCRIPTOR_SIZE];
+ if (e4crypt_policy_get(argv[1], e4crypt_policy, EXT4_KEY_DESCRIPTOR_SIZE, 0))
+ {
+ char* ptr = tar_policy;
+ memset(tar_policy, 0, sizeof(tar_policy));
+ char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX];
+ policy_to_hex(e4crypt_policy, policy_hex);
+ printf("%s\n", policy_hex);
+ } else {
+ printf("No policy set\n");
+ }
+ }
+ return 0;
+}
diff --git a/crypto/ext4crypt/ext4_crypt.cpp b/crypto/ext4crypt/ext4_crypt.cpp
new file mode 100644
index 000000000..029db7567
--- /dev/null
+++ b/crypto/ext4crypt/ext4_crypt.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* TWRP NOTE: Kanged from system/extras/ext4_utils/ext4_crypt.cpp
+ * because policy_to_hex, e4crypt_policy_set, and e4crypt_policy_get
+ * are not exposed to be used. There was also a bug in e4crypt_policy_get
+ * that may or may not be fixed in the user's local repo:
+ * https://android.googlesource.com/platform/system/extras/+/30b93dd5715abcabd621235733733c0503f9c552
+ */
+
+#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/file.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
+#define EXT4_ENCRYPTION_MODE_PRIVATE 127
+
+static int encryption_mode = EXT4_ENCRYPTION_MODE_PRIVATE;
+
+// 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"
+
+extern "C" 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';
+}
+
+extern "C" bool e4crypt_policy_set(const char *directory, const char *policy,
+ size_t policy_length, int contents_encryption_mode) {
+ if (contents_encryption_mode == 0)
+ contents_encryption_mode = encryption_mode;
+ if (policy_length != EXT4_KEY_DESCRIPTOR_SIZE) {
+ printf("policy wrong length\n");
+ LOG(ERROR) << "Policy wrong length: " << policy_length;
+ return false;
+ }
+ int fd = open(directory, O_DIRECTORY | O_NOFOLLOW | O_CLOEXEC);
+ if (fd == -1) {
+ printf("failed to open %s\n", directory);
+ PLOG(ERROR) << "Failed to open directory " << directory;
+ return false;
+ }
+
+ 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;
+ memcpy(eep.master_key_descriptor, policy, EXT4_KEY_DESCRIPTOR_SIZE);
+ if (ioctl(fd, EXT4_IOC_SET_ENCRYPTION_POLICY, &eep)) {
+ printf("failed to set policy for '%s' '%s'\n", directory, policy);
+ 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;
+}
+
+extern "C" bool e4crypt_policy_get(const char *directory, char *policy,
+ size_t policy_length, int contents_encryption_mode) {
+ if (contents_encryption_mode == 0)
+ contents_encryption_mode = encryption_mode;
+ 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 false;
+ }
+ close(fd);
+
+ if ((eep.version != 0)
+ || (eep.contents_encryption_mode != contents_encryption_mode)
+ || (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;
+}
+
+extern "C" bool e4crypt_set_mode() {
+ const char* mode_file = "/data/unencrypted/mode";
+ struct stat st;
+ if (stat(mode_file, &st) != 0 || st.st_size <= 0) {
+ printf("Invalid encryption mode file %s\n", mode_file);
+ return false;
+ }
+ size_t mode_size = st.st_size;
+ char contents_encryption_mode[mode_size + 1];
+ memset((void*)contents_encryption_mode, 0, mode_size + 1);
+ int fd = open(mode_file, O_RDONLY);
+ if (fd < 0) {
+ printf("error opening '%s': %s\n", mode_file, strerror(errno));
+ return false;
+ }
+ if (read(fd, contents_encryption_mode, mode_size) != mode_size) {
+ printf("read error on '%s': %s\n", mode_file, strerror(errno));
+ close(fd);
+ return false;
+ }
+ close(fd);
+ if (!strcmp(contents_encryption_mode, "software")) {
+ encryption_mode = EXT4_ENCRYPTION_MODE_AES_256_XTS;
+ } else if (!strcmp(contents_encryption_mode, "ice")) {
+ encryption_mode = EXT4_ENCRYPTION_MODE_PRIVATE;
+ } else {
+ printf("Invalid encryption mode '%s'\n", contents_encryption_mode);
+ return false;
+ }
+ printf("set encryption mode to %i\n", encryption_mode);
+ return true;
+}
diff --git a/crypto/ext4crypt/ext4crypt_tar.h b/crypto/ext4crypt/ext4crypt_tar.h
new file mode 100644
index 000000000..1c9cef0a5
--- /dev/null
+++ b/crypto/ext4crypt/ext4crypt_tar.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2016 Team Win Recovery Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __EXT4CRYPT_TAR_H
+#define __EXT4CRYPT_TAR_H
+
+#include <sys/cdefs.h>
+#include <stdbool.h>
+#include <cutils/multiuser.h>
+
+__BEGIN_DECLS
+
+bool lookup_ref_key(const char* policy, char* policy_type);
+bool lookup_ref_tar(const char* policy_type, char* policy);
+
+void policy_to_hex(const char* policy, char* hex);
+bool e4crypt_policy_set(const char *directory, const char *policy,
+ size_t policy_length, int contents_encryption_mode);
+bool e4crypt_policy_get(const char *directory, char *policy,
+ size_t policy_length, int contents_encryption_mode);
+
+bool e4crypt_set_mode();
+__END_DECLS
+
+#endif