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
This commit is contained in:
parent
3be890f59c
commit
3ad9072a5d
4 changed files with 74 additions and 0 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
59
cryptfs.c
59
cryptfs.c
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue