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