decrypt: AOSP 10 requires the use of fscrypt

fscrypt aosp doc: https://source.android.com/security/encryption/file-based
kernel fscrypt doc: https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html

This commit implements the ability for TWRP to use fscrypt to decrypt
files on the fscrypt implementation. It has been implemented mostly
in a new successor library to e4crypt called libtwrpfscrypt. Most of the
code was ported from AOSP vold.

Notable updates include:
 - updated policy storage by libtar
 - lookup of fbe policies by libtwrpfscrypt
 - threaded keystore operations

Big thanks to Dees_Troy for the initial trailblazing
of encryption in TWRP.

Change-Id: I69cd2eba3693a9914e00213d4943229635d0cdae
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index e0c40ea..ae4c70a 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -43,6 +43,7 @@
 #include <android-base/chrono_utils.h>
 #include <android-base/file.h>
 #include <android-base/logging.h>
+#include <android-base/properties.h>
 #include <android-base/strings.h>
 #include <fstab/fstab.h>
 #include <fs_avb/fs_avb.h>
@@ -84,18 +85,22 @@
 }
 
 #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
+#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
+	#ifdef USE_FSCRYPT
+	#include "crypto/fscrypt/MetadataCrypt.h"
+	#else
+	#include "crypto/ext4crypt/MetadataCrypt.h"
 	#endif
-	#ifdef TW_CRYPTO_USE_SYSTEM_VOLD
-		#include "crypto/vold_decrypt/vold_decrypt.h"
-	#endif
+#endif
+#endif
+#ifdef TW_CRYPTO_USE_SYSTEM_VOLD
+#include "crypto/vold_decrypt/vold_decrypt.h"
+#endif
 #endif
 
 #ifdef AB_OTA_UPDATER
@@ -307,13 +312,59 @@
 	if (settings_partition) {
 		Setup_Settings_Storage_Partition(settings_partition);
 	}
