Module: wine Branch: refs/heads/master Commit: dcfb0f44d1bef8516620d0886f220429ae9a2a56 URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=dcfb0f44d1bef8516620d088...
Author: Mike McCormack mike@codeweavers.com Date: Sun May 14 17:11:16 2006 +0900
advapi32: Implement and test SystemFunction004.
---
dlls/advapi32/advapi32.spec | 2 - dlls/advapi32/crypt.h | 6 ++ dlls/advapi32/crypt_arc4.c | 8 +-- dlls/advapi32/crypt_lmhash.c | 62 +++++++++++++++++++++++++ dlls/advapi32/tests/crypt_lmhash.c | 88 ++++++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 7 deletions(-)
diff --git a/dlls/advapi32/advapi32.spec b/dlls/advapi32/advapi32.spec index f9b909b..9f815f5 100644 --- a/dlls/advapi32/advapi32.spec +++ b/dlls/advapi32/advapi32.spec @@ -598,7 +598,7 @@ # @ stub StopTraceW @ stdcall SystemFunction001(ptr ptr ptr) @ stdcall SystemFunction002(ptr ptr ptr) @ stdcall SystemFunction003(ptr ptr) -@ stub SystemFunction004 +@ stdcall SystemFunction004(ptr ptr ptr) @ stub SystemFunction005 @ stdcall SystemFunction006(ptr ptr) @ stdcall SystemFunction007(ptr ptr) diff --git a/dlls/advapi32/crypt.h b/dlls/advapi32/crypt.h index 207ef5d..7959fcc 100644 --- a/dlls/advapi32/crypt.h +++ b/dlls/advapi32/crypt.h @@ -88,4 +88,10 @@ extern unsigned char *CRYPT_DEShash( uns extern unsigned char *CRYPT_DESunhash( unsigned char *dst, const unsigned char *key, const unsigned char *src );
+struct ustring { + DWORD Length; + DWORD MaximumLength; + unsigned char *Buffer; +}; + #endif /* __WINE_CRYPT_H_ */ diff --git a/dlls/advapi32/crypt_arc4.c b/dlls/advapi32/crypt_arc4.c index 9ee4b5e..2bdb5d3 100644 --- a/dlls/advapi32/crypt_arc4.c +++ b/dlls/advapi32/crypt_arc4.c @@ -27,6 +27,8 @@ #define WIN32_NO_STATUS #include "windef.h" #include "winternl.h"
+#include "crypt.h" + typedef struct tag_arc4_info { unsigned char state[256]; unsigned char x, y; @@ -76,12 +78,6 @@ static void arc4_ProcessString(arc4_info a4i->y = y; }
-struct ustring { - DWORD Length; - DWORD MaximumLength; - unsigned char *Buffer; -}; - /****************************************************************************** * SystemFunction032 [ADVAPI32.@] * diff --git a/dlls/advapi32/crypt_lmhash.c b/dlls/advapi32/crypt_lmhash.c index 0d00777..7070154 100644 --- a/dlls/advapi32/crypt_lmhash.c +++ b/dlls/advapi32/crypt_lmhash.c @@ -157,3 +157,65 @@ NTSTATUS WINAPI SystemFunction003(const CRYPT_DEShash(output, key, CRYPT_LMhash_Magic); return STATUS_SUCCESS; } + +/****************************************************************************** + * SystemFunction004 [ADVAPI32.@] + * + * Encrypts a block of data with DES in ECB mode, preserving the length + * + * PARAMS + * data [I] data to encrypt + * key [I] key data (up to 7 bytes) + * output [O] buffer to receive encrypted data + * + * RETURNS + * Success: STATUS_SUCCESS + * Failure: STATUS_BUFFER_TOO_SMALL if the output buffer is too small + * Failure: STATUS_INVALID_PARAMETER_2 if the key is zero length + * + * NOTES + * Encrypt buffer size should be input size rounded up to 8 bytes + * plus an extra 8 bytes. + */ +NTSTATUS WINAPI SystemFunction004(const struct ustring *in, + const struct ustring *key, + struct ustring *out) +{ + union { + unsigned char uc[8]; + unsigned int ui[2]; + } data; + unsigned char deskey[7]; + int crypt_len, ofs; + + if (key->Length<=0) + return STATUS_INVALID_PARAMETER_2; + + crypt_len = ((in->Length+7)&~7); + if (out->MaximumLength < (crypt_len+8)) + return STATUS_BUFFER_TOO_SMALL; + + data.ui[0] = in->Length; + data.ui[1] = 1; + + if (key->Length<sizeof deskey) + { + memset(deskey, 0, sizeof deskey); + memcpy(deskey, key->Buffer, key->Length); + } + else + memcpy(deskey, key->Buffer, sizeof deskey); + + CRYPT_DEShash(out->Buffer, deskey, data.uc); + + for(ofs=0; ofs<(crypt_len-8); ofs+=8) + CRYPT_DEShash(out->Buffer+8+ofs, deskey, in->Buffer+ofs); + + memset(data.uc, 0, sizeof data.uc); + memcpy(data.uc, in->Buffer+ofs, in->Length +8-crypt_len); + CRYPT_DEShash(out->Buffer+8+ofs, deskey, data.uc); + + out->Length = crypt_len+8; + + return STATUS_SUCCESS; +} diff --git a/dlls/advapi32/tests/crypt_lmhash.c b/dlls/advapi32/tests/crypt_lmhash.c index 207a3e6..2edb843 100644 --- a/dlls/advapi32/tests/crypt_lmhash.c +++ b/dlls/advapi32/tests/crypt_lmhash.c @@ -37,6 +37,7 @@ struct ustring { typedef NTSTATUS (WINAPI *fnSystemFunction001)(const LPBYTE, const LPBYTE, LPBYTE); typedef NTSTATUS (WINAPI *fnSystemFunction002)(const LPBYTE, const LPBYTE, LPBYTE); typedef NTSTATUS (WINAPI *fnSystemFunction003)(const LPBYTE, LPBYTE); +typedef NTSTATUS (WINAPI *fnSystemFunction004)(const struct ustring *, const struct ustring *, struct ustring *); typedef VOID (WINAPI *fnSystemFunction006)( PCSTR passwd, PSTR lmhash ); typedef NTSTATUS (WINAPI *fnSystemFunction008)(const LPBYTE, const LPBYTE, LPBYTE); typedef NTSTATUS (WINAPI *fnSystemFunction032)(struct ustring *, struct ustring *); @@ -44,6 +45,7 @@ typedef NTSTATUS (WINAPI *fnSystemFuncti fnSystemFunction001 pSystemFunction001; fnSystemFunction002 pSystemFunction002; fnSystemFunction003 pSystemFunction003; +fnSystemFunction004 pSystemFunction004; fnSystemFunction006 pSystemFunction006; fnSystemFunction008 pSystemFunction008; fnSystemFunction032 pSystemFunction032; @@ -190,6 +192,88 @@ static void test_SystemFunction003(void) ok( !memcmp(exp2, output, sizeof output), "decrypted message wrong\n"); }
+static void test_SystemFunction004(void) +{ + unsigned char inbuf[0x100], keybuf[0x100], resbuf[0x100]; + unsigned char output[8]; + int r; + struct ustring in, key, out; + + /* crash + r = pSystemFunction004(NULL, NULL, NULL); + ok(r == STATUS_UNSUCCESSFUL, "function failed\n"); + */ + + memset(inbuf, 0, sizeof inbuf); + memset(keybuf, 0, sizeof keybuf); + memset(resbuf, 0, sizeof resbuf); + + in.Buffer = NULL; + in.Length = in.MaximumLength = 0; + + key.Buffer = NULL; + key.Length = key.MaximumLength = 0; + + out.Buffer = NULL; + out.Length = out.MaximumLength = 0; + + r = pSystemFunction004(&in, &key, &out); + ok(r == STATUS_INVALID_PARAMETER_2, "function failed\n"); + + key.Buffer = keybuf; + key.Length = 0x100; + key.MaximumLength = 0x100; + + r = pSystemFunction004(&in, &key, (struct ustring *)&out); + ok(r == STATUS_BUFFER_TOO_SMALL, "function failed\n"); + + in.Buffer = inbuf; + in.Length = 0x0c; + in.MaximumLength = 0; + + /* add two identical blocks... */ + inbuf[0] = 1; + inbuf[1] = 2; + inbuf[2] = 3; + inbuf[3] = 4; + + inbuf[8] = 1; + inbuf[9] = 2; + inbuf[10] = 3; + inbuf[11] = 4; + + /* check that the Length field is really obeyed */ + keybuf[6] = 1; + + key.Buffer = keybuf; + key.Length = 6; + key.MaximumLength = 0; + + keybuf[1] = 0x33; + + out.Buffer = resbuf; + out.Length = 0; + out.MaximumLength = 0x40; + r = pSystemFunction004(&in, &key, &out); + ok(r == STATUS_SUCCESS, "function failed\n"); + + keybuf[6] = 0; + + memset(output, 0, sizeof output); + r = pSystemFunction002(out.Buffer, key.Buffer, output); + + ok(((unsigned int*)output)[0] == in.Length, "crypted length wrong\n"); + ok(((unsigned int*)output)[1] == 1, "crypted value wrong\n"); + + memset(output, 0, sizeof output); + r = pSystemFunction002(out.Buffer+8, key.Buffer, output); + ok(!memcmp(output, inbuf, sizeof output), "crypted data wrong\n"); + + memset(output, 0, sizeof output); + r = pSystemFunction002(out.Buffer+16, key.Buffer, output); + ok(!memcmp(output, inbuf, sizeof output), "crypted data wrong\n"); +} + START_TEST(crypt_lmhash) { HMODULE module; @@ -208,6 +292,10 @@ START_TEST(crypt_lmhash) if (pSystemFunction003) test_SystemFunction003();
+ pSystemFunction004 = (fnSystemFunction004)GetProcAddress( module, "SystemFunction004" ); + if (pSystemFunction004) + test_SystemFunction004(); + pSystemFunction006 = (fnSystemFunction006)GetProcAddress( module, "SystemFunction006" ); if (pSystemFunction006) test_SystemFunction006();