Add the new verifypw command to vold/cryptfs
This vold command returns 0 if the given password matches the password
used to decrypt the device on boot. It returns 1 if they don't match,
and it returns -1 on an internal error, and -2 if the device is not encrypted.
Also check the uid of the sender of the command and only allow the root and
system users to issue cryptfs commands.
Change-Id: I5e5ae3b72a2d7814ae68c2d49aa9deb90fb1dac5
diff --git a/cryptfs.c b/cryptfs.c
index e3672f7..052c033 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -62,6 +62,7 @@
static unsigned char saved_master_key[KEY_LEN_BYTES];
static char *saved_data_blkdev;
+static char *saved_mount_point;
static int master_key_saved = 0;
static void ioctl_init(struct dm_ioctl *io, size_t dataSize, const char *name, unsigned flags)
@@ -841,6 +842,7 @@
*/
memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES);
saved_data_blkdev = strdup(real_blkdev);
+ saved_mount_point = strdup(mount_point);
master_key_saved = 1;
rc = 0;
}
@@ -914,6 +916,63 @@
return rc;
}
+int cryptfs_verify_passwd(char *passwd)
+{
+ struct crypt_mnt_ftr crypt_ftr;
+ /* Allocate enough space for a 256 bit key, but we may use less */
+ unsigned char encrypted_master_key[32], decrypted_master_key[32];
+ unsigned char salt[SALT_LEN];
+ char real_blkdev[MAXPATHLEN];
+ char fs_type[PROPERTY_VALUE_MAX];
+ char fs_options[PROPERTY_VALUE_MAX];
+ unsigned long mnt_flags;
+ char encrypted_state[PROPERTY_VALUE_MAX];
+ int rc;
+
+ property_get("ro.crypto.state", encrypted_state, "");
+ if (strcmp(encrypted_state, "encrypted") ) {
+ SLOGE("device not encrypted, aborting");
+ return -2;
+ }
+
+ if (!master_key_saved) {
+ SLOGE("encrypted fs not yet mounted, aborting");
+ return -1;
+ }
+
+ if (!saved_mount_point) {
+ SLOGE("encrypted fs failed to save mount point, aborting");
+ return -1;
+ }
+
+ if (get_orig_mount_parms(saved_mount_point, fs_type, real_blkdev, &mnt_flags, fs_options)) {
+ SLOGE("Error reading original mount parms for mount point %s\n", saved_mount_point);
+ return -1;
+ }
+
+ if (get_crypt_ftr_and_key(real_blkdev, &crypt_ftr, encrypted_master_key, salt)) {
+ SLOGE("Error getting crypt footer and key\n");
+ return -1;
+ }
+
+ if (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) {
+ /* If the device has no password, then just say the password is valid */
+ rc = 0;
+ } else {
+ decrypt_master_key(passwd, salt, encrypted_master_key, decrypted_master_key);
+ if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
+ /* They match, the password is correct */
+ rc = 0;
+ } else {
+ /* If incorrect, sleep for a bit to prevent dictionary attacks */
+ sleep(1);
+ rc = 1;
+ }
+ }
+
+ return rc;
+}
+
/* Initialize a crypt_mnt_ftr structure. The keysize is
* defaulted to 16 bytes, and the filesystem size to 0.
* Presumably, at a minimum, the caller will update the