1*f61e14f5SRatin Gao /*
2*f61e14f5SRatin Gao  * PROJECT:     ReactOS API tests
3*f61e14f5SRatin Gao  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4*f61e14f5SRatin Gao  * PURPOSE:     Tests for basic hash APIs
5*f61e14f5SRatin Gao  * COPYRIGHT:   Copyright 2023 Ratin Gao <ratin@knsoft.org>
6*f61e14f5SRatin Gao  */
7*f61e14f5SRatin Gao 
8*f61e14f5SRatin Gao #include "precomp.h"
9*f61e14f5SRatin Gao 
10*f61e14f5SRatin Gao typedef struct _A_SHA_CTX
11*f61e14f5SRatin Gao {
12*f61e14f5SRatin Gao     UCHAR Buffer[64];
13*f61e14f5SRatin Gao     ULONG State[5];
14*f61e14f5SRatin Gao     ULONG Count[2];
15*f61e14f5SRatin Gao } A_SHA_CTX, *PA_SHA_CTX;
16*f61e14f5SRatin Gao 
17*f61e14f5SRatin Gao #define A_SHA_DIGEST_LEN 20
18*f61e14f5SRatin Gao 
19*f61e14f5SRatin Gao typedef struct _MD5_CTX
20*f61e14f5SRatin Gao {
21*f61e14f5SRatin Gao     ULONG Count[2];
22*f61e14f5SRatin Gao     ULONG State[4];
23*f61e14f5SRatin Gao     UCHAR Buffer[64];
24*f61e14f5SRatin Gao     UCHAR Hash[16];
25*f61e14f5SRatin Gao } MD5_CTX, *PMD5_CTX;
26*f61e14f5SRatin Gao 
27*f61e14f5SRatin Gao #define MD5_DIGEST_LEN 16
28*f61e14f5SRatin Gao 
29*f61e14f5SRatin Gao typedef struct _MD4_CTX
30*f61e14f5SRatin Gao {
31*f61e14f5SRatin Gao     ULONG State[4];
32*f61e14f5SRatin Gao     ULONG Count[2];
33*f61e14f5SRatin Gao     UCHAR Buffer[64];
34*f61e14f5SRatin Gao     UCHAR Hash[16];
35*f61e14f5SRatin Gao } MD4_CTX, *PMD4_CTX;
36*f61e14f5SRatin Gao 
37*f61e14f5SRatin Gao #define MD4_DIGEST_LEN 16
38*f61e14f5SRatin Gao 
39*f61e14f5SRatin Gao #ifndef RSA32API
40*f61e14f5SRatin Gao #define RSA32API __stdcall
41*f61e14f5SRatin Gao #endif
42*f61e14f5SRatin Gao 
43*f61e14f5SRatin Gao typedef
44*f61e14f5SRatin Gao VOID
45*f61e14f5SRatin Gao RSA32API
46*f61e14f5SRatin Gao FN_A_SHAInit(
47*f61e14f5SRatin Gao     _Out_ PA_SHA_CTX Context);
48*f61e14f5SRatin Gao 
49*f61e14f5SRatin Gao typedef
50*f61e14f5SRatin Gao VOID
51*f61e14f5SRatin Gao RSA32API
52*f61e14f5SRatin Gao FN_A_SHAUpdate(
53*f61e14f5SRatin Gao     _Inout_ PA_SHA_CTX Context,
54*f61e14f5SRatin Gao     _In_reads_(BufferSize) PUCHAR Buffer,
55*f61e14f5SRatin Gao     _In_ ULONG BufferSize);
56*f61e14f5SRatin Gao 
57*f61e14f5SRatin Gao typedef
58*f61e14f5SRatin Gao VOID
59*f61e14f5SRatin Gao RSA32API
60*f61e14f5SRatin Gao FN_A_SHAFinal(
61*f61e14f5SRatin Gao     _Inout_ PA_SHA_CTX Context,
62*f61e14f5SRatin Gao     _Out_ PUCHAR Result);
63*f61e14f5SRatin Gao 
64*f61e14f5SRatin Gao typedef
65*f61e14f5SRatin Gao VOID
66*f61e14f5SRatin Gao RSA32API
67*f61e14f5SRatin Gao FN_MD5Init(
68*f61e14f5SRatin Gao     _Out_ PMD5_CTX Context);
69*f61e14f5SRatin Gao 
70*f61e14f5SRatin Gao typedef
71*f61e14f5SRatin Gao VOID
72*f61e14f5SRatin Gao RSA32API
73*f61e14f5SRatin Gao FN_MD5Update(
74*f61e14f5SRatin Gao     _Inout_ PMD5_CTX Context,
75*f61e14f5SRatin Gao     _In_reads_(BufferSize) PUCHAR Buffer,
76*f61e14f5SRatin Gao     _In_ ULONG BufferSize);
77*f61e14f5SRatin Gao 
78*f61e14f5SRatin Gao typedef
79*f61e14f5SRatin Gao VOID
80*f61e14f5SRatin Gao RSA32API
81*f61e14f5SRatin Gao FN_MD5Final(
82*f61e14f5SRatin Gao     _Inout_ PMD5_CTX Context);
83*f61e14f5SRatin Gao 
84*f61e14f5SRatin Gao typedef
85*f61e14f5SRatin Gao VOID
86*f61e14f5SRatin Gao RSA32API
87*f61e14f5SRatin Gao FN_MD4Init(
88*f61e14f5SRatin Gao     _Out_ PMD4_CTX Context);
89*f61e14f5SRatin Gao 
90*f61e14f5SRatin Gao typedef
91*f61e14f5SRatin Gao VOID
92*f61e14f5SRatin Gao RSA32API
93*f61e14f5SRatin Gao FN_MD4Update(
94*f61e14f5SRatin Gao     _Inout_ PMD4_CTX Context,
95*f61e14f5SRatin Gao     _In_reads_(BufferSize) PUCHAR Buffer,
96*f61e14f5SRatin Gao     _In_ ULONG BufferSize);
97*f61e14f5SRatin Gao 
98*f61e14f5SRatin Gao typedef
99*f61e14f5SRatin Gao VOID
100*f61e14f5SRatin Gao RSA32API
101*f61e14f5SRatin Gao FN_MD4Final(
102*f61e14f5SRatin Gao     _Inout_ PMD4_CTX Context);
103*f61e14f5SRatin Gao 
104*f61e14f5SRatin Gao static HMODULE g_hAdvapi32 = NULL;
105*f61e14f5SRatin Gao static ANSI_STRING g_TestString = RTL_CONSTANT_STRING("ReactOS Hash API Test String");
106*f61e14f5SRatin Gao 
107*f61e14f5SRatin Gao static ULONG g_ctxSHA1StateInit[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 };
108*f61e14f5SRatin Gao static UCHAR g_aucSHA1Result[A_SHA_DIGEST_LEN] = {
109*f61e14f5SRatin Gao     0xEC, 0x05, 0x43, 0xE7, 0xDE, 0x8A, 0xEE, 0xFF,
110*f61e14f5SRatin Gao     0xAD, 0x72, 0x2B, 0x9D, 0x55, 0x4F, 0xCA, 0x6A,
111*f61e14f5SRatin Gao     0x8D, 0x81, 0xF1, 0xC7
112*f61e14f5SRatin Gao };
113*f61e14f5SRatin Gao 
114*f61e14f5SRatin Gao static ULONG g_aulMD5Or4StateInit[] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476 };
115*f61e14f5SRatin Gao static UCHAR g_aucMD5Result[MD5_DIGEST_LEN] = {
116*f61e14f5SRatin Gao     0x3D, 0xE8, 0x23, 0x8B, 0x9D, 0xE0, 0xCE, 0x48,
117*f61e14f5SRatin Gao     0xB1, 0x1B, 0xDD, 0xD9, 0xC6, 0x86, 0xB2, 0xDE
118*f61e14f5SRatin Gao };
119*f61e14f5SRatin Gao static UCHAR g_aucMD4Result[MD4_DIGEST_LEN] = {
120*f61e14f5SRatin Gao     0xE0, 0xE8, 0x50, 0x8A, 0x4D, 0x11, 0x02, 0xA6,
121*f61e14f5SRatin Gao     0x6A, 0xF0, 0xA7, 0xAB, 0xD8, 0xC4, 0x40, 0xED
122*f61e14f5SRatin Gao };
123*f61e14f5SRatin Gao 
Test_SHA1(void)124*f61e14f5SRatin Gao static void Test_SHA1(void)
125*f61e14f5SRatin Gao {
126*f61e14f5SRatin Gao     FN_A_SHAInit* pfnA_SHAInit;
127*f61e14f5SRatin Gao     FN_A_SHAUpdate* pfnA_SHAUpdate;
128*f61e14f5SRatin Gao     FN_A_SHAFinal* pfnA_SHAFinal;
129*f61e14f5SRatin Gao     DECLSPEC_ALIGN(4) A_SHA_CTX ctx;
130*f61e14f5SRatin Gao     UCHAR Result[A_SHA_DIGEST_LEN];
131*f61e14f5SRatin Gao     SIZE_T ComparedSize;
132*f61e14f5SRatin Gao 
133*f61e14f5SRatin Gao     /* Load functions */
134*f61e14f5SRatin Gao     pfnA_SHAInit = (FN_A_SHAInit*)GetProcAddress(g_hAdvapi32, "A_SHAInit");
135*f61e14f5SRatin Gao     pfnA_SHAUpdate = (FN_A_SHAUpdate*)GetProcAddress(g_hAdvapi32, "A_SHAUpdate");
136*f61e14f5SRatin Gao     pfnA_SHAFinal = (FN_A_SHAFinal*)GetProcAddress(g_hAdvapi32, "A_SHAFinal");
137*f61e14f5SRatin Gao 
138*f61e14f5SRatin Gao     if (!pfnA_SHAInit || !pfnA_SHAUpdate || !pfnA_SHAFinal)
139*f61e14f5SRatin Gao     {
140*f61e14f5SRatin Gao         skip("advapi32.dll!A_SHA*** not found\n");
141*f61e14f5SRatin Gao         return;
142*f61e14f5SRatin Gao     }
143*f61e14f5SRatin Gao 
144*f61e14f5SRatin Gao     /* Test A_SHAInit */
145*f61e14f5SRatin Gao     pfnA_SHAInit(&ctx);
146*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
147*f61e14f5SRatin Gao                                     g_ctxSHA1StateInit,
148*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(A_SHA_CTX, State));
149*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(A_SHA_CTX, State));
150*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0UL);
151*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
152*f61e14f5SRatin Gao 
153*f61e14f5SRatin Gao     /* Test A_SHAUpdate */
154*f61e14f5SRatin Gao     pfnA_SHAUpdate(&ctx, (PUCHAR)g_TestString.Buffer, g_TestString.Length);
155*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.Buffer,
156*f61e14f5SRatin Gao                                     g_TestString.Buffer,
157*f61e14f5SRatin Gao                                     g_TestString.Length);
158*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, g_TestString.Length);
159*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
160*f61e14f5SRatin Gao                                     g_ctxSHA1StateInit,
161*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(A_SHA_CTX, State));
162*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(A_SHA_CTX, State));
163*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0UL);
164*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], (ULONG)g_TestString.Length);
165*f61e14f5SRatin Gao 
166*f61e14f5SRatin Gao     /* Test A_SHAFinal */
167*f61e14f5SRatin Gao     pfnA_SHAFinal(&ctx, Result);
168*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemoryUlong(ctx.Buffer, sizeof(ctx.Buffer), 0);
169*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, sizeof(ctx.Buffer));
170*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
171*f61e14f5SRatin Gao                                     g_ctxSHA1StateInit,
172*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(A_SHA_CTX, State));
173*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(A_SHA_CTX, State));
174*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0UL);
175*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
176*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(Result, g_aucSHA1Result, A_SHA_DIGEST_LEN);
177*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, A_SHA_DIGEST_LEN);
178*f61e14f5SRatin Gao }
179*f61e14f5SRatin Gao 
Test_MD5(void)180*f61e14f5SRatin Gao static void Test_MD5(void)
181*f61e14f5SRatin Gao {
182*f61e14f5SRatin Gao     FN_MD5Init* pfnMD5Init;
183*f61e14f5SRatin Gao     FN_MD5Update* pfnMD5Update;
184*f61e14f5SRatin Gao     FN_MD5Final* pfnMD5Final;
185*f61e14f5SRatin Gao     DECLSPEC_ALIGN(4) MD5_CTX ctx;
186*f61e14f5SRatin Gao     SIZE_T ComparedSize;
187*f61e14f5SRatin Gao 
188*f61e14f5SRatin Gao     /* Load functions */
189*f61e14f5SRatin Gao     pfnMD5Init = (FN_MD5Init*)GetProcAddress(g_hAdvapi32, "MD5Init");
190*f61e14f5SRatin Gao     pfnMD5Update = (FN_MD5Update*)GetProcAddress(g_hAdvapi32, "MD5Update");
191*f61e14f5SRatin Gao     pfnMD5Final = (FN_MD5Final*)GetProcAddress(g_hAdvapi32, "MD5Final");
192*f61e14f5SRatin Gao 
193*f61e14f5SRatin Gao     if (!pfnMD5Init || !pfnMD5Update || !pfnMD5Final)
194*f61e14f5SRatin Gao     {
195*f61e14f5SRatin Gao         skip("advapi32.dll!MD5*** not found\n");
196*f61e14f5SRatin Gao         return;
197*f61e14f5SRatin Gao     }
198*f61e14f5SRatin Gao 
199*f61e14f5SRatin Gao     /* Test MD5Init */
200*f61e14f5SRatin Gao     pfnMD5Init(&ctx);
201*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0UL);
202*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
203*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
204*f61e14f5SRatin Gao                                     g_aulMD5Or4StateInit,
205*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(MD5_CTX, State));
206*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(MD5_CTX, State));
207*f61e14f5SRatin Gao 
208*f61e14f5SRatin Gao     /* Test MD5Update */
209*f61e14f5SRatin Gao     pfnMD5Update(&ctx, (PUCHAR)g_TestString.Buffer, g_TestString.Length);
210*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.Buffer,
211*f61e14f5SRatin Gao                                     g_TestString.Buffer,
212*f61e14f5SRatin Gao                                     g_TestString.Length);
213*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, g_TestString.Length);
214*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
215*f61e14f5SRatin Gao                                     g_aulMD5Or4StateInit,
216*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(MD5_CTX, State));
217*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(MD5_CTX, State));
218*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], (ULONG)g_TestString.Length * CHAR_BIT);
219*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
220*f61e14f5SRatin Gao 
221*f61e14f5SRatin Gao     /* Test MD5Final */
222*f61e14f5SRatin Gao     pfnMD5Final(&ctx);
223*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0x200UL);
224*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
225*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[0], 0x8B23E83DUL);
226*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[1], 0x48CEE09DUL);
227*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[2], 0xD9DD1BB1UL);
228*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[3], 0xDEB286C6UL);
229*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemoryUlong(ctx.Buffer, sizeof(ctx.Buffer), 0);
230*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, sizeof(ctx.Buffer));
231*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.Hash, &g_aucMD5Result, MD5_DIGEST_LEN);
232*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, MD5_DIGEST_LEN);
233*f61e14f5SRatin Gao }
234*f61e14f5SRatin Gao 
Test_MD4(void)235*f61e14f5SRatin Gao static void Test_MD4(void)
236*f61e14f5SRatin Gao {
237*f61e14f5SRatin Gao     FN_MD4Init* pfnMD4Init;
238*f61e14f5SRatin Gao     FN_MD4Update* pfnMD4Update;
239*f61e14f5SRatin Gao     FN_MD4Final* pfnMD4Final;
240*f61e14f5SRatin Gao     DECLSPEC_ALIGN(4) MD4_CTX ctx;
241*f61e14f5SRatin Gao     SIZE_T ComparedSize;
242*f61e14f5SRatin Gao 
243*f61e14f5SRatin Gao     /* Load functions */
244*f61e14f5SRatin Gao     pfnMD4Init = (FN_MD4Init*)GetProcAddress(g_hAdvapi32, "MD4Init");
245*f61e14f5SRatin Gao     pfnMD4Update = (FN_MD4Update*)GetProcAddress(g_hAdvapi32, "MD4Update");
246*f61e14f5SRatin Gao     pfnMD4Final = (FN_MD4Final*)GetProcAddress(g_hAdvapi32, "MD4Final");
247*f61e14f5SRatin Gao 
248*f61e14f5SRatin Gao     if (!pfnMD4Init || !pfnMD4Update || !pfnMD4Final)
249*f61e14f5SRatin Gao     {
250*f61e14f5SRatin Gao         skip("advapi32.dll!MD4*** not found\n");
251*f61e14f5SRatin Gao         return;
252*f61e14f5SRatin Gao     }
253*f61e14f5SRatin Gao 
254*f61e14f5SRatin Gao     /* Test MD4Init */
255*f61e14f5SRatin Gao     pfnMD4Init(&ctx);
256*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0UL);
257*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
258*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
259*f61e14f5SRatin Gao                                     g_aulMD5Or4StateInit,
260*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(MD4_CTX, State));
261*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(MD4_CTX, State));
262*f61e14f5SRatin Gao 
263*f61e14f5SRatin Gao     /* Test MD4Update */
264*f61e14f5SRatin Gao     pfnMD4Update(&ctx, (PUCHAR)g_TestString.Buffer, g_TestString.Length);
265*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.Buffer,
266*f61e14f5SRatin Gao                                     g_TestString.Buffer,
267*f61e14f5SRatin Gao                                     g_TestString.Length);
268*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, g_TestString.Length);
269*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.State,
270*f61e14f5SRatin Gao                                     g_aulMD5Or4StateInit,
271*f61e14f5SRatin Gao                                     RTL_FIELD_SIZE(MD4_CTX, State));
272*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, RTL_FIELD_SIZE(MD4_CTX, State));
273*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], (ULONG)g_TestString.Length * CHAR_BIT);
274*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
275*f61e14f5SRatin Gao 
276*f61e14f5SRatin Gao     /* Test MD4Final */
277*f61e14f5SRatin Gao     pfnMD4Final(&ctx);
278*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[0], 0x200UL);
279*f61e14f5SRatin Gao     ok_eq_ulong(ctx.Count[1], 0UL);
280*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[0], 0x8A50E8E0UL);
281*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[1], 0xA602114DUL);
282*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[2], 0xABA7F06AUL);
283*f61e14f5SRatin Gao     ok_eq_ulong(ctx.State[3], 0xED40C4D8UL);
284*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemoryUlong(ctx.Buffer, sizeof(ctx.Buffer), 0);
285*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, sizeof(ctx.Buffer));
286*f61e14f5SRatin Gao     ComparedSize = RtlCompareMemory(ctx.Hash, &g_aucMD4Result, MD4_DIGEST_LEN);
287*f61e14f5SRatin Gao     ok_eq_size(ComparedSize, MD4_DIGEST_LEN);
288*f61e14f5SRatin Gao }
289*f61e14f5SRatin Gao 
START_TEST(Hash)290*f61e14f5SRatin Gao START_TEST(Hash)
291*f61e14f5SRatin Gao {
292*f61e14f5SRatin Gao     /* Load advapi32.dll */
293*f61e14f5SRatin Gao     g_hAdvapi32 = GetModuleHandleW(L"advapi32.dll");
294*f61e14f5SRatin Gao     if (!g_hAdvapi32)
295*f61e14f5SRatin Gao     {
296*f61e14f5SRatin Gao         skip("Module advapi32 not found\n");
297*f61e14f5SRatin Gao         return;
298*f61e14f5SRatin Gao     }
299*f61e14f5SRatin Gao 
300*f61e14f5SRatin Gao     Test_SHA1();
301*f61e14f5SRatin Gao     Test_MD5();
302*f61e14f5SRatin Gao     Test_MD4();
303*f61e14f5SRatin Gao }
304