diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index c824421523..cb747b0ac8 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -596,7 +596,7 @@ # @ stub StopTraceW @ stdcall SynchronizeWindows31FilesAndWindowsNTRegistry(long long long long) @ stdcall SystemFunction001(ptr ptr ptr) -@ stub SystemFunction002 +@ stdcall SystemFunction002(ptr ptr ptr) @ stub SystemFunction003 @ stub SystemFunction004 @ stub SystemFunction005 diff --git a/dlls/advapi32/crypt.h b/dlls/advapi32/crypt.h index f5696e61dc..207ef5de0c 100644 --- a/dlls/advapi32/crypt.h +++ b/dlls/advapi32/crypt.h @@ -85,5 +85,7 @@ typedef struct tagCRYPTHASH extern unsigned char *CRYPT_DESkey8to7( unsigned char *dst, const unsigned char *key ); extern unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key, const unsigned char *src ); +extern unsigned char *CRYPT_DESunhash( unsigned char *dst, const unsigned char *key, + const unsigned char *src ); #endif /* __WINE_CRYPT_H_ */ diff --git a/dlls/advapi32/crypt_des.c b/dlls/advapi32/crypt_des.c index 4b527dddf2..c2d6e9f79c 100644 --- a/dlls/advapi32/crypt_des.c +++ b/dlls/advapi32/crypt_des.c @@ -1,5 +1,6 @@ /* * Copyright 2004 Hans Leidekker + * Copyright 2006 Mike McCormack * * Based on DES.c from libcifs * @@ -159,9 +160,9 @@ static void Permute( unsigned char *dst, const unsigned char *src, const unsigne if (GETBIT( src, map[i] )) SETBIT( dst, i ); } -} +} -static void KeyShift( unsigned char *key, const int numbits ) +static void KeyShiftLeft( unsigned char *key, const int numbits ) { int i; unsigned char keep = key[0]; @@ -190,6 +191,35 @@ static void KeyShift( unsigned char *key, const int numbits ) } } +static void KeyShiftRight( unsigned char *key, const int numbits ) +{ + int i; + unsigned char keep = key[6]; + + for (i = 0; i < numbits; i++) + { + int j; + + for (j = 7; j >= 0; j--) + { + if (j!=7 && (key[j] & 0x01)) + key[j+1] |= 0x80; + key[j] >>= 1; + } + + if (GETBIT( key, 28 )) + { + CLRBIT( key, 28 ); + SETBIT( key, 0 ); + } + + if (keep & 0x01) + SETBIT( key, 28 ); + + keep >>= 1; + } +} + static void sbox( unsigned char *dst, const unsigned char *src ) { int i; @@ -267,7 +297,7 @@ unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key, cons unsigned char Rn[4]; unsigned char SubK[6]; - KeyShift( K, KeyRotation[i] ); + KeyShiftLeft( K, KeyRotation[i] ); Permute( SubK, K, KeyCompression, 6 ); Permute( Rexp, R, DataExpansion, 6 ); @@ -288,3 +318,44 @@ unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *key, cons return dst; } + +unsigned char *CRYPT_DESunhash( unsigned char *dst, const unsigned char *key, const unsigned char *src ) +{ + int i; + unsigned char K[7]; + unsigned char D[8]; + + Permute( K, key, KeyPermuteMap, 7 ); + Permute( D, src, InitialPermuteMap, 8 ); + + for (i = 0; i < 16; i++) + { + int j; + unsigned char *L = D; + unsigned char *R = &(D[4]); + unsigned char Rexp[6]; + unsigned char Rn[4]; + unsigned char SubK[6]; + + Permute( SubK, K, KeyCompression, 6 ); + + Permute( Rexp, R, DataExpansion, 6 ); + xor( Rexp, Rexp, SubK, 6 ); + + sbox( Rn, Rexp ); + Permute( Rexp, Rn, PBox, 4 ); + xor( Rn, L, Rexp, 4 ); + + for (j = 0; j < 4; j++) + { + L[j] = R[j]; + R[j] = Rn[j]; + } + + KeyShiftRight( K, KeyRotation[15 - i] ); + } + + Permute( dst, D, FinalPermuteMap, 8 ); + + return dst; +} diff --git a/dlls/advapi32/crypt_lmhash.c b/dlls/advapi32/crypt_lmhash.c index 01f6049e41..85e29fb9b7 100644 --- a/dlls/advapi32/crypt_lmhash.c +++ b/dlls/advapi32/crypt_lmhash.c @@ -112,3 +112,26 @@ NTSTATUS WINAPI SystemFunction001(const LPBYTE data, const LPBYTE key, LPBYTE ou CRYPT_DEShash(output, key, data); return STATUS_SUCCESS; } + +/****************************************************************************** + * SystemFunction002 [ADVAPI32.@] + * + * Decrypts a single block of data using DES + * + * PARAMS + * data [I] data to decrypt (8 bytes) + * key [I] key data (7 bytes) + * output [O] the decrypted data (8 bytes) + * + * RETURNS + * Success: STATUS_SUCCESS + * Failure: STATUS_UNSUCCESSFUL + * + */ +NTSTATUS WINAPI SystemFunction002(const LPBYTE data, const LPBYTE key, LPBYTE output) +{ + if (!data || !output) + return STATUS_UNSUCCESSFUL; + CRYPT_DESunhash(output, key, data); + return STATUS_SUCCESS; +} diff --git a/dlls/advapi32/tests/crypt_lmhash.c b/dlls/advapi32/tests/crypt_lmhash.c index 0e45ddcafe..c0353d34e4 100644 --- a/dlls/advapi32/tests/crypt_lmhash.c +++ b/dlls/advapi32/tests/crypt_lmhash.c @@ -37,11 +37,13 @@ struct ustring { typedef VOID (WINAPI *fnSystemFunction006)( PCSTR passwd, PSTR lmhash ); typedef NTSTATUS (WINAPI *fnSystemFunction008)(const LPBYTE, const LPBYTE, LPBYTE); typedef NTSTATUS (WINAPI *fnSystemFunction001)(const LPBYTE, const LPBYTE, LPBYTE); +typedef NTSTATUS (WINAPI *fnSystemFunction002)(const LPBYTE, const LPBYTE, LPBYTE); typedef NTSTATUS (WINAPI *fnSystemFunction032)(struct ustring *, struct ustring *); fnSystemFunction006 pSystemFunction006; fnSystemFunction008 pSystemFunction008; fnSystemFunction001 pSystemFunction001; +fnSystemFunction002 pSystemFunction002; fnSystemFunction032 pSystemFunction032; static void test_SystemFunction006(void) @@ -122,6 +124,21 @@ static void test_SystemFunction001(void) ok(!memcmp(output, expected, sizeof expected), "response wrong\n"); } +static void test_SystemFunction002(void) +{ + /* reverse of SystemFunction001 */ + unsigned char key[8] = { 0xff, 0x37, 0x50, 0xbc, 0xc2, 0xb2, 0x24, 0 }; + unsigned char expected[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef }; + unsigned char data[8] = { 0xc3, 0x37, 0xcd, 0x5c, 0xbd, 0x44, 0xfc, 0x97 }; + unsigned char output[8]; + int r; + + memset(output, 0, sizeof output); + r = pSystemFunction002(data, key, output); + ok(r == STATUS_SUCCESS, "function failed\n"); + ok(!memcmp(output, expected, sizeof expected), "response wrong\n"); +} + static void test_SystemFunction032(void) { struct ustring key, data; @@ -143,7 +160,7 @@ static void test_SystemFunction032(void) r = pSystemFunction032(&data, &key); ok(r == STATUS_SUCCESS, "function failed\n"); - ok( !memcmp(expected, data.Buffer, data.Length), "wrong result\n"); + ok(!memcmp(expected, data.Buffer, data.Length), "wrong result\n"); } START_TEST(crypt_lmhash) @@ -168,5 +185,9 @@ START_TEST(crypt_lmhash) if (pSystemFunction032) test_SystemFunction032(); + pSystemFunction002 = (fnSystemFunction002)GetProcAddress( module, "SystemFunction002" ); + if (pSystemFunction002) + test_SystemFunction002(); + FreeLibrary( module ); }