Support Qualcomm hardware decrypt
Change-Id: I121ef0f5da209be48f6d87559d539c7fc6d85336
diff --git a/crypto/lollipop/Android.mk b/crypto/lollipop/Android.mk
index 148e328..938e0d1 100644
--- a/crypto/lollipop/Android.mk
+++ b/crypto/lollipop/Android.mk
@@ -8,8 +8,35 @@
LOCAL_SRC_FILES = cryptfs.c
LOCAL_SHARED_LIBRARIES := libcrypto libhardware libcutils
LOCAL_C_INCLUDES := external/openssl/include $(commands_recovery_local_path)/crypto/scrypt/lib/crypto
+
+ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
+ LOCAL_C_INCLUDES += device/qcom/common/cryptfs_hw
+ LOCAL_SHARED_LIBRARIES += libcryptfs_hw
+ LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
+endif
+
LOCAL_WHOLE_STATIC_LIBRARIES += libscrypttwrp_static
include $(BUILD_SHARED_LIBRARY)
+
+
+#include $(CLEAR_VARS)
+#LOCAL_MODULE := twrpdec
+#LOCAL_MODULE_TAGS := eng optional
+#LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+#LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/sbin
+#LOCAL_SRC_FILES := main.c cryptfs.c
+#LOCAL_SHARED_LIBRARIES := libcrypto libhardware libcutils libc
+#LOCAL_C_INCLUDES := external/openssl/include $(commands_recovery_local_path)/crypto/scrypt/lib/crypto
+
+#ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
+# LOCAL_C_INCLUDES += device/qcom/common/cryptfs_hw
+# LOCAL_SHARED_LIBRARIES += libcryptfs_hw
+# LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
+#endif
+
+#LOCAL_WHOLE_STATIC_LIBRARIES += libscrypttwrp_static
+#include $(BUILD_EXECUTABLE)
+
endif
diff --git a/crypto/lollipop/cryptfs.c b/crypto/lollipop/cryptfs.c
index 496b960..697593f 100644
--- a/crypto/lollipop/cryptfs.c
+++ b/crypto/lollipop/cryptfs.c
@@ -21,6 +21,7 @@
*/
#include <sys/types.h>
+#include <linux/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <ctype.h>
@@ -52,6 +53,10 @@
#define UNUSED __attribute__((unused))
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+#include "cryptfs_hw.h"
+#endif
+
#define DM_CRYPT_BUF_SIZE 4096
#define HASH_COUNT 2000
@@ -592,12 +597,26 @@
tgt->status = 0;
tgt->sector_start = 0;
tgt->length = crypt_ftr->fs_size;
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name) && is_hw_fde_enabled()) {
+ printf("load_crypto_mapping_table using req-crypt\n");
+ strlcpy(tgt->target_type, "req-crypt",DM_MAX_TYPE_NAME);
+ } else {
+ printf("load_crypto_mapping_table using crypt\n");
+ strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
+ }
+#else
strcpy(tgt->target_type, "crypt");
+#endif
crypt_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);
convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
sprintf(crypt_params, "%s %s 0 %s 0 %s", crypt_ftr->crypto_type_name,
master_key_ascii, real_blk_name, extra_params);
+
+ printf("%s: target_type = %s\n", __func__, tgt->target_type);
+ printf("%s: real_blk_name = %s, extra_params = %s\n", __func__, real_blk_name, extra_params);
+
crypt_params += strlen(crypt_params) + 1;
crypt_params = (char *) (((unsigned long)crypt_params + 7) & ~8); /* Align to an 8 byte boundary */
tgt->next = crypt_params - buffer;
@@ -623,6 +642,7 @@
char buffer[DM_CRYPT_BUF_SIZE];
struct dm_ioctl *io;
struct dm_target_versions *v;
+ int flag;
int i;
io = (struct dm_ioctl *) buffer;
@@ -638,7 +658,17 @@
*/
v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
while (v->next) {
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ if (is_hw_fde_enabled()) {
+ flag = (!strcmp(v->name, "crypt") || !strcmp(v->name, "req-crypt"));
+ } else {
+ flag = (!strcmp(v->name, "crypt"));
+ }
+ printf("get_dm_crypt_version flag: %i, name: '%s'\n", flag, v->name);
+ if (flag) {
+#else
if (! strcmp(v->name, "crypt")) {
+#endif
/* We found the crypt driver, return the version, and get out */
version[0] = v->version[0];
version[1] = v->version[1];
@@ -660,12 +690,16 @@
struct dm_ioctl *io;
struct dm_target_spec *tgt;
unsigned int minor;
- int fd;
+ int fd=0;
int i;
int retval = -1;
int version[3];
char *extra_params;
int load_count;
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ char encrypted_state[PROPERTY_VALUE_MAX] = {0};
+ char progress[PROPERTY_VALUE_MAX] = {0};
+#endif
if ((fd = open("/dev/device-mapper", O_RDWR)) < 0 ) {
printf("Cannot open device-mapper\n");
@@ -689,6 +723,31 @@
minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ if (is_hw_fde_enabled() && is_hw_disk_encryption((char*) crypt_ftr->crypto_type_name)) {
+ /* Set fde_enabled if either FDE completed or in-progress */
+ property_get("ro.crypto.state", encrypted_state, ""); /* FDE completed */
+ property_get("vold.encrypt_progress", progress, ""); /* FDE in progress */
+ if (!strcmp(encrypted_state, "encrypted") || strcmp(progress, "")) {
+ extra_params = "fde_enabled";
+ printf("create_crypto_blk_dev extra_params set to fde_enabled\n");
+ } else {
+ extra_params = "fde_disabled";
+ printf("create_crypto_blk_dev extra_params set to fde_disabled\n");
+ }
+ } else {
+ extra_params = "";
+ printf("create_crypto_blk_dev extra_params set to empty string\n");
+ if (!get_dm_crypt_version(fd, name, version)) {
+ /* Support for allow_discards was added in version 1.11.0 */
+ if ((version[0] >= 2) ||
+ ((version[0] == 1) && (version[1] >= 11))) {
+ extra_params = "1 allow_discards";
+ printf("Enabling support for allow_discards in dmcrypt.\n");
+ }
+ }
+ }
+#else
extra_params = "";
if (! get_dm_crypt_version(fd, name, version)) {
/* Support for allow_discards was added in version 1.11.0 */
@@ -698,6 +757,7 @@
printf("Enabling support for allow_discards in dmcrypt.\n");
}
}
+#endif
load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name,
fd, extra_params);
@@ -1020,7 +1080,7 @@
char crypto_blkdev[MAXPATHLEN];
char tmp_mount_point[64];
unsigned int orig_failed_decrypt_count;
- int rc;
+ int rc = 0;
kdf_func kdf;
void *kdf_params;
int use_keymaster = 0;
@@ -1040,6 +1100,18 @@
}
}
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ if (is_hw_fde_enabled()) {
+ if(is_hw_disk_encryption((char*) crypt_ftr->crypto_type_name)) {
+ if (!set_hw_device_encryption_key(passwd, (char*) crypt_ftr->crypto_type_name)) {
+ rc = -1;
+ printf("Failed to set_hw_device_encryption_key\n");
+ goto errout;
+ }
+ }
+ }
+#endif
+
// Create crypto block device - all (non fatal) code paths
// need it
if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
@@ -1207,7 +1279,7 @@
// an even length, since each character encodes to two characters.
length = strlen(passwd);
if (length % 2) {
- printf("Password not correctly hex encoded.");
+ printf("Password not correctly hex encoded.\n");
return 0;
}
@@ -1241,10 +1313,10 @@
* regular character codes to their hexadecimal representation to make
* decrypt work properly with Android 5.0 lollipop decryption.
*/
-char* hexadj_passwd(const char* passwd)
+char* hexadj_passwd(const char* passwd, int has_hw_crypto)
{
size_t index, length;
- char* ptr = passwd;
+ const char* ptr = passwd;
if (!passwd) {
return 0;
@@ -1261,7 +1333,15 @@
sprintf(hex + (index * 2), "%02X", *ptr);
ptr++;
}
-
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ if (has_hw_crypto) {
+ printf("hexadj_passwd converting to lower case for hardware disk crypto.\n");
+ length *= 2;
+ for (index = 0; index < length; index++) {
+ hex[index] = tolower(hex[index]);
+ }
+ }
+#endif
return hex;
}
@@ -1279,22 +1359,36 @@
{
struct crypt_mnt_ftr crypt_ftr;
int rc;
+ int has_hw_crypto = 0;
rc = check_unmounted_and_get_ftr(&crypt_ftr);
if (rc)
return rc;
- char* adjusted_passwd = adjust_passwd(passwd);
- char* hex_passwd = hexadj_passwd(passwd);
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+ printf("CONFIG_HW_DISK_ENCRYPTION present\n");
+ if (is_hw_fde_enabled() && is_hw_disk_encryption((char*) crypt_ftr.crypto_type_name))
+ has_hw_crypto = 1;
+#endif
- if (adjusted_passwd) {
+ //if (passwd) printf("passwd: '%s'\n", passwd);
+ char* adjusted_passwd;
+ if (!has_hw_crypto)
+ adjusted_passwd = adjust_passwd(passwd);
+ //if (adjusted_passwd) printf("adjusted_passwd: '%s'\n", adjusted_passwd);
+ char* hex_passwd = hexadj_passwd(passwd, has_hw_crypto);
+ //if (hex_passwd) printf("hex_passwd: '%s'\n", hex_passwd);
+ printf("has_hw_crypto is %i\n", has_hw_crypto);
+ if (!has_hw_crypto && adjusted_passwd) {
int failed_decrypt_count = crypt_ftr.failed_decrypt_count;
- rc = test_mount_encrypted_fs(&crypt_ftr, adjusted_passwd,
+ //printf("trying adjusted password '%s'\n", adjusted_passwd);
+ rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd,
DATA_MNT_POINT, "userdata");
// Maybe the original one still works?
if (rc) {
// Don't double count this failure
+ //printf("trying passwd '%s'\n", passwd);
crypt_ftr.failed_decrypt_count = failed_decrypt_count;
rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
DATA_MNT_POINT, "userdata");
@@ -1305,16 +1399,23 @@
printf("TWRP NOT Updating pattern to new format");
//cryptfs_changepw(CRYPT_TYPE_PATTERN, passwd);
} else if (hex_passwd) {
+ //printf("trying hex_passwd '%s'\n", hex_passwd);
rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd,
DATA_MNT_POINT, "userdata");
}
}
free(adjusted_passwd);
} else {
- rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
- DATA_MNT_POINT, "userdata");
- if (rc && hex_passwd) {
+ if (hex_passwd) {
+ //printf("2trying hex_passwd '%s'\n", hex_passwd);
rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd,
+ DATA_MNT_POINT, "userdata");
+ } else {
+ rc = 1;
+ }
+ if (rc && passwd) {
+ //printf("2trying passwd '%s'\n", passwd);
+ rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
DATA_MNT_POINT, "userdata");
}
}
@@ -1323,7 +1424,7 @@
free(hex_passwd);
/*if (rc == 0 && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
- printf("cryptfs_check_passwd update expiry time?\n");
+ printf("cryptfs_check_passwd update expiry time?\n");
cryptfs_clear_password();
password = strdup(passwd);
struct timespec now;
diff --git a/crypto/lollipop/main.c b/crypto/lollipop/main.c
new file mode 100644
index 0000000..4edec86
--- /dev/null
+++ b/crypto/lollipop/main.c
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <linux/types.h>
+#include <sys/wait.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <linux/dm-ioctl.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <string.h>
+#include <sys/mount.h>
+#include <openssl/evp.h>
+#include <errno.h>
+#include <linux/kdev_t.h>
+#include <time.h>
+#include "cryptfs.h"
+#include "cutils/properties.h"
+#include "crypto_scrypt.h"
+#include <hardware/keymaster.h>
+
+int main() {
+ printf("blah\n");
+ set_partition_data("/dev/block/mmcblk0p28", "/dev/block/mmcblk0p27", "ext4");
+ printf("blah2\n");
+ int ret = cryptfs_check_passwd("30303030");
+ //int ret = cryptfs_check_passwd("0000");
+ return 0;
+}
diff --git a/partition.cpp b/partition.cpp
index ef29bb6..87ba0bc 100644
--- a/partition.cpp
+++ b/partition.cpp
@@ -259,6 +259,7 @@
Wipe_Available_in_GUI = true;
Can_Be_Backed_Up = true;
} else if (Mount_Point == "/data") {
+ UnMount(false); // added in case /data is mounted as tmpfs for qcom hardware decrypt
Display_Name = "Data";
Backup_Display_Name = Display_Name;
Storage_Name = Display_Name;
diff --git a/prebuilt/Android.mk b/prebuilt/Android.mk
index 07e24e3..1449dc8 100644
--- a/prebuilt/Android.mk
+++ b/prebuilt/Android.mk
@@ -131,6 +131,9 @@
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcryptfslollipop.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so
RELINK_SOURCE_FILES += $(TARGET_OUT_SHARED_LIBRARIES)/libhardware.so
+ ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
+ RELINK_SOURCE_FILES += $(TARGET_OUT)/vendor/lib/libcryptfs_hw.so
+ endif
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
RELINK_SOURCE_FILES += $(TARGET_OUT_EXECUTABLES)/make_ext4fs