From c579f3458775ca45bd86dcb9b8ef09e7d2a03bdc Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 5 Aug 2009 11:36:56 -0700 Subject: MPQCryptography.c doesn't really have anything to do anymore with its original piece of code; cleaning it up and renaming it. --- mpq-crypto.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 mpq-crypto.c (limited to 'mpq-crypto.c') diff --git a/mpq-crypto.c b/mpq-crypto.c new file mode 100644 index 0000000..7ddbad5 --- /dev/null +++ b/mpq-crypto.c @@ -0,0 +1,164 @@ +#include +#include + +#include "mpq-crypto.h" + +static int crypt_table_initialized = 0; +static uint32_t crypt_table[0x500]; + +/****TODO****/ +/* Re-implement various endianess fixes. */ + +const uint32_t *__mpqlib_get_cryptography_table() +{ + assert(crypt_table_initialized); + return crypt_table; +} + +void __mpqlib_init_cryptography() +{ + // Prepare crypt_table + uint32_t seed = 0x00100001; + uint32_t index1 = 0; + uint32_t index2 = 0; + int32_t i; + + if (!crypt_table_initialized) { + crypt_table_initialized = 1; + + for (index1 = 0; index1 < 0x100; index1++) { + for (index2 = index1, i = 0; i < 5; i++, index2 += 0x100) { + uint32_t temp1, temp2; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp1 = (seed & 0xFFFF) << 0x10; + + seed = (seed * 125 + 3) % 0x2AAAAB; + temp2 = (seed & 0xFFFF); + + crypt_table[index2] = (temp1 | temp2); + } + } + } +} + +void __mpqlib_encrypt(void *_data, uint32_t length, uint32_t key, char disable_input_swapping) +{ + char * data = (char *) _data; + uint32_t *buffer32 = (uint32_t *) data; + uint32_t seed = 0xEEEEEEEE; + uint32_t ch; + + assert(crypt_table_initialized); + assert(data); + + // Round to 4 bytes + length = length / 4; + + // We duplicate the loop to avoid costly branches + if (disable_input_swapping) { + while (length-- > 0) { + seed += crypt_table[0x400 + (key & 0xFF)]; + ch = *buffer32 ^ (key + seed); + + key = ((~key << 0x15) + 0x11111111) | (key >> 0x0B); + seed = *buffer32 + seed + (seed << 5) + 3; + + *buffer32++ = ch; + } + } else { + while (length-- > 0) { + seed += crypt_table[0x400 + (key & 0xFF)]; + ch = *buffer32 ^ (key + seed); + + key = ((~key << 0x15) + 0x11111111) | (key >> 0x0B); + seed = *buffer32 + seed + (seed << 5) + 3; + + *buffer32++ = ch; + } + } +} + +void __mpqlib_decrypt(void *_data, uint32_t length, uint32_t key, char disable_output_swapping) +{ + char * data = (char *) _data; + uint32_t *buffer32 = (uint32_t *) data; + uint32_t seed = 0xEEEEEEEE; + uint32_t ch; + + assert(crypt_table_initialized); + assert(data); + + // Round to 4 bytes + length = length / 4; + + if (disable_output_swapping) { + while (length-- > 0) { + ch = *buffer32; + + seed += crypt_table[0x400 + (key & 0xFF)]; + ch = ch ^ (key + seed); + + key = ((~key << 0x15) + 0x11111111) | (key >> 0x0B); + seed = ch + seed + (seed << 5) + 3; + + *buffer32++ = ch; + } + + } else { + while (length-- > 0) { + ch = *buffer32; + + seed += crypt_table[0x400 + (key & 0xFF)]; + ch = ch ^ (key + seed); + + key = ((~key << 0x15) + 0x11111111) | (key >> 0x0B); + seed = ch + seed + (seed << 5) + 3; + + *buffer32++ = ch; + } + } +} + +uint32_t __mpqlib_hash_cstring(const char *string, uint32_t type) +{ + uint32_t seed1 = 0x7FED7FED; + uint32_t seed2 = 0xEEEEEEEE; + uint32_t shifted_type = (type << 8); + int32_t ch; + + assert(crypt_table_initialized); + assert(string); + + while (*string != 0) { + ch = *string++; + if (ch > 0x60 && ch < 0x7b) + ch -= 0x20; + + seed1 = crypt_table[shifted_type + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + } + + return seed1; +} + +uint32_t __mpqlib_hash_data(const char *data, uint32_t length, uint32_t type) +{ + uint32_t seed1 = 0x7FED7FED; + uint32_t seed2 = 0xEEEEEEEE; + uint32_t shifted_type = (type << 8); + int32_t ch; + + assert(crypt_table_initialized); + assert(data); + + while (length > 0) { + ch = *data++; + + seed1 = crypt_table[shifted_type + ch] ^ (seed1 + seed2); + seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3; + length--; + } + + return seed1; +} -- cgit v1.2.3