From 32074d2315791ce0fd5cb6f3f531ef18bdaf2787 Mon Sep 17 00:00:00 2001
From: magnum <magnum>
Date: Sun, 24 Jul 2011 17:54:46 +0200
Subject: [PATCH 6/6] Unified get_key for NT and mscash, non-thread safe utf16toplain et al

---
 src/NT_fmt_plug.c            |   58 ++++++------------------------------------
 src/mscash1_fmt_plug.c       |   38 ++-------------------------
 src/mssql-old_fmt_plug.c     |   10 +------
 src/oracle_fmt_plug.c        |   14 +---------
 src/rawMD5unicode_fmt_plug.c |   35 +++++++------------------
 src/unicode.c                |   24 +++++++++++++---
 src/unicode.h                |    6 +++-
 7 files changed, 46 insertions(+), 139 deletions(-)

diff --git a/src/NT_fmt_plug.c b/src/NT_fmt_plug.c
index 416cbac..c22554d 100644
--- a/src/NT_fmt_plug.c
+++ b/src/NT_fmt_plug.c
@@ -219,7 +219,6 @@ static unsigned int last_i[NT_NUM_KEYS];
 #define MAX_KEYS_PER_CRYPT		NT_NUM_KEYS
 
 static void set_key_utf8(char *_key, int index);
-static char *get_key_utf8(int index);
 extern struct fmt_main fmt_NT;
 
 static void fmt_NT_init(struct fmt_main *pFmt)
@@ -236,7 +235,6 @@ static void fmt_NT_init(struct fmt_main *pFmt)
 	if (options.utf8) {
 		/* This avoids an if clause for every set_key */
 		fmt_NT.methods.set_key = set_key_utf8;
-		fmt_NT.methods.get_key = get_key_utf8;
 		/* kick it up from 27. We will 'adjust' in the setkey_utf8 function.  */
 		fmt_NT.params.plaintext_length = 3 * PLAINTEXT_LENGTH;
 		tests[1].plaintext = "\xC3\xBC";         // German u-umlaut in UTF-8
@@ -624,44 +622,6 @@ static void set_key(char *_key, int index)
 #endif
 }
 
