Openwall GNU/*/Linux - a small security-enhanced Linux distro for servers
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Fri, 1 Feb 2013 07:24:22 +0400
From: Solar Designer <solar@...nwall.com>
To: john-dev@...ts.openwall.com
Subject: Re: NetNTLMv1

On Thu, Jan 31, 2013 at 06:36:22PM +0100, magnum wrote:
> This is now committed, as well as SIMD support. New Bull figures:

I am getting much better speeds; you might have run your benchmarks when
bull was under other load.

Anyhow, I've attached a patch that tries to speedup cmp_all() by use of
a bitmap.  This only makes sense when cmp_all() is called multiple times
per crypt_all()'s actual processing - that is, when cracking two or more
C/R pairs at once.  There's a check for that in the code.  Moreover, use
of the bitmap is automatically disabled when the C/R pair count reduces
to 1.

This does appear to provide some speedup, although not as much as I had
expected.

Alexander

--- NETNTLM_fmt_plug.c.orig	2013-02-01 01:57:08.781752612 +0000
+++ NETNTLM_fmt_plug.c	2013-02-01 03:12:27.255722279 +0000
@@ -122,6 +122,9 @@ static UTF16 (*saved_key)[PLAINTEXT_LENG
 static int (*saved_key_length);
 #endif
 
+static ARCH_WORD_32 *bitmap;
+static int cmps_per_crypt, use_bitmap;
+
 static uchar (*crypt_key)[21]; // NT hash
 static uchar *challenge;
 static int keys_prepared;
@@ -153,6 +156,9 @@ static void init(struct fmt_main *self)
 	saved_key_length = mem_calloc_tiny(sizeof(*saved_key_length) * self->params.max_keys_per_crypt, MEM_ALIGN_WORD);
 #endif
 	crypt_key = mem_calloc_tiny(sizeof(*crypt_key) * self->params.max_keys_per_crypt, MEM_ALIGN_WORD);
+	bitmap = mem_alloc_tiny(0x10000 / 8, 4);
+	use_bitmap = 0; /* we did not use bitmap yet */
+	cmps_per_crypt = 2; /* try bitmap */
 }
 
 static int valid(char *ciphertext, struct fmt_main *self)
@@ -284,17 +290,50 @@ out:
 static int crypt_all(int *pcount, struct db_salt *salt)
 {
 	int count = *pcount;
-	int i = 0;
 
 	if (!keys_prepared) {
+		int i;
+
+		if (use_bitmap) {
+#if 0
+/* too slow since max_keys_per_crypt is normally smaller */
+			memset(bitmap, 0, 0x10000 / 8);
+#else
+#ifdef MMX_COEF
+			for (i = 0; i < NBKEYS; i++)
+#else
+			for (i = 0; i < count; i++)
+#endif
+			{
+				unsigned int value =
+				    ((unsigned short *)crypt_key[i])[7];
+				bitmap[value >> 5] = 0;
+			}
+#endif
+		}
+
+		use_bitmap = cmps_per_crypt >= 2;
+		cmps_per_crypt = 0;
+
 #ifdef MMX_COEF
 #if defined(MD4_SSE_PARA)
 		SSEmd4body(saved_key, (unsigned int*)nthash, 1);
 #else
 		mdfourmmx(nthash, saved_key, total_len);
 #endif
-		for (i = 0; i < NBKEYS; i++)
+		if (use_bitmap)
+		for (i = 0; i < NBKEYS; i++) {
+			((ARCH_WORD_32*)crypt_key[i])[3] = *(ARCH_WORD_32*)&nthash[GETOUTPOS(12, i)];
+			{
+				unsigned int value =
+				    ((unsigned short *)crypt_key[i])[7];
+				bitmap[value >> 5] |= 1U << (value & 0x1f);
+			}
+		}
+		else
+		for (i = 0; i < NBKEYS; i++) {
 			((ARCH_WORD_32*)crypt_key[i])[3] = *(ARCH_WORD_32*)&nthash[GETOUTPOS(12, i)];
+		}
 #else
 #if defined(_OPENMP) || (MAX_KEYS_PER_CRYPT > 1)
 #ifdef _OPENMP
@@ -308,6 +347,11 @@ static int crypt_all(int *pcount, struct
 			MD4_Init( &ctx );
 			MD4_Update(&ctx, saved_key[i], saved_key_length[i]);
 			MD4_Final((uchar*)crypt_key[i], &ctx);
+			if (use_bitmap) {
+				unsigned int value =
+				    ((unsigned short *)crypt_key[i])[7];
+				bitmap[value >> 5] |= 1U << (value & 0x1f);
+			}
 		}
 #endif
 		keys_prepared = 1;
@@ -340,16 +384,27 @@ static int cmp_one(void *binary, int ind
 
 static int cmp_all(void *binary, int count)
 {
+	unsigned int value = *(unsigned short *)binary;
 	int index;
 
+	cmps_per_crypt++;
+
+	if (use_bitmap && !(bitmap[value >> 5] & (1U << (value & 0x1f))))
+		goto out;
+
 #ifdef MMX_COEF
 	/* Let's give the optimizer a hint! */
-	for (index = 0; index < NBKEYS; index++) {
+	for (index = 0; index < NBKEYS; index += 2) {
 #else
-	for (index = 0; index < count; index++) {
+	for (index = 0; index < count; index += 2) {
+#endif
+		unsigned int a = ((unsigned short *)crypt_key[index])[7];
+		unsigned int b = ((unsigned short *)crypt_key[index + 1])[7];
+#if 0
+		if (((a | b) & value) != value)
+			continue;
 #endif
-		if (crypt_key[index][14] == ((uchar *)binary)[0] &&
-		    crypt_key[index][15] == ((uchar *)binary)[1])
+		if (a == value || b == value)
 			goto thorough;
 	}
 

Powered by blists - more mailing lists

Your e-mail address:

Powered by Openwall GNU/*/Linux - Powered by OpenVZ