From d3e96ff43e6b47da0e92d0e41c9f3f577ba24ff5 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Wed, 17 Feb 2016 13:36:43 -0600 Subject: Restore some old decrypt functionality Some of the convoluted convert_hex_ascii_to_key code is needed to properly decrypt CM 12.1 patterns where grid size is larger than 3x3. Change-Id: I497e17980046c60d2c69ba56e4b83c8b64b0b80e --- crypto/lollipop/cryptfs.c | 71 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 66 insertions(+), 5 deletions(-) (limited to 'crypto') diff --git a/crypto/lollipop/cryptfs.c b/crypto/lollipop/cryptfs.c index fe075c4ad..56f10b92b 100644 --- a/crypto/lollipop/cryptfs.c +++ b/crypto/lollipop/cryptfs.c @@ -842,6 +842,49 @@ 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 */ @@ -1114,9 +1157,14 @@ 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 */ - 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); + memset(master_key, 0, keysize); + free (master_key); return 0; } @@ -1132,9 +1180,14 @@ 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 */ - crypto_scrypt((const uint8_t *)passwd, strlen(passwd), salt, SALT_LEN, - N, r, p, ikey, KEY_LEN_BYTES + IV_LEN_BYTES); - + 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); return 0; } @@ -1153,8 +1206,16 @@ static int scrypt_keymaster(const char *passwd, const unsigned char *salt, int r = 1 << ftr->r_factor; int p = 1 << ftr->p_factor; - rc = crypto_scrypt((const uint8_t *)passwd, strlen(passwd), salt, SALT_LEN, + 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, 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"); -- cgit v1.2.3