Add metadata decrypt support for FBE

Change-Id: Ie0292f4ffea5993a4ae74fa04fc5c8252ca2cfcf
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index da407fa..45460d1 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -71,6 +71,9 @@
 	#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"
@@ -277,6 +280,27 @@
 #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
+			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());
+				property_set("ro.crypto.state", "encrypted");
+				Decrypt_Data->Is_Decrypted = true; // Needed to make the mount function work correctly
+				int retry_count = 10;
+				while (!Decrypt_Data->Mount(false) && --retry_count)
+					usleep(500);
+				if (Decrypt_Data->Mount(false)) {
+					Decrypt_Data->Decrypt_FBE_DE();
+				} else {
+					LOGINFO("Failed to mount data after metadata decrypt\n");
+				}
+			} else {
+				LOGINFO("Unable to decrypt metadata encryption\n");
+			}
+#else
+			LOGERR("Metadata FBE decrypt support not present in this TWRP\n");
+#endif
+		}
 		if (Decrypt_Data->Is_FBE) {
 			if (DataManager::GetIntValue(TW_CRYPTO_PWTYPE) == 0) {
 				if (Decrypt_Device("!") == 0) {
@@ -467,6 +491,8 @@
 		printf("   Mount_Flags: %i, Mount_Options: %s\n", Part->Mount_Flags, Part->Mount_Options.c_str());
 	if (Part->MTP_Storage_ID)
 		printf("   MTP_Storage_ID: %i\n", Part->MTP_Storage_ID);
+	if (!Part->Key_Directory.empty())
+		printf("   Metadata Key Directory: %s\n", Part->Key_Directory.c_str());
 	printf("\n");
 }