vold: cryptfs: Don't update KDF without validating pwd/key.

Prior to this, the Key derivation function would get
 blindly updated even if the user entered the wrong password.
Now, we only attempt to upgrade the KDF if the pwd/key have
been verified (i.e. after a successful mount).

Bug: 11460197
Change-Id: I0469228cc9b87c47754e8ca3c7146651da177da5
diff --git a/cryptfs.c b/cryptfs.c
index 03d714e..6247014 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -351,6 +351,9 @@
 
     if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version)) {
         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.
+         */
         crypt_ftr->kdf_type = KDF_PBKDF2;
         get_device_scrypt_params(crypt_ftr);
         crypt_ftr->minor_version = 2;
@@ -922,7 +925,7 @@
     }
 }
 
-static int decrypt_master_key(char *passwd, unsigned char *salt,
+static int decrypt_master_key_aux(char *passwd, unsigned char *salt,
                               unsigned char *encrypted_master_key,
                               unsigned char *decrypted_master_key,
                               kdf_func kdf, void *kdf_params)
@@ -966,7 +969,7 @@
     }
 }
 
-static int decrypt_master_key_and_upgrade(char *passwd, unsigned char *decrypted_master_key,
+static int decrypt_master_key(char *passwd, unsigned char *decrypted_master_key,
         struct crypt_mnt_ftr *crypt_ftr)
 {
     kdf_func kdf;
@@ -974,21 +977,10 @@
     int ret;
 
     get_kdf_func(crypt_ftr, &kdf, &kdf_params);
-    ret = decrypt_master_key(passwd, crypt_ftr->salt, crypt_ftr->master_key, decrypted_master_key, kdf,
+    ret = decrypt_master_key_aux(passwd, crypt_ftr->salt, crypt_ftr->master_key, decrypted_master_key, kdf,
             kdf_params);
     if (ret != 0) {
         SLOGW("failure decrypting master key");
-        return ret;
-    }
-
-    /*
-     * Upgrade if we're not using the latest KDF.
-     */
-    if (crypt_ftr->kdf_type != KDF_SCRYPT) {
-        crypt_ftr->kdf_type = KDF_SCRYPT;
-        encrypt_master_key(passwd, crypt_ftr->salt, decrypted_master_key, crypt_ftr->master_key,
-                crypt_ftr);
-        put_crypt_ftr_and_key(crypt_ftr);
     }
 
     return ret;
@@ -1230,7 +1222,10 @@
   orig_failed_decrypt_count = crypt_ftr.failed_decrypt_count;
 
   if (! (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) ) {
-    decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
+    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,
@@ -1280,7 +1275,20 @@
     memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES);
     saved_mount_point = strdup(mount_point);
     master_key_saved = 1;
+    SLOGD("%s(): Master key saved\n", __FUNCTION__);
     rc = 0;
+    /*
+     * 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 (!rc) {
+            rc = put_crypt_ftr_and_key(&crypt_ftr);
+        }
+        SLOGD("Key Derivation Function upgrade: rc=%d\n", rc);
+    }
   }
 
   return rc;
@@ -1383,7 +1391,7 @@
         /* If the device has no password, then just say the password is valid */
         rc = 0;
     } else {
-        decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
+        decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr);
         if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
             /* They match, the password is correct */
             rc = 0;
@@ -1777,7 +1785,7 @@
         save_persistent_data();
     }
 
-    decrypt_master_key_and_upgrade(passwd, decrypted_master_key, &crypt_ftr);
+    decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr);
     create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
                           "userdata");