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

@@ -651,17 +651,20 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
DataManager::SetValue(TW_IS_DECRYPTED, 1);
Is_Encrypted = true;
Is_Decrypted = true;
if (Key_Directory.empty())
if (Key_Directory.empty()) {
Is_FBE = false;
else
DataManager::SetValue(TW_IS_FBE, 0);
} else {
Is_FBE = true;
DataManager::SetValue(TW_IS_FBE, 0);
DataManager::SetValue(TW_IS_FBE, 1);
}
Decrypted_Block_Device = crypto_blkdev;
LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
} else if (!Mount(false)) {
if (Is_Present) {
if (Key_Directory.empty()) {
set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(), Fstab_File_System.c_str());
set_partition_data(Actual_Block_Device.c_str(), Crypto_Key_Location.c_str(),
Fstab_File_System.c_str());
if (cryptfs_check_footer() == 0) {
Is_Encrypted = true;
Is_Decrypted = false;
@@ -670,6 +673,7 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
Setup_Image();
DataManager::SetValue(TW_IS_ENCRYPTED, 1);
DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
DataManager::SetValue("tw_crypto_pwtype_0", cryptfs_get_password_type());
DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
DataManager::SetValue("tw_crypto_display", "");
} else {
@@ -680,10 +684,10 @@ void TWPartition::Setup_Data_Partition(bool Display_Error) {
Is_Decrypted = false;
}
} else if (Key_Directory.empty()) {
LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
LOGERR("Primary block device '%s' for mount point '%s' is not present!\n",
Primary_Block_Device.c_str(), Mount_Point.c_str());
}
} else {
if (!Decrypt_FBE_DE()) {
char wrappedvalue[PROPERTY_VALUE_MAX];
property_get("fbe.data.wrappedkey", wrappedvalue, "");
@@ -715,46 +719,54 @@ bool TWPartition::Decrypt_FBE_DE() {
if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
LOGINFO("File Based Encryption is present\n");
#ifdef TW_INCLUDE_FBE
ExcludeAll(Mount_Point + "/convert_fbe");
ExcludeAll(Mount_Point + "/unencrypted");
//ExcludeAll(Mount_Point + "/system/users/0"); // we WILL need to retain some of this if multiple users are present or we just need to delete more folders for the extra users somewhere else
ExcludeAll(Mount_Point + "/misc/vold/user_keys");
//ExcludeAll(Mount_Point + "/system_ce");
//ExcludeAll(Mount_Point + "/system_de");
//ExcludeAll(Mount_Point + "/misc_ce");
//ExcludeAll(Mount_Point + "/misc_de");
ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
ExcludeAll(Mount_Point + "/system/locksettings.db");
//ExcludeAll(Mount_Point + "/system/locksettings.db-shm"); // don't seem to need this one, but the other 2 are needed
ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
//ExcludeAll(Mount_Point + "/user_de");
//ExcludeAll(Mount_Point + "/misc/profiles/cur/0"); // might be important later
ExcludeAll(Mount_Point + "/misc/gatekeeper");
ExcludeAll(Mount_Point + "/misc/keystore");
ExcludeAll(Mount_Point + "/drm/kek.dat");
ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
int retry_count = 3;
while (!Decrypt_DE() && --retry_count)
usleep(2000);
if (retry_count > 0) {
property_set("ro.crypto.state", "encrypted");
Is_Encrypted = true;
Is_Decrypted = false;
Is_FBE = true;
DataManager::SetValue(TW_IS_FBE, 1);
DataManager::SetValue(TW_IS_ENCRYPTED, 1);
string filename;
int pwd_type = Get_Password_Type(0, filename);
if (pwd_type < 0) {
LOGERR("This TWRP does not have synthetic password decrypt support\n");
pwd_type = 0; // default password
}
DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type);
DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
DataManager::SetValue("tw_crypto_display", "");
return true;
Is_FBE = true;
DataManager::SetValue(TW_IS_FBE, 1);
ExcludeAll(Mount_Point + "/convert_fbe");
ExcludeAll(Mount_Point + "/unencrypted");
ExcludeAll(Mount_Point + "/misc/vold/user_keys");
ExcludeAll(Mount_Point + "/system/gatekeeper.password.key");
ExcludeAll(Mount_Point + "/system/gatekeeper.pattern.key");
ExcludeAll(Mount_Point + "/system/locksettings.db");
ExcludeAll(Mount_Point + "/system/locksettings.db-wal");
ExcludeAll(Mount_Point + "/misc/gatekeeper");
ExcludeAll(Mount_Point + "/misc/keystore");
ExcludeAll(Mount_Point + "/drm/kek.dat");
ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
ExcludeAll(Mount_Point + "/system/users/0/gatekeeper.password.key");
ExcludeAll(Mount_Point + "/system/users/0/gatekeeper.pattern.key");
ExcludeAll(Mount_Point + "/cache");
int retry_count = 3;
while (!Decrypt_DE() && --retry_count)
usleep(2000);
PartitionManager.Parse_Users(); // after load_all_de_keys() to parse_users
std::vector<users_struct>::iterator iter;
std::vector<users_struct>* userList = PartitionManager.Get_Users_List();
for (iter = userList->begin(); iter != userList->end(); iter++) {
if (atoi((*iter).userId.c_str()) != 0) {
ExcludeAll(Mount_Point + "/system_de/" + (*iter).userId + "/spblob");
ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/gatekeeper.password.key");
ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/gatekeeper.pattern.key");
ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/locksettings.db");
ExcludeAll(Mount_Point + "/system/users/" + (*iter).userId + "/locksettings.db-wal");
}
}
if (retry_count > 0) {
property_set("ro.crypto.state", "encrypted");
Is_Encrypted = true;
Is_Decrypted = false;
DataManager::SetValue(TW_IS_ENCRYPTED, 1);
string filename;
int pwd_type = Get_Password_Type(0, filename);
if (pwd_type < 0) {
LOGERR("This TWRP does not have synthetic password decrypt support\n");
pwd_type = 0; // default password
}
DataManager::SetValue(TW_CRYPTO_PWTYPE, pwd_type);
DataManager::SetValue("tw_crypto_pwtype_0", pwd_type);
DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
DataManager::SetValue("tw_crypto_display", "");
return true;
}
#else
LOGERR("FBE found but FBE support not present in TWRP\n");
#endif
@@ -2557,6 +2569,22 @@ bool TWPartition::Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_p
Full_FileName = part_settings->Backup_Folder + "/" + Backup_FileName;
if (Has_Data_Media)
gui_msg(Msg(msg::kWarning, "backup_storage_warning=Backups of {1} do not include any files in internal storage such as pictures or downloads.")(Display_Name));
if (Mount_Point == "/data" && DataManager::GetIntValue(TW_IS_FBE)) {
std::vector<users_struct>::iterator iter;
std::vector<users_struct>* userList = PartitionManager.Get_Users_List();
for (iter = userList->begin(); iter != userList->end(); iter++) {
if (!(*iter).isDecrypted && (*iter).userId != "0") {
gui_msg(Msg(msg::kWarning,
"backup_storage_undecrypt_warning=Backup will not include some files from user {1} "
"because the user is not decrypted.")((*iter).userId));
backup_exclusions.add_absolute_dir("/data/system_ce/" + (*iter).userId);
backup_exclusions.add_absolute_dir("/data/misc_ce/" + (*iter).userId);
backup_exclusions.add_absolute_dir("/data/vendor_ce/" + (*iter).userId);
backup_exclusions.add_absolute_dir("/data/media/" + (*iter).userId);
backup_exclusions.add_absolute_dir("/data/user/" + (*iter).userId);
}
}
}
tar.part_settings = part_settings;
tar.backup_exclusions = &backup_exclusions;
tar.setdir(Backup_Path);