diff --git a/src/MYSQL_fast_fmt_plug.c b/src/MYSQL_fast_fmt_plug.c index d34129a..6ae863f 100644 --- a/src/MYSQL_fast_fmt_plug.c +++ b/src/MYSQL_fast_fmt_plug.c @@ -14,12 +14,19 @@ * Unbelievable good optimization by Péter Kasza * * http://rycon.hu/ + * + * OpenMP support and other assorted hacks by Solar Designer */ #include #include #include +#ifdef _OPENMP +#include +#define OMP_SCALE 10240 +#endif + #include "arch.h" #include "misc.h" #include "common.h" @@ -35,7 +42,7 @@ #define PLAINTEXT_LENGTH 32 #define CIPHERTEXT_LENGTH 16 -#define BINARY_SIZE 8 +#define BINARY_SIZE 4 #define SALT_SIZE 0 #define MIN_KEYS_PER_CRYPT 1 @@ -59,8 +66,22 @@ static struct fmt_tests mysql_tests[] = { {NULL} }; -static ARCH_WORD_32 crypt_key[MAX_KEYS_PER_CRYPT][BINARY_SIZE / 4]; -static char saved_key[MAX_KEYS_PER_CRYPT][PLAINTEXT_LENGTH + 1]; +static char (*saved_key)[PLAINTEXT_LENGTH + 1]; +static ARCH_WORD_32 (*crypt_key)[BINARY_SIZE / 4]; + +static void mysql_init(struct fmt_main *pFmt) +{ +#ifdef _OPENMP + int omp_t = omp_get_max_threads(); + if (omp_t > 1) { + pFmt->params.min_keys_per_crypt *= omp_t; + omp_t *= OMP_SCALE; + pFmt->params.max_keys_per_crypt *= omp_t; + } +#endif + saved_key = mem_alloc_tiny(sizeof(*saved_key) * pFmt->params.max_keys_per_crypt, MEM_ALIGN_CACHE); + crypt_key = mem_alloc_tiny(sizeof(*crypt_key) * pFmt->params.max_keys_per_crypt, MEM_ALIGN_CACHE); +} static int mysql_valid(char* ciphertext, struct fmt_main *pFmt) { @@ -70,27 +91,33 @@ static int mysql_valid(char* ciphertext, struct fmt_main *pFmt) return 0; for (i = 0; i < CIPHERTEXT_LENGTH; i++) - { - if (!(((ciphertext[i] >= '0') && (ciphertext[i] <= '9')) || - ((ciphertext[i] >= 'a') && (ciphertext[i] <= 'f')) || - ((ciphertext[i] >= 'A') && (ciphertext[i] <= 'F'))) - ) + if (atoi16[ARCH_INDEX(ciphertext[i])] > 15) return 0; - } return 1; } -static void* mysql_get_binary(char* ciphertext) +static char *mysql_split(char *ciphertext, int index) +{ + static char out[CIPHERTEXT_LENGTH + 1]; + + memcpy(out, ciphertext, CIPHERTEXT_LENGTH); + out[CIPHERTEXT_LENGTH] = 0; + strlwr(out); + + return out; +} + +static void *mysql_get_binary_size(char *ciphertext, int size) { - static unsigned long buff_[BINARY_SIZE / sizeof(unsigned long)]; + /* maybe bigger than BINARY_SIZE for use from cmp_exact() */ + static ARCH_WORD_32 buff_[8]; unsigned char *buff = (unsigned char *)buff_; unsigned int i; - for (i = 0; i < BINARY_SIZE / 2; i++) - { -#if ARCH_LITTLE_ENDIAN == 1 - buff[((BINARY_SIZE / 2) - 1) - i] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])]; + for (i = 0; i < size; i++) { +#if ARCH_LITTLE_ENDIAN + buff[(i & ~3U) | (3 - (i & 3))] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])]; #else buff[i] = atoi16[ARCH_INDEX(ciphertext[i * 2])] * 16 + atoi16[ARCH_INDEX(ciphertext[i * 2 + 1])]; #endif @@ -99,6 +126,11 @@ static void* mysql_get_binary(char* ciphertext) return buff; } +static void *mysql_get_binary(char *ciphertext) +{ + return mysql_get_binary_size(ciphertext, BINARY_SIZE); +} + static void mysql_set_key(char* key, int index) { strnzcpy(saved_key[index], key, PLAINTEXT_LENGTH + 1); @@ -116,63 +148,85 @@ static int mysql_cmp_one(void* binary, int index) static int mysql_cmp_all(void* binary, int count) { - unsigned int i; + int i; - for (i = 0; i < count; i++) { +#ifdef _OPENMP + int retval = 0; +#pragma omp parallel for default(none) private(i) shared(count, binary, crypt_key, retval) + for (i = 0; i < count; i++) + if (*(ARCH_WORD_32 *)binary == crypt_key[i][0]) +#pragma omp critical + retval = 1; + return retval; +#else + for (i = 0; i < count; i++) if (*(ARCH_WORD_32 *)binary == crypt_key[i][0]) return 1; - } - return 0; +#endif } static int mysql_cmp_exact(char* source, int index) { - register unsigned long nr = 1345345333L, add = 7, nr2 = 0x12345671L; - register unsigned long tmp; - char* password; - char ctmp[CIPHERTEXT_LENGTH+1]; + register ARCH_WORD_32 nr = 1345345333, add = 7, nr2 = 0x12345671; + register ARCH_WORD_32 tmp; + unsigned char *p; - password = saved_key[index]; - for (; *password; password++) - { - if (*password == ' ' || *password == '\t') + p = (unsigned char *)saved_key[index]; + for (; *p; p++) { + if (*p == ' ' || *p == '\t') continue; - tmp = (unsigned long) (unsigned char) *password; + tmp = (ARCH_WORD_32)*p; nr ^= (((nr & 63) + add) * tmp) + (nr << 8); nr2 += (nr2 << 8) ^ nr; add += tmp; } - sprintf(ctmp, "%08lx%08lx", (nr & (((unsigned long) 1L << 31) -1L)), (nr2 & (((unsigned long) 1L << 31) -1L))); - return !memcmp(source, ctmp, CIPHERTEXT_LENGTH); +#if 0 + { + char ctmp[CIPHERTEXT_LENGTH + 1]; + sprintf(ctmp, "%08x%08x", nr & (((ARCH_WORD_32)1 << 31) - 1), nr2 & (((ARCH_WORD_32)1 << 31) - 1)); + return !memcmp(source, ctmp, CIPHERTEXT_LENGTH); + } +#else + { + ARCH_WORD_32 *binary = mysql_get_binary_size(source, 8); + return + binary[0] == (nr & (((ARCH_WORD_32)1 << 31) - 1)) && + binary[1] == (nr2 & (((ARCH_WORD_32)1 << 31) - 1)); + } +#endif } static void mysql_crypt_all(int count) { - unsigned long nr, add; - unsigned long tmp; - unsigned int i; - char* password; + int i; - for (i = 0; i < count; i++) - { - nr=1345345333L; - add=7; - - password = saved_key[i]; - for (; *password; password++) - { - if (*password == ' ' || *password == '\t') - continue; - - tmp = (unsigned long) (unsigned char) *password; - nr ^= (((nr & 63) + add) * tmp) + (nr << 8); - add += tmp; +#ifdef _OPENMP +#pragma omp parallel for default(none) private(i) shared(count, saved_key, crypt_key) +#endif + for (i = 0; i < count; i++) { + unsigned char *p = (unsigned char *)saved_key[i]; + if (*p) { + ARCH_WORD_32 nr, add; + ARCH_WORD_32 tmp; + while (*p == ' ' || *p == '\t') + p++; + tmp = (ARCH_WORD_32) (unsigned char) *p++; + nr = 1345345333 ^ ((((1345345333 & 63) + 7) * tmp) + (1345345333 << 8)); + add = 7 + tmp; + for (; *p; p++) { + if (*p == ' ' || *p == '\t') + continue; + tmp = (ARCH_WORD_32) (unsigned char) *p; + nr ^= (((nr & 63) + add) * tmp) + (nr << 8); + add += tmp; + } + crypt_key[i][0] = (nr & (((ARCH_WORD_32)1 << 31) - 1)); + continue; } - - crypt_key[i][0] = (nr & (((ARCH_WORD_32)1 << 31) - 1)); + crypt_key[i][0] = (1345345333 & (((ARCH_WORD_32)1 << 31) - 1)); } } @@ -201,6 +255,16 @@ int mysql_binary_hash_4(void *binary) return *(ARCH_WORD_32 *)binary & 0xFFFFF; } +int mysql_binary_hash_5(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0xFFFFFF; +} + +int mysql_binary_hash_6(void *binary) +{ + return *(ARCH_WORD_32 *)binary & 0x7FFFFFF; +} + int mysql_get_hash_0(int index) { return crypt_key[index][0] & 0xF; @@ -226,6 +290,16 @@ int mysql_get_hash_4(int index) return crypt_key[index][0] & 0xFFFFF; } +int mysql_get_hash_5(int index) +{ + return crypt_key[index][0] & 0xFFFFFF; +} + +int mysql_get_hash_6(int index) +{ + return crypt_key[index][0] & 0x7FFFFFF; +} + struct fmt_main fmt_MYSQL_fast = { { @@ -239,13 +313,13 @@ struct fmt_main fmt_MYSQL_fast = SALT_SIZE, MIN_KEYS_PER_CRYPT, MAX_KEYS_PER_CRYPT, - FMT_CASE | FMT_8_BIT, + FMT_CASE | FMT_8_BIT | FMT_SPLIT_UNIFIES_CASE | FMT_OMP, mysql_tests }, { - fmt_default_init, + mysql_init, fmt_default_prepare, mysql_valid, - fmt_default_split, + mysql_split, mysql_get_binary, fmt_default_salt, { @@ -253,7 +327,9 @@ struct fmt_main fmt_MYSQL_fast = mysql_binary_hash_1, mysql_binary_hash_2, mysql_binary_hash_3, - mysql_binary_hash_4 + mysql_binary_hash_4, + mysql_binary_hash_5, + mysql_binary_hash_6 }, fmt_default_salt_hash, fmt_default_set_salt, @@ -266,7 +342,9 @@ struct fmt_main fmt_MYSQL_fast = mysql_get_hash_1, mysql_get_hash_2, mysql_get_hash_3, - mysql_get_hash_4 + mysql_get_hash_4, + mysql_get_hash_5, + mysql_get_hash_6 }, mysql_cmp_all, mysql_cmp_one,