Mike McCormack : advapi32: Implement and test SystemFunction004.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon May 15 07:35:00 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: dcfb0f44d1bef8516620d0886f220429ae9a2a56
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=dcfb0f44d1bef8516620d0886f220429ae9a2a56
Author: Mike McCormack <mike at 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();
More information about the wine-cvs
mailing list