Support default, pattern, pin and password encryption types

Store encryption type in crypto footer, and provide functions to
manipulate it. Add mount_default_encrypted command to vdc to allow
mounting of default encrypted volumes at boot time.

Bug: 8769627
Change-Id: Ie41848f258e128b48b579e09789abfa24c95e2b2
diff --git a/cryptfs.c b/cryptfs.c
index 40ad36a..4dd7a6b 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -23,6 +23,7 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/stat.h>
+#include <ctype.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -61,6 +62,9 @@
 
 #define KEY_IN_FOOTER  "footer"
 
+// "default_password" encoded into hex (d=0x64 etc)
+#define DEFAULT_PASSWORD "64656661756c745f70617373776f7264"
+
 #define EXT4_FS 1
 #define FAT_FS 2
 
@@ -351,7 +355,7 @@
         crypt_ftr->minor_version = 1;
     }
 
-    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version)) {
+    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) {
         SLOGW("upgrading crypto footer to 1.2");
         /* But keep the old kdf_type.
          * It will get updated later to KDF_SCRYPT after the password has been verified.
@@ -361,6 +365,12 @@
         crypt_ftr->minor_version = 2;
     }
 
+    if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 2)) {
+        SLOGW("upgrading crypto footer to 1.3");
+        crypt_ftr->crypt_type = CRYPT_TYPE_PASSWORD;
+        crypt_ftr->minor_version = 3;
+    }
+
     if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) {
         if (lseek64(fd, offset, SEEK_SET) == -1) {
             SLOGE("Cannot seek to crypt footer\n");
@@ -663,10 +673,53 @@
     return -1;
 }
 
+static int hexdigit (char c)
+{
+    if (c >= '0' && c <= '9') return c - '0';
+    c = tolower(c);
+    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+    return -1;
+}
+
+static unsigned char* convert_hex_ascii_to_key(const char* master_key_ascii,
+                                               unsigned int* out_keysize)
+{
+    unsigned int i;
+    *out_keysize = 0;
+
+    size_t size = strlen (master_key_ascii);
+    if (size % 2) {
+        SLOGE("Trying to convert ascii string of odd length");
+        return NULL;
+    }
+
+    unsigned char* master_key = (unsigned char*) malloc(size / 2);
+    if (master_key == 0) {
+        SLOGE("Cannot allocate");
+        return NULL;
+    }
+
+    for (i = 0; i < size; i += 2) {
+        int high_nibble = hexdigit (master_key_ascii[i]);
+        int low_nibble = hexdigit (master_key_ascii[i + 1]);
+
+        if(high_nibble < 0 || low_nibble < 0) {
+            SLOGE("Invalid hex string");
+            free (master_key);
+            return NULL;
+        }
+
+        master_key[*out_keysize] = high_nibble * 16 + low_nibble;
+        (*out_keysize)++;
+    }
+
+    return master_key;
+}
+
 /* Convert a binary key of specified length into an ascii hex string equivalent,
  * without the leading 0x and with null termination
  */
-void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize,
+static void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize,
                               char *master_key_ascii)
 {
   unsigned int i, a;
@@ -870,13 +923,23 @@
 
 }
 
