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:
@@ -72,18 +72,18 @@ extern "C" {
|
||||
}
|
||||
|
||||
#ifdef TW_INCLUDE_CRYPTO
|
||||
#include "crypto/fde/cryptfs.h"
|
||||
#include "gui/rapidxml.hpp"
|
||||
#include "gui/pages.hpp"
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
#include "crypto/ext4crypt/Decrypt.h"
|
||||
#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
|
||||
#include "crypto/ext4crypt/MetadataCrypt.h"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TW_CRYPTO_USE_SYSTEM_VOLD
|
||||
#include "crypto/vold_decrypt/vold_decrypt.h"
|
||||
#endif
|
||||
#include "crypto/fde/cryptfs.h"
|
||||
#include "gui/rapidxml.hpp"
|
||||
#include "gui/pages.hpp"
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
#include "crypto/ext4crypt/Decrypt.h"
|
||||
#ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
|
||||
#include "crypto/ext4crypt/MetadataCrypt.h"
|
||||
#endif
|
||||
#endif
|
||||
#ifdef TW_CRYPTO_USE_SYSTEM_VOLD
|
||||
#include "crypto/vold_decrypt/vold_decrypt.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef AB_OTA_UPDATER
|
||||
@@ -92,6 +92,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
extern bool datamedia;
|
||||
std::vector<users_struct> Users_List;
|
||||
|
||||
TWPartitionManager::TWPartitionManager(void) {
|
||||
mtp_was_enabled = false;
|
||||
@@ -349,10 +350,12 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error,
|
||||
}
|
||||
} else {
|
||||
DataManager::SetValue("TW_CRYPTO_TYPE", password_type);
|
||||
DataManager::SetValue("tw_crypto_pwtype_0", password_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) && Decrypt_Data->Mount(false)) {
|
||||
if (Decrypt_Data && (!Decrypt_Data->Is_Encrypted || Decrypt_Data->Is_Decrypted) &&
|
||||
Decrypt_Data->Mount(false)) {
|
||||
Decrypt_Adopted();
|
||||
}
|
||||
#endif
|
||||
@@ -1673,11 +1676,11 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) {
|
||||
} else {
|
||||
gui_msg("decrypt_success_nodev=Data successfully decrypted");
|
||||
}
|
||||
property_set("twrp.decrypt.done", "true");
|
||||
dat->Setup_File_System(false);
|
||||
dat->Current_File_System = dat->Fstab_File_System; // Needed if we're ignoring blkid because encrypted devices start out as emmc
|
||||
dat->Current_File_System = dat->Fstab_File_System; // Needed if we're ignoring blkid because encrypted devices start out as emmc
|
||||
|
||||
// Sleep for a bit so that the device will be ready
|
||||
sleep(1);
|
||||
sleep(1); // Sleep for a bit so that the device will be ready
|
||||
if (dat->Has_Data_Media && dat->Mount(false) && TWFunc::Path_Exists("/data/media/0")) {
|
||||
dat->Storage_Path = "/data/media/0";
|
||||
dat->Symlink_Path = dat->Storage_Path;
|
||||
@@ -1692,7 +1695,92 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) {
|
||||
LOGERR("Unable to locate data partition.\n");
|
||||
}
|
||||
|
||||
int TWPartitionManager::Decrypt_Device(string Password) {
|
||||
void TWPartitionManager::Parse_Users() {
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
char user_check_result[PROPERTY_VALUE_MAX];
|
||||
for (int userId = 0; userId <= 9999; userId++) {
|
||||
string prop = "twrp.user." + to_string(userId) + ".decrypt";
|
||||
property_get(prop.c_str(), user_check_result, "-1");
|
||||
if (strcmp(user_check_result, "-1") != 0) {
|
||||
if (userId < 0 || userId > 9999) {
|
||||
LOGINFO("Incorrect user id %d\n", userId);
|
||||
continue;
|
||||
}
|
||||
struct users_struct user;
|
||||
user.userId = to_string(userId);
|
||||
|
||||
// Attempt to get name of user. Fallback to user ID if this fails.
|
||||
char* userFile = PageManager::LoadFileToBuffer("/data/system/users/" + to_string(userId) + ".xml", NULL);
|
||||
if (userFile == NULL)
|
||||
user.userName = to_string(userId);
|
||||
else {
|
||||
xml_document<> *userXml = new xml_document<>();
|
||||
userXml->parse<0>(userFile);
|
||||
xml_node<>* userNode = userXml->first_node("user");
|
||||
if (userNode == nullptr) {
|
||||
user.userName = to_string(userId);
|
||||
} else {
|
||||
xml_node<>* nameNode = userNode->first_node("name");
|
||||
if (nameNode == nullptr)
|
||||
user.userName = to_string(userId);
|
||||
else {
|
||||
string userName = nameNode->value();
|
||||
user.userName = userName + " (" + to_string(userId) + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string filename;
|
||||
user.type = Get_Password_Type(userId, filename);
|
||||
|
||||
user.isDecrypted = false;
|
||||
if (strcmp(user_check_result, "1") == 0)
|
||||
user.isDecrypted = true;
|
||||
Users_List.push_back(user);
|
||||
}
|
||||
}
|
||||
Check_Users_Decryption_Status();
|
||||
#endif
|
||||
}
|
||||
|
||||
std::vector<users_struct>* TWPartitionManager::Get_Users_List() {
|
||||
return &Users_List;
|
||||
}
|
||||
|
||||
void TWPartitionManager::Mark_User_Decrypted(int userID) {
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
std::vector<users_struct>::iterator iter;
|
||||
for (iter = Users_List.begin(); iter != Users_List.end(); iter++) {
|
||||
if (atoi((*iter).userId.c_str()) == userID) {
|
||||
(*iter).isDecrypted = true;
|
||||
string user_prop_decrypted = "twrp.user." + to_string(userID) + ".decrypt";
|
||||
property_set(user_prop_decrypted.c_str(), "1");
|
||||
break;
|
||||
}
|
||||
}
|
||||
Check_Users_Decryption_Status();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TWPartitionManager::Check_Users_Decryption_Status() {
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
int all_is_decrypted = 1;
|
||||
std::vector<users_struct>::iterator iter;
|
||||
for (iter = Users_List.begin(); iter != Users_List.end(); iter++) {
|
||||
if (!(*iter).isDecrypted) {
|
||||
all_is_decrypted = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (all_is_decrypted == 1) {
|
||||
DataManager::SetValue("tw_all_users_decrypted", "1");
|
||||
property_set("twrp.all.users.decrypted", "true");
|
||||
} else
|
||||
DataManager::SetValue("tw_all_users_decrypted", "0");
|
||||
#endif
|
||||
}
|
||||
|
||||
int TWPartitionManager::Decrypt_Device(string Password, int user_id) {
|
||||
#ifdef TW_INCLUDE_CRYPTO
|
||||
char crypto_state[PROPERTY_VALUE_MAX], crypto_blkdev[PROPERTY_VALUE_MAX];
|
||||
std::vector<TWPartition*>::iterator iter;
|
||||
@@ -1716,14 +1804,49 @@ int TWPartitionManager::Decrypt_Device(string Password) {
|
||||
#ifdef TW_INCLUDE_FBE
|
||||
if (!Mount_By_Path("/data", true)) // /data has to be mounted for FBE
|
||||
return -1;
|
||||
|
||||
bool user_need_decrypt = false;
|
||||
std::vector<users_struct>::iterator iter;
|
||||
for (iter = Users_List.begin(); iter != Users_List.end(); iter++) {
|
||||
if (atoi((*iter).userId.c_str()) == user_id && !(*iter).isDecrypted) {
|
||||
user_need_decrypt = true;
|
||||
}
|
||||
}
|
||||
if (!user_need_decrypt) {
|
||||
LOGINFO("User %d does not require decryption\n", user_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int retry_count = 10;
|
||||
while (!TWFunc::Path_Exists("/data/system/users/gatekeeper.password.key") && --retry_count)
|
||||
usleep(2000); // A small sleep is needed after mounting /data to ensure reliable decrypt... maybe because of DE?
|
||||
int user_id = DataManager::GetIntValue("tw_decrypt_user_id");
|
||||
LOGINFO("Decrypting FBE for user %i\n", user_id);
|
||||
usleep(2000); // A small sleep is needed after mounting /data to ensure reliable decrypt...maybe because of DE?
|
||||
gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(user_id));
|
||||
if (Decrypt_User(user_id, Password)) {
|
||||
Post_Decrypt("");
|
||||
gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(user_id));
|
||||
Mark_User_Decrypted(user_id);
|
||||
if (user_id == 0) {
|
||||
// When decrypting user 0 also try all other users
|
||||
std::vector<users_struct>::iterator iter;
|
||||
for (iter = Users_List.begin(); iter != Users_List.end(); iter++) {
|
||||
if ((*iter).userId == "0" || (*iter).isDecrypted)
|
||||
continue;
|
||||
|
||||
int tmp_user_id = atoi((*iter).userId.c_str());
|
||||
gui_msg(Msg("decrypting_user_fbe=Attempting to decrypt FBE for user {1}...")(tmp_user_id));
|
||||
if (Decrypt_User(tmp_user_id, Password) ||
|
||||
(Password != "!" && Decrypt_User(tmp_user_id, "!"))) { // "!" means default password
|
||||
gui_msg(Msg("decrypt_user_success_fbe=User {1} Decrypted Successfully")(tmp_user_id));
|
||||
Mark_User_Decrypted(tmp_user_id);
|
||||
} else {
|
||||
gui_msg(Msg("decrypt_user_fail_fbe=Failed to decrypt user {1}")(tmp_user_id));
|
||||
}
|
||||
}
|
||||
Post_Decrypt("");
|
||||
}
|
||||
|
||||
return 0;
|
||||
} else {
|
||||
gui_msg(Msg(msg::kError, "decrypt_user_fail_fbe=Failed to decrypt user {1}")(user_id));
|
||||
}
|
||||
#else
|
||||
LOGERR("FBE support is not present\n");
|
||||
@@ -1731,6 +1854,13 @@ int TWPartitionManager::Decrypt_Device(string Password) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char isdecrypteddata[PROPERTY_VALUE_MAX];
|
||||
property_get("twrp.decrypt.done", isdecrypteddata, "");
|
||||
if (strcmp(isdecrypteddata, "true") == 0) {
|
||||
LOGINFO("Data has no decryption required\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pwret = -1;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
|
||||
Reference in New Issue
Block a user