diff --git a/CommandListener.cpp b/CommandListener.cpp index 795c01c..490dd75 100644 --- a/CommandListener.cpp +++ b/CommandListener.cpp @@ -558,12 +558,32 @@ int CommandListener::CryptfsCmd::runCommand(SocketClient *cli, } } else if (!strcmp(argv[1], "changepw")) { - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs changepw ", false); + const char* syntax = "Usage: cryptfs changepw " + "default|password|pin|pattern [newpasswd]"; + char* password; + if (argc == 3) { + password = ""; + } else if (argc == 4) { + password = argv[3]; + } else { + cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false); + return 0; + } + int type = 0; + if (!strcmp(argv[2], "default")) { + type = CRYPT_TYPE_DEFAULT; + } else if (!strcmp(argv[2], "password")) { + type = CRYPT_TYPE_PASSWORD; + } else if (!strcmp(argv[2], "pin")) { + type = CRYPT_TYPE_PIN; + } else if (!strcmp(argv[2], "pattern")) { + type = CRYPT_TYPE_PATTERN; + } else { + cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false); return 0; - } - SLOGD("cryptfs changepw {}"); - rc = cryptfs_changepw(argv[2]); + } + SLOGD("cryptfs changepw %s {}", argv[2]); + rc = cryptfs_changepw(type, password); } else if (!strcmp(argv[1], "verifypw")) { if (argc != 3) { cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw ", false); @@ -590,9 +610,35 @@ int CommandListener::CryptfsCmd::runCommand(SocketClient *cli, } dumpArgs(argc, argv, -1); rc = cryptfs_setfield(argv[2], argv[3]); + } else if (!strcmp(argv[1], "mountdefaultencrypted")) { + SLOGD("cryptfs mountdefaultencrypted"); + dumpArgs(argc, argv, -1); + rc = cryptfs_mount_default_encrypted(); + } else if (!strcmp(argv[1], "getpwtype")) { + SLOGD("cryptfs getpwtype"); + dumpArgs(argc, argv, -1); + switch(cryptfs_get_password_type()) { + case CRYPT_TYPE_PASSWORD: + cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false); + return 0; + case CRYPT_TYPE_PATTERN: + cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false); + return 0; + case CRYPT_TYPE_PIN: + cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false); + return 0; + case CRYPT_TYPE_DEFAULT: + cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false); + return 0; + default: + /** @TODO better error and make sure handled by callers */ + cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false); + return 0; + } } else { dumpArgs(argc, argv, -1); cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false); + return 0; } // Always report that the command succeeded and return the error code. diff --git a/ResponseCode.h b/ResponseCode.h index 26ebfcd..0dc0500 100644 --- a/ResponseCode.h +++ b/ResponseCode.h @@ -33,6 +33,7 @@ public: static const int ShareStatusResult = 210; static const int AsecPathResult = 211; static const int ShareEnabledResult = 212; + static const int PasswordTypeResult = 213; // 400 series - The command was accepted but the requested action // did not take place. diff --git a/cryptfs.c b/cryptfs.c index 40ad36a..4dd7a6b 100644 --- a/cryptfs.c +++ b/cryptfs.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,9 @@ #define KEY_IN_FOOTER "footer" +// "default_password" encoded into hex (d=0x64 etc) +#define DEFAULT_PASSWORD "64656661756c745f70617373776f7264" + #define EXT4_FS 1 #define FAT_FS 2 @@ -351,7 +355,7 @@ static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t o crypt_ftr->minor_version = 1; } - if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version)) { + if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) { 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. @@ -361,6 +365,12 @@ static void upgrade_crypt_ftr(int fd, struct crypt_mnt_ftr *crypt_ftr, off64_t o crypt_ftr->minor_version = 2; } + if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 2)) { + SLOGW("upgrading crypto footer to 1.3"); + crypt_ftr->crypt_type = CRYPT_TYPE_PASSWORD; + crypt_ftr->minor_version = 3; + } + if ((orig_major != crypt_ftr->major_version) || (orig_minor != crypt_ftr->minor_version)) { if (lseek64(fd, offset, SEEK_SET) == -1) { SLOGE("Cannot seek to crypt footer\n"); @@ -663,10 +673,53 @@ err: return -1; } +static int hexdigit (char c) +{ + if (c >= '0' && c <= '9') return c - '0'; + c = tolower(c); + if (c >= 'a' && c <= 'f') return c - 'a' + 10; + return -1; +} + +static unsigned char* convert_hex_ascii_to_key(const char* master_key_ascii, + unsigned int* out_keysize) +{ + unsigned int i; + *out_keysize = 0; + + size_t size = strlen (master_key_ascii); + if (size % 2) { + SLOGE("Trying to convert ascii string of odd length"); + return NULL; + } + + unsigned char* master_key = (unsigned char*) malloc(size / 2); + if (master_key == 0) { + SLOGE("Cannot allocate"); + return NULL; + } + + for (i = 0; i < size; i += 2) { + int high_nibble = hexdigit (master_key_ascii[i]); + int low_nibble = hexdigit (master_key_ascii[i + 1]); + + if(high_nibble < 0 || low_nibble < 0) { + SLOGE("Invalid hex string"); + free (master_key); + return NULL; + } + + master_key[*out_keysize] = high_nibble * 16 + low_nibble; + (*out_keysize)++; + } + + return master_key; +} + /* Convert a binary key of specified length into an ascii hex string equivalent, * without the leading 0x and with null termination */ -void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize, +static void convert_key_to_hex_ascii(unsigned char *master_key, unsigned int keysize, char *master_key_ascii) { unsigned int i, a; @@ -870,13 +923,23 @@ errout: } -static void pbkdf2(char *passwd, unsigned char *salt, unsigned char *ikey, void *params UNUSED) { +static int pbkdf2(char *passwd, unsigned char *salt, + unsigned char *ikey, void *params UNUSED) +{ /* Turn the password into a key and IV that can decrypt the master key */ - PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN, + unsigned int keysize; + char* master_key = (char*)convert_hex_ascii_to_key(passwd, &keysize); + if (!master_key) return -1; + PKCS5_PBKDF2_HMAC_SHA1(master_key, keysize, salt, SALT_LEN, HASH_COUNT, KEY_LEN_BYTES+IV_LEN_BYTES, ikey); + + free (master_key); + return 0; } -static void scrypt(char *passwd, unsigned char *salt, unsigned char *ikey, void *params) { +static int scrypt(char *passwd, unsigned char *salt, + unsigned char *ikey, void *params) +{ struct crypt_mnt_ftr *ftr = (struct crypt_mnt_ftr *) params; int N = 1 << ftr->N_factor; @@ -884,8 +947,14 @@ static void scrypt(char *passwd, unsigned char *salt, unsigned char *ikey, void int p = 1 << ftr->p_factor; /* Turn the password into a key and IV that can decrypt the master key */ - crypto_scrypt((unsigned char *) passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey, + unsigned int keysize; + unsigned char* master_key = convert_hex_ascii_to_key(passwd, &keysize); + if (!master_key) return -1; + crypto_scrypt(master_key, keysize, salt, SALT_LEN, N, r, p, ikey, KEY_LEN_BYTES + IV_LEN_BYTES); + + free (master_key); + return 0; } static int encrypt_master_key(char *passwd, unsigned char *salt, @@ -899,7 +968,10 @@ static int encrypt_master_key(char *passwd, unsigned char *salt, /* Turn the password into a key and IV that can decrypt the master key */ get_device_scrypt_params(crypt_ftr); - scrypt(passwd, salt, ikey, crypt_ftr); + if (scrypt(passwd, salt, ikey, crypt_ftr)) { + SLOGE("scrypt failed"); + return -1; + } /* Initialize the decryption engine */ if (! EVP_EncryptInit(&e_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { @@ -937,7 +1009,10 @@ static int decrypt_master_key_aux(char *passwd, unsigned char *salt, int decrypted_len, final_len; /* Turn the password into a key and IV that can decrypt the master key */ - kdf(passwd, salt, ikey, kdf_params); + if (kdf(passwd, salt, ikey, kdf_params)) { + SLOGE("kdf failed"); + return -1; + } /* Initialize the decryption engine */ if (! EVP_DecryptInit(&d_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { @@ -1068,7 +1143,7 @@ static int prep_data_fs(void) } } -int cryptfs_restart(void) +static int cryptfs_restart_internal(int restart_main) { char fs_type[32]; char real_blkdev[MAXPATHLEN]; @@ -1090,32 +1165,34 @@ int cryptfs_restart(void) return -1; } - /* Here is where we shut down the framework. The init scripts - * start all services in one of three classes: core, main or late_start. - * On boot, we start core and main. Now, we stop main, but not core, - * as core includes vold and a few other really important things that - * we need to keep running. Once main has stopped, we should be able - * to umount the tmpfs /data, then mount the encrypted /data. - * We then restart the class main, and also the class late_start. - * At the moment, I've only put a few things in late_start that I know - * are not needed to bring up the framework, and that also cause problems - * with unmounting the tmpfs /data, but I hope to add add more services - * to the late_start class as we optimize this to decrease the delay - * till the user is asked for the password to the filesystem. - */ + if (restart_main) { + /* Here is where we shut down the framework. The init scripts + * start all services in one of three classes: core, main or late_start. + * On boot, we start core and main. Now, we stop main, but not core, + * as core includes vold and a few other really important things that + * we need to keep running. Once main has stopped, we should be able + * to umount the tmpfs /data, then mount the encrypted /data. + * We then restart the class main, and also the class late_start. + * At the moment, I've only put a few things in late_start that I know + * are not needed to bring up the framework, and that also cause problems + * with unmounting the tmpfs /data, but I hope to add add more services + * to the late_start class as we optimize this to decrease the delay + * till the user is asked for the password to the filesystem. + */ - /* The init files are setup to stop the class main when vold.decrypt is - * set to trigger_reset_main. - */ - property_set("vold.decrypt", "trigger_reset_main"); - SLOGD("Just asked init to shut down class main\n"); + /* The init files are setup to stop the class main when vold.decrypt is + * set to trigger_reset_main. + */ + property_set("vold.decrypt", "trigger_reset_main"); + SLOGD("Just asked init to shut down class main\n"); - /* Ugh, shutting down the framework is not synchronous, so until it - * can be fixed, this horrible hack will wait a moment for it all to - * shut down before proceeding. Without it, some devices cannot - * restart the graphics services. - */ - sleep(2); + /* Ugh, shutting down the framework is not synchronous, so until it + * can be fixed, this horrible hack will wait a moment for it all to + * shut down before proceeding. Without it, some devices cannot + * restart the graphics services. + */ + sleep(2); + } /* Now that the framework is shutdown, we should be able to umount() * the tmpfs filesystem, and mount the real one. @@ -1163,6 +1240,12 @@ int cryptfs_restart(void) return rc; } +int cryptfs_restart(void) +{ + /* Call internal implementation forcing a restart of main service group */ + return cryptfs_restart_internal(1); +} + static int do_crypto_complete(char *mount_point UNUSED) { struct crypt_mnt_ftr crypt_ftr; @@ -1204,45 +1287,33 @@ static int do_crypto_complete(char *mount_point UNUSED) return 0; } -static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) +static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, + char *passwd, char *mount_point, char *label) { - struct crypt_mnt_ftr crypt_ftr; /* Allocate enough space for a 256 bit key, but we may use less */ unsigned char decrypted_master_key[32]; char crypto_blkdev[MAXPATHLEN]; char real_blkdev[MAXPATHLEN]; char tmp_mount_point[64]; unsigned int orig_failed_decrypt_count; - char encrypted_state[PROPERTY_VALUE_MAX]; int rc; kdf_func kdf; void *kdf_params; - property_get("ro.crypto.state", encrypted_state, ""); - if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) { - SLOGE("encrypted fs already validated or not running with encryption, aborting"); - return -1; - } + SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr->fs_size); + orig_failed_decrypt_count = crypt_ftr->failed_decrypt_count; - fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev)); - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - SLOGE("Error getting crypt footer and key\n"); - return -1; - } - - SLOGD("crypt_ftr->fs_size = %lld\n", crypt_ftr.fs_size); - orig_failed_decrypt_count = crypt_ftr.failed_decrypt_count; - - if (! (crypt_ftr.flags & CRYPT_MNT_KEY_UNENCRYPTED) ) { - if (decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr)) { + if (! (crypt_ftr->flags & CRYPT_MNT_KEY_UNENCRYPTED) ) { + 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, - real_blkdev, crypto_blkdev, label)) { + fs_mgr_get_crypt_info(fstab, 0, real_blkdev, sizeof(real_blkdev)); + + if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, + real_blkdev, crypto_blkdev, label)) { SLOGE("Error creating decrypted block device\n"); return -1; } @@ -1259,22 +1330,22 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) 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); - crypt_ftr.failed_decrypt_count++; + crypt_ftr->failed_decrypt_count++; } else { /* Success, so just umount and we'll mount it properly when we restart * the framework. */ umount(tmp_mount_point); - crypt_ftr.failed_decrypt_count = 0; + crypt_ftr->failed_decrypt_count = 0; } - if (orig_failed_decrypt_count != crypt_ftr.failed_decrypt_count) { - put_crypt_ftr_and_key(&crypt_ftr); + if (orig_failed_decrypt_count != crypt_ftr->failed_decrypt_count) { + put_crypt_ftr_and_key(crypt_ftr); } - if (crypt_ftr.failed_decrypt_count) { + if (crypt_ftr->failed_decrypt_count) { /* We failed to mount the device, so return an error */ - rc = crypt_ftr.failed_decrypt_count; + rc = crypt_ftr->failed_decrypt_count; } else { /* Woot! Success! Save the name of the crypto block device @@ -1293,12 +1364,12 @@ static int test_mount_encrypted_fs(char *passwd, char *mount_point, char *label) /* * 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 (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); + rc = put_crypt_ftr_and_key(crypt_ftr); } SLOGD("Key Derivation Function upgrade: rc=%d\n", rc); } @@ -1362,12 +1433,35 @@ int cryptfs_crypto_complete(void) return do_crypto_complete("/data"); } +int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) +{ + char encrypted_state[PROPERTY_VALUE_MAX]; + property_get("ro.crypto.state", encrypted_state, ""); + if ( master_key_saved || strcmp(encrypted_state, "encrypted") ) { + SLOGE("encrypted fs already validated or not running with encryption," + " aborting"); + return -1; + } + + if (get_crypt_ftr_and_key(crypt_ftr)) { + SLOGE("Error getting crypt footer and key"); + return -1; + } + + return 0; +} + int cryptfs_check_passwd(char *passwd) { - int rc = -1; + struct crypt_mnt_ftr crypt_ftr; + int rc; - rc = test_mount_encrypted_fs(passwd, DATA_MNT_POINT, "userdata"); + rc = check_unmounted_and_get_ftr(&crypt_ftr); + if (rc) + return rc; + rc = test_mount_encrypted_fs(&crypt_ftr, passwd, + DATA_MNT_POINT, "userdata"); return rc; } @@ -1987,6 +2081,11 @@ int cryptfs_enable(char *howarg, char *passwd, int allow_reboot) crypt_ftr.fs_size = nr_sec; } crypt_ftr.flags |= CRYPT_ENCRYPTION_IN_PROGRESS; + + /** @TODO If we keep this route, must pass in crypt_type. + * If all devices are encrypted by default, we don't need that change. + */ + crypt_ftr.crypt_type = CRYPT_TYPE_PASSWORD; strcpy((char *)crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256"); /* Make an encrypted master key */ @@ -2143,24 +2242,36 @@ error_shutting_down: return -1; } -int cryptfs_changepw(char *newpw) +int cryptfs_changepw(int crypt_type, char *newpw) { struct crypt_mnt_ftr crypt_ftr; unsigned char decrypted_master_key[KEY_LEN_BYTES]; /* This is only allowed after we've successfully decrypted the master key */ - if (! master_key_saved) { + if (!master_key_saved) { SLOGE("Key not saved, aborting"); return -1; } + if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) { + SLOGE("Invalid crypt_type %d", crypt_type); + return -1; + } + /* get key */ if (get_crypt_ftr_and_key(&crypt_ftr)) { - SLOGE("Error getting crypt footer and key"); - return -1; + SLOGE("Error getting crypt footer and key"); + return -1; } - encrypt_master_key(newpw, crypt_ftr.salt, saved_master_key, crypt_ftr.master_key, &crypt_ftr); + crypt_ftr.crypt_type = crypt_type; + + encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD + : newpw, + crypt_ftr.salt, + saved_master_key, + crypt_ftr.master_key, + &crypt_ftr); /* save the key */ put_crypt_ftr_and_key(&crypt_ftr); @@ -2307,3 +2418,52 @@ int cryptfs_setfield(char *fieldname, char *value) out: return rc; } + +/* Checks userdata. Attempt to mount the volume if default- + * encrypted. + * On success trigger next init phase and return 0. + * Currently do not handle failure - see TODO below. + */ +int cryptfs_mount_default_encrypted(void) +{ + char decrypt_state[PROPERTY_VALUE_MAX]; + property_get("vold.decrypt", decrypt_state, "0"); + if (!strcmp(decrypt_state, "0")) { + SLOGE("Not encrypted - should not call here"); + } else { + int crypt_type = cryptfs_get_password_type(); + if (crypt_type < 0 || crypt_type > CRYPT_TYPE_MAX_TYPE) { + SLOGE("Bad crypt type - error"); + } else if (crypt_type != CRYPT_TYPE_DEFAULT) { + SLOGD("Password is not default - " + "starting min framework to prompt"); + property_set("vold.decrypt", "trigger_restart_min_framework"); + return 0; + } else if (cryptfs_check_passwd(DEFAULT_PASSWORD) == 0) { + SLOGD("Password is default - restarting filesystem"); + cryptfs_restart_internal(0); + return 0; + } else { + SLOGE("Encrypted, default crypt type but can't decrypt"); + } + } + + /** @TODO make sure we factory wipe in this situation + * In general if we got here there is no recovery + */ + return 0; +} + +/* Returns type of the password, default, pattern, pin or password. + */ +int cryptfs_get_password_type(void) +{ + struct crypt_mnt_ftr crypt_ftr; + + if (get_crypt_ftr_and_key(&crypt_ftr)) { + SLOGE("Error getting crypt footer and key\n"); + return -1; + } + + return crypt_ftr.crypt_type; +} diff --git a/cryptfs.h b/cryptfs.h index dc3ce3e..0e8bd76 100644 --- a/cryptfs.h +++ b/cryptfs.h @@ -30,7 +30,7 @@ /* The current cryptfs version */ #define CURRENT_MAJOR_VERSION 1 -#define CURRENT_MINOR_VERSION 2 +#define CURRENT_MINOR_VERSION 3 #define CRYPT_FOOTER_OFFSET 0x4000 #define CRYPT_FOOTER_TO_PERSIST_OFFSET 0x1000 @@ -46,6 +46,16 @@ #define CRYPT_ENCRYPTION_IN_PROGRESS 0x2 /* Set when starting encryption, * clear when done before rebooting */ +/* Allowed values for type in the structure below */ +#define CRYPT_TYPE_PASSWORD 0 /* master_key is encrypted with a password + * Must be zero to be compatible with pre-L + * devices where type is always password.*/ +#define CRYPT_TYPE_DEFAULT 1 /* master_key is encrypted with default + * password */ +#define CRYPT_TYPE_PATTERN 2 /* master_key is encrypted with a pattern */ +#define CRYPT_TYPE_PIN 3 /* master_key is encrypted with a pin */ +#define CRYPT_TYPE_MAX_TYPE 3 /* type cannot be larger than this value */ + #define CRYPT_MNT_MAGIC 0xD0B5B1C4 #define PERSIST_DATA_MAGIC 0xE950CD44 @@ -60,16 +70,17 @@ #define __le8 unsigned char struct crypt_mnt_ftr { - __le32 magic; /* See above */ + __le32 magic; /* See above */ __le16 major_version; __le16 minor_version; - __le32 ftr_size; /* in bytes, not including key following */ - __le32 flags; /* See above */ - __le32 keysize; /* in bytes */ - __le32 spare1; /* ignored */ + __le32 ftr_size; /* in bytes, not including key following */ + __le32 flags; /* See above */ + __le32 keysize; /* in bytes */ + __le32 crypt_type; /* how master_key is encrypted. Must be a + * CRYPT_TYPE_XXX value */ __le64 fs_size; /* Size of the encrypted fs, in 512 byte sectors */ __le32 failed_decrypt_count; /* count of # of failed attempts to decrypt and - mount, set to 0 on successful mount */ + mount, set to 0 on successful mount */ unsigned char crypto_type_name[MAX_CRYPTO_TYPE_NAME_LEN]; /* The type of encryption needed to decrypt this partition, null terminated */ @@ -137,20 +148,22 @@ struct volume_info { extern "C" { #endif - typedef void (*kdf_func)(char *passwd, unsigned char *salt, unsigned char *ikey, void *params); + typedef int (*kdf_func)(char *passwd, unsigned char *salt, unsigned char *ikey, void *params); 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 allow_reboot); - int cryptfs_changepw(char *newpw); + int cryptfs_changepw(int type, char *newpw); int cryptfs_setup_volume(const char *label, int major, int minor, char *crypto_dev_path, unsigned int max_pathlen, int *new_major, int *new_minor); int cryptfs_revert_volume(const char *label); int cryptfs_getfield(char *fieldname, char *value, int len); int cryptfs_setfield(char *fieldname, char *value); + int cryptfs_mount_default_encrypted(void); + int cryptfs_get_password_type(void); #ifdef __cplusplus } #endif diff --git a/vdc.c b/vdc.c index 59f34d6..210ef22 100644 --- a/vdc.c +++ b/vdc.c @@ -38,20 +38,36 @@ static int do_cmd(int sock, int argc, char **argv); int main(int argc, char **argv) { int sock; + int wait_for_socket; if (argc < 2) usage(argv[0]); - if ((sock = socket_local_client("vold", - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM)) < 0) { - fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); - exit(4); + wait_for_socket = strcmp(argv[1], "--wait") == 0; + if(wait_for_socket) { + argv++; + argc--; } - if (!strcmp(argv[1], "monitor")) + if(argc < 2) + exit(5); + + while ((sock = socket_local_client("vold", + ANDROID_SOCKET_NAMESPACE_RESERVED, + SOCK_STREAM)) < 0) { + if(!wait_for_socket) { + fprintf(stderr, "Error connecting (%s)\n", strerror(errno)); + exit(4); + } else { + sleep(1); + } + } + + if (!strcmp(argv[1], "monitor")) { exit(do_monitor(sock, 0)); - exit(do_cmd(sock, argc, argv)); + } else { + exit(do_cmd(sock, argc, argv)); + } } static int do_cmd(int sock, int argc, char **argv) { @@ -118,7 +134,7 @@ static int do_monitor(int sock, int stop_after_cmd) { return ECONNRESET; return errno; } - + int offset = 0; int i = 0; @@ -146,7 +162,7 @@ static int do_monitor(int sock, int stop_after_cmd) { } static void usage(char *progname) { - fprintf(stderr, "Usage: %s | [arg1] [arg2...]\n", progname); - exit(1); -} + fprintf(stderr, + "Usage: %s [--wait] | [arg1] [arg2...]\n", progname); + }