Commit dcfb0f44 authored by Mike McCormack's avatar Mike McCormack Committed by Alexandre Julliard

advapi32: Implement and test SystemFunction004.

parent 09fc7e04
......@@ -598,7 +598,7 @@
@ 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)
......
......@@ -88,4 +88,10 @@ extern unsigned char *CRYPT_DEShash( unsigned char *dst, const unsigned char *ke
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_ */
......@@ -27,6 +27,8 @@
#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, BYTE *inoutString, unsigned int l
a4i->y = y;
}
struct ustring {
DWORD Length;
DWORD MaximumLength;
unsigned char *Buffer;
};
/******************************************************************************
* SystemFunction032 [ADVAPI32.@]
*
......
......@@ -157,3 +157,65 @@ NTSTATUS WINAPI SystemFunction003(const LPBYTE key, LPBYTE output)
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;
}
......@@ -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 *fnSystemFunction032)(struct ustring *, struct ustring
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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment