From 21d8a81f52c278d86b20710616438c896275bc51 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Sat, 12 Nov 2011 02:13:52 +0100
Subject: [PATCH] j8: intrinsics for mssql formats

---
 src/mssql-old_fmt_plug.c |  228 +++++++++++++++++++++++----------
 src/mssql05_fmt_plug.c   |  316 +++++++++++++++++++++++++++-------------------
 2 files changed, 349 insertions(+), 195 deletions(-)

diff --git a/src/mssql-old_fmt_plug.c b/src/mssql-old_fmt_plug.c
index 3fd3191..6462c99 100644
--- a/src/mssql-old_fmt_plug.c
+++ b/src/mssql-old_fmt_plug.c
@@ -2,7 +2,7 @@
  * This software is Copyright © 2004 bartavelle, <bartavelle at bandecon.com>, and it is hereby released to the general public under the following terms:
  * Redistribution and use in source and binary forms, with or without modification, are permitted.
  *
- * UTF-8 support by magnum 2011, no rights reserved
+ * UTF-8 support and use of intrinsics by magnum 2011, no rights reserved
  *
  * microsoft MS SQL cracker
  *
@@ -11,6 +11,15 @@
 #include <string.h>
 
 #include "arch.h"
+
+#ifdef SHA1_SSE_PARA
+#define MMX_COEF	4
+#include "sse-intrinsics.h"
+#define NBKEYS	(MMX_COEF * SHA1_SSE_PARA)
+#elif MMX_COEF
+#define NBKEYS	MMX_COEF
+#endif
+
 #include "misc.h"
 #include "params.h"
 #include "common.h"
@@ -19,18 +28,19 @@
 #include "unicode.h"
 #include "sha.h"
 
-//#define MSSQL_DEBUG
-
 #define FORMAT_LABEL			"mssql"
 #define FORMAT_NAME			"MS-SQL"
-#ifdef MMX_COEF
-#if (MMX_COEF == 2)
-#define ALGORITHM_NAME			"mssql MMX"
-#else
-#define ALGORITHM_NAME			"mssql SSE2"
-#endif
+
+#ifdef SHA1_N_STR
+#define ALGORITHM_NAME			"SSE2i " SHA1_N_STR
+#elif defined(MMX_COEF) && MMX_COEF == 4
+#define ALGORITHM_NAME			"SSE2 4x"
+#elif defined(MMX_COEF) && MMX_COEF == 2
+#define ALGORITHM_NAME			"MMX 2x"
+#elif defined(MMX_COEF)
+#define ALGORITHM_NAME			"?"
 #else
-#define ALGORITHM_NAME			"mssql"
+#define ALGORITHM_NAME			"32/" ARCH_BITS_STR
 #endif
 
 #define BENCHMARK_COMMENT		""
@@ -43,10 +53,9 @@
 #define SALT_SIZE			4
 
 #ifdef MMX_COEF
-#define MIN_KEYS_PER_CRYPT		MMX_COEF
-#define MAX_KEYS_PER_CRYPT		MMX_COEF
-//#define GETPOS(i, index)		( (index)*4 + ((i)& (0xffffffff-3) )*MMX_COEF + ((i)&3) ) //std getpos
-#define GETPOS(i, index)		( (index)*4 + ((i)& (0xffffffff-3) )*MMX_COEF + (3-((i)&3)) ) //for endianity conversion
+#define MIN_KEYS_PER_CRYPT		NBKEYS
+#define MAX_KEYS_PER_CRYPT		NBKEYS
+#define GETPOS(i, index)		( (index&(MMX_COEF-1))*4 + ((i)&(0xffffffff-3))*MMX_COEF + (3-((i)&3)) + (index>>(MMX_COEF>>1))*80*MMX_COEF*4 ) //for endianity conversion
 #if (MMX_COEF==2)
 #define SALT_EXTRA_LEN          0x40004
 #else
@@ -66,7 +75,7 @@
 #define ENDIAN_SHIFT_R  >> 8
 #endif
 
