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