-static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey, void *params UNUSED) {
+static int pbkdf2(char *passwd, unsigned char *salt,
+                  unsigned char *ikey, void *params UNUSED)
+{
     /* Turn the password into a key and IV that can decrypt the master key */
-    PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN,
+    unsigned int keysize;
+    char* master_key = (char*)convert_hex_ascii_to_key(passwd, &keysize);
+    if (!master_key) return -1;
+    PKCS5_PBKDF2_HMAC_SHA1(master_key, keysize, salt, SALT_LEN,
                            HASH_COUNT, KEY_LEN_BYTES+IV_LEN_BYTES, ikey);
+
+    free (master_key);
+    return 0;
 }
 
-static void scrypt(char *passwd, unsigned char *salt, unsigned char *ikey, void *params) {
+static int scrypt(char *passwd, unsigned char *salt,
+                  unsigned char *ikey, void *params)
+{
     struct crypt_mnt_ftr *ftr = (struct crypt_mnt_ftr *) params;
 
     int N = 1 << ftr->N_factor;
@@ -884,8 +947,14 @@
     int p = 1 << ftr->p_factor;
 
     /* Turn the password into a key and IV that can decrypt the master key */
-    crypto_scrypt((unsigned char *) passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey,
+    unsigned int keysize;
+    unsigned char* master_key = convert_hex_ascii_to_key(passwd, &keysize);
+    if (!master_key) return -1;
+    crypto_scrypt(master_key, keysize, salt, SALT_LEN, N, r, p, ikey,
             KEY_LEN_BYTES + IV_LEN_BYTES);
+
+    free (master_key);
+    return 0;
 }
 
 static int encrypt_master_key(char *passwd, unsigned char *salt,
@@ -899,7 +968,10 @@
 
     /* Turn the password into a key and IV that can decrypt the master key */
     get_device_scrypt_params(crypt_ftr);
-    scrypt(passwd, salt, ikey, crypt_ftr);
+    if (scrypt(passwd, salt, ikey, crypt_ftr)) {
+        SLOGE("scrypt failed");
+        return -1;
+    }
 
     /* Initialize the decryption engine */
     if (! EVP_EncryptInit(&e_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) {
@@ -937,7 +1009,10 @@
   int decrypted_len, final_len;
 
   /* Turn the password into a key and IV that can decrypt the master key */
-  kdf(passwd, salt, ikey, kdf_params);
+  if (kdf(passwd, salt, ikey, kdf_params)) {
+    SLOGE("kdf failed");
+    return -1;
+  }
 
   /* Initialize the decryption engine */
   if (! EVP_DecryptInit(&d_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) {
@@ -1068,7 +1143,7 @@
     }
 }
 
-int cryptfs_restart(void)
+static int cryptfs_restart_internal(int restart_main)
 {
     char fs_type[32];
     char real_blkdev[MAXPATHLEN];
@@ -1090,32 +1165,34 @@
         return -1;
     }
 
-    /* Here is where we shut down the framework.  The init scripts
-     * start all services in one of three classes: core, main or late_start.
-     * On boot, we start core and main.  Now, we stop main, but not core,
-     * as core includes vold and a few other really important things that
-     * we need to keep running.  Once main has stopped, we should be able
-     * to umount the tmpfs /data, then mount the encrypted /data.
-     * We then restart the class main, and also the class late_start.
-     * At the moment, I've only put a few things in late_start that I know
-     * are not needed to bring up the framework, and that also cause problems
-     * with unmounting the tmpfs /data, but I hope to add add more services
-     * to the late_start class as we optimize this to decrease the delay
-     * till the user is asked for the password to the filesystem.
-     */
+    if (restart_main) {
+        /* Here is where we shut down the framework.  The init scripts
+         * start all services in one of three classes: core, main or late_start.
+         * On boot, we start core and main.  Now, we stop main, but not core,
+         * as core includes vold and a few other really important things that
+         * we need to keep running.  Once main has stopped, we should be able
+         * to umount the tmpfs /data, then mount the encrypted /data.
+         * We then restart the class main, and also the class late_start.
+         * At the moment, I've only put a few things in late_start that I know
+         * are not needed to bring up the framework, and that also cause problems
+         * with unmounting the tmpfs /data, but I hope to add add more services
+         * to the late_start class as we optimize this to decrease the delay
+         * till the user is asked for the password to the filesystem.
+         */
 
-    /* The init files are setup to stop the class main when vold.decrypt is
-     * set to trigger_reset_main.
-     */
-    property_set("vold.decrypt", "trigger_reset_main");
-    SLOGD("Just asked init to shut down class main\n");
+        /* The init files are setup to stop the class main when vold.decrypt is
+         * set to trigger_reset_main.
+         */
+        property_set("vold.decrypt", "trigger_reset_main");
+        SLOGD("Just asked init to shut down class main\n");
 
-    /* Ugh, shutting down the framework is not synchronous, so until it
-     * can be fixed, this horrible hack will wait a moment for it all to
-     * shut down before proceeding.  Without it, some devices cannot
-     * restart the graphics services.
-     */
-    sleep(2);
+        /* Ugh, shutting down the framework is not synchronous, so until it
+         * can be fixed, this horrible hack will wait a moment for it all to
+         * shut down before proceeding.  Without it, some devices cannot
+         * restart the graphics services.
+         */
+        sleep(2);
+    }
 
     /* Now that the framework is shutdown, we should be able to umount()
      * the tmpfs filesystem, and mount the real one.
@@ -1163,6 +1240,12 @@
     return rc;
 }
 
+int cryptfs_restart(void)
+{
+    /* Call internal implementation forcing a restart of main service group */
+    return cryptfs_restart_internal(1);
+}
+
 static int do_crypto_complete(char *mount_point UNUSED)
 {
   struct crypt_mnt_ftr crypt_ftr;
@@ -1204,45 +1287,33 @@
   return 0;
 }
 
-static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label)
+static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
+                                   char *passwd, char *mount_point, char *label)
 {
-  struct crypt_mnt_ftr crypt_ftr;
   /* Allocate enough space for a 256 bit key, but we may use less */
   unsigned char decrypted_master_key[32];
   char crypto_blkdev[MAXPATHLEN];
   char real_blkdev[MAXPATHLEN];
   char tmp_mount_point[64];
   unsigned int orig_failed_decrypt_count;
-  char encrypted_state[PROPERTY_VALUE_MAX];
   int rc;
   kdf_func kdf;
   void *kdf_params;
 
-  property_get("ro.crypto.state", encrypted_state, "");
-  if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
-    SLOGE("encrypted fs already validated or not running with encryption, aborting");
-    return -1;
-  }
+  SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr->fs_size);
+  orig_failed_decrypt_count = crypt_ftr->failed_decrypt_count;
 
-  fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
-
-  if (get_crypt_ftr_and_key(&crypt_ftr)) {
-    SLOGE("Error getting crypt footer and key\n");
-    return -1;
-  }
-
-  SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr.fs_size);
-  orig_failed_decrypt_count = crypt_ftr.failed_decrypt_count;
-
-  if (! (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) ) {
-    if (decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr)) {
+  if (! (crypt_ftr->flags & CRYPT_MNT_KEY_UNENCRYPTED) ) {
+    if (decrypt_master_key(passwd, decrypted_master_key, crypt_ftr)) {
       SLOGE("Failed to decrypt master key\n");
       return -1;
     }
   }
 
-  if (create_crypto_blk_dev(&crypt_ftr, decrypted_master_key,
-                               real_blkdev, crypto_blkdev, label)) {
+  fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
+
+  if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
+                            real_blkdev, crypto_blkdev, label)) {
     SLOGE("Error creating decrypted block device\n");
     return -1;
   }
@@ -1259,22 +1330,22 @@
   if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, tmp_mount_point)) {
     SLOGE("Error temp mounting decrypted block device\n");
     delete_crypto_blk_dev(label);
-    crypt_ftr.failed_decrypt_count++;
+    crypt_ftr->failed_decrypt_count++;
   } else {
     /* Success, so just umount and we'll mount it properly when we restart
      * the framework.
      */
     umount(tmp_mount_point);
-    crypt_ftr.failed_decrypt_count  = 0;
+    crypt_ftr->failed_decrypt_count  = 0;
   }
 
