Merge "Don't try to encrypt in place a filesystem that is too large and return proper errors" into honeycomb
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 4459981..daee95d 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -543,12 +543,12 @@
         dumpArgs(argc, argv, 3);
         rc = cryptfs_enable(argv[2], argv[3]);
     } else if (!strcmp(argv[1], "changepw")) {
-        if (argc != 4) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs changepw <oldpasswd> <newpasswd>", false);
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs changepw <newpasswd>", false);
             return 0;
         } 
-        SLOGD("cryptfs changepw {} {}");
-        rc = cryptfs_changepw(argv[2], argv[3]);
+        SLOGD("cryptfs changepw {}");
+        rc = cryptfs_changepw(argv[2]);
     } else {
         dumpArgs(argc, argv, -1);
         cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
diff --git a/cryptfs.c b/cryptfs.c
index 5b3a504..afba726 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -45,10 +45,14 @@
 #define DM_CRYPT_BUF_SIZE 4096
 #define DATA_MNT_POINT "/data"
 
+#define HASH_COUNT 2000
+#define KEY_LEN_BYTES 16
+#define IV_LEN_BYTES 16
+
 char *me = "cryptfs";
 
-static unsigned char saved_key_sha1[20] = { '\0' };
-static int  key_sha1_saved = 0;
+static unsigned char saved_master_key[KEY_LEN_BYTES];
+static int  master_key_saved = 0;
 
 static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags)
 {
@@ -144,7 +148,7 @@
   }
 
   if (key) {
-    if (crypt_ftr->keysize != 16) {
+    if (crypt_ftr->keysize != KEY_LEN_BYTES) {
       SLOGE("Keysize of %d bits not supported for real block device %s\n",
             crypt_ftr->keysize * 8, real_blk_name);
       goto errout; 
@@ -242,7 +246,7 @@
     }
   }
 
-  if (crypt_ftr->keysize != 16) {
+  if (crypt_ftr->keysize != KEY_LEN_BYTES) {
     SLOGE("Keysize of %d bits not supported for real block device %s\n",
           crypt_ftr->keysize * 8, real_blk_name);
     goto errout;
@@ -400,10 +404,6 @@
 
 }
 
-#define HASH_COUNT 2000
-#define KEY_LEN_BYTES 16
-#define IV_LEN_BYTES 16
-
 static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey)
 {
     /* Turn the password into a key and IV that can decrypt the master key */
@@ -586,7 +586,7 @@
     static int restart_successful = 0;
 
     /* Validate that it's OK to call this routine */
-    if (! key_sha1_saved) {
+    if (! master_key_saved) {
         SLOGE("Encrypted filesystem not validated, aborting");
         return -1;
     }
@@ -671,7 +671,7 @@
   int rc;
 
   property_get("ro.crypto.state", encrypted_state, "");
-  if ( key_sha1_saved || strcmp(encrypted_state, "encrypted") ) {
+  if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) {
     SLOGE("encrypted fs already validated or not running with encryption, aborting");
     return -1;
   }
@@ -732,12 +732,12 @@
      * so we can mount it when restarting the framework.
      */
     property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
-    /* Also save a SHA1 of the master key so we can know if we
-     * successfully decrypted the key when we want to change the
-     * password on it.
+
+    /* Also save a the master key so we can reencrypted the key
+     * the key when we want to change the password on it.
      */
-    SHA1(decrypted_master_key, KEY_LEN_BYTES, saved_key_sha1);
-    key_sha1_saved = 1;
+    memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES);
+    master_key_saved = 1;
     rc = 0;
   }
 
@@ -765,7 +765,7 @@
     ftr->minor_version = 0;
     ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
     ftr->flags = 0;
-    ftr->keysize = 16;
+    ftr->keysize = KEY_LEN_BYTES;
     ftr->spare1 = 0;
     ftr->fs_size = 0;
     ftr->failed_decrypt_count = 0;
@@ -891,7 +891,7 @@
     char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN];
     char fs_type[32], fs_options[256], mount_point[32];
     unsigned long mnt_flags, nr_sec;
-    unsigned char master_key[16], decrypted_master_key[16];
+    unsigned char master_key[KEY_LEN_BYTES], decrypted_master_key[KEY_LEN_BYTES];
     unsigned char salt[SALT_LEN];
     int rc=-1, fd, i;
     struct crypt_mnt_ftr crypt_ftr;
@@ -1048,16 +1048,15 @@
     return -1;
 }
 
-int cryptfs_changepw(char *oldpw, char *newpw)
+int cryptfs_changepw(char *newpw)
 {
     struct crypt_mnt_ftr crypt_ftr;
-    unsigned char encrypted_master_key[32], decrypted_master_key[32];
+    unsigned char encrypted_master_key[KEY_LEN_BYTES], decrypted_master_key[KEY_LEN_BYTES];
     unsigned char salt[SALT_LEN];
-    unsigned char new_key_sha1[20];
     char real_blkdev[MAXPATHLEN];
 
     /* This is only allowed after we've successfully decrypted the master key */
-    if (! key_sha1_saved) {
+    if (! master_key_saved) {
         SLOGE("Key not saved, aborting");
         return -1;
     }
@@ -1074,24 +1073,10 @@
       return -1;
     }
 
-    /* decrypt key with old passwd */
-    decrypt_master_key(oldpw, salt, encrypted_master_key, decrypted_master_key);
+    encrypt_master_key(newpw, salt, saved_master_key, encrypted_master_key);
 
-    /* compute sha1 of decrypted key */
-    SHA1(decrypted_master_key, KEY_LEN_BYTES, new_key_sha1);
-
-    /* If computed sha1 and saved sha1 match, encrypt key with new passwd */
-    if (! memcmp(saved_key_sha1, new_key_sha1, sizeof(saved_key_sha1))) {
-        /* they match, it's safe to re-encrypt the key */
-        encrypt_master_key(newpw, salt, decrypted_master_key, encrypted_master_key);
-
-        /* save the key */
-        put_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, 0);
-    } else {
-        SLOGE("SHA1 mismatch");
-        return -1;
-    }
+    /* save the key */
+    put_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt);
 
     return 0;
 }
-
diff --git a/cryptfs.h b/cryptfs.h
index 432450c..ca3cc95 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -62,7 +62,7 @@
   int cryptfs_check_passwd(char *pw);
   int cryptfs_restart(void);
   int cryptfs_enable(char *flag, char *passwd);
-  int cryptfs_changepw(char *oldpw, char *newpw);
+  int cryptfs_changepw(char *newpw);
 #ifdef __cplusplus
 }
 #endif