Add support for multi-user decryption

* Add CLI support using the command "twrp decrypt <PASSWORD> [USER ID]"
* Add GUI support using the menu Advanced --> Decrypt User

multiuser: Parse users only when Decrypt_DE runs successfully

multiuser: Warn when not all users are decrypted

Change-Id: Ia5e943b13c2d5ec5c34ae97661133c19ff471e6d
diff --git a/crypto/ext4crypt/Ext4Crypt.cpp b/crypto/ext4crypt/Ext4Crypt.cpp
index c9e71fd..9360b1a 100644
--- a/crypto/ext4crypt/Ext4Crypt.cpp
+++ b/crypto/ext4crypt/Ext4Crypt.cpp
@@ -63,6 +63,7 @@
 #define MANAGE_MISC_DIRS 0
 
 #include <cutils/fs.h>
+#include <cutils/properties.h>
 
 #include <android-base/file.h>
 //#include <android-base/logging.h>
@@ -316,16 +317,6 @@
     return true;
 }
 
-static bool ensure_policy(const std::string& raw_ref __unused, const std::string& path) {
-    return true;
-    // ensure policy will set a policy if one is not set on an empty folder - we don't want to do this in recovery
-    /*if (e4crypt_policy_ensure(path.c_str(), raw_ref.data(), raw_ref.size()) != 0) {
-        LOG(ERROR) << "Failed to set policy on: " << path << "\n";
-        return false;
-    }
-    return true;*/
-}
-
 static bool is_numeric(const char* name) {
     for (const char* p = name; *p != '\0'; p++) {
         if (!isdigit(*p)) return false;
@@ -363,6 +354,9 @@
             if (!install_key(key, &raw_ref)) return false;
             s_de_key_raw_refs[user_id] = raw_ref;
             LOG(DEBUG) << "Installed de key for user " << user_id;
+
+            std::string user_prop = "twrp.user." + std::to_string(user_id) + ".decrypt";
+            property_set(user_prop.c_str(), "0");
         }
     }
     // ext4enc:TODO: go through all DE directories, ensure that all user dirs have the
@@ -411,13 +405,6 @@
         // explicit calls to install DE keys for secondary users
         if (!load_all_de_keys()) return false;
     }
-    // We can only safely prepare DE storage here, since CE keys are probably
-    // entangled with user credentials.  The framework will always prepare CE
-    // storage once CE keys are installed.
-    if (!e4crypt_prepare_user_storage(nullptr, 0, 0, FLAG_STORAGE_DE)) {
-        LOG(ERROR) << "Failed to prepare user 0 storage";
-        return false;
-    }
 
     // If this is a non-FBE device that recently left an emulated mode,
     // restore user data directories to known-good state.
@@ -458,79 +445,6 @@
         }
     } else {
 		printf("Emulation mode not supported in TWRP\n");
-        // When in emulation mode, we just use chmod. However, we also
-        // unlock directories when not in emulation mode, to bring devices
-        // back into a known-good state.
-        /*if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) ||
-            !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) ||
-            !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) ||
-            !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) {
-            LOG(ERROR) << "Failed to unlock user " << user_id;
-            return false;
-        }*/
     }
     return true;
 }
-
-bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial __unused,
-        int flags) {
-
-    if (flags & FLAG_STORAGE_DE) {
-        // DE_sys key
-        auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id);
-        auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id);
-        auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
-        auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id);
-
-        // DE_n key
-        auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
-        auto misc_de_path = android::vold::BuildDataMiscDePath(user_id);
-        auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
-
-        if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
-#if MANAGE_MISC_DIRS
-        if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM),
-                multiuser_get_uid(user_id, AID_EVERYBODY))) return false;
-#endif
-        if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-        if (!prepare_dir(foreign_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) return false;
-
-        if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
-        if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false;
-        if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-
-        // For now, FBE is only supported on internal storage
-        if (e4crypt_is_native() && volume_uuid == nullptr) {
-            std::string de_raw_ref;
-            if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false;
-            if (!ensure_policy(de_raw_ref, system_de_path)) return false;
-            if (!ensure_policy(de_raw_ref, misc_de_path)) return false;
-            if (!ensure_policy(de_raw_ref, user_de_path)) return false;
-        }
-    }
-
-    if (flags & FLAG_STORAGE_CE) {
-        // CE_n key
-        auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
-        auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);
-        auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id);
-        auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
-
-        if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
-        if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
-        if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
-        if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-
-        // For now, FBE is only supported on internal storage
-        if (e4crypt_is_native() && volume_uuid == nullptr) {
-            std::string ce_raw_ref;
-            if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false;
-            if (!ensure_policy(ce_raw_ref, system_ce_path)) return false;
-            if (!ensure_policy(ce_raw_ref, misc_ce_path)) return false;
-            if (!ensure_policy(ce_raw_ref, media_ce_path)) return false;
-            if (!ensure_policy(ce_raw_ref, user_ce_path)) return false;
-        }
-    }
-
-    return true;
-}