Adding support of dm-req-crypt

Currently Android provides disk encryption support using dm-crypt
which is based on bios. dm-crypt uses 512 bytes packet size for
crypto operations. While 512 bytes size packet is ok for SW based
disk encryption, it is inefficient for HW based crypto engines.
dm-req-crypt is similar to dm-crypt except it uses block requests
rathe bios for crypto operations. block requests when unpacked
carries data upto 512KB. Hence, HW based crypto engine can be used
more efficiently.

Also move create disk encryption key before framework start as
HW based disk encryption creates key in secure side. Key creation
can take sometime to create the key securely. If framework is
started before creating the key, it is possible that framework
requests service from secure side. Secure side can serve mostly one
request at a time. Secure side may reject framework request if key
creation request is still going on. This may cause problem in the
system

b/17475056 Enable hardware crypto for userdata encryption

Change-Id: I5480ab72a37c02532218a18faaba598a824589fd
Signed-off-by: Iliyan Malchev <malchev@google.com>
diff --git a/Android.mk b/Android.mk
index 1a1d28a..d90b1c2 100644
--- a/Android.mk
+++ b/Android.mk
@@ -82,6 +82,12 @@
 
 LOCAL_CFLAGS := -Werror=format
 
+ifeq ($(TARGET_HW_DISK_ENCRYPTION),true)
+LOCAL_C_INCLUDES += $(TARGET_CRYPTFS_HW_PATH)
+common_shared_libraries += libcryptfs_hw
+LOCAL_CFLAGS += -DCONFIG_HW_DISK_ENCRYPTION
+endif
+
 LOCAL_SHARED_LIBRARIES := $(common_shared_libraries)
 
 LOCAL_STATIC_LIBRARIES := $(common_static_libraries)
diff --git a/cryptfs.c b/cryptfs.c
index 17f5e57..a8211cc 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -63,6 +63,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
@@ -992,7 +996,11 @@
   tgt->status = 0;
   tgt->sector_start = 0;
   tgt->length = crypt_ftr->fs_size;
-  strcpy(tgt->target_type, "crypt");
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+  strlcpy(tgt->target_type, "req-crypt", DM_MAX_TYPE_NAME);
+#else
+  strlcpy(tgt->target_type, "crypt", DM_MAX_TYPE_NAME);
+#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);
@@ -1038,7 +1046,11 @@
      */
     v = (struct dm_target_versions *) &buffer[sizeof(struct dm_ioctl)];
     while (v->next) {
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+        if(!strcmp(v->name, "crypt") || !strcmp(v->name, "req-crypt")) {
+#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];
@@ -1060,7 +1072,7 @@
   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];
@@ -1751,6 +1763,12 @@
 
   fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
 
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+  if(!set_hw_device_encryption_key(passwd, (char*) crypt_ftr->crypto_type_name)) {
+    SLOGE("Hardware encryption key does not match");
+  }
+#endif
+
   // Create crypto block device - all (non fatal) code paths
   // need it
   if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
@@ -2199,7 +2217,11 @@
 /* aligned 32K writes tends to make flash happy.
  * SD card association recommends it.
  */
+#ifndef CONFIG_HW_DISK_ENCRYPTION
 #define BLOCKS_AT_A_TIME 8
+#else
+#define BLOCKS_AT_A_TIME 1024
+#endif
 
 struct encryptGroupsData
 {
@@ -3058,16 +3080,6 @@
          * restart the graphics services.
          */
         sleep(2);
-
-        /* startup service classes main and late_start */
-        property_set("vold.decrypt", "trigger_restart_min_framework");
-        SLOGD("Just triggered restart_min_framework\n");
-
-        /* OK, the framework is restarted and will soon be showing a
-         * progress bar.  Time to setup an encrypted mapping, and
-         * either write a new filesystem, or encrypt in place updating
-         * the progress bar as we work.
-         */
     }
 
     /* Start the actual work of making an encrypted filesystem */
@@ -3089,7 +3101,23 @@
            On successfully completing encryption, remove this flag */
         crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
         crypt_ftr.crypt_type = crypt_type;
-        strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256");
+#ifndef CONFIG_HW_DISK_ENCRYPTION
+        strlcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256", MAX_CRYPTO_TYPE_NAME_LEN);
+#else
+        strlcpy((char *)crypt_ftr.crypto_type_name, "aes-xts", MAX_CRYPTO_TYPE_NAME_LEN);
+
+	rc = clear_hw_device_encryption_key();
+        if (!rc) {
+          SLOGE("Error clearing device encryption hardware key. rc = %d", rc);
+        }
+
+        rc = set_hw_device_encryption_key(passwd,
+                                          (char*) crypt_ftr.crypto_type_name);
+        if (!rc) {
+          SLOGE("Error initializing device encryption hardware key. rc = %d", rc);
+          goto error_shutting_down;
+        }
+#endif
 
         /* Make an encrypted master key */
         if (create_encrypted_random_key(passwd, crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
@@ -3115,6 +3143,18 @@
         }
     }
 
+    if (how == CRYPTO_ENABLE_INPLACE) {
+        /* startup service classes main and late_start */
+        property_set("vold.decrypt", "trigger_restart_min_framework");
+        SLOGD("Just triggered restart_min_framework\n");
+
+        /* OK, the framework is restarted and will soon be showing a
+         * progress bar.  Time to setup an encrypted mapping, and
+         * either write a new filesystem, or encrypt in place updating
+         * the progress bar as we work.
+         */
+    }
+
     decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
     create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
                           "userdata");
@@ -3300,6 +3340,20 @@
     put_crypt_ftr_and_key(&crypt_ftr);
 
     free(adjusted_passwd);
+
+#ifdef CONFIG_HW_DISK_ENCRYPTION
+    if (crypt_type == CRYPT_TYPE_DEFAULT) {
+        int rc = update_hw_device_encryption_key(DEFAULT_PASSWORD, (char*) crypt_ftr.crypto_type_name);
+        SLOGD("Update hardware encryption key to default for crypt_type: %d. rc = %d", crypt_type, rc);
+        if (!rc)
+            return -1;
+    } else {
+        int rc = update_hw_device_encryption_key(newpw, (char*) crypt_ftr.crypto_type_name);
+        SLOGD("Update hardware encryption key for crypt_type: %d. rc = %d", crypt_type, rc);
+        if (!rc)
+            return -1;
+    }
+#endif
     return 0;
 }