Don't test mount when we can use the crypto footer to test the password
Note that this also changes the boot sequence, and moves the test for corrupted
data to cryptfs_restart_internal.
Bug: 17213613
Change-Id: I0f86e8fe3d482e2d1373bd0f4d0d861e63ad8904
diff --git a/cryptfs.c b/cryptfs.c
index ac250e5..8bed8cb 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -1429,6 +1429,40 @@
}
}
+static void cryptfs_set_corrupt()
+{
+ // Mark the footer as bad
+ struct crypt_mnt_ftr crypt_ftr;
+ if (get_crypt_ftr_and_key(&crypt_ftr)) {
+ SLOGE("Failed to get crypto footer - panic");
+ return;
+ }
+
+ crypt_ftr.flags |= CRYPT_DATA_CORRUPT;
+ if (put_crypt_ftr_and_key(&crypt_ftr)) {
+ SLOGE("Failed to set crypto footer - panic");
+ return;
+ }
+}
+
+static void cryptfs_trigger_restart_min_framework()
+{
+ if (fs_mgr_do_tmpfs_mount(DATA_MNT_POINT)) {
+ SLOGE("Failed to mount tmpfs on data - panic");
+ return;
+ }
+
+ if (property_set("vold.decrypt", "trigger_post_fs_data")) {
+ SLOGE("Failed to trigger post fs data - panic");
+ return;
+ }
+
+ if (property_set("vold.decrypt", "trigger_restart_min_framework")) {
+ SLOGE("Failed to trigger restart min framework - panic");
+ return;
+ }
+}
+
static int cryptfs_restart_internal(int restart_main)
{
char fs_type[32];
@@ -1503,7 +1537,13 @@
}
/* If that succeeded, then mount the decrypted filesystem */
- fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0);
+ if (fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0)) {
+ SLOGE("Failed to mount decrypted data");
+ cryptfs_set_corrupt();
+ cryptfs_trigger_restart_min_framework();
+ SLOGI("Started framework to offer wipe");
+ return -1;
+ }
property_set("vold.decrypt", "trigger_load_persist_props");
/* Create necessary paths on /data */
@@ -1541,7 +1581,7 @@
property_get("ro.crypto.state", encrypted_state, "");
if (strcmp(encrypted_state, "encrypted") ) {
SLOGE("not running with encryption, aborting");
- return 1;
+ return CRYPTO_COMPLETE_NOT_ENCRYPTED;
}
if (get_crypt_ftr_and_key(&crypt_ftr)) {
@@ -1556,22 +1596,31 @@
*/
if ((key_loc[0] == '/') && (access("key_loc", F_OK) == -1)) {
SLOGE("master key file does not exist, aborting");
- return 1;
+ return CRYPTO_COMPLETE_NOT_ENCRYPTED;
} else {
SLOGE("Error getting crypt footer and key\n");
- return -1;
+ return CRYPTO_COMPLETE_BAD_METADATA;
}
}
- if (crypt_ftr.flags
- & (CRYPT_ENCRYPTION_IN_PROGRESS | CRYPT_INCONSISTENT_STATE)) {
- SLOGE("Encryption process didn't finish successfully\n");
- return -2; /* -2 is the clue to the UI that there is no usable data on the disk,
- * and give the user an option to wipe the disk */
+ // Test for possible error flags
+ if (crypt_ftr.flags & CRYPT_ENCRYPTION_IN_PROGRESS){
+ SLOGE("Encryption process is partway completed\n");
+ return CRYPTO_COMPLETE_PARTIAL;
+ }
+
+ if (crypt_ftr.flags & CRYPT_INCONSISTENT_STATE){
+ SLOGE("Encryption process was interrupted but cannot continue\n");
+ return CRYPTO_COMPLETE_INCONSISTENT;
+ }
+
+ if (crypt_ftr.flags & CRYPT_DATA_CORRUPT){
+ SLOGE("Encryption is successful but data is corrupt\n");
+ return CRYPTO_COMPLETE_CORRUPT;
}
/* We passed the test! We shall diminish, and return to the west */
- return 0;
+ return CRYPTO_COMPLETE_ENCRYPTED;
}
static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr,
@@ -1605,72 +1654,68 @@
fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev));
+ // Create crypto block device - all (non fatal) code paths
+ // need it
if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
real_blkdev, crypto_blkdev, label)) {
- SLOGE("Error creating decrypted block device\n");
- rc = -1;
- goto errout;
+ SLOGE("Error creating decrypted block device\n");
+ rc = -1;
+ goto errout;
}
- /* If init detects an encrypted filesystem, it writes a file for each such
- * encrypted fs into the tmpfs /data filesystem, and then the framework finds those
- * files and passes that data to me */
- /* Create a tmp mount point to try mounting the decryptd fs
- * Since we're here, the mount_point should be a tmpfs filesystem, so make
- * a directory in it to test mount the decrypted filesystem.
- */
- sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point);
- mkdir(tmp_mount_point, 0755);
- 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);
+ /* Work out if the problem is the password or the data */
+ unsigned char scrypted_intermediate_key[sizeof(crypt_ftr->
+ scrypted_intermediate_key)];
+ int N = 1 << crypt_ftr->N_factor;
+ int r = 1 << crypt_ftr->r_factor;
+ int p = 1 << crypt_ftr->p_factor;
- /* Work out if the problem is the password or the data */
- unsigned char scrypted_intermediate_key[sizeof(crypt_ftr->
- scrypted_intermediate_key)];
- int N = 1 << crypt_ftr->N_factor;
- int r = 1 << crypt_ftr->r_factor;
- int p = 1 << crypt_ftr->p_factor;
+ rc = crypto_scrypt(intermediate_key, intermediate_key_size,
+ crypt_ftr->salt, sizeof(crypt_ftr->salt),
+ N, r, p, scrypted_intermediate_key,
+ sizeof(scrypted_intermediate_key));
- rc = crypto_scrypt(intermediate_key, intermediate_key_size,
- crypt_ftr->salt, sizeof(crypt_ftr->salt),
- N, r, p, scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key));
- if (rc == 0 && memcmp(scrypted_intermediate_key,
- crypt_ftr->scrypted_intermediate_key,
- sizeof(scrypted_intermediate_key)) == 0) {
- SLOGE("Right password, so wipe");
- rc = -1;
- } else {
- SLOGE(rc ? "scrypt failure, so allow retry" :
- "Wrong password, so allow retry");
+ // Does the key match the crypto footer?
+ if (rc == 0 && memcmp(scrypted_intermediate_key,
+ crypt_ftr->scrypted_intermediate_key,
+ sizeof(scrypted_intermediate_key)) == 0) {
+ SLOGI("Password matches");
+ rc = 0;
+ } else {
+ /* Try mounting the file system anyway, just in case the problem's with
+ * the footer, not the key. */
+ sprintf(tmp_mount_point, "%s/tmp_mnt", mount_point);
+ mkdir(tmp_mount_point, 0755);
+ 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);
+
rc = ++crypt_ftr->failed_decrypt_count;
put_crypt_ftr_and_key(crypt_ftr);
+ } else {
+ /* Success! */
+ SLOGI("Password did not match but decrypted drive mounted - continue");
+ umount(tmp_mount_point);
+ rc = 0;
}
- } else {
- /* Success!
- * umount and we'll mount it properly when we restart the framework.
- */
- umount(tmp_mount_point);
- crypt_ftr->failed_decrypt_count = 0;
+ }
+
+ if (rc == 0) {
+ crypt_ftr->failed_decrypt_count = 0;
/* Save the name of the crypto block device
- * so we can mount it when restarting the framework.
- */
+ * so we can mount it when restarting the framework. */
property_set("ro.crypto.fs_crypto_blkdev", crypto_blkdev);
/* Also save a the master key so we can reencrypted the key
- * the key when we want to change the password on it.
- */
+ * the key when we want to change the password on it. */
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.
- */
+ // Upgrade if we're not using the latest KDF.
use_keymaster = keymaster_check_compatibility();
if (crypt_ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
// Don't allow downgrade to KDF_SCRYPT
@@ -2139,7 +2184,7 @@
{
u32 i;
struct encryptGroupsData data;
- int rc = -1;
+ int rc; // Can't initialize without causing warning -Wclobbered
if (previously_encrypted_upto > *size_already_done) {
SLOGD("Not fast encrypting since resuming part way through");
@@ -2153,22 +2198,26 @@
if ( (data.realfd = open(real_blkdev, O_RDWR)) < 0) {
SLOGE("Error opening real_blkdev %s for inplace encrypt\n",
real_blkdev);
+ rc = -1;
goto errout;
}
if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n",
crypto_blkdev);
+ rc = -1;
goto errout;
}
if (setjmp(setjmp_env)) {
SLOGE("Reading extent caused an exception");
+ rc = -1;
goto errout;
}
if (read_ext(data.realfd, 0) != 0) {
SLOGE("Failed to read extent");
+ rc = -1;
goto errout;
}