-// We can get our key back from the key buffer instead of storing it
-// This is common code for the SSE/MMX/generic variants
-static inline char *get_key_helper(unsigned int * keybuffer, unsigned int xBuf)
-{
-	static unsigned char key[PLAINTEXT_LENGTH + 1];
-	unsigned int md4_size=0;
-	unsigned int i=0;
-
-	for(; md4_size < PLAINTEXT_LENGTH; i += xBuf, md4_size++)
-	{
-		key[md4_size] = keybuffer[i];
-		if (key[md4_size] == 0x80) {
-			key[md4_size] = 0;
-			break;
-		}
-		key[++md4_size] = keybuffer[i] >> 16;
-		if (key[md4_size] == 0x80) {
-			key[md4_size] = 0;
-			break;
-		}
-	}
-	return (char *) key;
-}
-
-static char *get_key(int index)
-{
-#if defined(NT_X86_64)
-	return get_key_helper(&nt_buffer8x[128 * (index >> 3) + index % 8], 8);
-#elif defined(NT_SSE2)
-	if(index < NT_NUM_KEYS4)
-		return get_key_helper(&nt_buffer4x[64 * (index >> 2) + index % 4], 4);
-	else
-		return get_key_helper(&nt_buffer1x[16 * (index - NT_NUM_KEYS4)], 1);
-#else
-	return get_key_helper(&nt_buffer1x[index << 4], 1);
-#endif
-}
-
 // UTF-8 conversion right into key buffer
 // This is common code for the SSE/MMX/generic variants
 static inline void set_key_helper_utf8(unsigned int * keybuffer, unsigned int xBuf,
@@ -787,7 +747,7 @@ static void set_key_utf8(char *_key, int index)
 
 // Get the key back from the key buffer, from UCS-2
 // This is common code for the SSE/MMX/generic variants
-static inline UTF16 *get_key_helper_utf8(unsigned int * keybuffer, unsigned int xBuf)
+static inline UTF16 *get_key_helper(unsigned int * keybuffer, unsigned int xBuf)
 {
 	static UTF16 key[PLAINTEXT_LENGTH + 1];
 	unsigned int md4_size=0;
@@ -809,21 +769,19 @@ static inline UTF16 *get_key_helper_utf8(unsigned int * keybuffer, unsigned int
 	return key;
 }
 
-static char *get_key_utf8(int index)
+static char *get_key(int index)
 {
-	static UTF8 ret_Key[PLAINTEXT_LENGTH*3+1];
 #if defined(NT_X86_64)
-	return (char *)utf16toutf8(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper_utf8(&nt_buffer8x[128 * (index >> 3) +
-	                                                   index % 8], 8));
+	return (char*)utf16toplain(get_key_helper(&nt_buffer8x[128 * (index >> 3) +
+	                                                index % 8], 8));
 #elif defined(NT_SSE2)
 	if(index < NT_NUM_KEYS4)
-		return (char *)utf16toutf8(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper_utf8(&nt_buffer4x[64 * (index >> 2) +
-		                                                   index % 4], 4));
+		return (char*)utf16toplain(get_key_helper(&nt_buffer4x[64 * (index >> 2) +
+		                                                index % 4], 4));
 	else
-		return (char *)utf16toutf8(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper_utf8(&nt_buffer1x[16 * (index -
-		                                                         NT_NUM_KEYS4)], 1));
+		return (char*)utf16toplain(get_key_helper(&nt_buffer1x[16 * (index - NT_NUM_KEYS4)], 1));
 #else
-	return (char *)utf16toutf8(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper_utf8(&nt_buffer1x[index << 4], 1));
+	return (char*)utf16toplain(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper(&nt_buffer1x[index << 4], 1));
 
 #endif
 }
diff --git a/src/mscash1_fmt_plug.c b/src/mscash1_fmt_plug.c
index 4552807..81914d7 100644
--- a/src/mscash1_fmt_plug.c
+++ b/src/mscash1_fmt_plug.c
@@ -94,7 +94,6 @@ static unsigned int new_key;
 #endif
 
 static void set_key_utf8(char *_key, int index);
-static char *get_key_utf8(int index);
 static void * get_salt_utf8(char *_ciphertext);
 struct fmt_main fmt_mscash;
 
@@ -119,7 +118,6 @@ static void init(struct fmt_main *pFmt)
 
 	if (options.utf8) {
 		fmt_mscash.methods.set_key = set_key_utf8;
-		fmt_mscash.methods.get_key = get_key_utf8;
 		fmt_mscash.methods.salt = get_salt_utf8;
 		fmt_mscash.params.plaintext_length = (PLAINTEXT_LENGTH * 3);
 		tests[1].ciphertext = "M$\xC3\xBC#48f84e6f73d6d5305f6558a33fa2c9bb";
@@ -638,35 +636,6 @@ static void set_key(char *_key, int index)
 //{static int i;if (++i==1)exit(0);}
 }
 
-// We can get our key back from the key buffer instead of storing it
-// This is common code for the SSE/MMX/generic variants
-static inline char *get_key_helper(unsigned int * keybuffer, unsigned int xBuf)
-{
-	static unsigned char key[PLAINTEXT_LENGTH + 1];
-	unsigned int md4_size=0;
-	unsigned int i=0;
-
-	for(; md4_size < PLAINTEXT_LENGTH; i += xBuf, md4_size++)
-	{
-		key[md4_size] = keybuffer[i];
-		if (key[md4_size] == 0x80) {
-			key[md4_size] = 0;
-			break;
-		}
-		key[++md4_size] = keybuffer[i] >> 16;
-		if (key[md4_size] == 0x80) {
-			key[md4_size] = 0;
-			break;
-		}
-	}
-	return (char *) key;
-}
-
-static char *get_key(int index)
-{
-	return get_key_helper(&ms_buffer1x[index << 4], 1);
-}
-
 // UTF-8 conversion right into key buffer
 // This is common code for the SSE/MMX/generic variants
 static inline void set_key_helper_utf8(unsigned int * keybuffer, unsigned int xBuf,
@@ -782,7 +751,7 @@ static void set_key_utf8(char *_key, int index)
 
 // Get the key back from the key buffer, from UCS-2
 // This is common code for the SSE/MMX/generic variants
-static inline UTF16 *get_key_helper_utf8(unsigned int * keybuffer, unsigned int xBuf)
+static inline UTF16 *get_key_helper(unsigned int * keybuffer, unsigned int xBuf)
 {
 	static UTF16 key[PLAINTEXT_LENGTH + 1];
 	unsigned int md4_size=0;
@@ -804,10 +773,9 @@ static inline UTF16 *get_key_helper_utf8(unsigned int * keybuffer, unsigned int
 	return key;
 }
 
-static char *get_key_utf8(int index)
+static char *get_key(int index)
 {
-	static UTF8 ret_Key[PLAINTEXT_LENGTH*3+1];
-	return (char *)utf16toutf8(ret_Key,PLAINTEXT_LENGTH*3,get_key_helper_utf8(&ms_buffer1x[index << 4], 1));
+	return (char *)utf16toplain(get_key_helper(&ms_buffer1x[index << 4], 1));
 }
 
 // Public domain hash function by DJ Bernstein (salt is a username)
diff --git a/src/mssql-old_fmt_plug.c b/src/mssql-old_fmt_plug.c
index 83628d0..18a59b2 100644
--- a/src/mssql-old_fmt_plug.c
+++ b/src/mssql-old_fmt_plug.c
@@ -245,7 +245,6 @@ static void mssql_set_key_utf8(char *key, int index) {
 
 static char *mssql_get_key(int index) {
 	UTF16 key[PLAINTEXT_LENGTH + 1];
-	static UTF8 key8[PLAINTEXT_LENGTH*3 + 1];
 	int i;
 #ifdef MMX_COEF
 	int key_length = (total_len >> ((32/MMX_COEF)*index)) & 0xFF;
@@ -268,14 +267,7 @@ static char *mssql_get_key(int index) {
 	}
 #endif
 	key[i]=0;
-	utf16toplain(key8,PLAINTEXT_LENGTH*3,key);
-
-#ifdef MSSQL_DEBUG
-	dump_stuff_msg("saved_key ", saved_key, key_length<<1);
-	dump_stuff_msg("key8      ", key8, strlen(key8));
-#endif
-
-	return (char*)key8;
+	return (char*)utf16toplain(key);
 }
 
 static int mssql_cmp_all(void *binary, int count) {
diff --git a/src/oracle_fmt_plug.c b/src/oracle_fmt_plug.c
index 521225a..bc552d7 100644
--- a/src/oracle_fmt_plug.c
+++ b/src/oracle_fmt_plug.c
@@ -207,7 +207,6 @@ static void oracle_set_key(char *key, int index) {
 
 static char *oracle_get_key(int index) {
 	UTF16 key[PLAINTEXT_LENGTH + 1];
-	static UTF8 key8[PLAINTEXT_LENGTH*3 + 1];
 	int i;
 	for(i = 0; i < key_length; i++)
 #if ARCH_LITTLE_ENDIAN
@@ -216,18 +215,7 @@ static char *oracle_get_key(int index) {
 		key[i] = cur_key[i];
 #endif
 	key[i]=0;
-	utf16toplain(key8,PLAINTEXT_LENGTH*3,key);
-
-#ifdef DEBUG_ORACLE
-	{
-		static int cnt;
-		if (++cnt == 60) exit(0);
-		dump_stuff_msg("key    ", (unsigned char*)key, key_length);
-		dump_stuff_msg("key8   ", (unsigned char*)key8, strlen((char*)key8));
-	}
-#endif
-
-	return (char*)key8;
+	return (char*)utf16toplain(key);
 }
 
 static void oracle_crypt_all(int count)
diff --git a/src/rawMD5unicode_fmt_plug.c b/src/rawMD5unicode_fmt_plug.c
index 484b953..0904871 100644
--- a/src/rawMD5unicode_fmt_plug.c
+++ b/src/rawMD5unicode_fmt_plug.c
@@ -251,34 +251,19 @@ static char *rawmd5_get_key(int index)
 	unsigned int idx;
 	idx = (((unsigned) index) >> (MMX_COEF >> 1));
 #endif
-	if (options.utf8) {
-		static UTF16 key[PLAINTEXT_LENGTH / 2 + 1];
-		static UTF8 key8[(PLAINTEXT_LENGTH / 2)*3 + 1];
+	static UTF16 key[PLAINTEXT_LENGTH / 2 + 1];
 #ifdef MMX_COEF
-		for (i = 0; saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))] != 0x80; i += 2)
-			key[outlen++] = saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))] |
-				saved_key[idx][GETPOS(i + 1, index & (MMX_COEF - 1))] << 8;
+	for (i = 0; saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))] != 0x80; i += 2)
+		key[outlen++] = saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))] |
+			saved_key[idx][GETPOS(i + 1, index & (MMX_COEF - 1))] << 8;
 #else