-static struct fmt_tests mssql_tests[] = {
+static struct fmt_tests tests[] = {
 	{"0x0100A607BA7C54A24D17B565C59F1743776A10250F581D482DA8B6D6261460D3F53B279CC6913CE747006A2E3254", "FOO"},
 	{"0x01000508513EADDF6DB7DDD270CCA288BF097F2FF69CC2DB74FBB9644D6901764F999BAB9ECB80DE578D92E3F80D", "BAR"},
 	{"0x01008408C523CF06DCB237835D701C165E68F9460580132E28ED8BC558D22CEDF8801F4503468A80F9C52A12C0A3", "CANARD"},
@@ -77,18 +86,20 @@ static struct fmt_tests mssql_tests[] = {
 static unsigned char cursalt[SALT_SIZE];
 
 #ifdef MMX_COEF
+#ifdef _MSC_VER
 /* Cygwin would not guarantee the alignment if these were declared static */
 #define saved_key mssql_saved_key
 #define crypt_key mssql_crypt_key
-#ifdef _MSC_VER
-__declspec(align(16)) char saved_key[80*4*MMX_COEF];
-__declspec(align(16)) char crypt_key[BINARY_SIZE*MMX_COEF];
+__declspec(align(16)) char saved_key[80*4*NBKEYS];
+__declspec(align(16)) char crypt_key[BINARY_SIZE*NBKEYS];
 #else
-char saved_key[80*4*MMX_COEF] __attribute__ ((aligned(16)));
-char crypt_key[BINARY_SIZE*MMX_COEF] __attribute__ ((aligned(16)));
+static char saved_key[80*4*NBKEYS] __attribute__ ((aligned(16)));
+static char crypt_key[BINARY_SIZE*NBKEYS] __attribute__ ((aligned(16)));
 #endif
+#ifndef SHA1_SSE_PARA
 static unsigned long total_len;
-static char plain_keys[MMX_COEF][PLAINTEXT_LENGTH*3+1];
+#endif
+static char plain_keys[NBKEYS][PLAINTEXT_LENGTH*3+1];
 #else
 
 static unsigned char *saved_key;
@@ -114,12 +125,12 @@ static int valid(char *ciphertext, struct fmt_main *pFmt)
 	return 1;
 }
 
-static void mssql_set_salt(void *salt)
+static void set_salt(void *salt)
 {
 	memcpy(cursalt, salt, SALT_SIZE);
 }
 
-static void * mssql_get_salt(char * ciphertext)
+static void * get_salt(char * ciphertext)
 {
 	static unsigned char *out2;
 	int l;
@@ -135,10 +146,10 @@ static void * mssql_get_salt(char * ciphertext)
 	return out2;
 }
 
-static void mssql_set_key_enc(char *_key, int index);
+static void set_key_enc(char *_key, int index);
 extern struct fmt_main fmt_mssql;
 
-static void mssql_init(struct fmt_main *pFmt)
+static void init(struct fmt_main *pFmt)
 {
 	initUnicode(UNICODE_MS_OLD);
 #ifdef MMX_COEF
@@ -147,7 +158,7 @@ static void mssql_init(struct fmt_main *pFmt)
 	saved_key = mem_alloc_tiny(PLAINTEXT_LENGTH*2 + 1 + SALT_SIZE, MEM_ALIGN_WORD);
 #endif
 	if (options.utf8) {
-		fmt_mssql.methods.set_key = mssql_set_key_enc;
+		fmt_mssql.methods.set_key = set_key_enc;
 		fmt_mssql.params.plaintext_length = PLAINTEXT_LENGTH * 3;
 	}
 	else if (options.iso8859_1 || options.ascii) {
@@ -155,11 +166,11 @@ static void mssql_init(struct fmt_main *pFmt)
 	}
 	else {
 		// this function made to handle both utf8 and 'codepage' encodings.
-		fmt_mssql.methods.set_key = mssql_set_key_enc;
+		fmt_mssql.methods.set_key = set_key_enc;
 	}
 }
 
-static void mssql_set_key(char *key, int index) {
+static void set_key(char *key, int index) {
 	UTF8 utf8[PLAINTEXT_LENGTH+1];
 	int utf8len, orig_len;
 #ifdef MMX_COEF
@@ -176,11 +187,20 @@ static void mssql_set_key(char *key, int index) {
 #ifdef MMX_COEF
 	if(index==0)
 	{
-		total_len = 0;
+#ifdef SHA1_SSE_PARA
+		int j;
+		for (j=0; j<SHA1_SSE_PARA; j++)
+			memset(saved_key+j*4*80*MMX_COEF, 0, 60*MMX_COEF);
+#else
 		memset(saved_key, 0, 64*MMX_COEF);
+		total_len = 0;
+#endif
 	}
-
+#ifdef SHA1_SSE_PARA
+	((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF] = (2*utf8len+SALT_SIZE)<<3;
+#else
 	total_len += (utf8len*2) << ( ( (32/MMX_COEF) * index ) );
+#endif
 	for(i=0;i<utf8len;i++)
 		saved_key[GETPOS((i*2), index)] = utf8[i];
 	saved_key[GETPOS((i*2+SALT_SIZE) , index)] = 0x80;
@@ -189,16 +209,10 @@ static void mssql_set_key(char *key, int index) {
 
 	while( (((unsigned short *)saved_key)[key_length] = (utf8[key_length] ENDIAN_SHIFT_L ))  )
 		key_length++;
-
-#ifdef MSSQL_DEBUG
-	printf ("key_len=%d ", key_length);
-	dump_stuff(saved_key, key_length<<1);
-#endif
-
 #endif
 }
 
-static void mssql_set_key_enc(char *key, int index) {
+static void set_key_enc(char *key, int index) {
 	UTF16 utf16key[PLAINTEXT_LENGTH+1], utf16key_tmp[PLAINTEXT_LENGTH+1];
 	int utf8len = strlen(key);
 	int i;
@@ -222,22 +236,27 @@ static void mssql_set_key_enc(char *key, int index) {
 #ifdef MMX_COEF
 	if(index==0)
 	{
-		total_len = 0;
+#ifdef SHA1_SSE_PARA
+		int j;
+		for (j=0; j<SHA1_SSE_PARA; j++)
+			memset(saved_key+j*4*80*MMX_COEF, 0, 60*MMX_COEF);
+#else
 		memset(saved_key, 0, 64*MMX_COEF);
+		total_len = 0;
+#endif
 	}
 
+#ifdef SHA1_SSE_PARA
+	((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF] = (2*utf16len+SALT_SIZE)<<3;
+#else
 	total_len += (utf16len*2) << ( ( (32/MMX_COEF) * index ) );
+#endif
 	for(i=0;i<utf16len;i++)
 	{
 		saved_key[GETPOS((i*2), index)] = (char)utf16key[i];
 		saved_key[GETPOS((i*2+1), index)] = (char)(utf16key[i]>>8);
 	}
 	saved_key[GETPOS((i*2+SALT_SIZE) , index)] = 0x80;
-#ifdef MSSQL_DEBUG
-	printf ("utf16len=%d ", utf16len);
-	dump_stuff_mmx(saved_key, utf16len<<1, index);
-#endif
-
 #else
 	for(i=0;i<utf16len;i++)
 	{
@@ -251,16 +270,10 @@ static void mssql_set_key_enc(char *key, int index) {
 #endif
 	}
 	key_length = i;
-
-#ifdef MSSQL_DEBUG
-	printf ("keylen8=%d ", key_length);
-	dump_stuff(saved_key, key_length<<1);
-#endif
-
 #endif
 }
 
-static char *mssql_get_key(int index) {
+static char *get_key(int index) {
 	static UTF8 UC_Key[PLAINTEXT_LENGTH*3*3+1];
 	// Calling this will ONLY upcase characters 'valid' in the code page. There are MANY
 	// code pages which mssql WILL upcase the letter (in UCS-2), but there is no upper case value
@@ -269,8 +282,19 @@ static char *mssql_get_key(int index) {
 	return (char*)UC_Key;
 }
 
-static int mssql_cmp_all(void *binary, int count) {
+static int cmp_all(void *binary, int count) {
 #ifdef MMX_COEF
+#ifdef SHA1_SSE_PARA
+	unsigned int x,y=0;
+
+	for(;y<SHA1_SSE_PARA;y++)
+	for(x=0;x<MMX_COEF;x++)
+	{
+		if( ((unsigned int *)binary)[0] == ((unsigned int *)crypt_key)[x+y*MMX_COEF*5] )
+			return 1;
+	}
+	return 0;
+#else
 	int i=0;
 	while(i< (BINARY_SIZE/4) )
 	{
@@ -286,39 +310,65 @@ static int mssql_cmp_all(void *binary, int count) {
 		i++;
 	}
 	return 1;
+#endif
 #else
 	return !memcmp(binary, crypt_key, BINARY_SIZE);
 #endif
 }
 
-static int mssql_cmp_exact(char *source, int count){
+static int cmp_exact(char *source, int count){
   return (1);
 }
 
-static int mssql_cmp_one(void * binary, int index)
+static int cmp_one(void * binary, int index)
 {
 #ifdef MMX_COEF
+#if SHA1_SSE_PARA
+	unsigned int x,y;
+	x = index&3;
+	y = index/4;
+
+	if( ((unsigned int *)binary)[0] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5] )
+		return 0;
+	if( ((unsigned int *)binary)[1] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+4] )
+		return 0;
+	if( ((unsigned int *)binary)[2] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+8] )
+		return 0;
+	if( ((unsigned int *)binary)[3] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+12] )
+		return 0;
+	if( ((unsigned int *)binary)[4] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+16] )
+		return 0;
+	return 1;
+#else
 	int i = 0;
 	for(i=0;i<(BINARY_SIZE/4);i++)
 		if ( ((unsigned long *)binary)[i] != ((unsigned long *)crypt_key)[i*MMX_COEF+index] )
 			return 0;
 	return 1;
+#endif
 #else
-	return mssql_cmp_all(binary, index);
+	return cmp_all(binary, index);
 #endif
 }
 
-static void mssql_crypt_all(int count) {
-  // get plaintext input in saved_key put it into ciphertext crypt_key
+static void crypt_all(int count) {
 #ifdef MMX_COEF
 	unsigned i, index;
 	for (index = 0; index < count; ++index)
 	{
+#ifdef SHA1_SSE_PARA
+		unsigned len = (((((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF]) >> 3) & 0xff) - SALT_SIZE;
+#else
 		unsigned len = (total_len >> ((32/MMX_COEF)*index)) & 0xFF;
+#endif
 		for(i=0;i<SALT_SIZE;i++)
 			saved_key[GETPOS((len+i), index)] = cursalt[i];
 	}
+#ifdef SHA1_SSE_PARA
+	SSESHA1body(saved_key, (unsigned int *)crypt_key, NULL, 0);
+#else
 	shammx( (unsigned char *) crypt_key, (unsigned char *) saved_key, total_len + SALT_EXTRA_LEN);
+#endif
 #else
 	SHA_CTX ctx;
 	memcpy(saved_key+key_length*2, cursalt, SALT_SIZE);
@@ -329,16 +379,20 @@ static void mssql_crypt_all(int count) {
 
 }
 
-static void * mssql_binary(char *ciphertext)
+static void * binary(char *ciphertext)
 {
 	static char *realcipher;
 	int i;
+
 	if(!realcipher) realcipher = mem_alloc_tiny(BINARY_SIZE, MEM_ALIGN_WORD);
 
 	for(i=0;i<BINARY_SIZE;i++)
 	{
 		realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2+54])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+55])];
 	}
+#ifdef SHA1_SSE_PARA
+	alter_endianity((unsigned char *)realcipher, BINARY_SIZE);
+#endif
 	return (void *)realcipher;
 }
 
@@ -367,6 +421,43 @@ static int binary_hash_4(void *binary)
 	return ((ARCH_WORD_32 *)binary)[0] & 0xFFFFF;
 }
 
+#ifdef SHA1_SSE_PARA
+static int get_hash_0(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xf;
+}
+static int get_hash_1(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xff;
+}
+static int get_hash_2(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xfff;
+}
+static int get_hash_3(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xffff;
+}
+static int get_hash_4(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xfffff;
+}
+#else
 static int get_hash_0(int index)
 {
 	return ((ARCH_WORD_32 *)crypt_key)[index] & 0xF;
@@ -391,6 +482,7 @@ static int get_hash_4(int index)
 {
 	return ((ARCH_WORD_32 *)crypt_key)[index] & 0xFFFFF;
 }
+#endif
 
 static int salt_hash(void *salt)
 {
@@ -411,14 +503,14 @@ struct fmt_main fmt_mssql = {
 		MIN_KEYS_PER_CRYPT,
 		MAX_KEYS_PER_CRYPT,
 		FMT_8_BIT | FMT_UNICODE | FMT_UTF8,
-		mssql_tests
+		tests
 	}, {
-		mssql_init,
+		init,
 		fmt_default_prepare,
 		valid,
 		fmt_default_split,
-		mssql_binary,
-		mssql_get_salt,
+		binary,
+		get_salt,
 		{
 			binary_hash_0,
 			binary_hash_1,
@@ -427,11 +519,11 @@ struct fmt_main fmt_mssql = {
 			binary_hash_4
 		},
 		salt_hash,
-		mssql_set_salt,
-		mssql_set_key,
-		mssql_get_key,
+		set_salt,
+		set_key,
+		get_key,
 		fmt_default_clear_keys,
-		mssql_crypt_all,
+		crypt_all,
 		{
 			get_hash_0,
 			get_hash_1,
@@ -439,8 +531,8 @@ struct fmt_main fmt_mssql = {
 			get_hash_3,
 			get_hash_4
 		},
-		mssql_cmp_all,
-		mssql_cmp_one,
-		mssql_cmp_exact
+		cmp_all,
+		cmp_one,
+		cmp_exact
 	}
 };
diff --git a/src/mssql05_fmt_plug.c b/src/mssql05_fmt_plug.c
index 4aecc24..5d1c591 100644
--- a/src/mssql05_fmt_plug.c
+++ b/src/mssql05_fmt_plug.c
@@ -5,13 +5,22 @@
  * Modified by Mathieu Perrin (mathieu at tpfh.org) 09/06
  * Microsoft MS-SQL05 password cracker
  *
- * UTF-8 support by magnum 2011, no rights reserved
+ * UTF-8 support and use of intrinsics by magnum 2011, no rights reserved
  *
  */
 
 #include <string.h>
 
 #include "arch.h"
+
+#ifdef SHA1_SSE_PARA
+#define MMX_COEF	4
+#include "sse-intrinsics.h"
+#define NBKEYS	(MMX_COEF * SHA1_SSE_PARA)
+#elif MMX_COEF
+#define NBKEYS	MMX_COEF
+#endif
+
 #include "misc.h"
 #include "params.h"
 #include "common.h"
@@ -22,14 +31,17 @@
 
 #define FORMAT_LABEL			"mssql05"
 #define FORMAT_NAME			"MS-SQL05"
-#ifdef MMX_COEF
-#if (MMX_COEF == 2)
-#define ALGORITHM_NAME			"ms-sql05 MMX"
-#else
-#define ALGORITHM_NAME			"ms-sql05 SSE2"
-#endif
+
+#ifdef SHA1_N_STR
+#define ALGORITHM_NAME			"SSE2i " SHA1_N_STR
+#elif defined(MMX_COEF) && MMX_COEF == 4
+#define ALGORITHM_NAME			"SSE2 4x"
+#elif defined(MMX_COEF) && MMX_COEF == 2
+#define ALGORITHM_NAME			"MMX 2x"
+#elif defined(MMX_COEF)
+#define ALGORITHM_NAME			"?"
 #else
-#define ALGORITHM_NAME			"ms-sql05"
+#define ALGORITHM_NAME			"32/" ARCH_BITS_STR
 #endif
 
 #define BENCHMARK_COMMENT		""
@@ -42,10 +54,9 @@
 #define SALT_SIZE			4
 
 #ifdef MMX_COEF
-#define MIN_KEYS_PER_CRYPT		MMX_COEF
-#define MAX_KEYS_PER_CRYPT		MMX_COEF
-//#define GETPOS(i, index)		( (index)*4 + ((i)& (0xffffffff-3) )*MMX_COEF + ((i)&3) ) //std getpos
-#define GETPOS(i, index)		( (index)*4 + ((i)& (0xffffffff-3) )*MMX_COEF + (3-((i)&3)) ) //for endianity conversion
+#define MIN_KEYS_PER_CRYPT		NBKEYS
+#define MAX_KEYS_PER_CRYPT		NBKEYS
+#define GETPOS(i, index)		( (index&(MMX_COEF-1))*4 + ((i)&(0xffffffff-3))*MMX_COEF + (3-((i)&3)) + (index>>(MMX_COEF>>1))*80*MMX_COEF*4 ) //for endianity conversion
 #if (MMX_COEF==2)
 #define SALT_EXTRA_LEN          0x40004
 #else
@@ -65,7 +76,7 @@
 #define ENDIAN_SHIFT_R  >> 8
 #endif
 
-static struct fmt_tests mssql05_tests[] = {
+static struct fmt_tests tests[] = {
 	{"0x01004086CEB6BF932BC4151A1AF1F13CD17301D70816A8886908", "toto"},
 	{"0x01004086CEB60ED526885801C23B366965586A43D3DEAC6DD3FD", "titi"},
 	{"0x0100A607BA7C54A24D17B565C59F1743776A10250F581D482DA8B6D6261460D3F53B279CC6913CE747006A2E3254", "foo",    {"User1"} },
@@ -78,24 +89,27 @@ static struct fmt_tests mssql05_tests[] = {
 static unsigned char cursalt[SALT_SIZE];
 
 #ifdef MMX_COEF
+#ifdef _MSC_VER
 /* Cygwin would not guarantee the alignment if these were declared static */
 #define saved_key mssql05_saved_key
 #define crypt_key mssql05_crypt_key
-#ifdef _MSC_VER
-__declspec(align(16)) char saved_key[80*4*MMX_COEF];
-__declspec(align(16)) char crypt_key[BINARY_SIZE*MMX_COEF];
+__declspec(align(16)) char saved_key[80*4*NBKEYS];
+__declspec(align(16)) char crypt_key[BINARY_SIZE*NBKEYS];
 #else
-char saved_key[80*4*MMX_COEF] __attribute__ ((aligned(16)));
-char crypt_key[BINARY_SIZE*MMX_COEF] __attribute__ ((aligned(16)));
+static char saved_key[80*4*NBKEYS] __attribute__ ((aligned(16)));
+static char crypt_key[BINARY_SIZE*NBKEYS] __attribute__ ((aligned(16)));
 #endif
+#ifndef SHA1_SSE_PARA
 static unsigned long total_len;
-static unsigned char saved_plain[MMX_COEF][PLAINTEXT_LENGTH*3+1];
+#endif
+static char plain_keys[NBKEYS][PLAINTEXT_LENGTH*3+1];
 #else
 
 static unsigned char *saved_key;
-static unsigned char saved_plain[PLAINTEXT_LENGTH*3 + 1];
 static ARCH_WORD_32 crypt_key[BINARY_SIZE / 4];
 static unsigned int key_length;
+static char *plain_keys[1];
+
 #endif
 
 static int valid(char *ciphertext, struct fmt_main *pFmt)
@@ -135,12 +149,12 @@ static char *prepare(char *split_fields[10], struct fmt_main *pFmt)
 	return split_fields[1];
 }
 
-static void mssql05_set_salt(void *salt)
+static void set_salt(void *salt)
 {
 	memcpy(cursalt, salt, SALT_SIZE);
 }
 
-static void * mssql05_get_salt(char * ciphertext)
+static void * get_salt(char * ciphertext)
 {
 	static unsigned char *out2;
 	int l;
@@ -156,160 +170,143 @@ static void * mssql05_get_salt(char * ciphertext)
 	return out2;
 }
 
-static void mssql05_set_key_utf8(char *_key, int index);
-static void mssql05_set_key_encoding(char *key, int index);
+static void set_key_enc(char *_key, int index);
 extern struct fmt_main fmt_mssql05;
 
-static void mssql05_init(struct fmt_main *pFmt)
+static void init(struct fmt_main *pFmt)
 {
 #ifdef MMX_COEF
 	memset(saved_key, 0, sizeof(saved_key));
 #else
-	saved_key = mem_alloc_tiny(PLAINTEXT_LENGTH*3 + 1 + SALT_SIZE, MEM_ALIGN_WORD);
+	saved_key = mem_alloc_tiny(PLAINTEXT_LENGTH*2 + 1 + SALT_SIZE, MEM_ALIGN_WORD);
 #endif
 	if (options.utf8) {
-		fmt_mssql05.methods.set_key = mssql05_set_key_utf8;
+		fmt_mssql05.methods.set_key = set_key_enc;
 		fmt_mssql05.params.plaintext_length = PLAINTEXT_LENGTH * 3;
 	}
 	else if (options.iso8859_1 || options.ascii) {
 		; // do nothing
 	}
 	else {
-		fmt_mssql05.methods.set_key = mssql05_set_key_encoding;
+		// this function made to handle both utf8 and 'codepage' encodings.
+		fmt_mssql05.methods.set_key = set_key_enc;
 	}
 }
 
-static void mssql05_set_key(char *key, int index) {
-#ifdef MMX_COEF
+static void set_key(char *_key, int index) {
+	unsigned char *key = (unsigned char*)_key;
 	int len;
+#ifdef MMX_COEF
 	int i;
+	strnzcpy(plain_keys[index], _key, PLAINTEXT_LENGTH);
+#else
+	plain_keys[index] = key;
+#endif
+	len = strlen(_key);
 
+#ifdef MMX_COEF
 	if(index==0)
 	{
-		total_len = 0;
+#ifdef SHA1_SSE_PARA
+		int j;
+		for (j=0; j<SHA1_SSE_PARA; j++)
+			memset(saved_key+j*4*80*MMX_COEF, 0, 60*MMX_COEF);
+#else
 		memset(saved_key, 0, 64*MMX_COEF);
+		total_len = 0;
+#endif
 	}
-	len = strlen(key);
-	if(len>PLAINTEXT_LENGTH)
-		len = PLAINTEXT_LENGTH;
-
+#ifdef SHA1_SSE_PARA
+	((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF] = (2*len+SALT_SIZE)<<3;
+#else
 	total_len += (len*2) << ( ( (32/MMX_COEF) * index ) );
+#endif
 	for(i=0;i<len;i++)
-	{
-		saved_key[GETPOS((i*2), index)] = saved_plain[index][i] = key[i];
-//		saved_key[GETPOS((i*2+1), index)] = 0;
-	}
+		saved_key[GETPOS((i*2), index)] = key[i];
 	saved_key[GETPOS((i*2+SALT_SIZE) , index)] = 0x80;
-	saved_plain[index][i] = 0;
 #else
 	key_length = 0;
-	while( (((unsigned short *)saved_key)[key_length] = (saved_plain[key_length] = key[key_length]) ENDIAN_SHIFT_L ))
+
+	while( (((unsigned short *)saved_key)[key_length] = (key[key_length] ENDIAN_SHIFT_L ))  )
 		key_length++;
 #endif
 }
 
-static void mssql05_set_key_utf8(char *_key, int index) {
-	unsigned char *key = (unsigned char*)_key;
-	int utf8len = strlen(_key);
-	int i;
+static void set_key_enc(char *key, int index) {
 	UTF16 utf16key[PLAINTEXT_LENGTH+1];
-	int utf16len = utf8_to_utf16(utf16key, PLAINTEXT_LENGTH, key, utf8len);
-	if (utf16len <= 0) {
-		utf8len = -utf16len;
-		if (utf16len != 0)
-			utf16len = strlen16(utf16key);
-	}
-#ifdef MMX_COEF
-	if(index==0)
-	{
-		total_len = 0;
-		memset(saved_key, 0, 64*MMX_COEF);
-	}
+	int utf8len = strlen(key);
+	int i;
+	int utf16len;
 
-	total_len += (utf16len*2) << ( ( (32/MMX_COEF) * index ) );
-	for(i=0;i<utf16len;i++)
-	{
-		saved_key[GETPOS((i*2), index)] = (char)utf16key[i];
-		saved_key[GETPOS((i*2+1), index)] = (char)(utf16key[i]>>8);
-	}
-	saved_key[GETPOS((i*2+SALT_SIZE) , index)] = 0x80;
-	for(i=0;i<utf8len;i++)
-		saved_plain[index][i] = key[i];
-	saved_plain[index][i] = 0;
-#else
-	for(i=0;i<utf16len;i++)
-	{
-#if ARCH_LITTLE_ENDIAN
-		saved_key[i*2] = (char)utf16key[i];
-		saved_key[i*2+1] = (char)(utf16key[i]>>8);
+#ifdef MMX_COEF
+	strnzcpy(plain_keys[index], key, PLAINTEXT_LENGTH*3);
 #else
-		saved_key[i*2+1] = (char)utf16key[i];
-		saved_key[i*2] = (char)(utf16key[i]>>8);
+	plain_keys[index] = key;
 #endif
-	}
-	key_length = i;
-	for(i=0;i<utf8len;i++)
-		saved_plain[i] = key[i];
-	saved_plain[i] = 0;
-#endif
-}
-
-static void mssql05_set_key_encoding(char *_key, int index) {
-	unsigned char *key = (unsigned char*)_key;
-	int utf8len = strlen(_key);
-	int i;
-	UTF16 utf16key[PLAINTEXT_LENGTH+1];
-	int utf16len = enc_to_utf16(utf16key, PLAINTEXT_LENGTH, key, utf8len);
+	utf16len = enc_to_utf16(utf16key, PLAINTEXT_LENGTH, (unsigned char*)key, utf8len);
 	if (utf16len <= 0) {
 		utf8len = -utf16len;
 		if (utf16len != 0)
 			utf16len = strlen16(utf16key);
 	}
+
 #ifdef MMX_COEF
 	if(index==0)
 	{
-		total_len = 0;
+#ifdef SHA1_SSE_PARA
+		int j;
+		for (j=0; j<SHA1_SSE_PARA; j++)
+			memset(saved_key+j*4*80*MMX_COEF, 0, 60*MMX_COEF);
+#else
 		memset(saved_key, 0, 64*MMX_COEF);
+		total_len = 0;
+#endif
 	}
 
+#ifdef SHA1_SSE_PARA
+	((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF] = (2*utf16len+SALT_SIZE)<<3;
+#else
 	total_len += (utf16len*2) << ( ( (32/MMX_COEF) * index ) );
+#endif
 	for(i=0;i<utf16len;i++)
 	{
 		saved_key[GETPOS((i*2), index)] = (char)utf16key[i];
 		saved_key[GETPOS((i*2+1), index)] = (char)(utf16key[i]>>8);
 	}
 	saved_key[GETPOS((i*2+SALT_SIZE) , index)] = 0x80;
-	for(i=0;i<utf8len;i++)
-		saved_plain[index][i] = key[i];
-	saved_plain[index][i] = 0;
 #else
 	for(i=0;i<utf16len;i++)
 	{
+		unsigned char *uc = (unsigned char*)&(utf16key[i]);
 #if ARCH_LITTLE_ENDIAN
-		saved_key[i*2] = (char)utf16key[i];
-		saved_key[i*2+1] = (char)(utf16key[i]>>8);
+		saved_key[(i<<1)  ] = uc[0];
+		saved_key[(i<<1)+1] = uc[1];
 #else
-		saved_key[i*2+1] = (char)utf16key[i];
-		saved_key[i*2] = (char)(utf16key[i]>>8);
+		saved_key[(i<<1)  ] = uc[1];
+		saved_key[(i<<1)+1] = uc[0];
 #endif
 	}
 	key_length = i;
-	for(i=0;i<utf8len;i++)
-		saved_plain[i] = key[i];
-	saved_plain[i] = 0;
 #endif
 }
 
-static char *mssql05_get_key(int index) {
-#ifdef MMX_COEF
-	return (char*) saved_plain[index];
-#else
-	return (char*) saved_plain;
-#endif
+static char *get_key(int index) {
+	return (char*) plain_keys[index];
 }
 
-static int mssql05_cmp_all(void *binary, int cound) {
+static int cmp_all(void *binary, int count) {
 #ifdef MMX_COEF
+#ifdef SHA1_SSE_PARA
+	unsigned int x,y=0;
+
+	for(;y<SHA1_SSE_PARA;y++)
+	for(x=0;x<MMX_COEF;x++)
+	{
+		if( ((unsigned int *)binary)[0] == ((unsigned int *)crypt_key)[x+y*MMX_COEF*5] )
+			return 1;
+	}
+	return 0;
+#else
 	int i=0;
 	while(i< (BINARY_SIZE/4) )
 	{
@@ -325,52 +322,76 @@ static int mssql05_cmp_all(void *binary, int cound) {
 		i++;
 	}
 	return 1;
+#endif
 #else
 	return !memcmp(binary, crypt_key, BINARY_SIZE);
 #endif
 }
 
-static int mssql05_cmp_exact(char *source, int count){
+static int cmp_exact(char *source, int count){
   return (1);
 }
 
-static int mssql05_cmp_one(void * binary, int index)
+static int cmp_one(void * binary, int index)
 {
 #ifdef MMX_COEF
+#if SHA1_SSE_PARA
+	unsigned int x,y;
+	x = index&3;
+	y = index/4;
+
+	if( ((unsigned int *)binary)[0] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5] )
+		return 0;
+	if( ((unsigned int *)binary)[1] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+4] )
+		return 0;
+	if( ((unsigned int *)binary)[2] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+8] )
+		return 0;
+	if( ((unsigned int *)binary)[3] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+12] )
+		return 0;
+	if( ((unsigned int *)binary)[4] != ((unsigned int *)crypt_key)[x+y*MMX_COEF*5+16] )
+		return 0;
+	return 1;
+#else
 	int i = 0;
 	for(i=0;i<(BINARY_SIZE/4);i++)
 		if ( ((unsigned long *)binary)[i] != ((unsigned long *)crypt_key)[i*MMX_COEF+index] )
 			return 0;
 	return 1;
+#endif
 #else
-	return mssql05_cmp_all(binary, index);
+	return cmp_all(binary, index);
 #endif
 }
 
-static void mssql05_crypt_all(int count) {
-  // get plaintext input in saved_key put it into ciphertext crypt_key
+static void crypt_all(int count) {
 #ifdef MMX_COEF
 	unsigned i, index;
 	for (index = 0; index < count; ++index)
 	{
+#ifdef SHA1_SSE_PARA
+		unsigned len = (((((unsigned int *)saved_key)[15*MMX_COEF + (index&3) + (index>>2)*80*MMX_COEF]) >> 3) & 0xff) - SALT_SIZE;
+#else
 		unsigned len = (total_len >> ((32/MMX_COEF)*index)) & 0xFF;
+#endif
 		for(i=0;i<SALT_SIZE;i++)
 			saved_key[GETPOS((len+i), index)] = cursalt[i];
 	}
-	shammx((unsigned char *) crypt_key, (unsigned char *) saved_key, total_len + SALT_EXTRA_LEN);
+#ifdef SHA1_SSE_PARA
+	SSESHA1body(saved_key, (unsigned int *)crypt_key, NULL, 0);
+#else
+	shammx( (unsigned char *) crypt_key, (unsigned char *) saved_key, total_len + SALT_EXTRA_LEN);
+#endif
 #else
 	SHA_CTX ctx;
 	memcpy(saved_key+key_length*2, cursalt, SALT_SIZE);
 	SHA1_Init( &ctx );
-//	dump_stuff_msg("setkey utf8", (unsigned char*)&saved_key[0], 20*4);
-//	exit(0);
 	SHA1_Update( &ctx, saved_key, key_length*2+SALT_SIZE );
 	SHA1_Final( (unsigned char *) crypt_key, &ctx);
 #endif
 
 }
 
-static void * mssql05_binary(char *ciphertext)
+static void * binary(char *ciphertext)
 {
 	static char *realcipher;
 	int i;
@@ -381,6 +402,9 @@ static void * mssql05_binary(char *ciphertext)
 	{
 		realcipher[i] = atoi16[ARCH_INDEX(ciphertext[i*2+14])]*16 + atoi16[ARCH_INDEX(ciphertext[i*2+15])];
 	}
+#ifdef SHA1_SSE_PARA
+	alter_endianity((unsigned char *)realcipher, BINARY_SIZE);
+#endif
 	return (void *)realcipher;
 }
 
@@ -409,6 +433,43 @@ static int binary_hash_4(void *binary)
 	return ((ARCH_WORD_32 *)binary)[0] & 0xFFFFF;
 }
 
+#ifdef SHA1_SSE_PARA
+static int get_hash_0(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xf;
+}
+static int get_hash_1(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xff;
+}
+static int get_hash_2(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xfff;
+}
+static int get_hash_3(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xffff;
+}
+static int get_hash_4(int index)
+{
+	unsigned int x,y;
+        x = index&3;
+        y = index/4;
+	return ((ARCH_WORD_32*)crypt_key)[x+y*MMX_COEF*5] & 0xfffff;
+}
+#else
 static int get_hash_0(int index)
 {
 	return ((ARCH_WORD_32 *)crypt_key)[index] & 0xF;
@@ -433,6 +494,7 @@ static int get_hash_4(int index)
 {
 	return ((ARCH_WORD_32 *)crypt_key)[index] & 0xFFFFF;
 }
+#endif
 
 static int salt_hash(void *salt)
 {
@@ -453,14 +515,14 @@ struct fmt_main fmt_mssql05 = {
 		MIN_KEYS_PER_CRYPT,
 		MAX_KEYS_PER_CRYPT,
 		FMT_CASE | FMT_8_BIT | FMT_UNICODE | FMT_UTF8,
-		mssql05_tests
+		tests
 	}, {
-		mssql05_init,
+		init,
 		prepare,
 		valid,
 		fmt_default_split,
-		mssql05_binary,
-		mssql05_get_salt,
+		binary,
+		get_salt,
 		{
 			binary_hash_0,
 			binary_hash_1,
@@ -469,11 +531,11 @@ struct fmt_main fmt_mssql05 = {
 			binary_hash_4
 		},
 		salt_hash,
-		mssql05_set_salt,
-		mssql05_set_key,
-		mssql05_get_key,
+		set_salt,
+		set_key,
+		get_key,
 		fmt_default_clear_keys,
-		mssql05_crypt_all,
+		crypt_all,
 		{
 			get_hash_0,
 			get_hash_1,
@@ -481,8 +543,8 @@ struct fmt_main fmt_mssql05 = {
 			get_hash_3,
 			get_hash_4
 		},
-		mssql05_cmp_all,
-		mssql05_cmp_one,
-		mssql05_cmp_exact
+		cmp_all,
+		cmp_one,
+		cmp_exact
 	}
 };
-- 
1.7.5.4

