diff options
author | Ken Sumrall <ksumrall@android.com> | 2011-10-04 20:38:29 -0700 |
---|---|---|
committer | Ken Sumrall <ksumrall@android.com> | 2011-10-12 19:10:38 -0700 |
commit | 3ad9072a5d6f6bda32123b367545649364e3c11d (patch) | |
tree | aca223fe5d71e2a0f62c7a1d644571532fe3e0e8 | |
parent | 3be890f59c04f94537f2f66f1d2841ed591f1a6e (diff) | |
download | vold-ics-factoryrom-2-release.tar.gz |
Add the new verifypw command to vold/cryptfsandroid-sdk-adt_r16.0.1android-sdk-4.0.3_r1android-sdk-4.0.3-tools_r1android-cts-verifier-4.0_r1android-cts-verifier-4.0.3_r1android-cts-4.0_r1android-cts-4.0.3_r2android-cts-4.0.3_r1android-4.0.4_r2.1android-4.0.4_r2android-4.0.4_r1.2android-4.0.4_r1.1android-4.0.4_r1android-4.0.3_r1.1android-4.0.3_r1android-4.0.2_r1android-4.0.1_r1.2android-4.0.1_r1.1android-4.0.1_r1ics-mr1-releaseics-mr1ics-mr0-releaseics-mr0ics-factoryrom-2-release
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
-rw-r--r-- | CommandListener.cpp | 13 | ||||
-rw-r--r-- | ResponseCode.h | 1 | ||||
-rw-r--r-- | cryptfs.c | 59 | ||||
-rw-r--r-- | cryptfs.h | 1 |
4 files changed, 74 insertions, 0 deletions
diff --git a/CommandListener.cpp b/CommandListener.cpp index 3a83d2ac..97ed2ced 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -28,6 +28,7 @@ #include <cutils/log.h> #include <sysutils/SocketClient.h> +#include <private/android_filesystem_config.h> #include "CommandListener.h" #include "VolumeManager.h" @@ -498,6 +499,11 @@ CommandListener::CryptfsCmd::CryptfsCmd() : int CommandListener::CryptfsCmd::runCommand(SocketClient *cli, int argc, char **argv) { + if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) { + cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false); + return 0; + } + if (argc < 2) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false); return 0; @@ -540,6 +546,13 @@ int CommandListener::CryptfsCmd::runCommand(SocketClient *cli, } SLOGD("cryptfs changepw {}"); rc = cryptfs_changepw(argv[2]); + } else if (!strcmp(argv[1], "verifypw")) { + if (argc != 3) { + cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false); + return 0; + } + SLOGD("cryptfs verifypw {}"); + rc = cryptfs_verify_passwd(argv[2]); } else { dumpArgs(argc, argv, -1); cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false); diff --git a/ResponseCode.h b/ResponseCode.h index a858b99c..402e35b4 100644 --- a/ResponseCode.h +++ b/ResponseCode.h @@ -48,6 +48,7 @@ public: // action did not take place. static const int CommandSyntaxError = 500; static const int CommandParameterError = 501; + static const int CommandNoPermission = 502; // 600 series - Unsolicited broadcasts static const int UnsolicitedInformational = 600; @@ -62,6 +62,7 @@ char *me = "cryptfs"; 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 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) */ 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 @@ int cryptfs_check_passwd(char *passwd) 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 @@ -75,6 +75,7 @@ extern "C" { #endif int cryptfs_crypto_complete(void); int cryptfs_check_passwd(char *pw); + int cryptfs_verify_passwd(char *newpw); int cryptfs_restart(void); int cryptfs_enable(char *flag, char *passwd); int cryptfs_changepw(char *newpw); |