-		for (i = 0; i < saved_key_len[index]; i += 2) {
-			key[outlen++] = saved_key[index][i] |
-				saved_key[index][i + 1] << 8;
-		}
-#endif
-		key[outlen] = 0;
-		return (char *)utf16toutf8(key8,(PLAINTEXT_LENGTH / 2)*3, key);
-	} else {
-		static unsigned char key[PLAINTEXT_LENGTH/2 + 1];
-#ifdef MMX_COEF
-		for (i = 0; saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))] != 0x80; i += 2)
-			key[outlen++] = saved_key[idx][GETPOS(i, index & (MMX_COEF - 1))];
-#else
-		for (i = 0; i < saved_key_len[index]; i += 2) {
-			key[outlen++] = saved_key[index][i];
-		}
-#endif
-		key[outlen] = 0;
-		return (char *)key;
+	for (i = 0; i < saved_key_len[index]; i += 2) {
+		key[outlen++] = saved_key[index][i] |
+			saved_key[index][i + 1] << 8;
 	}
+#endif
+	key[outlen] = 0;
+	return (char *)utf16toplain(key);
 }
 
 static int rawmd5_cmp_all(void *binary, int count)
diff --git a/src/unicode.c b/src/unicode.c
index 10cd2b4..640e39a 100644
--- a/src/unicode.c
+++ b/src/unicode.c
@@ -415,7 +415,14 @@ int E_md4hash(const UTF8 * passwd, unsigned int len, unsigned char *p16)
 
 // Convert UTF-16LE to UTF-8. This is not optimised as it's
 // only used in get_key() as of now.