-#ifdef TW_INCLUDE_CRYPTO
+
+	Update_System_Details();
+	UnMount_Main_Partitions();
+#ifdef AB_OTA_UPDATER
+	DataManager::SetValue("tw_active_slot", Get_Active_Slot_Display());
+#endif
+	setup_uevent();
+	return true;
+}
+
+int TWPartitionManager::Write_Fstab(void) {
+	FILE *fp;
+	std::vector<TWPartition*>::iterator iter;
+	string Line;
+
+	fp = fopen("/etc/fstab", "w");
+	if (fp == NULL) {
+		LOGINFO("Can not open /etc/fstab.\n");
+		return false;
+	}
+	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
+		if ((*iter)->Can_Be_Mounted) {
+			Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw 0 0\n";
+			fputs(Line.c_str(), fp);
+		}
+		// Handle subpartition tracking
+		if ((*iter)->Is_SubPartition) {
+			TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
+			if (ParentPartition)
+				ParentPartition->Has_SubPartition = true;
+			else
+				LOGERR("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
+		}
+	}
+	fclose(fp);
+	return true;
+}
+
+void TWPartitionManager::Decrypt_Data() {
+	#ifdef TW_INCLUDE_CRYPTO
 	TWPartition* Decrypt_Data = Find_Partition_By_Path("/data");
 	if (Decrypt_Data && Decrypt_Data->Is_Encrypted && !Decrypt_Data->Is_Decrypted) {
 		if (!Decrypt_Data->Key_Directory.empty() && Mount_By_Path(Decrypt_Data->Key_Directory, false)) {
 #ifdef TW_INCLUDE_FBE_METADATA_DECRYPT
+#ifdef USE_FSCRYPT
+			if (fscrypt_mount_metadata_encrypted(Decrypt_Data->Actual_Block_Device, Decrypt_Data->Mount_Point, false)) {
+				std::string crypto_blkdev =  android::base::GetProperty("ro.crypto.fs_crypto_blkdev", "error");
+				LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", crypto_blkdev.c_str());
+#else
 			if (e4crypt_mount_metadata_encrypted(Decrypt_Data->Mount_Point, false, Decrypt_Data->Key_Directory, Decrypt_Data->Actual_Block_Device, &Decrypt_Data->Decrypted_Block_Device)) {
-				LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", Decrypt_Data->Decrypted_Block_Device.c_str());
+				LOGINFO("Successfully decrypted metadata encrypted data partition with new block device: '%s'\n", 
+				Decrypt_Data->Decrypted_Block_Device.c_str());
+#endif
 				property_set("ro.crypto.state", "encrypted");
 				Decrypt_Data->Is_Decrypted = true; // Needed to make the mount function work correctly
 				int retry_count = 10;
@@ -373,41 +424,6 @@
 		Decrypt_Adopted();
 	}
 #endif
-	Update_System_Details();
-	UnMount_Main_Partitions();
-#ifdef AB_OTA_UPDATER
-	DataManager::SetValue("tw_active_slot", Get_Active_Slot_Display());
-#endif
-	setup_uevent();
-	return true;
-}
-
-int TWPartitionManager::Write_Fstab(void) {
-	FILE *fp;
-	std::vector<TWPartition*>::iterator iter;
-	string Line;
-
-	fp = fopen("/etc/fstab", "w");
-	if (fp == NULL) {
-		LOGINFO("Can not open /etc/fstab.\n");
-		return false;
-	}
-	for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
-		if ((*iter)->Can_Be_Mounted) {
-			Line = (*iter)->Actual_Block_Device + " " + (*iter)->Mount_Point + " " + (*iter)->Current_File_System + " rw 0 0\n";
-			fputs(Line.c_str(), fp);
-		}
-		// Handle subpartition tracking
-		if ((*iter)->Is_SubPartition) {
-			TWPartition* ParentPartition = Find_Partition_By_Path((*iter)->SubPartition_Of);
-			if (ParentPartition)
-				ParentPartition->Has_SubPartition = true;
-			else
-				LOGERR("Unable to locate parent partition '%s' of '%s'\n", (*iter)->SubPartition_Of.c_str(), (*iter)->Mount_Point.c_str());
-		}
-	}
-	fclose(fp);
-	return true;
 }
 
 void TWPartitionManager::Setup_Settings_Storage_Partition(TWPartition* Part) {
@@ -479,8 +495,6 @@
 		printf("Is_Settings_Storage ");
 	if (Part->Ignore_Blkid)
 		printf("Ignore_Blkid ");
-	if (Part->Retain_Layout_Version)
-		printf("Retain_Layout_Version ");
 	if (Part->Mount_To_Decrypt)
 		printf("Mount_To_Decrypt ");
 	if (Part->Can_Flash_Img)
@@ -877,10 +891,12 @@
 
 	LOGINFO("Calculating backup details...\n");
 	DataManager::GetValue("tw_backup_list", Backup_List);
+	LOGINFO("Backup_List: %s\n", Backup_List.c_str());
 	if (!Backup_List.empty()) {
 		end_pos = Backup_List.find(";", start_pos);
 		while (end_pos != string::npos && start_pos < Backup_List.size()) {
 			backup_path = Backup_List.substr(start_pos, end_pos - start_pos);
+			LOGINFO("backup_path: %s\n", backup_path.c_str());
 			part_settings.Part = Find_Partition_By_Path(backup_path);
 			if (part_settings.Part != NULL) {
 				partition_count++;
@@ -1503,9 +1519,6 @@
 	TWPartition* dat = Find_Partition_By_Path("/data");
 
 	if (dat != NULL) {
-		if (!dat->UnMount(true))
-			return false;
-
 		return dat->Wipe_Encryption();
 	} else {
 		gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/data"));
@@ -1665,11 +1678,13 @@
 	TWPartition* FreeStorage = Find_Partition_By_Path(current_storage_path);
 	if (FreeStorage != NULL) {
 		// Attempt to mount storage
-		if (!FreeStorage->Mount(false)) {
-			gui_msg(Msg(msg::kError, "unable_to_mount_storage=Unable to mount storage"));
-			DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
-		} else {
-			DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
+		if (!TWFunc::Is_Mount_Wiped("/data")) {
+			if (!FreeStorage->Mount(false)) {
+				gui_msg(Msg(msg::kWarning, "unable_to_mount_storage=Unable to mount storage"));
+				DataManager::SetValue(TW_STORAGE_FREE_SIZE, 0);
+			} else {
+				DataManager::SetValue(TW_STORAGE_FREE_SIZE, (int)(FreeStorage->Free / 1048576LLU));
+			}
 		}
 	} else {
 		LOGINFO("Unable to find storage partition '%s'.\n", current_storage_path.c_str());
@@ -1681,6 +1696,9 @@
 
 void TWPartitionManager::Post_Decrypt(const string& Block_Device) {
 	TWPartition* dat = Find_Partition_By_Path("/data");
+#ifdef USE_FSCRYPT
+	dat->Set_Block_Device("/dev/block/mapper/userdata");
+#endif
 	if (dat != NULL) {
 		DataManager::SetValue(TW_IS_DECRYPTED, 1);
 		dat->Is_Decrypted = true;
@@ -3326,8 +3344,14 @@
 void TWPartitionManager::Setup_Super_Devices() {
 	std::string superPart = Get_Super_Partition();
 	android::fs_mgr::CreateLogicalPartitions(superPart);
+}
+
+void TWPartitionManager::Setup_Super_Partition() {
 	TWPartition* superPartition = new TWPartition();
-	superPartition->Mount_Point = "super";
+	std::string superPart = Get_Super_Partition();
+
+	superPartition->Backup_Path = "/super";
+	superPartition->Mount_Point = "/super";
 	superPartition->Actual_Block_Device = superPart;
 	superPartition->Alternate_Block_Device = superPart;
 	superPartition->Backup_Display_Name = "super";
@@ -3336,6 +3360,7 @@
 	superPartition->Can_Be_Backed_Up = true;
 	superPartition->Is_Present = true;
 	superPartition->Is_SubPartition = false;
+	superPartition->Setup_Image();
 	Add_Partition(superPartition);
 	PartitionManager.Output_Partition(superPartition);
 	Update_System_Details();