diff --git a/CASA/test/micasa_dump/Makefile b/CASA/test/micasa_dump/Makefile new file mode 100644 index 00000000..974b9282 --- /dev/null +++ b/CASA/test/micasa_dump/Makefile @@ -0,0 +1,9 @@ +CFLAGS=-fpermissive -g + +all: micasa-decrypt.exe + +micasa-decrypt.exe: main.cpp + g++ $(CFLAGS) $^ -o $@ -lcrypto + +clean: + rm -f micasa-decrypt.exe diff --git a/CASA/test/micasa_dump/main.cpp b/CASA/test/micasa_dump/main.cpp new file mode 100644 index 00000000..3d7e5c51 --- /dev/null +++ b/CASA/test/micasa_dump/main.cpp @@ -0,0 +1,193 @@ +#include + +#include +#include +#include +#include +#include + +using namespace std; + +#define AES_KEY_128 128 +#define AES_KEY_256 256 +#define AES_KEY_BYTES_128 (AES_KEY_128/8) +#define AES_KEY_BYTES_256 (AES_KEY_256/8) + +int password_to_key(const string *password, + const unsigned char *salt, + size_t salt_len, + unsigned char *key, + size_t key_len) +{ + int rc; + unsigned char hash[20]; + assert(key_len == AES_KEY_BYTES_128); + assert(salt_len == 64); + + rc = PKCS5_PBKDF2_HMAC_SHA1(password->c_str(), + password->length(), + salt, + salt_len, + 1000 /*iter*/, + key_len, + key); + + return (rc == 1)? 0 : 1; +} + +int decrypt(const unsigned char *in, + unsigned char *out, + size_t len, + const unsigned char *key, + size_t key_len, + const unsigned char *IV, + size_t IV_len) +{ + AES_KEY key_dec; + + assert((key_len == AES_KEY_BYTES_128) || (key_len = AES_KEY_BYTES_256)); + assert(IV_len == AES_KEY_BYTES_128); + + assert(len % 16 == 0); + + AES_set_decrypt_key(key, key_len*8, &key_dec); + AES_cbc_encrypt(in, out, len, &key_dec, IV, AES_DECRYPT); + + return 0; +} + +/* decrypt and validate checksum. in := (256 bit checksum) | (cipher text) */ +int decrypt_and_validate(const unsigned char *in, + unsigned char *out, + size_t *len, + const unsigned char *key, + size_t key_len, + const unsigned char *IV, + size_t IV_len) { + int rc, l = *len; + const unsigned char *hash = in, *CT = in + 32; + unsigned char *h, md[32]; + + assert(*len > 32); + + rc = decrypt(CT, out, *len - 32, key, key_len, IV, IV_len); + + *len = (*len - 32) - out[*len - 32 - 1]; + bzero(out + *len, l - *len); + h = SHA256(out, *len, md); + assert(memcmp(md, hash, 32) == 0); + + return rc; +} + +int decrypt_and_validate_file(string file, + unsigned char *out, + size_t *len, + const unsigned char *key, + size_t key_len) +{ + int rc, l, in_len = *len; + unsigned char IV[16], *CT; + FILE *fd; + + /* Open the encrypted file and read contents */ + fd = fopen(file.c_str(), "r"); + assert(fd != NULL); + CT = new unsigned char[*len]; + *len = fread((void *)CT, 1, *len, fd); + assert(*len < in_len); + fclose(fd); + + /* Read the IV */ + file.append(".IV"); + fd = fopen(file.c_str(), "r"); + assert(fd != NULL); + l = fread((void *)IV, 1, sizeof(IV), fd); + assert(l == sizeof(IV)); + /* Add a check to ensure that file size is exactly 16 bytes */ + fclose(fd); + + /* Decrypt */ + rc = decrypt_and_validate(CT, out, len, key, key_len, IV, sizeof(IV)); + + bzero(out + (*len), in_len - (*len)); + + delete [] CT; + + return rc; +} + +main() +{ + int rc; + size_t len; + FILE *fd; + unsigned char passcode[16], key[32]; + string user, user_store; + + cout << "User: "; + cin >> user; + + user_store = "/home/.casa/" + user + "/"; + + /* Get passcode. Usually encrypted with desktop password */ + { + unsigned char salt[64], passcode_dec[32], IV[16]; + unsigned char passcode_enc[128], password_key[16]; + string password; + + /* Read salt */ + fd = fopen((user_store + ".miCASAPCByDesktop.salt").c_str(), "r"); + len = fread((void *)salt, 1, sizeof(salt), fd); + assert(len == sizeof(salt)); + fclose(fd); + + /* Read IV */ + fd = fopen((user_store + ".miCASAPCByDesktop.IV").c_str(), "r"); + len = fread((void *)IV, 1, sizeof(IV), fd); + assert(len == sizeof(IV)); + fclose(fd); + + /* Prompt user for password and convert password to key */ + cout << "Password: "; + cin >> password; + password_to_key(&password, salt, sizeof(salt), password_key, sizeof(password_key)); + + /* Read encrypted passcode */ + fd = fopen((user_store + ".miCASAPCByDesktop").c_str(), "r"); + len = fread((void *)passcode_enc, 1, sizeof(passcode_enc), fd); + assert(len == sizeof(passcode_dec)); + fclose(fd); + + /* Decrypt */ + rc = decrypt(passcode_enc, passcode_dec, len, password_key, + sizeof(password_key), IV, sizeof(IV)); + assert(rc == 0); + + memcpy(passcode, passcode_dec, sizeof(passcode)); + } + + /* get secret key from .miCASAKey */ + { + unsigned char plain_text[128]; + + len = sizeof(plain_text); + rc = decrypt_and_validate_file(user_store + ".miCASAKey", + plain_text, &len, passcode, + sizeof(passcode)); + assert(len == sizeof(key)); + memcpy(key, plain_text, sizeof(key)); + } + + + /* Decrypt micasa store */ + { + unsigned char plain_text[4096]; + + len = sizeof(plain_text); + rc = decrypt_and_validate_file(user_store + ".miCASA", + plain_text, &len, key, + sizeof(key)); + puts(plain_text); + } +}