[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
diff --git a/ext4_utils/ext4_crypt.cpp b/ext4_utils/ext4_crypt.cpp
new file mode 100644
index 0000000..2a51f41
--- /dev/null
+++ b/ext4_utils/ext4_crypt.cpp
@@ -0,0 +1,127 @@
+#include "ext4_crypt.h"
+
+#include <string>
+#include <fstream>
+#include <map>
+
+#include <errno.h>
+#include <sys/mount.h>
+#include <cutils/properties.h>
+
+// ext4enc:TODO Use include paths
+#include "../../core/init/log.h"
+
+// ext4enc::TODO remove this duplicated const
+static const std::string unencrypted_path = "/unencrypted";
+
+static std::map<std::string, std::string> s_password_store;
+
+bool e4crypt_non_default_key(const char* dir)
+{
+ int type = e4crypt_get_password_type(dir);
+ return type != -1 && type != 1;
+}
+
+int e4crypt_get_password_type(const char* path)
+{
+ auto full_path = std::string() + path + unencrypted_path;
+ if (!std::ifstream(full_path + "/key")) {
+ INFO("No master key, so not ext4enc\n");
+ return -1;
+ }
+
+ std::ifstream type(full_path + "/type");
+ if (!type) {
+ INFO("No password type so default\n");
+ return 1; // Default
+ }
+
+ int value = 0;
+ type >> value;
+ INFO("Password type is %d\n", value);
+ return value;
+}
+
+int e4crypt_change_password(const char* path, int crypt_type,
+ const char* password)
+{
+ // ext4enc:TODO Encrypt master key with password securely. Store hash of
+ // master key for validation
+ auto full_path = std::string() + path + unencrypted_path;
+ std::ofstream(full_path + "/password") << password;
+ std::ofstream(full_path + "/type") << crypt_type;
+ return 0;
+}
+
+int e4crypt_crypto_complete(const char* path)
+{
+ INFO("ext4 crypto complete called on %s\n", path);
+
+ auto full_path = std::string() + path + unencrypted_path;
+ if (!std::ifstream(full_path + "/key")) {
+ INFO("No master key, so not ext4enc\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int e4crypt_check_passwd(const char* path, const char* password)
+{
+ auto full_path = std::string() + path + unencrypted_path;
+ if (!std::ifstream(full_path + "/key")) {
+ INFO("No master key, so not ext4enc\n");
+ return -1;
+ }
+
+ std::string actual_password;
+ std::ifstream(full_path + "/password") >> actual_password;
+
+ if (actual_password == password) {
+ s_password_store[path] = password;
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+int e4crypt_restart(const char* path)
+{
+ int rc = 0;
+
+ INFO("ext4 restart called on %s\n", path);
+ property_set("vold.decrypt", "trigger_reset_main");
+ INFO("Just asked init to shut down class main\n");
+ sleep(2);
+
+ std::string tmp_path = std::string() + path + "/tmp_mnt";
+
+ // ext4enc:TODO add retry logic
+ rc = umount(tmp_path.c_str());
+ if (rc) {
+ ERROR("umount %s failed with rc %d, msg %s\n",
+ tmp_path.c_str(), rc, strerror(errno));
+ return rc;
+ }
+
+ // ext4enc:TODO add retry logic
+ rc = umount(path);
+ if (rc) {
+ ERROR("umount %s failed with rc %d, msg %s\n",
+ path, rc, strerror(errno));
+ return rc;
+ }
+
+ return 0;
+}
+
+const char* e4crypt_get_password(const char* path)
+{
+ // 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();
+ }
+}