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

Change-Id: Id2681bc2b1012a0571417f7a6e0b980b1b25c61c
(cherry picked from commit 5a79f67a1b1bd1bcadeca0a4896a871646652534)
This commit is contained in:
Noah Jacobson
2019-04-28 00:10:07 -04:00
committed by bigbiff
parent 784073e9fe
commit 0b25b1d79b
18 changed files with 640 additions and 655 deletions

View File

@@ -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 @@ bool lookup_key_ref(const std::map<userid_t, std::string>& key_map, userid_t use
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 @@ static bool load_all_de_keys() {
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 @@ bool e4crypt_init_user0() {
// 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 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial __unused, const char*
}
} 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;
}