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 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 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 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 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