From a7e63a28c87bf866f62449c37cddc13a9e2d64f7 Mon Sep 17 00:00:00 2001 From: Sultan Qasim Khan Date: Fri, 12 Feb 2016 20:57:15 -0500 Subject: cryptfs: major overhaul and cleanup - Don't upgrade HW encrypted Lollipop devices to Marshmallow crypto - Fix support for passwords and patterns with an odd number of elements - Remove unused code - Fix build warnings Change-Id: I25f015085e5c859d0353f42f6a2fbc7ccecd48ed --- crypto/lollipop/cryptfs.c | 607 +++------------------------------------------- 1 file changed, 32 insertions(+), 575 deletions(-) (limited to 'crypto/lollipop/cryptfs.c') diff --git a/crypto/lollipop/cryptfs.c b/crypto/lollipop/cryptfs.c index fa440ed17..fe075c4ad 100644 --- a/crypto/lollipop/cryptfs.c +++ b/crypto/lollipop/cryptfs.c @@ -74,9 +74,6 @@ #define KEY_IN_FOOTER "footer" -// "default_password" encoded into hex (d=0x64 etc) -#define DEFAULT_PASSWORD "64656661756c745f70617373776f7264" - #define EXT4_FS 1 #define F2FS_FS 2 @@ -101,13 +98,10 @@ static char real_blkdev[PROPERTY_VALUE_MAX] = ""; static char file_system[PROPERTY_VALUE_MAX] = ""; #ifdef CONFIG_HW_DISK_ENCRYPTION -#define DEFAULT_HEX_PASSWORD "64656661756c745f70617373776f7264" static int scrypt_keymaster(const char *passwd, const unsigned char *salt, unsigned char *ikey, void *params); static void convert_key_to_hex_ascii(const unsigned char *master_key, unsigned int keysize, char *master_key_ascii); -static int put_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr); - static int get_keymaster_hw_fde_passwd(const char* passwd, unsigned char* newpw, unsigned char* salt, const struct crypt_mnt_ftr *ftr) @@ -140,82 +134,6 @@ static int verify_hw_fde_passwd(char *passwd, struct crypt_mnt_ftr* crypt_ftr) (char*) crypt_ftr->crypto_type_name); return key_index; } - -static int verify_and_update_hw_fde_passwd(char *passwd, - struct crypt_mnt_ftr* crypt_ftr) -{ - char* new_passwd = NULL; - unsigned char newpw[32] = {0}; - int key_index = -1; - int passwd_updated = -1; - int ascii_passwd_updated = (crypt_ftr->flags & CRYPT_ASCII_PASSWORD_UPDATED); - - key_index = verify_hw_fde_passwd(passwd, crypt_ftr); - if (key_index < 0) { - ++crypt_ftr->failed_decrypt_count; - - if (ascii_passwd_updated) { - printf("Ascii password was updated"); - } else { - /* Code in else part would execute only once: - * When device is upgraded from L->M release. - * Once upgraded, code flow should never come here. - * L release passed actual password in hex, so try with hex - * Each nible of passwd was encoded as a byte, so allocate memory - * twice of password len plus one more byte for null termination - */ - if (crypt_ftr->crypt_type == CRYPT_TYPE_DEFAULT) { - new_passwd = (char*)malloc(strlen(DEFAULT_HEX_PASSWORD) + 1); - if (new_passwd == NULL) { - printf("System out of memory. Password verification incomplete"); - goto out; - } - strlcpy(new_passwd, DEFAULT_HEX_PASSWORD, strlen(DEFAULT_HEX_PASSWORD) + 1); - } else { - new_passwd = (char*)malloc(strlen(passwd) * 2 + 1); - if (new_passwd == NULL) { - printf("System out of memory. Password verification incomplete"); - goto out; - } - convert_key_to_hex_ascii((const unsigned char*)passwd, - strlen(passwd), new_passwd); - } - key_index = set_hw_device_encryption_key((const char*)new_passwd, - (char*) crypt_ftr->crypto_type_name); - if (key_index >=0) { - crypt_ftr->failed_decrypt_count = 0; - printf("Hex password verified...will try to update with Ascii value"); - /* Before updating password, tie that with keymaster to tie with ROT */ - - if (get_keymaster_hw_fde_passwd(passwd, newpw, - crypt_ftr->salt, crypt_ftr)) { - passwd_updated = update_hw_device_encryption_key(new_passwd, - passwd, (char*)crypt_ftr->crypto_type_name); - } else { - passwd_updated = update_hw_device_encryption_key(new_passwd, - (const char*)newpw, (char*)crypt_ftr->crypto_type_name); - } - - if (passwd_updated >= 0) { - crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED; - printf("Ascii password recorded and updated"); - } else { - printf("Passwd verified, could not update...Will try next time"); - } - } else { - ++crypt_ftr->failed_decrypt_count; - } - free(new_passwd); - } - } else { - if (!ascii_passwd_updated) - crypt_ftr->flags |= CRYPT_ASCII_PASSWORD_UPDATED; - } -out: - // DO NOT update footer before leaving - // put_crypt_ftr_and_key(crypt_ftr); - return key_index; -} #endif void set_partition_data(const char* block_device, const char* key_location, const char* fs) @@ -853,23 +771,6 @@ static int get_crypt_ftr_info(char **metadata_fname, off64_t *off) return rc; } -static inline int unix_read(int fd, void* buff, int len) -{ - return TEMP_FAILURE_RETRY(read(fd, buff, len)); -} - -static inline int unix_write(int fd, const void* buff, int len) -{ - return TEMP_FAILURE_RETRY(write(fd, buff, len)); -} - -static void init_empty_persist_data(struct crypt_persist_data *pdata, int len) -{ - memset(pdata, 0, len); - pdata->persist_magic = PERSIST_DATA_MAGIC; - pdata->persist_valid_entries = 0; -} - static int get_crypt_ftr_and_key(struct crypt_mnt_ftr *crypt_ftr) { int fd; @@ -941,49 +842,6 @@ errout: return rc; } -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) { - printf("Trying to convert ascii string of odd length\n"); - return NULL; - } - - unsigned char* master_key = (unsigned char*) malloc(size / 2); - if (master_key == 0) { - printf("Cannot allocate\n"); - 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) { - printf("Invalid hex string\n"); - 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 */ @@ -1006,8 +864,8 @@ static void convert_key_to_hex_ascii(const unsigned char *master_key, } -static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, const char *name, int fd, +static int load_crypto_mapping_table(struct crypt_mnt_ftr *crypt_ftr, const unsigned char *master_key, + const char *real_blk_name, const char *name, int fd, char *extra_params) { char buffer[DM_CRYPT_BUF_SIZE]; @@ -1117,8 +975,8 @@ static int get_dm_crypt_version(int fd, const char *name, int *version) return -1; } -static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, unsigned char *master_key, - char *real_blk_name, char *crypto_blk_name, const char *name) +static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr, const unsigned char *master_key, + const char *real_blk_name, char *crypto_blk_name, const char *name) { char buffer[DM_CRYPT_BUF_SIZE]; char master_key_ascii[129]; /* Large enough to hold 512 bit key and null */ @@ -1256,14 +1114,9 @@ static int pbkdf2(const char *passwd, const unsigned char *salt, printf("Using pbkdf2 for cryptfs KDF\n"); /* Turn the password into a key and IV that can decrypt the master key */ - 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, + PKCS5_PBKDF2_HMAC_SHA1(passwd, strlen(passwd), salt, SALT_LEN, HASH_COUNT, KEY_LEN_BYTES+IV_LEN_BYTES, ikey); - memset(master_key, 0, keysize); - free (master_key); return 0; } @@ -1279,14 +1132,9 @@ static int scrypt(const char *passwd, const unsigned char *salt, int p = 1 << ftr->p_factor; /* Turn the password into a key and IV that can decrypt the master key */ - 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); - - memset(master_key, 0, keysize); - free (master_key); + crypto_scrypt((const uint8_t *)passwd, strlen(passwd), salt, SALT_LEN, + N, r, p, ikey, KEY_LEN_BYTES + IV_LEN_BYTES); + return 0; } @@ -1305,16 +1153,8 @@ static int scrypt_keymaster(const char *passwd, const unsigned char *salt, int r = 1 << ftr->r_factor; int p = 1 << ftr->p_factor; - unsigned char* master_key = convert_hex_ascii_to_key(passwd, &key_size); - if (!master_key) { - printf("Failed to convert passwd from hex\n"); - return -1; - } - - rc = crypto_scrypt(master_key, key_size, salt, SALT_LEN, + rc = crypto_scrypt((const uint8_t *)passwd, strlen(passwd), salt, SALT_LEN, N, r, p, ikey, KEY_LEN_BYTES + IV_LEN_BYTES); - memset(master_key, 0, key_size); - free(master_key); if (rc) { printf("scrypt failed\n"); @@ -1339,94 +1179,6 @@ static int scrypt_keymaster(const char *passwd, const unsigned char *salt, return 0; } -static int encrypt_master_key(const char *passwd, const unsigned char *salt, - const unsigned char *decrypted_master_key, - unsigned char *encrypted_master_key, - struct crypt_mnt_ftr *crypt_ftr) -{ - unsigned char ikey[32+32] = { 0 }; /* Big enough to hold a 256 bit key and 256 bit IV */ - EVP_CIPHER_CTX e_ctx; - int encrypted_len, final_len; - int rc = 0; - - /* Turn the password into an intermediate key and IV that can decrypt the master key */ - get_device_scrypt_params(crypt_ftr); - - switch (crypt_ftr->kdf_type) { - case KDF_SCRYPT_KEYMASTER_UNPADDED: - case KDF_SCRYPT_KEYMASTER_BADLY_PADDED: - case KDF_SCRYPT_KEYMASTER: - if (keymaster_create_key(crypt_ftr)) { - printf("keymaster_create_key failed\n"); - return -1; - } - - if (scrypt_keymaster(passwd, salt, ikey, crypt_ftr)) { - printf("scrypt failed\n"); - return -1; - } - break; - - case KDF_SCRYPT: - if (scrypt(passwd, salt, ikey, crypt_ftr)) { - printf("scrypt failed\n"); - return -1; - } - break; - - default: - printf("Invalid kdf_type\n"); - return -1; - } - - /* Initialize the decryption engine */ - if (! EVP_EncryptInit(&e_ctx, EVP_aes_128_cbc(), ikey, ikey+KEY_LEN_BYTES)) { - printf("EVP_EncryptInit failed\n"); - return -1; - } - EVP_CIPHER_CTX_set_padding(&e_ctx, 0); /* Turn off padding as our data is block aligned */ - - /* Encrypt the master key */ - if (! EVP_EncryptUpdate(&e_ctx, encrypted_master_key, &encrypted_len, - decrypted_master_key, KEY_LEN_BYTES)) { - printf("EVP_EncryptUpdate failed\n"); - return -1; - } -#ifndef TW_CRYPTO_HAVE_KEYMASTERX - if (! EVP_EncryptFinal(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) { -#else - if (! EVP_EncryptFinal_ex(&e_ctx, encrypted_master_key + encrypted_len, &final_len)) { -#endif - printf("EVP_EncryptFinal failed\n"); - return -1; - } - - if (encrypted_len + final_len != KEY_LEN_BYTES) { - printf("EVP_Encryption length check failed with %d, %d bytes\n", encrypted_len, final_len); - return -1; - } - - /* Store the scrypt of the intermediate key, so we can validate if it's a - password error or mount error when things go wrong. - Note there's no need to check for errors, since if this is incorrect, we - simply won't wipe userdata, which is the correct default behavior - */ - int N = 1 << crypt_ftr->N_factor; - int r = 1 << crypt_ftr->r_factor; - int p = 1 << crypt_ftr->p_factor; - - rc = crypto_scrypt(ikey, KEY_LEN_BYTES, - crypt_ftr->salt, sizeof(crypt_ftr->salt), N, r, p, - crypt_ftr->scrypted_intermediate_key, - sizeof(crypt_ftr->scrypted_intermediate_key)); - - if (rc) { - printf("encrypt_master_key: crypto_scrypt failed\n"); - } - - return 0; -} - static int decrypt_master_key_aux(char *passwd, unsigned char *salt, unsigned char *encrypted_master_key, unsigned char *decrypted_master_key, @@ -1522,7 +1274,6 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, unsigned char decrypted_master_key[32]; char crypto_blkdev[MAXPATHLEN]; char tmp_mount_point[64]; - unsigned int orig_failed_decrypt_count; int rc = 0; kdf_func kdf; void *kdf_params; @@ -1532,7 +1283,6 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, size_t intermediate_key_size = 0; printf("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, @@ -1546,9 +1296,10 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, #ifdef CONFIG_HW_DISK_ENCRYPTION int key_index = 0; if(is_hw_disk_encryption((char*)crypt_ftr->crypto_type_name)) { - key_index = verify_and_update_hw_fde_passwd(passwd, crypt_ftr); + key_index = verify_hw_fde_passwd(passwd, crypt_ftr); + if (key_index < 0) { - rc = crypt_ftr->failed_decrypt_count; + rc = 1; goto errout; } else { @@ -1617,9 +1368,7 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, if (mount(crypto_blkdev, tmp_mount_point, file_system, 0, NULL) != 0) { printf("Error temp mounting decrypted block device '%s'\n", crypto_blkdev); delete_crypto_blk_dev(label); - - rc = ++crypt_ftr->failed_decrypt_count; - //put_crypt_ftr_and_key(crypt_ftr); // Do not penalize for attempting to decrypt in recovery + rc = 1; } else { /* Success! */ printf("Password did not match but decrypted drive mounted - continue\n"); @@ -1629,54 +1378,14 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, } if (rc == 0) { - /*crypt_ftr->failed_decrypt_count = 0; - if (orig_failed_decrypt_count != 0) { - put_crypt_ftr_and_key(crypt_ftr); - }*/ + // Don't increment the failed attempt counter as it doesn't + // make sense to do so in TWRP /* Save the name of the crypto block device * 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. */ - /*memcpy(saved_master_key, decrypted_master_key, KEY_LEN_BYTES); - saved_mount_point = strdup(mount_point); - master_key_saved = 1; - printf("%s(): Master key saved\n", __FUNCTION__);*/ - rc = 0; - - // 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 - } else if (use_keymaster == 1 && crypt_ftr->kdf_type != KDF_SCRYPT_KEYMASTER) { - crypt_ftr->kdf_type = KDF_SCRYPT_KEYMASTER; - upgrade = 1; - } else if (use_keymaster == 0 && crypt_ftr->kdf_type != KDF_SCRYPT) { - crypt_ftr->kdf_type = KDF_SCRYPT; - upgrade = 1; - } - - if (upgrade) { - 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); - } - printf("Key Derivation Function upgrade: rc=%d\n", rc); - - // Do not fail even if upgrade failed - machine is bootable - // Note that if this code is ever hit, there is a *serious* problem - // since KDFs should never fail. You *must* fix the kdf before - // proceeding! - if (rc) { - printf("Upgrade failed with error %d," - " but continuing with previous state\n", - rc); - rc = 0; - } - }*/ + // TWRP shouldn't change the stored key } errout: @@ -1687,15 +1396,6 @@ static int test_mount_encrypted_fs(struct crypt_mnt_ftr* crypt_ftr, return rc; } -/* Called by vold when it wants to undo the crypto mapping of a volume it - * manages. This is usually in response to a factory reset, when we want - * to undo the crypto mapping so the volume is formatted in the clear. - */ -int cryptfs_revert_volume(const char *label) -{ - return delete_crypto_blk_dev((char *)label); -} - int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) { char encrypted_state[PROPERTY_VALUE_MAX]; @@ -1714,107 +1414,6 @@ int check_unmounted_and_get_ftr(struct crypt_mnt_ftr* crypt_ftr) return 0; } -/* - * TODO - transition patterns to new format in calling code - * and remove this vile hack, and the use of hex in - * the password passing code. - * - * Patterns are passed in zero based (i.e. the top left dot - * is represented by zero, the top middle one etc), but we want - * to store them '1' based. - * This is to allow us to migrate the calling code to use this - * convention. It also solves a nasty problem whereby scrypt ignores - * trailing zeros, so patterns ending at the top left could be - * truncated, and similarly, you could add the top left to any - * pattern and still match. - * adjust_passwd is a hack function that returns the alternate representation - * if the password appears to be a pattern (hex numbers all less than 09) - * If it succeeds we need to try both, and in particular try the alternate - * first. If the original matches, then we need to update the footer - * with the alternate. - * All code that accepts passwords must adjust them first. Since - * cryptfs_check_passwd is always the first function called after a migration - * (and indeed on any boot) we only need to do the double try in this - * function. - */ -char* adjust_passwd(const char* passwd) -{ - size_t index, length; - - if (!passwd) { - return 0; - } - - // Check even length. Hex encoded passwords are always - // an even length, since each character encodes to two characters. - length = strlen(passwd); - if (length % 2) { - printf("Password not correctly hex encoded.\n"); - return 0; - } - - // Check password is old-style pattern - a collection of hex - // encoded bytes less than 9 (00 through 08) - for (index = 0; index < length; index +=2) { - if (passwd[index] != '0' - || passwd[index + 1] < '0' || passwd[index + 1] > '8') { - return 0; - } - } - - // Allocate room for adjusted passwd and null terminate - char* adjusted = malloc(length + 1); - adjusted[length] = 0; - - // Add 0x31 ('1') to each character - for (index = 0; index < length; index += 2) { - // output is 31 through 39 so set first byte to three, second to src + 1 - adjusted[index] = '3'; - adjusted[index + 1] = passwd[index + 1] + 1; - } - - return adjusted; -} - -/* - * Passwords in L get passed from Android to cryptfs in hex, so a '1' - * gets converted to '31' where 31 is 0x31 which is the ascii character - * code in hex of the character '1'. This function will convert the - * regular character codes to their hexadecimal representation to make - * decrypt work properly with Android 5.0 lollipop decryption. - */ -char* hexadj_passwd(const char* passwd, int has_hw_crypto) -{ - size_t index, length; - const char* ptr = passwd; - - if (!passwd) { - return 0; - } - - length = strlen(passwd); - - // Allocate room for hex passwd and null terminate - char* hex = malloc((length * 2) + 1); - hex[length * 2] = 0; - - // Convert to hex - for (index = 0; index < length; index++) { - sprintf(hex + (index * 2), "%02X", *ptr); - ptr++; - } -#ifdef CONFIG_HW_DISK_ENCRYPTION - if (has_hw_crypto) { - printf("hexadj_passwd converting to lower case for hardware disk crypto.\n"); - length *= 2; - for (index = 0; index < length; index++) { - hex[index] = tolower(hex[index]); - } - } -#endif - return hex; -} - int cryptfs_check_footer() { int rc = -1; @@ -1829,178 +1428,36 @@ int cryptfs_check_passwd(char *passwd) { struct crypt_mnt_ftr crypt_ftr; int rc; - int has_hw_crypto = 0; + + if (!passwd) { + printf("cryptfs_check_passwd: passwd is NULL!\n"); + return -1; + } rc = check_unmounted_and_get_ftr(&crypt_ftr); if (rc) return rc; -#ifdef CONFIG_HW_DISK_ENCRYPTION - printf("CONFIG_HW_DISK_ENCRYPTION present\n"); - if (is_hw_fde_enabled() && is_hw_disk_encryption((char*) crypt_ftr.crypto_type_name)) - has_hw_crypto = 1; -#endif + rc = test_mount_encrypted_fs(&crypt_ftr, passwd, + DATA_MNT_POINT, "userdata"); - //if (passwd) printf("passwd: '%s'\n", passwd); - char* adjusted_passwd; - if (!has_hw_crypto) - adjusted_passwd = adjust_passwd(passwd); - //if (adjusted_passwd) printf("adjusted_passwd: '%s'\n", adjusted_passwd); - char* hex_passwd = hexadj_passwd(passwd, has_hw_crypto); - //if (hex_passwd) printf("hex_passwd: '%s'\n", hex_passwd); - printf("has_hw_crypto is %i\n", has_hw_crypto); - if (!has_hw_crypto && adjusted_passwd) { - int failed_decrypt_count = crypt_ftr.failed_decrypt_count; - //printf("trying adjusted password '%s'\n", adjusted_passwd); - rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd, - DATA_MNT_POINT, "userdata"); - - // Maybe the original one still works? - if (rc) { - // Don't double count this failure - //printf("trying passwd '%s'\n", passwd); - crypt_ftr.failed_decrypt_count = failed_decrypt_count; - rc = test_mount_encrypted_fs(&crypt_ftr, passwd, - DATA_MNT_POINT, "userdata"); - if (!rc) { - // cryptfs_changepw also adjusts so pass original - // Note that adjust_passwd only recognises patterns - // so we can safely use CRYPT_TYPE_PATTERN - printf("TWRP NOT Updating pattern to new format\n"); - //cryptfs_changepw(CRYPT_TYPE_PATTERN, passwd); - } else if (hex_passwd) { - //printf("trying hex_passwd '%s'\n", hex_passwd); - rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd, - DATA_MNT_POINT, "userdata"); - } - } - free(adjusted_passwd); - } else { + // try falling back to Lollipop hex passwords + if (rc) { + int hex_pass_len = strlen(passwd) * 2 + 1; + char *hex_passwd = (char *)malloc(hex_pass_len); if (hex_passwd) { - //printf("2trying hex_passwd '%s'\n", hex_passwd); + convert_key_to_hex_ascii((unsigned char *)passwd, + strlen(passwd), hex_passwd); rc = test_mount_encrypted_fs(&crypt_ftr, hex_passwd, - DATA_MNT_POINT, "userdata"); - } else { - rc = 1; - } - if (rc && passwd) { - //printf("2trying passwd '%s'\n", passwd); - rc = test_mount_encrypted_fs(&crypt_ftr, passwd, - DATA_MNT_POINT, "userdata"); - } - } - - if (hex_passwd) - free(hex_passwd); - - /*if (rc == 0 && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) { - printf("cryptfs_check_passwd update expiry time?\n"); - cryptfs_clear_password(); - password = strdup(passwd); - struct timespec now; - clock_gettime(CLOCK_BOOTTIME, &now); - password_expiry_time = now.tv_sec + password_max_age_seconds; - }*/ - - 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 decrypted_master_key[32]; - char encrypted_state[PROPERTY_VALUE_MAX]; - int rc; - - property_get("ro.crypto.state", encrypted_state, ""); - if (strcmp(encrypted_state, "encrypted") ) { - printf("device not encrypted, aborting\n"); - return -2; - } - - if (!master_key_saved) { - printf("encrypted fs not yet mounted, aborting\n"); - return -1; - } - - if (!saved_mount_point) { - printf("encrypted fs failed to save mount point, aborting\n"); - return -1; - } - - if (get_crypt_ftr_and_key(&crypt_ftr)) { - printf("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 { - char* adjusted_passwd = adjust_passwd(passwd); - if (adjusted_passwd) { - passwd = adjusted_passwd; - } - - decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0); - 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; + DATA_MNT_POINT, "userdata"); + memset(hex_passwd, 0, hex_pass_len); + free(hex_passwd); } - - free(adjusted_passwd); } 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 - * filesystem size and crypto_type_name after calling this function. - */ -static int cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr *ftr) -{ - off64_t off; - - memset(ftr, 0, sizeof(struct crypt_mnt_ftr)); - ftr->magic = CRYPT_MNT_MAGIC; - ftr->major_version = CURRENT_MAJOR_VERSION; - ftr->minor_version = CURRENT_MINOR_VERSION; - ftr->ftr_size = sizeof(struct crypt_mnt_ftr); - ftr->keysize = KEY_LEN_BYTES; - - switch (keymaster_check_compatibility()) { - case 1: - ftr->kdf_type = KDF_SCRYPT_KEYMASTER; - break; - - case 0: - ftr->kdf_type = KDF_SCRYPT; - break; - - default: - printf("keymaster_check_compatibility failed\n"); - return -1; - } - - get_device_scrypt_params(ftr); - - ftr->persist_data_size = CRYPT_PERSIST_DATA_SIZE; - if (get_crypt_ftr_info(NULL, &off) == 0) { - ftr->persist_data_offset[0] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET; - ftr->persist_data_offset[1] = off + CRYPT_FOOTER_TO_PERSIST_OFFSET + - ftr->persist_data_size; - } - - return 0; -} - /* Returns type of the password, default, pattern, pin or password. */ int cryptfs_get_password_type(void) -- cgit v1.2.3