-  if (orig_failed_decrypt_count != crypt_ftr.failed_decrypt_count) {
-    put_crypt_ftr_and_key(&crypt_ftr);
+  if (orig_failed_decrypt_count != crypt_ftr->failed_decrypt_count) {
+    put_crypt_ftr_and_key(crypt_ftr);
   }
 
-  if (crypt_ftr.failed_decrypt_count) {
+  if (crypt_ftr->failed_decrypt_count) {
     /* We failed to mount the device, so return an error */
-    rc = crypt_ftr.failed_decrypt_count;
+    rc = crypt_ftr->failed_decrypt_count;
 
   } else {
     /* Woot!  Success!  Save the name of the crypto block device
@@ -1293,12 +1364,12 @@
     /*
      * Upgrade if we're not using the latest KDF.
      */
-    if (crypt_ftr.kdf_type != KDF_SCRYPT) {
-        crypt_ftr.kdf_type = KDF_SCRYPT;
-        rc = encrypt_master_key(passwd, crypt_ftr.salt, saved_master_key, crypt_ftr.master_key,
-                &crypt_ftr);
+    if (crypt_ftr->kdf_type != KDF_SCRYPT) {
+        crypt_ftr->kdf_type = KDF_SCRYPT;
+        rc = encrypt_master_key(passwd, crypt_ftr->salt, saved_master_key,
+                                crypt_ftr->master_key, crypt_ftr);
         if (!rc) {
-            rc = put_crypt_ftr_and_key(&crypt_ftr);
+            rc = put_crypt_ftr_and_key(crypt_ftr);
         }
         SLOGD("Key Derivation Function upgrade: rc=%d\n", rc);
     }
@@ -1362,12 +1433,35 @@
   return do_crypto_complete("/data");
 }
 
+int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr)
+{
+    char encrypted_state[PROPERTY_VALUE_MAX];
+    property_get("ro.crypto.state", encrypted_state, "");
+    if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
+        SLOGE("encrypted fs already validated or not running with encryption,"
+              " aborting");
+        return -1;
+    }
+
+    if (get_crypt_ftr_and_key(crypt_ftr)) {
+        SLOGE("Error getting crypt footer and key");
+        return -1;
+    }
+
+    return 0;
+}
+
 int cryptfs_check_passwd(char *passwd)
 {
-    int rc = -1;
+    struct crypt_mnt_ftr crypt_ftr;
+    int rc;
 
-    rc = test_mount_encrypted_fs(passwd, DATA_MNT_POINT, "userdata");
+    rc = check_unmounted_and_get_ftr(&crypt_ftr);
+    if (rc)
+        return rc;
 
+    rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
+                                 DATA_MNT_POINT, "userdata");
     return rc;
 }
 
