Merge "Check crypto footer before offering to decrypt" into android-4.4
diff --git a/crypto/ics/cryptfs.c b/crypto/ics/cryptfs.c
index 193339e..4f3d5d0 100644
--- a/crypto/ics/cryptfs.c
+++ b/crypto/ics/cryptfs.c
@@ -653,6 +653,28 @@
   return -1;
 }
 
+int cryptfs_check_footer(void)
+{
+    int rc = -1;
+    char fs_type[PROPERTY_VALUE_MAX];
+    char real_blkdev[MAXPATHLEN];
+    char fs_options[PROPERTY_VALUE_MAX];
+    unsigned long mnt_flags;
+    struct crypt_mnt_ftr crypt_ftr;
+    /* Allocate enough space for a 256 bit key, but we may use less */
+    unsigned char encrypted_master_key[256];
+    unsigned char salt[SALT_LEN];
+
+    if (get_orig_mount_parms(DATA_MNT_POINT, fs_type, real_blkdev, &mnt_flags, fs_options)) {
+        printf("Error reading original mount parms for mount point %s\n", DATA_MNT_POINT);
+        return rc;
+    }
+
+    rc = get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt);
+
+    return rc;
+}
+
 int cryptfs_check_passwd(const char *passwd)
 {
     char pwbuf[256];
diff --git a/crypto/ics/cryptfs.h b/crypto/ics/cryptfs.h
index eee43b3..8c80376 100644
--- a/crypto/ics/cryptfs.h
+++ b/crypto/ics/cryptfs.h
@@ -76,6 +76,7 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+  int cryptfs_check_footer(void);
   int cryptfs_check_passwd(const char *pw);
 #ifdef __cplusplus
 }
diff --git a/crypto/jb/cryptfs.c b/crypto/jb/cryptfs.c
index 4e5706b..f9c0d74 100644
--- a/crypto/jb/cryptfs.c
+++ b/crypto/jb/cryptfs.c
@@ -1354,13 +1354,32 @@
 
 #define FSTAB_PREFIX "/fstab."
 
+int cryptfs_check_footer(void)
+{
+    int rc = -1;
+    char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
+    char propbuf[PROPERTY_VALUE_MAX];
+    struct crypt_mnt_ftr crypt_ftr;
+
+    property_get("ro.hardware", propbuf, "");
+    snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
+
+    fstab = fs_mgr_read_fstab(fstab_filename);
+    if (!fstab) {
+        printf("failed to open %s\n", fstab_filename);
+        return -1;
+    }
+
+    rc = get_crypt_ftr_and_key(&crypt_ftr);
+
+    return rc;
+}
+
 int cryptfs_check_passwd(char *passwd)
 {
     int rc = -1;
     char fstab_filename[PROPERTY_VALUE_MAX + sizeof(FSTAB_PREFIX)];
     char propbuf[PROPERTY_VALUE_MAX];
-    int i;
-    int flags;
 
     property_get("ro.hardware", propbuf, "");
     snprintf(fstab_filename, sizeof(fstab_filename), FSTAB_PREFIX"%s", propbuf);
diff --git a/crypto/jb/cryptfs.h b/crypto/jb/cryptfs.h
index 162159e..d815814 100644
--- a/crypto/jb/cryptfs.h
+++ b/crypto/jb/cryptfs.h
@@ -139,6 +139,7 @@
   typedef void (*kdf_func)(char *passwd, unsigned char *salt, unsigned char *ikey, void *params);
 
   int cryptfs_crypto_complete(void);
+  int cryptfs_check_footer(void);
   int cryptfs_check_passwd(char *pw);
   int cryptfs_verify_passwd(char *newpw);
   int cryptfs_restart(void);
diff --git a/partition.cpp b/partition.cpp
index 20ceda1..57a6923 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -50,6 +50,14 @@
 #ifdef USE_EXT4
 	#include "make_ext4fs.h"
 #endif
+
+#ifdef TW_INCLUDE_CRYPTO
+	#ifdef TW_INCLUDE_JB_CRYPTO
+		#include "crypto/jb/cryptfs.h"
+	#else
+		#include "crypto/ics/cryptfs.h"
+	#endif
+#endif
 }
 #ifdef HAVE_SELINUX
 #include "selinux/selinux.h"
@@ -290,14 +298,38 @@
 				Decrypted_Block_Device = crypto_blkdev;
 				LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
 			} else if (!Mount(false)) {
-				Is_Encrypted = true;
-				Is_Decrypted = false;
-				Can_Be_Mounted = false;
-				Current_File_System = "emmc";
-				Setup_Image(Display_Error);
-				DataManager::SetValue(TW_IS_ENCRYPTED, 1);
-				DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
-				DataManager::SetValue("tw_crypto_display", "");
+				if (Is_Present) {
+#ifdef TW_INCLUDE_JB_CRYPTO
+					// No extra flags needed
+#else
+					property_set("ro.crypto.fs_type", CRYPTO_FS_TYPE);
+					property_set("ro.crypto.fs_real_blkdev", CRYPTO_REAL_BLKDEV);
+					property_set("ro.crypto.fs_mnt_point", CRYPTO_MNT_POINT);
+					property_set("ro.crypto.fs_options", CRYPTO_FS_OPTIONS);
+					property_set("ro.crypto.fs_flags", CRYPTO_FS_FLAGS);
+					property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
+#ifdef CRYPTO_SD_FS_TYPE
+					property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
+					property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
+					property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
+#endif
+					property_set("rw.km_fips_status", "ready");
+#endif
+					if (cryptfs_check_footer() == 0) {
+						Is_Encrypted = true;
+						Is_Decrypted = false;
+						Can_Be_Mounted = false;
+						Current_File_System = "emmc";
+						Setup_Image(Display_Error);
+						DataManager::SetValue(TW_IS_ENCRYPTED, 1);
+						DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
+						DataManager::SetValue("tw_crypto_display", "");
+					} else {
+						LOGERR("Could not mount /data and unable to find crypto footer.\n");
+					}
+				} else {
+					LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
+				}
 			} else {
 				// Filesystem is not encrypted and the mount
 				// succeeded, so get it back to the original
diff --git a/partitionmanager.cpp b/partitionmanager.cpp
index e8b362c..e6193f9 100644
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -1383,9 +1383,9 @@
 	property_set("ro.crypto.keyfile.userdata", CRYPTO_KEY_LOC);
 
 #ifdef CRYPTO_SD_FS_TYPE
-    property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
-    property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
-    property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
+	property_set("ro.crypto.sd_fs_type", CRYPTO_SD_FS_TYPE);
+	property_set("ro.crypto.sd_fs_real_blkdev", CRYPTO_SD_REAL_BLKDEV);
+	property_set("ro.crypto.sd_fs_mnt_point", EXPAND(TW_INTERNAL_STORAGE_PATH));
 #endif
 
     property_set("rw.km_fips_status", "ready");