-UTF8 * utf16toutf8 (UTF8 *dst, int dst_len, const UTF16* source) {
+// Non thread-safe version
+UTF8 * utf16toutf8 (const UTF16* source) {
+	static UTF8 ret_Key[PLAINTEXT_BUFFER_SIZE*3+1];
+	return utf16toutf8_r(ret_Key, PLAINTEXT_BUFFER_SIZE*3, source);
+}
+
+// Thread-safe version
+UTF8 * utf16toutf8_r (UTF8 *dst, int dst_len, const UTF16* source) {
 	UTF8 *tpt = dst;
 	UTF8 *targetEnd = tpt + dst_len;
 	while (*source) {
@@ -453,9 +460,16 @@ UTF8 * utf16toutf8 (UTF8 *dst, int dst_len, const UTF16* source) {
 
 // Convert UTF-16LE to UTF-8 or ISO-8859-1 depending on --utf8 flag.
 // This is not optimised as it's only used in get_key() as of now.
-UTF8 * utf16toplain (UTF8 *dst, int dst_len, const UTF16* source) {
+// Non thread-safe version
+UTF8 * utf16toplain (const UTF16* source) {
+	static UTF8 ret_Key[PLAINTEXT_BUFFER_SIZE*3+1];
+	return utf16toplain_r(ret_Key, PLAINTEXT_BUFFER_SIZE*3, source);
+}
+
+// Thread-safe version
+UTF8 * utf16toplain_r (UTF8 *dst, int dst_len, const UTF16* source) {
 	if (options.utf8)
-		return utf16toutf8(dst, dst_len, source);
+		return utf16toutf8_r(dst, dst_len, source);
 	else {
 		UTF8 *tgt = dst;
 		UTF8 *targetEnd = tgt + dst_len;
@@ -607,7 +621,7 @@ int utf8_lc(UTF8 *dst, unsigned dst_len, const UTF8 *src, unsigned src_len) {
 	utf16len = utf16_lc(tmp16l, 512, tmp16, utf16len);
 	if (utf16len <= 0)
 		return 0;
-	utf16toplain(dst, dst_len, tmp16l);
+	utf16toplain_r(dst, dst_len, tmp16l);
 	return strlen((char*)dst);
 }
 
@@ -646,6 +660,6 @@ int utf8_uc(UTF8 *dst, unsigned dst_len, const UTF8 *src, unsigned src_len) {
 	utf16len = utf16_uc(tmp16u, 512, tmp16, utf16len);
 	if (utf16len <= 0)
 		return 0;
-	utf16toplain(dst, dst_len, tmp16u);
+	utf16toplain_r(dst, dst_len, tmp16u);
 	return strlen((char*)dst);
 }
diff --git a/src/unicode.h b/src/unicode.h
index b630ba2..2320a9e 100644
--- a/src/unicode.h
+++ b/src/unicode.h
@@ -72,11 +72,13 @@ extern int plaintowcs(UTF16 * dst, unsigned int maxdstlen, const UTF8 * src,
     unsigned int srclen);
 
 /* Convert back to UTF-8 (for get_key without a saved_plain) */
-extern UTF8 * utf16toutf8 (UTF8 *dst, int dst_len, const UTF16* source);
+extern UTF8 * utf16toutf8 (const UTF16* source);
+extern UTF8 * utf16toutf8_r (UTF8 *dst, int dst_len, const UTF16* source);
 
 /* Convert back to UTF-8 or ISO-8859-1 depending on --utf8 flag
  * (for get_key without a saved_plain) */
-extern UTF8 * utf16toplain (UTF8 *dst, int dst_len, const UTF16* source);
+extern UTF8 * utf16toplain (const UTF16* source);
+extern UTF8 * utf16toplain_r (UTF8 *dst, int dst_len, const UTF16* source);
 
 /* These were in smbencrypt.c before: */
 
-- 
1.7.4.1