@@ -1987,6 +2081,11 @@
         crypt_ftr.fs_size = nr_sec;
     }
     crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS;
+
+    /** @TODO If we keep this route, must pass in crypt_type.
+     * If all devices are encrypted by default, we don't need that change.
+     */
+    crypt_ftr.crypt_type = CRYPT_TYPE_PASSWORD;
     strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256");
 
     /* Make an encrypted master key */
@@ -2143,24 +2242,36 @@
     return -1;
 }
 
-int cryptfs_changepw(char *newpw)
+int cryptfs_changepw(int crypt_type, char *newpw)
 {
     struct crypt_mnt_ftr crypt_ftr;
     unsigned char decrypted_master_key[KEY_LEN_BYTES];
 
     /* This is only allowed after we've successfully decrypted the master key */
-    if (! master_key_saved) {
+    if (!master_key_saved) {
         SLOGE("Key not saved, aborting");
         return -1;
     }
 
+    if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
+        SLOGE("Invalid crypt_type %d", crypt_type);
+        return -1;
+    }
+
     /* get key */
     if (get_crypt_ftr_and_key(&crypt_ftr)) {
-      SLOGE("Error getting crypt footer and key");
-      return -1;
+        SLOGE("Error getting crypt footer and key");
+        return -1;
     }
 
-    encrypt_master_key(newpw, crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr);
+    crypt_ftr.crypt_type = crypt_type;
+
+    encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD
+                                                        : newpw,
+                       crypt_ftr.salt,
+                       saved_master_key,
+                       crypt_ftr.master_key,
+                       &crypt_ftr);
 
     /* save the key */
     put_crypt_ftr_and_key(&crypt_ftr);
@@ -2307,3 +2418,52 @@
 out:
     return rc;
 }
+
+/* Checks userdata. Attempt to mount the volume if default-
+ * encrypted.
+ * On success trigger next init phase and return 0.
+ * Currently do not handle failure - see TODO below.
+ */
+int cryptfs_mount_default_encrypted(void)
+{
+    char decrypt_state[PROPERTY_VALUE_MAX];
+    property_get("vold.decrypt", decrypt_state, "0");
+    if (!strcmp(decrypt_state, "0")) {
+        SLOGE("Not encrypted - should not call here");
+    } else {
+        int crypt_type = cryptfs_get_password_type();
+        if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) {
+            SLOGE("Bad crypt type - error");
+        } else if (crypt_type != CRYPT_TYPE_DEFAULT) {
+            SLOGD("Password is not default - "
+                  "starting min framework to prompt");
+            property_set("vold.decrypt", "trigger_restart_min_framework");
+            return 0;
+        } else if (cryptfs_check_passwd(DEFAULT_PASSWORD) == 0) {
+            SLOGD("Password is default - restarting filesystem");
+            cryptfs_restart_internal(0);
+            return 0;
+        } else {
+            SLOGE("Encrypted, default crypt type but can't decrypt");
+        }
+    }
+
+    /** @TODO make sure we factory wipe in this situation
+     *  In general if we got here there is no recovery
+     */
+    return 0;
+}
+
+/* Returns type of the password, default, pattern, pin or password.
+ */
+int cryptfs_get_password_type(void)
+{
+    struct crypt_mnt_ftr crypt_ftr;
+
+    if (get_crypt_ftr_and_key(&crypt_ftr)) {
+        SLOGE("Error getting crypt footer and key\n");
+        return -1;
+    }
+
+    return crypt_ftr.crypt_type;
+}