[<prev] [next>] [day] [month] [year] [list]
Date: Sun, 26 Dec 2010 21:55:11 +0100
From: Matthias Deeg <thes3nf@...glemail.com>
To: john-users@...ts.openwall.com
Subject: Support for Domain Cached Credentials of modern Windows operating
systems (MSCash2)
Hello people,
I've uploaded a patch for supporting domain cached credentials (DCCs) used
in modern Windows operating systems (e.g. Windows Vista, Windows 7, Windows
Server 2008) and some further information about the MSCash2 algorithm to the
Openwall Community Wiki (see http://openwall.info/wiki/john/patches and
http://openwall.info/wiki/john/MSCash2 ).
The uncompressed patch is also attached to this e-mail.
Best regards,
S3nf
[ CONTENT OF TYPE text/html SKIPPED ]
diff -urpN john-1.7.6-jumbo-9/src/john.c john-1.7.6-jumbo-9-mscash2/src/john.c
--- john-1.7.6-jumbo-9/src/john.c 2010-12-26 16:03:36.000000000 +0000
+++ john-1.7.6-jumbo-9-mscash2/src/john.c 2010-12-26 16:03:59.000000000 +0000
@@ -67,6 +67,7 @@ extern struct fmt_main fmt_NSLDAP;
extern struct fmt_main fmt_NSLDAPS;
extern struct fmt_main fmt_OPENLDAPS;
extern struct fmt_main fmt_mscash;
+extern struct fmt_main fmt_mscash2;
extern struct fmt_main fmt_rawSHA1;
extern struct fmt_main fmt_XSHA;
extern struct fmt_main fmt_sha1_gen;
@@ -127,6 +128,7 @@ static void john_register_all(void)
john_register_one(&fmt_NT);
john_register_one(&fmt_XSHA);
john_register_one(&fmt_mscash);
+ john_register_one(&fmt_mscash2);
john_register_one(&fmt_MD5_apache);
john_register_one(&fmt_hmacMD5);
john_register_one(&fmt_PO);
diff -urpN john-1.7.6-jumbo-9/src/loader.c john-1.7.6-jumbo-9-mscash2/src/loader.c
--- john-1.7.6-jumbo-9/src/loader.c 2010-12-26 16:03:12.000000000 +0000
+++ john-1.7.6-jumbo-9-mscash2/src/loader.c 2010-12-26 16:03:28.000000000 +0000
@@ -484,6 +484,7 @@ static void ldr_load_pw_line(struct db_m
size_t pw_size, salt_size;
extern struct fmt_main fmt_mscash;
+ extern struct fmt_main fmt_mscash2;
extern struct fmt_main fmt_oracle;
count = ldr_split_line(&login, &ciphertext, &gecos, &home,
@@ -513,7 +514,7 @@ static void ldr_load_pw_line(struct db_m
ldr_init_password_hash(db);
for (index = 0; index < count; index++) {
- if (db->format == &fmt_mscash) {
+ if ((db->format == &fmt_mscash) || (db->format == &fmt_mscash2)) {
piece = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4);
sprintf(piece, "M$%s#%s", login, ciphertext);
} else if (db->format == &fmt_oracle) {
@@ -988,6 +989,7 @@ static void ldr_show_pw_line(struct db_m
struct db_cracked *current;
extern struct fmt_main fmt_mscash;
+ extern struct fmt_main fmt_mscash2;
extern struct fmt_main fmt_oracle;
format = NULL;
@@ -1003,7 +1005,7 @@ static void ldr_show_pw_line(struct db_m
if (format) {
split = format->methods.split;
unify = format->params.flags & FMT_SPLIT_UNIFIES_CASE;
- if(format == &fmt_mscash)
+ if((format == &fmt_mscash) || (format == &fmt_mscash2))
{
char * ciphertext2 = (char *) mem_alloc(strlen(login) + strlen(ciphertext) + 4);
sprintf(ciphertext2, "M$%s#%s", login, ciphertext);
diff -urpN john-1.7.6-jumbo-9/src/Makefile john-1.7.6-jumbo-9-mscash2/src/Makefile
--- john-1.7.6-jumbo-9/src/Makefile 2010-12-26 16:03:12.000000000 +0000
+++ john-1.7.6-jumbo-9-mscash2/src/Makefile 2010-12-26 16:03:28.000000000 +0000
@@ -64,6 +64,7 @@ JOHN_OBJS = \
NSLDAP_fmt.o NSLDAPS_fmt.o OPENLDAPS_fmt.o base64.o \
md4.o smbencrypt.o \
mscash_fmt.o \
+ mscash2_fmt.o \
NETLM_fmt.o \
NETNTLM_fmt.o \
NETLMv2_fmt.o \
diff -urpN john-1.7.6-jumbo-9/src/mscash2_fmt.c john-1.7.6-jumbo-9-mscash2/src/mscash2_fmt.c
--- john-1.7.6-jumbo-9/src/mscash2_fmt.c 1970-01-01 00:00:00.000000000 +0000
+++ john-1.7.6-jumbo-9-mscash2/src/mscash2_fmt.c 2010-12-26 19:48:08.000000000 +0000
@@ -0,0 +1,1270 @@
+/* MSCASH2 patch for John the Ripper written by S3nf <thes3nf at googlemail.com> in 2010
+ * a slow but working version 1.0
+ *
+ * Cracking Domain Cached Credentials for modern Windows operating systems, supporting:
+ * - Windows Vista
+ * - Windows 7
+ * - Windows Server 2008
+ *
+ * This module is based on:
+ * - the MSCASH patch for john written by Alain Espinosa <alainesp at gmail.com> in 2007
+ * - RFC 1320 - The MD4 Message-Digest Algorithm
+ * - RFC 2104 - HMAC: Keyed-Hashing for Message Authentication
+ * - RFC 3174 - US Secure Hash Algorithm 1 (SHA1)
+ * - the HMAC-SHA1 implementation of the PolarSSL open source cryptagraphic library (http://polarssl.org/)
+ *
+ * This software was written by S3nf in 2010. No copyright is claimed, and the software is hereby placed in
+ * the public domain. In case this attempt to disclaim copyright and place the software in the public domain
+ * is deemed null and void, then the software is Copyright (c) 2010 S3nf 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.
+ *
+ */
+
+#include <string.h>
+#include "arch.h"
+#include "misc.h"
+#include "memory.h"
+#include "common.h"
+#include "formats.h"
+
+#define ITERATIONS 10240
+
+// MD4 init values
+#define INIT_MD4_A 0x67452301
+#define INIT_MD4_B 0xefcdab89
+#define INIT_MD4_C 0x98badcfe
+#define INIT_MD4_D 0x10325476
+
+#define SQRT_2 0x5a827999
+#define SQRT_3 0x6ed9eba1
+
+#define SHA1_DIGEST_LENGTH 20
+
+#define INIT_SHA1_A 0x67452301
+#define INIT_SHA1_B 0xEFCDAB89
+#define INIT_SHA1_C 0x98BADCFE
+#define INIT_SHA1_D 0x10325476
+#define INIT_SHA1_E 0xC3D2E1F0
+
+#ifndef GET_WORD_32_BE
+#define GET_WORD_32_BE(n,b,i) \
+{ \
+ (n) = ( (unsigned long) (b)[(i) ] << 24 ) \
+ | ( (unsigned long) (b)[(i) + 1] << 16 ) \
+ | ( (unsigned long) (b)[(i) + 2] << 8 ) \
+ | ( (unsigned long) (b)[(i) + 3] ); \
+}
+#endif
+
+#ifndef PUT_WORD_32_BE
+#define PUT_WORD_32_BE(n,b,i) \
+{ \
+ (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) ); \
+}
+#endif
+
+#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
+
+#define R(t) \
+( \
+ temp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
+ W[(t - 14) & 0x0F] ^ W[ t & 0x0F], \
+ ( W[t & 0x0F] = S(temp,1) ) \
+)
+
+#define P(a,b,c,d,e,x) \
+{ \
+ e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \
+}
+
+
+static struct fmt_tests tests[] = {
+ {"M$test1#607bbe89611e37446e736f7856515bf8", "test1" },
+ {"M$test2#c6758e5be7fc943d00b97972a8a97620", "test2" },
+ {"M$test3#360e51304a2d383ea33467ab0b639cc4", "test3" },
+ {"M$test4#6f79ee93518306f071c47185998566ae", "test4" },
+ {NULL}
+};
+
+#define FORMAT_LABEL "mscash2"
+#define FORMAT_NAME "M$ Cache Hash 2"
+
+#define BENCHMARK_COMMENT ""
+#define BENCHMARK_LENGTH 0
+
+#define PLAINTEXT_LENGTH 27
+#define MAX_CIPHERTEXT_LENGTH (2 + 32 + 1 + 32)
+
+#define ALGORITHM_NAME "Generic 1x"
+
+#define BINARY_SIZE 16
+#define SALT_SIZE (11*4)
+
+#define MS_NUM_KEYS 64
+#define MIN_KEYS_PER_CRYPT MS_NUM_KEYS
+#define MAX_KEYS_PER_CRYPT MS_NUM_KEYS
+
+static unsigned int ms_buffer1x[16 * MS_NUM_KEYS];
+static unsigned int output1x[4 * MS_NUM_KEYS];
+static unsigned int output1x_dcc2[4 * MS_NUM_KEYS];
+
+static unsigned int crypt[4 * MS_NUM_KEYS];
+static unsigned int last[4 * MS_NUM_KEYS];
+
+static unsigned int last_i[MS_NUM_KEYS];
+static char saved_plain[32 * MS_NUM_KEYS];
+
+static unsigned int *salt_buffer;
+static unsigned int salt_len;
+static unsigned int new_key;
+
+
+static void init(void)
+{
+ memset(ms_buffer1x, 0, 64 * MS_NUM_KEYS);
+ memset(last_i, 0, 4 * MS_NUM_KEYS);
+ new_key = 1;
+}
+
+
+static char * ms_split(char *ciphertext, int index)
+{
+ static char out[MAX_CIPHERTEXT_LENGTH + 1];
+ int i = 0;
+
+ for(; ciphertext[i] && i < MAX_CIPHERTEXT_LENGTH; i++)
+ out[i] = ciphertext[i];
+
+ out[i] = 0;
+
+ if (i >= 32)
+ strlwr(&out[i - 32]);
+
+ return out;
+}
+
+
+static int valid(char *ciphertext)
+{
+ unsigned int i;
+ unsigned int l;
+
+ /*
+ * 2 cases
+ * 1 - it comes from the disk, and does not have M$ + salt
+ * 2 - it comes from memory, and has got M$ + salt + # + blah
+ */
+
+ if (!strncmp(ciphertext, "M$", 2))
+ {
+ l = strlen(ciphertext);
+ if (l <= 32 || l > MAX_CIPHERTEXT_LENGTH)
+ return 0;
+ l -= 32;
+ if (ciphertext[l - 1] != '#')
+ return 0;
+ }
+ else
+ {
+ if (strlen(ciphertext) != 32)
+ return 0;
+ l = 0;
+ }
+ for (i = l; i < l + 32; i++)
+ if (atoi16[ARCH_INDEX(ciphertext[i])] == 0x7F)
+ return 0;
+
+ return 1;
+}
+
+
+static void set_salt(void *salt) {
+ // calculate salt length, 0x80 is terminating char
+ for (salt_len = 0; ((unsigned char *)salt)[salt_len] != 0x80; salt_len++);
+
+ salt_buffer = salt;
+}
+
+
+static void *get_salt(char *ciphertext)
+{
+ // lenght = 11 for save memory + 1 for PBKDF2 count
+ // last position = 0
+ // 4 first position are crypt[?]
+ static unsigned int out[11];
+ unsigned int md4_size = 0;
+
+ memset(out, 0, 44);
+
+ ciphertext += 2;
+
+ for (;;md4_size++)
+ if (ciphertext[md4_size] != '#' && md4_size < 19)
+ {
+ md4_size++;
+
+ out[md4_size >> 1] = ciphertext[md4_size - 1] | ((ciphertext[md4_size] != '#') ? (ciphertext[md4_size] << 16) : 0x800000);
+
+ if (ciphertext[md4_size] == '#')
+ break;
+ }
+ else
+ {
+ out[md4_size >> 1] = 0x80;
+ break;
+ }
+
+ out[10] = (8 + md4_size) << 4;
+
+ return out;
+}
+
+
+static void *get_binary(char *ciphertext)
+{
+ static unsigned int out[4];
+ unsigned int i = 0;
+ unsigned int temp;
+
+ for (; ciphertext[0] != '#'; ciphertext++);
+ ciphertext++;
+
+ for (; i < 4 ;i++)
+ {
+ temp = (atoi16[ARCH_INDEX(ciphertext[i * 8 + 0])]) << 4;
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 1])]);
+
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 2])]) << 12;
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 3])]) << 8;
+
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 4])]) << 20;
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 5])]) << 16;
+
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 6])]) << 28;
+ temp |= (atoi16[ARCH_INDEX(ciphertext[i * 8 + 7])]) << 24;
+
+ out[i] = temp;
+ }
+
+ return out;
+}
+
+
+static int binary_hash_0(void *binary)
+{
+ return ((unsigned int*)binary)[3] & 0x0F;
+}
+
+
+static int binary_hash_1(void *binary)
+{
+ return ((unsigned int*)binary)[3] & 0xFF;
+}
+
+
+static int binary_hash_2(void *binary)
+{
+ return ((unsigned int*)binary)[3] & 0x0FFF;
+}
+
+
+static int get_hash_0(int index)
+{
+ return output1x_dcc2[4 * index + 3] & 0x0F;
+}
+
+
+static int get_hash_1(int index)
+{
+ return output1x_dcc2[4 * index + 3] & 0xFF;
+}
+
+
+static int get_hash_2(int index)
+{
+ return output1x_dcc2[4 * index + 3] & 0x0FFF;
+}
+
+
+static void nt_hash(void)
+{
+ unsigned int a;
+ unsigned int b;
+ unsigned int c;
+ unsigned int d;
+ unsigned int i = 0;
+
+ for(; i < MS_NUM_KEYS; i++)
+ {
+ // round 1
+ a = 0xFFFFFFFF + ms_buffer1x[16 * i + 0]; a = (a << 3 ) | (a >> 29);
+ d = INIT_MD4_D + (INIT_MD4_C ^ (a & 0x77777777)) + ms_buffer1x[16 * i +1]; d = (d << 7 ) | (d >> 25);
+ c = INIT_MD4_C + (INIT_MD4_B ^ (d & (a ^ INIT_MD4_B))) + ms_buffer1x[16 * i +2]; c = (c << 11) | (c >> 21);
+ b = INIT_MD4_B + (a ^ (c & (d ^ a))) + ms_buffer1x[16 * i +3]; b = (b << 19) | (b >> 13);
+
+ a += (d ^ (b & (c ^ d))) + ms_buffer1x[16 * i + 4] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + ms_buffer1x[16 * i + 5] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + ms_buffer1x[16 * i + 6] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a))) + ms_buffer1x[16 * i + 7] ;b = (b << 19) | (b >> 13);
+
+ a += (d ^ (b & (c ^ d))) + ms_buffer1x[16 * i + 8] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + ms_buffer1x[16 * i + 9] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + ms_buffer1x[16 * i + 10] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a))) + ms_buffer1x[16 * i + 11] ;b = (b << 19) | (b >> 13);
+
+ a += (d ^ (b & (c ^ d))) + ms_buffer1x[16 * i + 12] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + ms_buffer1x[16 * i + 13] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + ms_buffer1x[16 * i + 14] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a)))/* + ms_buffer1x[16 * i + 15]*/;b = (b << 19) | (b >> 13);
+
+ // round 2
+ a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16 * i + 0] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16 * i + 4] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16 * i + 8] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16 * i + 12] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16 * i + 1] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16 * i + 5] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16 * i + 9] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16 * i + 13] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16 * i + 2] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16 * i + 6] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16 * i + 10] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + ms_buffer1x[16 * i + 14] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + ms_buffer1x[16 * i + 3] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + ms_buffer1x[16 * i + 7] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + ms_buffer1x[16 * i + 11] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a))/* + ms_buffer1x[ 16 * i + 15]*/+SQRT_2; b = (b << 13) | (b >> 19);
+
+ // round 3
+ a += (b ^ c ^ d) + ms_buffer1x[16 * i + 0] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + ms_buffer1x[16 * i + 8] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + ms_buffer1x[16 * i + 4] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + ms_buffer1x[16 * i + 12] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + ms_buffer1x[16 * i + 2] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + ms_buffer1x[16 * i + 10] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + ms_buffer1x[16 * i + 6] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + ms_buffer1x[16 * i + 14] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + ms_buffer1x[16 * i + 1] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + ms_buffer1x[16 * i + 9] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + ms_buffer1x[16 * i + 5] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + ms_buffer1x[16 * i + 13] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + ms_buffer1x[16 * i + 3] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + ms_buffer1x[16 * i + 11] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + ms_buffer1x[16 * i + 7] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) /*+ ms_buffer1x[16 * i + 15] */+ SQRT_3; b = (b << 15) | (b >> 17);
+
+ crypt[4 * i + 0] = a + INIT_MD4_A;
+ crypt[4 * i + 1] = b + INIT_MD4_B;
+ crypt[4 * i + 2] = c + INIT_MD4_C;
+ crypt[4 * i + 3] = d + INIT_MD4_D;
+
+ // another MD4 crypt for the salt
+ // round 1
+ a = 0xFFFFFFFF + crypt[ 4 * i + 0]; a = ( a << 3 )| ( a >> 29);
+ d = INIT_MD4_D + (INIT_MD4_C ^ (a & 0x77777777)) + crypt[4 * i + 1]; d =(d << 7 ) | (d >> 25);
+ c = INIT_MD4_C + (INIT_MD4_B ^ (d & (a ^ INIT_MD4_B))) + crypt[4 * i + 2]; c = (c << 11) | (c >> 21);
+ b = INIT_MD4_B + (a ^ (c & (d ^ a))) + crypt[4 * i + 3]; b = (b << 19) |(b >> 13);
+
+ last[4 * i + 0] = a;
+ last[4 * i + 1] = b;
+ last[4 * i + 2] = c;
+ last[4 * i + 3] = d;
+ }
+}
+
+
+/*
+ * hmac_sha1
+ * based on RFC 2104, RFC 3174 and the HMAC-SHA1 implementation of the PolarSSL
+ * open source cryptographic library (http://www.polarssl.org)
+ */
+static void hmac_sha1(const unsigned char *key, unsigned int keylen, const unsigned char *input, unsigned int inputlen, unsigned char *output)
+{
+ unsigned int i, temp, W[16];
+ unsigned int A, B, C, D, E, state[5];
+ unsigned char buf[64];
+ unsigned char ipad[64];
+ unsigned char opad[64];
+
+ memset(ipad, 0x36, 64);
+ memset(opad, 0x5C, 64);
+ memset(buf, 0, 64);
+
+ // step 1: append zeros to the end of K to create a B Byte string
+ memcpy(buf, input, inputlen);
+ buf[inputlen] = 0x80;
+ PUT_WORD_32_BE((64 + inputlen) << 3, buf, 60);
+
+ // step 2: XOR (bitwise exclusive-OR) the B byte string computed in step 1 with ipad
+ // step 5: XOR (bitwise exclusive-OR) the B byte string computed in step 1 with opad
+ for(i = 0; i < keylen; i++)
+ {
+ ipad[i] = ipad[i] ^ key[i];
+ opad[i] = opad[i] ^ key[i];
+ }
+
+ // step 3: append the stream of data 'text' to the B byte sting resulting from step 2
+ // first part of stream (64 bytes) is ipad, second part of stream (64 bytes) is buf
+
+ // step 4: apply H to the stream (ipad & buf) generated in step 3
+ GET_WORD_32_BE(W[ 0], ipad, 0);
+ GET_WORD_32_BE(W[ 1], ipad, 4);
+ GET_WORD_32_BE(W[ 2], ipad, 8);
+ GET_WORD_32_BE(W[ 3], ipad, 12);
+ GET_WORD_32_BE(W[ 4], ipad, 16);
+ GET_WORD_32_BE(W[ 5], ipad, 20);
+ GET_WORD_32_BE(W[ 6], ipad, 24);
+ GET_WORD_32_BE(W[ 7], ipad, 28);
+ GET_WORD_32_BE(W[ 8], ipad, 32);
+ GET_WORD_32_BE(W[ 9], ipad, 36);
+ GET_WORD_32_BE(W[10], ipad, 40);
+ GET_WORD_32_BE(W[11], ipad, 44);
+ GET_WORD_32_BE(W[12], ipad, 48);
+ GET_WORD_32_BE(W[13], ipad, 52);
+ GET_WORD_32_BE(W[14], ipad, 56);
+ GET_WORD_32_BE(W[15], ipad, 60);
+
+ A = INIT_SHA1_A;
+ B = INIT_SHA1_B;
+ C = INIT_SHA1_C;
+ D = INIT_SHA1_D;
+ E = INIT_SHA1_E;
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P(A, B, C, D, E, W[0] );
+ P(E, A, B, C, D, W[1] );
+ P(D, E, A, B, C, W[2] );
+ P(C, D, E, A, B, W[3] );
+ P(B, C, D, E, A, W[4] );
+ P(A, B, C, D, E, W[5] );
+ P(E, A, B, C, D, W[6] );
+ P(D, E, A, B, C, W[7] );
+ P(C, D, E, A, B, W[8] );
+ P(B, C, D, E, A, W[9] );
+ P(A, B, C, D, E, W[10]);
+ P(E, A, B, C, D, W[11]);
+ P(D, E, A, B, C, W[12]);
+ P(C, D, E, A, B, W[13]);
+ P(B, C, D, E, A, W[14]);
+ P(A, B, C, D, E, W[15]);
+ P(E, A, B, C, D, R(16));
+ P(D, E, A, B, C, R(17));
+ P(C, D, E, A, B, R(18));
+ P(B, C, D, E, A, R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P(A, B, C, D, E, R(20));
+ P(E, A, B, C, D, R(21));
+ P(D, E, A, B, C, R(22));
+ P(C, D, E, A, B, R(23));
+ P(B, C, D, E, A, R(24));
+ P(A, B, C, D, E, R(25));
+ P(E, A, B, C, D, R(26));
+ P(D, E, A, B, C, R(27));
+ P(C, D, E, A, B, R(28));
+ P(B, C, D, E, A, R(29));
+ P(A, B, C, D, E, R(30));
+ P(E, A, B, C, D, R(31));
+ P(D, E, A, B, C, R(32));
+ P(C, D, E, A, B, R(33));
+ P(B, C, D, E, A, R(34));
+ P(A, B, C, D, E, R(35));
+ P(E, A, B, C, D, R(36));
+ P(D, E, A, B, C, R(37));
+ P(C, D, E, A, B, R(38));
+ P(B, C, D, E, A, R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P(A, B, C, D, E, R(40));
+ P(E, A, B, C, D, R(41));
+ P(D, E, A, B, C, R(42));
+ P(C, D, E, A, B, R(43));
+ P(B, C, D, E, A, R(44));
+ P(A, B, C, D, E, R(45));
+ P(E, A, B, C, D, R(46));
+ P(D, E, A, B, C, R(47));
+ P(C, D, E, A, B, R(48));
+ P(B, C, D, E, A, R(49));
+ P(A, B, C, D, E, R(50));
+ P(E, A, B, C, D, R(51));
+ P(D, E, A, B, C, R(52));
+ P(C, D, E, A, B, R(53));
+ P(B, C, D, E, A, R(54));
+ P(A, B, C, D, E, R(55));
+ P(E, A, B, C, D, R(56));
+ P(D, E, A, B, C, R(57));
+ P(C, D, E, A, B, R(58));
+ P(B, C, D, E, A, R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P(A, B, C, D, E, R(60));
+ P(E, A, B, C, D, R(61));
+ P(D, E, A, B, C, R(62));
+ P(C, D, E, A, B, R(63));
+ P(B, C, D, E, A, R(64));
+ P(A, B, C, D, E, R(65));
+ P(E, A, B, C, D, R(66));
+ P(D, E, A, B, C, R(67));
+ P(C, D, E, A, B, R(68));
+ P(B, C, D, E, A, R(69));
+ P(A, B, C, D, E, R(70));
+ P(E, A, B, C, D, R(71));
+ P(D, E, A, B, C, R(72));
+ P(C, D, E, A, B, R(73));
+ P(B, C, D, E, A, R(74));
+ P(A, B, C, D, E, R(75));
+ P(E, A, B, C, D, R(76));
+ P(D, E, A, B, C, R(77));
+ P(C, D, E, A, B, R(78));
+ P(B, C, D, E, A, R(79));
+
+#undef K
+#undef F
+
+ A += INIT_SHA1_A;
+ B += INIT_SHA1_B;
+ C += INIT_SHA1_C;
+ D += INIT_SHA1_D;
+ E += INIT_SHA1_E;
+
+ state[0] = A;
+ state[1] = B;
+ state[2] = C;
+ state[3] = D;
+ state[4] = E;
+
+ // process buf (2nd part of stream)
+ GET_WORD_32_BE(W[ 0], buf, 0);
+ GET_WORD_32_BE(W[ 1], buf, 4);
+ GET_WORD_32_BE(W[ 2], buf, 8);
+ GET_WORD_32_BE(W[ 3], buf, 12);
+ GET_WORD_32_BE(W[ 4], buf, 16);
+ GET_WORD_32_BE(W[ 5], buf, 20);
+ GET_WORD_32_BE(W[ 6], buf, 24);
+ GET_WORD_32_BE(W[ 7], buf, 28);
+ GET_WORD_32_BE(W[ 8], buf, 32);
+ GET_WORD_32_BE(W[ 9], buf, 36);
+ GET_WORD_32_BE(W[10], buf, 40);
+ GET_WORD_32_BE(W[11], buf, 44);
+ GET_WORD_32_BE(W[12], buf, 48);
+ GET_WORD_32_BE(W[13], buf, 52);
+ GET_WORD_32_BE(W[14], buf, 56);
+ GET_WORD_32_BE(W[15], buf, 60);
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P(A, B, C, D, E, W[0] );
+ P(E, A, B, C, D, W[1] );
+ P(D, E, A, B, C, W[2] );
+ P(C, D, E, A, B, W[3] );
+ P(B, C, D, E, A, W[4] );
+ P(A, B, C, D, E, W[5] );
+ P(E, A, B, C, D, W[6] );
+ P(D, E, A, B, C, W[7] );
+ P(C, D, E, A, B, W[8] );
+ P(B, C, D, E, A, W[9] );
+ P(A, B, C, D, E, W[10]);
+ P(E, A, B, C, D, W[11]);
+ P(D, E, A, B, C, W[12]);
+ P(C, D, E, A, B, W[13]);
+ P(B, C, D, E, A, W[14]);
+ P(A, B, C, D, E, W[15]);
+ P(E, A, B, C, D, R(16));
+ P(D, E, A, B, C, R(17));
+ P(C, D, E, A, B, R(18));
+ P(B, C, D, E, A, R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P(A, B, C, D, E, R(20));
+ P(E, A, B, C, D, R(21));
+ P(D, E, A, B, C, R(22));
+ P(C, D, E, A, B, R(23));
+ P(B, C, D, E, A, R(24));
+ P(A, B, C, D, E, R(25));
+ P(E, A, B, C, D, R(26));
+ P(D, E, A, B, C, R(27));
+ P(C, D, E, A, B, R(28));
+ P(B, C, D, E, A, R(29));
+ P(A, B, C, D, E, R(30));
+ P(E, A, B, C, D, R(31));
+ P(D, E, A, B, C, R(32));
+ P(C, D, E, A, B, R(33));
+ P(B, C, D, E, A, R(34));
+ P(A, B, C, D, E, R(35));
+ P(E, A, B, C, D, R(36));
+ P(D, E, A, B, C, R(37));
+ P(C, D, E, A, B, R(38));
+ P(B, C, D, E, A, R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P(A, B, C, D, E, R(40));
+ P(E, A, B, C, D, R(41));
+ P(D, E, A, B, C, R(42));
+ P(C, D, E, A, B, R(43));
+ P(B, C, D, E, A, R(44));
+ P(A, B, C, D, E, R(45));
+ P(E, A, B, C, D, R(46));
+ P(D, E, A, B, C, R(47));
+ P(C, D, E, A, B, R(48));
+ P(B, C, D, E, A, R(49));
+ P(A, B, C, D, E, R(50));
+ P(E, A, B, C, D, R(51));
+ P(D, E, A, B, C, R(52));
+ P(C, D, E, A, B, R(53));
+ P(B, C, D, E, A, R(54));
+ P(A, B, C, D, E, R(55));
+ P(E, A, B, C, D, R(56));
+ P(D, E, A, B, C, R(57));
+ P(C, D, E, A, B, R(58));
+ P(B, C, D, E, A, R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P(A, B, C, D, E, R(60));
+ P(E, A, B, C, D, R(61));
+ P(D, E, A, B, C, R(62));
+ P(C, D, E, A, B, R(63));
+ P(B, C, D, E, A, R(64));
+ P(A, B, C, D, E, R(65));
+ P(E, A, B, C, D, R(66));
+ P(D, E, A, B, C, R(67));
+ P(C, D, E, A, B, R(68));
+ P(B, C, D, E, A, R(69));
+ P(A, B, C, D, E, R(70));
+ P(E, A, B, C, D, R(71));
+ P(D, E, A, B, C, R(72));
+ P(C, D, E, A, B, R(73));
+ P(B, C, D, E, A, R(74));
+ P(A, B, C, D, E, R(75));
+ P(E, A, B, C, D, R(76));
+ P(D, E, A, B, C, R(77));
+ P(C, D, E, A, B, R(78));
+ P(B, C, D, E, A, R(79));
+
+#undef K
+#undef F
+
+ A += state[0];
+ B += state[1];
+ C += state[2];
+ D += state[3];
+ E += state[4];
+
+ PUT_WORD_32_BE(A, buf, 0);
+ PUT_WORD_32_BE(B, buf, 4);
+ PUT_WORD_32_BE(C, buf, 8);
+ PUT_WORD_32_BE(D, buf, 12);
+ PUT_WORD_32_BE(E, buf, 16);
+
+ buf[20] = 0x80;
+ PUT_WORD_32_BE(0x2A0, buf, 60);
+
+ // step 6: append the stream of data 'text' to the B byte sting resulting from step 2
+ // first part of stream (64 bytes) is opad, second part of stream (64 bytes) is the H result from step 4
+
+ // step 7: apply H to the stream (opad & buf) generated in step 6 and output the result
+ GET_WORD_32_BE(W[ 0], opad, 0);
+ GET_WORD_32_BE(W[ 1], opad, 4);
+ GET_WORD_32_BE(W[ 2], opad, 8);
+ GET_WORD_32_BE(W[ 3], opad, 12);
+ GET_WORD_32_BE(W[ 4], opad, 16);
+ GET_WORD_32_BE(W[ 5], opad, 20);
+ GET_WORD_32_BE(W[ 6], opad, 24);
+ GET_WORD_32_BE(W[ 7], opad, 28);
+ GET_WORD_32_BE(W[ 8], opad, 32);
+ GET_WORD_32_BE(W[ 9], opad, 36);
+ GET_WORD_32_BE(W[10], opad, 40);
+ GET_WORD_32_BE(W[11], opad, 44);
+ GET_WORD_32_BE(W[12], opad, 48);
+ GET_WORD_32_BE(W[13], opad, 52);
+ GET_WORD_32_BE(W[14], opad, 56);
+ GET_WORD_32_BE(W[15], opad, 60);
+
+ A = INIT_SHA1_A;
+ B = INIT_SHA1_B;
+ C = INIT_SHA1_C;
+ D = INIT_SHA1_D;
+ E = INIT_SHA1_E;
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P(A, B, C, D, E, W[0] );
+ P(E, A, B, C, D, W[1] );
+ P(D, E, A, B, C, W[2] );
+ P(C, D, E, A, B, W[3] );
+ P(B, C, D, E, A, W[4] );
+ P(A, B, C, D, E, W[5] );
+ P(E, A, B, C, D, W[6] );
+ P(D, E, A, B, C, W[7] );
+ P(C, D, E, A, B, W[8] );
+ P(B, C, D, E, A, W[9] );
+ P(A, B, C, D, E, W[10]);
+ P(E, A, B, C, D, W[11]);
+ P(D, E, A, B, C, W[12]);
+ P(C, D, E, A, B, W[13]);
+ P(B, C, D, E, A, W[14]);
+ P(A, B, C, D, E, W[15]);
+ P(E, A, B, C, D, R(16));
+ P(D, E, A, B, C, R(17));
+ P(C, D, E, A, B, R(18));
+ P(B, C, D, E, A, R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P(A, B, C, D, E, R(20));
+ P(E, A, B, C, D, R(21));
+ P(D, E, A, B, C, R(22));
+ P(C, D, E, A, B, R(23));
+ P(B, C, D, E, A, R(24));
+ P(A, B, C, D, E, R(25));
+ P(E, A, B, C, D, R(26));
+ P(D, E, A, B, C, R(27));
+ P(C, D, E, A, B, R(28));
+ P(B, C, D, E, A, R(29));
+ P(A, B, C, D, E, R(30));
+ P(E, A, B, C, D, R(31));
+ P(D, E, A, B, C, R(32));
+ P(C, D, E, A, B, R(33));
+ P(B, C, D, E, A, R(34));
+ P(A, B, C, D, E, R(35));
+ P(E, A, B, C, D, R(36));
+ P(D, E, A, B, C, R(37));
+ P(C, D, E, A, B, R(38));
+ P(B, C, D, E, A, R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P(A, B, C, D, E, R(40));
+ P(E, A, B, C, D, R(41));
+ P(D, E, A, B, C, R(42));
+ P(C, D, E, A, B, R(43));
+ P(B, C, D, E, A, R(44));
+ P(A, B, C, D, E, R(45));
+ P(E, A, B, C, D, R(46));
+ P(D, E, A, B, C, R(47));
+ P(C, D, E, A, B, R(48));
+ P(B, C, D, E, A, R(49));
+ P(A, B, C, D, E, R(50));
+ P(E, A, B, C, D, R(51));
+ P(D, E, A, B, C, R(52));
+ P(C, D, E, A, B, R(53));
+ P(B, C, D, E, A, R(54));
+ P(A, B, C, D, E, R(55));
+ P(E, A, B, C, D, R(56));
+ P(D, E, A, B, C, R(57));
+ P(C, D, E, A, B, R(58));
+ P(B, C, D, E, A, R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P(A, B, C, D, E, R(60));
+ P(E, A, B, C, D, R(61));
+ P(D, E, A, B, C, R(62));
+ P(C, D, E, A, B, R(63));
+ P(B, C, D, E, A, R(64));
+ P(A, B, C, D, E, R(65));
+ P(E, A, B, C, D, R(66));
+ P(D, E, A, B, C, R(67));
+ P(C, D, E, A, B, R(68));
+ P(B, C, D, E, A, R(69));
+ P(A, B, C, D, E, R(70));
+ P(E, A, B, C, D, R(71));
+ P(D, E, A, B, C, R(72));
+ P(C, D, E, A, B, R(73));
+ P(B, C, D, E, A, R(74));
+ P(A, B, C, D, E, R(75));
+ P(E, A, B, C, D, R(76));
+ P(D, E, A, B, C, R(77));
+ P(C, D, E, A, B, R(78));
+ P(B, C, D, E, A, R(79));
+
+#undef K
+#undef F
+
+ A += INIT_SHA1_A;
+ B += INIT_SHA1_B;
+ C += INIT_SHA1_C;
+ D += INIT_SHA1_D;
+ E += INIT_SHA1_E;
+
+ // store state for 2nd part
+ state[0] = A;
+ state[1] = B;
+ state[2] = C;
+ state[3] = D;
+ state[4] = E;
+
+ GET_WORD_32_BE(W[ 0], buf, 0);
+ GET_WORD_32_BE(W[ 1], buf, 4);
+ GET_WORD_32_BE(W[ 2], buf, 8);
+ GET_WORD_32_BE(W[ 3], buf, 12);
+ GET_WORD_32_BE(W[ 4], buf, 16);
+ GET_WORD_32_BE(W[ 5], buf, 20);
+ GET_WORD_32_BE(W[ 6], buf, 24);
+ GET_WORD_32_BE(W[ 7], buf, 28);
+ GET_WORD_32_BE(W[ 8], buf, 32);
+ GET_WORD_32_BE(W[ 9], buf, 36);
+ GET_WORD_32_BE(W[10], buf, 40);
+ GET_WORD_32_BE(W[11], buf, 44);
+ GET_WORD_32_BE(W[12], buf, 48);
+ GET_WORD_32_BE(W[13], buf, 52);
+ GET_WORD_32_BE(W[14], buf, 56);
+ GET_WORD_32_BE(W[15], buf, 60);
+
+#define F(x,y,z) (z ^ (x & (y ^ z)))
+#define K 0x5A827999
+
+ P(A, B, C, D, E, W[0] );
+ P(E, A, B, C, D, W[1] );
+ P(D, E, A, B, C, W[2] );
+ P(C, D, E, A, B, W[3] );
+ P(B, C, D, E, A, W[4] );
+ P(A, B, C, D, E, W[5] );
+ P(E, A, B, C, D, W[6] );
+ P(D, E, A, B, C, W[7] );
+ P(C, D, E, A, B, W[8] );
+ P(B, C, D, E, A, W[9] );
+ P(A, B, C, D, E, W[10]);
+ P(E, A, B, C, D, W[11]);
+ P(D, E, A, B, C, W[12]);
+ P(C, D, E, A, B, W[13]);
+ P(B, C, D, E, A, W[14]);
+ P(A, B, C, D, E, W[15]);
+ P(E, A, B, C, D, R(16));
+ P(D, E, A, B, C, R(17));
+ P(C, D, E, A, B, R(18));
+ P(B, C, D, E, A, R(19));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0x6ED9EBA1
+
+ P(A, B, C, D, E, R(20));
+ P(E, A, B, C, D, R(21));
+ P(D, E, A, B, C, R(22));
+ P(C, D, E, A, B, R(23));
+ P(B, C, D, E, A, R(24));
+ P(A, B, C, D, E, R(25));
+ P(E, A, B, C, D, R(26));
+ P(D, E, A, B, C, R(27));
+ P(C, D, E, A, B, R(28));
+ P(B, C, D, E, A, R(29));
+ P(A, B, C, D, E, R(30));
+ P(E, A, B, C, D, R(31));
+ P(D, E, A, B, C, R(32));
+ P(C, D, E, A, B, R(33));
+ P(B, C, D, E, A, R(34));
+ P(A, B, C, D, E, R(35));
+ P(E, A, B, C, D, R(36));
+ P(D, E, A, B, C, R(37));
+ P(C, D, E, A, B, R(38));
+ P(B, C, D, E, A, R(39));
+
+#undef K
+#undef F
+
+#define F(x,y,z) ((x & y) | (z & (x | y)))
+#define K 0x8F1BBCDC
+
+ P(A, B, C, D, E, R(40));
+ P(E, A, B, C, D, R(41));
+ P(D, E, A, B, C, R(42));
+ P(C, D, E, A, B, R(43));
+ P(B, C, D, E, A, R(44));
+ P(A, B, C, D, E, R(45));
+ P(E, A, B, C, D, R(46));
+ P(D, E, A, B, C, R(47));
+ P(C, D, E, A, B, R(48));
+ P(B, C, D, E, A, R(49));
+ P(A, B, C, D, E, R(50));
+ P(E, A, B, C, D, R(51));
+ P(D, E, A, B, C, R(52));
+ P(C, D, E, A, B, R(53));
+ P(B, C, D, E, A, R(54));
+ P(A, B, C, D, E, R(55));
+ P(E, A, B, C, D, R(56));
+ P(D, E, A, B, C, R(57));
+ P(C, D, E, A, B, R(58));
+ P(B, C, D, E, A, R(59));
+
+#undef K
+#undef F
+
+#define F(x,y,z) (x ^ y ^ z)
+#define K 0xCA62C1D6
+
+ P(A, B, C, D, E, R(60));
+ P(E, A, B, C, D, R(61));
+ P(D, E, A, B, C, R(62));
+ P(C, D, E, A, B, R(63));
+ P(B, C, D, E, A, R(64));
+ P(A, B, C, D, E, R(65));
+ P(E, A, B, C, D, R(66));
+ P(D, E, A, B, C, R(67));
+ P(C, D, E, A, B, R(68));
+ P(B, C, D, E, A, R(69));
+ P(A, B, C, D, E, R(70));
+ P(E, A, B, C, D, R(71));
+ P(D, E, A, B, C, R(72));
+ P(C, D, E, A, B, R(73));
+ P(B, C, D, E, A, R(74));
+ P(A, B, C, D, E, R(75));
+ P(E, A, B, C, D, R(76));
+ P(D, E, A, B, C, R(77));
+ P(C, D, E, A, B, R(78));
+ P(B, C, D, E, A, R(79));
+
+#undef K
+#undef F
+
+ A += state[0];
+ B += state[1];
+ C += state[2];
+ D += state[3];
+ E += state[4];
+
+ PUT_WORD_32_BE(A, output, 0);
+ PUT_WORD_32_BE(B, output, 4);
+ PUT_WORD_32_BE(C, output, 8);
+ PUT_WORD_32_BE(D, output, 12);
+ PUT_WORD_32_BE(E, output, 16);
+}
+
+
+/* PBKDF2
+ * stripped-down implementation
+ * based on the source code written by Dr Stephen N Henson (shenson@...foot.com) for the OpenSSL Project 1999
+ */
+static void PBKDF2_DCC2(const unsigned char *pass, const unsigned char *salt, int saltlen, unsigned char *out)
+{
+ unsigned char temp[SHA1_DIGEST_LENGTH];
+ unsigned char buf[48];
+ unsigned int i;
+
+ memset(buf, 0, 48);
+ memcpy(buf, salt, saltlen);
+ buf[saltlen + 3] = 0x01;
+
+ hmac_sha1(pass, 16, buf, saltlen + 4, temp);
+
+ memcpy(out, temp, 16);
+
+ for (i = 1; i < ITERATIONS; i++)
+ {
+ hmac_sha1(pass, 16, temp, SHA1_DIGEST_LENGTH, temp);
+
+ out[ 0] ^= temp[0];
+ out[ 1] ^= temp[1];
+ out[ 2] ^= temp[2];
+ out[ 3] ^= temp[3];
+ out[ 4] ^= temp[4];
+ out[ 5] ^= temp[5];
+ out[ 6] ^= temp[6];
+ out[ 7] ^= temp[7];
+ out[ 8] ^= temp[8];
+ out[ 9] ^= temp[9];
+ out[10] ^= temp[10];
+ out[11] ^= temp[11];
+ out[12] ^= temp[12];
+ out[13] ^= temp[13];
+ out[14] ^= temp[14];
+ out[15] ^= temp[15];
+ out[16] ^= temp[16];
+ }
+}
+
+
+static void crypt_all(int count)
+{
+ unsigned int a;
+ unsigned int b;
+ unsigned int c;
+ unsigned int d;
+ unsigned int i = 0;
+
+ if (new_key)
+ {
+ new_key = 0;
+ nt_hash();
+ }
+
+ for(; i < MS_NUM_KEYS; i++)
+ {
+ a = last[4 * i + 0];
+ b = last[4 * i + 1];
+ c = last[4 * i + 2];
+ d = last[4 * i + 3];
+
+ a += (d ^ (b & (c ^ d))) + salt_buffer[0] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + salt_buffer[1] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + salt_buffer[2] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a))) + salt_buffer[3] ;b = (b << 19) | (b >> 13);
+
+ a += (d ^ (b & (c ^ d))) + salt_buffer[4] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + salt_buffer[5] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + salt_buffer[6] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a))) + salt_buffer[7] ;b = (b << 19) | (b >> 13);
+
+ a += (d ^ (b & (c ^ d))) + salt_buffer[8] ;a = (a << 3 ) | (a >> 29);
+ d += (c ^ (a & (b ^ c))) + salt_buffer[9] ;d = (d << 7 ) | (d >> 25);
+ c += (b ^ (d & (a ^ b))) + salt_buffer[10] ;c = (c << 11) | (c >> 21);
+ b += (a ^ (c & (d ^ a)))/*+salt_buffer[11]*/;b = (b << 19) | (b >> 13);
+
+ // round 2
+ a += ((b & (c | d)) | (c & d)) + crypt[4 * i + 0] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + salt_buffer[0] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + salt_buffer[4] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + salt_buffer[8] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + crypt[4 * i + 1] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + salt_buffer[1] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + salt_buffer[5] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + salt_buffer[9] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + crypt[4 * i + 2] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + salt_buffer[2] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + salt_buffer[6] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a)) + salt_buffer[10] + SQRT_2; b = (b << 13) | (b >> 19);
+
+ a += ((b & (c | d)) | (c & d)) + crypt[4 * i + 3] + SQRT_2; a = (a << 3 ) | (a >> 29);
+ d += ((a & (b | c)) | (b & c)) + salt_buffer[3] + SQRT_2; d = (d << 5 ) | (d >> 27);
+ c += ((d & (a | b)) | (a & b)) + salt_buffer[7] + SQRT_2; c = (c << 9 ) | (c >> 23);
+ b += ((c & (d | a)) | (d & a))/*+ salt_buffer[11]*/ + SQRT_2; b = (b << 13) | (b >> 19);
+
+ // round 3
+ a += (b ^ c ^ d) + crypt[4 * i + 0] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + salt_buffer[4] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + salt_buffer[0] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + salt_buffer[8] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + crypt[4 * i + 2] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + salt_buffer[6] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + salt_buffer[2] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + salt_buffer[10] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + crypt[4 * i + 1] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + salt_buffer[5] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + salt_buffer[1] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) + salt_buffer[9] + SQRT_3; b = (b << 15) | (b >> 17);
+
+ a += (b ^ c ^ d) + crypt[4 * i + 3] + SQRT_3; a = (a << 3 ) | (a >> 29);
+ d += (a ^ b ^ c) + salt_buffer[7] + SQRT_3; d = (d << 9 ) | (d >> 23);
+ c += (d ^ a ^ b) + salt_buffer[3] + SQRT_3; c = (c << 11) | (c >> 21);
+ b += (c ^ d ^ a) /*+ salt_buffer[11] */ + SQRT_3; b = (b << 15) | (b >> 17);
+
+ output1x[4 * i + 0] = a + INIT_MD4_A;
+ output1x[4 * i + 1] = b + INIT_MD4_B;
+ output1x[4 * i + 2] = c + INIT_MD4_C;
+ output1x[4 * i + 3] = d + INIT_MD4_D;
+
+ // PBKDF2 for new Domain Cached Credentials (MS Cash 2)
+ PBKDF2_DCC2((unsigned char *)&output1x[4 * i], (unsigned char *)salt_buffer, salt_len, (unsigned char *)&output1x_dcc2[4 * i]);
+ }
+}
+
+
+static int cmp_all(void *binary, int count)
+{
+ unsigned int i = 0;
+ unsigned int d = ((unsigned int *)binary)[3];
+
+ for (; i < MS_NUM_KEYS; i++)
+ if (d == output1x_dcc2[i * 4 + 3])
+ return 1;
+
+ return 0;
+}
+
+
+static int cmp_one(void * binary, int index)
+{
+ unsigned int *t = (unsigned int *)binary;
+ unsigned int a = output1x_dcc2[4 * index + 0];
+ unsigned int b = output1x_dcc2[4 * index + 1];
+ unsigned int c = output1x_dcc2[4 * index + 2];
+ unsigned int d = output1x_dcc2[4 * index + 3];
+
+ if (d != t[3])
+ return 0;
+
+ if (c != t[2])
+ return 0;
+
+ if (b != t[1])
+ return 0;
+
+ return (a == t[0]);
+}
+
+
+static int cmp_exact(char *source, int index)
+{
+ // This check is for the improbable case of collisions.
+ // It checks if the salts are the same.
+ unsigned int *salt = get_salt(source);
+ unsigned int i = 0;
+ for(; i < 11; i++)
+ if(salt[i] != salt_buffer[i])
+ return 0;
+ return 1;
+}
+
+
+static void set_key(char *key, int index)
+{
+ unsigned int md4_size = 0;
+ unsigned int i = 0;
+ unsigned int temp;
+ unsigned int saved_base = index << 5;
+ unsigned int buff_base = index << 4;
+
+ for(; key[md4_size] && md4_size < PLAINTEXT_LENGTH; i++, md4_size++)
+ {
+ saved_plain[saved_base + md4_size] = key[md4_size];
+ temp = key[++md4_size];
+ saved_plain[saved_base + md4_size] = temp;
+
+ if(temp)
+ {
+ ms_buffer1x[buff_base + i] = key[md4_size - 1] | (temp << 16);
+ }
+ else
+ {
+ ms_buffer1x[buff_base + i] = key[md4_size - 1] | 0x800000;
+ goto key_cleaning;
+ }
+ }
+
+ ms_buffer1x[buff_base + i] = 0x80;
+ saved_plain[saved_base + md4_size] = 0;
+
+key_cleaning:
+ i++;
+ for(; i <= last_i[index]; i++)
+ ms_buffer1x[buff_base + i] = 0;
+
+ last_i[index] = md4_size >> 1;
+
+ ms_buffer1x[buff_base + 14] = md4_size << 4;
+
+ // new password candidate
+ new_key = 1;
+}
+
+
+static char *get_key(int index)
+{
+ return saved_plain +( index << 5);
+}
+
+
+static int salt_hash(void *salt)
+{
+ return ((unsigned char*)salt)[0];
+}
+
+
+struct fmt_main fmt_mscash2 = {
+ {
+ FORMAT_LABEL,
+ FORMAT_NAME,
+ ALGORITHM_NAME,
+ BENCHMARK_COMMENT,
+ BENCHMARK_LENGTH,
+ PLAINTEXT_LENGTH,
+ BINARY_SIZE,
+ SALT_SIZE,
+ MIN_KEYS_PER_CRYPT,
+ MAX_KEYS_PER_CRYPT,
+ FMT_CASE | FMT_8_BIT | FMT_SPLIT_UNIFIES_CASE,
+ tests
+ }, {
+ init,
+ valid,
+ ms_split,
+ get_binary,
+ get_salt,
+ {
+ binary_hash_0,
+ binary_hash_1,
+ binary_hash_2,
+ NULL,
+ NULL
+ },
+ salt_hash,
+ set_salt,
+ set_key,
+ get_key,
+ fmt_default_clear_keys,
+ crypt_all,
+ {
+ get_hash_0,
+ get_hash_1,
+ get_hash_2,
+ NULL,
+ NULL
+ },
+ cmp_all,
+ cmp_one,
+ cmp_exact
+ }
+};
+
diff -urpN john-1.7.6-jumbo-9/src/options.c john-1.7.6-jumbo-9-mscash2/src/options.c
--- john-1.7.6-jumbo-9/src/options.c 2010-12-26 16:03:43.000000000 +0000
+++ john-1.7.6-jumbo-9-mscash2/src/options.c 2010-12-26 16:04:10.000000000 +0000
@@ -141,7 +141,7 @@ static struct opt_entry opt_list[] = {
" DES/BSDI/MD5/BF/AFS/LM/NT/XSHA/PO/raw-MD5/MD5-gen/\n" \
" IPB2/raw-sha1/md5a/hmac-md5/phpass-md5/KRB5/bfegg/\n" \
" nsldap/ssha/openssha/oracle/oracle11/MYSQL/\n" \
-" mysql-sha1/mscash/lotus5/DOMINOSEC/\n" \
+" mysql-sha1/mscash/mscash2/lotus5/DOMINOSEC/\n" \
" NETLM/NETNTLM/NETLMv2/NETNTLMv2/NETHALFLM/MSCHAPv2/\n" \
" mssql/mssql05/epi/phps/mysql-fast/pix-md5/sapG/\n" \
" sapB/md5ns/HDAA/DMD5/raw-md4/md4-gen/sha1-gen" \
Powered by blists - more mailing lists
Powered by Openwall GNU/*/Linux -
Powered by OpenVZ