Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

409 lines
9.8 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (c) Microsoft Corporation 1992 - 1992
  6. //
  7. // File: cryptest.cxx
  8. //
  9. // Contents: test program to test encryption functions
  10. //
  11. //
  12. // History: 07-Oct-1996 MikeSw Created
  13. //
  14. //------------------------------------------------------------------------
  15. extern "C"
  16. {
  17. #include <nt.h>
  18. #include <ntrtl.h>
  19. #include <nturtl.h>
  20. #include <windows.h>
  21. #define SECURITY_WIN32
  22. #include <security.h>
  23. #include <cryptdll.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <stdlib.h>
  27. #include <kerbcomm.h>
  28. #include <align.h>
  29. #include "md5.h"
  30. }
  31. typedef enum _CRYPT_ACTIONS {
  32. HashPassword,
  33. EncryptData,
  34. ChecksumData,
  35. EnumTypes,
  36. NoAction
  37. } CRYPT_ACTIONS;
  38. VOID
  39. DoMd5(
  40. PUCHAR Buffer,
  41. ULONG BufferLength
  42. )
  43. {
  44. MD5_CTX Md5Context;
  45. MD5Init(&Md5Context);
  46. MD5Update(&Md5Context, Buffer, BufferLength);
  47. MD5Final(&Md5Context);
  48. }
  49. void _cdecl
  50. main(int argc, char *argv[])
  51. {
  52. NTSTATUS Status;
  53. UNICODE_STRING Password;
  54. UNICODE_STRING User;
  55. UNICODE_STRING Domain;
  56. UNICODE_STRING Salt;
  57. ULONG CryptType = 0;
  58. ULONG HashType = 0;
  59. ULONG SumType = 0;
  60. WCHAR PasswordBuffer[100];
  61. WCHAR UserBuffer[100];
  62. WCHAR DomainBuffer[100];
  63. KERB_ACCOUNT_TYPE AccountType = UserAccount;
  64. CRYPT_ACTIONS Command = NoAction;
  65. int Index;
  66. ULONG uI;
  67. KERB_ENCRYPTION_KEY Key;
  68. KERBERR KerbErr;
  69. ULONG BlockSize;
  70. ULONG Overhead;
  71. ULONG BufferLength;
  72. ULONG ReqBufferLength;
  73. UCHAR OriginalBuffer[1000];
  74. PUCHAR EncryptedBuffer = NULL;
  75. PUCHAR DecryptedBuffer = NULL;
  76. PCRYPTO_SYSTEM Crypto;
  77. PCRYPT_STATE_BUFFER StateBuffer = NULL;
  78. Index = 1;
  79. while (Index < argc)
  80. {
  81. if (_stricmp(argv[Index],"-hash") == 0)
  82. {
  83. Command = HashPassword;
  84. if (argc < Index+1)
  85. {
  86. goto Cleanup;
  87. }
  88. sscanf(argv[++Index],"%d",&HashType);
  89. }
  90. else if (_stricmp(argv[Index],"-pass") == 0)
  91. {
  92. if (argc < Index + 1)
  93. {
  94. goto Cleanup;
  95. }
  96. mbstowcs(PasswordBuffer,argv[++Index],100);
  97. RtlInitUnicodeString(
  98. &Password,
  99. PasswordBuffer
  100. );
  101. }
  102. else if (_stricmp(argv[Index],"-user") == 0)
  103. {
  104. if (argc < Index + 1)
  105. {
  106. goto Cleanup;
  107. }
  108. mbstowcs(UserBuffer,argv[++Index],100);
  109. RtlInitUnicodeString(
  110. &User,
  111. UserBuffer
  112. );
  113. }
  114. else if (_stricmp(argv[Index],"-domain") == 0)
  115. {
  116. if (argc < Index + 1)
  117. {
  118. goto Cleanup;
  119. }
  120. mbstowcs(DomainBuffer,argv[++Index],100);
  121. RtlInitUnicodeString(
  122. &Domain,
  123. DomainBuffer
  124. );
  125. }
  126. else if (_stricmp(argv[Index],"-type") == 0)
  127. {
  128. if (argc < Index + 1)
  129. {
  130. goto Cleanup;
  131. }
  132. if (_stricmp(argv[Index+1],"user") == 0)
  133. {
  134. AccountType = UserAccount;
  135. }
  136. else if (_stricmp(argv[Index+1],"machine") == 0)
  137. {
  138. AccountType = MachineAccount;
  139. }
  140. else if (_stricmp(argv[Index+1],"domain") == 0)
  141. {
  142. AccountType = DomainTrustAccount;
  143. }
  144. else
  145. {
  146. printf("Illegal account type: %s\n",argv[Index+1]);
  147. goto Cleanup;
  148. }
  149. Index++;
  150. }
  151. else if (_stricmp(argv[Index],"-crypt") == 0)
  152. {
  153. Command = EncryptData;
  154. if (argc < Index + 1)
  155. {
  156. goto Cleanup;
  157. }
  158. sscanf(argv[++Index],"%d",&CryptType);
  159. }
  160. else if (_stricmp(argv[Index],"-sum") == 0)
  161. {
  162. Command = ChecksumData;
  163. if (argc < Index + 1)
  164. {
  165. goto Cleanup;
  166. }
  167. sscanf(argv[++Index],"%d",&SumType);
  168. }
  169. else if (_stricmp(argv[Index],"-enum") == 0)
  170. {
  171. Command = EnumTypes;
  172. }
  173. else
  174. {
  175. goto Cleanup;
  176. }
  177. Index++;
  178. }
  179. if (Command == NoAction)
  180. {
  181. goto Cleanup;
  182. }
  183. switch(Command)
  184. {
  185. case EnumTypes:
  186. break;
  187. case HashPassword:
  188. KerbErr = KerbBuildKeySalt(
  189. &Domain,
  190. &User,
  191. AccountType,
  192. &Salt
  193. );
  194. if (!KERB_SUCCESS(KerbErr))
  195. {
  196. printf("Failed to build key salt: 0x%x\n",KerbErr);
  197. goto Cleanup;
  198. }
  199. printf("KeySalt = %wZ\n",&Salt);
  200. KerbErr = KerbHashPasswordEx(
  201. &Password,
  202. &Salt,
  203. HashType,
  204. &Key
  205. );
  206. if (!KERB_SUCCESS(KerbErr))
  207. {
  208. printf("Failed to hash password: 0x%x\n",KerbErr);
  209. goto Exit;
  210. }
  211. printf("Hash: ");
  212. for (uI = 0; uI < Key.keyvalue.length ; uI++ )
  213. {
  214. printf("%0.2x ",Key.keyvalue.value[uI]);
  215. }
  216. printf("\n");
  217. break;
  218. case EncryptData:
  219. //
  220. // First hash the password
  221. //
  222. KerbErr= KerbHashPassword(
  223. &Password,
  224. CryptType,
  225. &Key
  226. );
  227. if (!KERB_SUCCESS(KerbErr))
  228. {
  229. printf("Failed to hash password: %0x%x\n",KerbErr);
  230. goto Exit;
  231. }
  232. KerbErr = KerbGetEncryptionOverhead(
  233. CryptType,
  234. &Overhead,
  235. &BlockSize
  236. );
  237. if (!KERB_SUCCESS(KerbErr))
  238. {
  239. printf("Failed to get enc overhead: 0x%x\n",KerbErr);
  240. goto Exit;
  241. }
  242. BufferLength = sizeof(OriginalBuffer);
  243. memset(OriginalBuffer,'A',BufferLength);
  244. #ifdef notdef
  245. KerbErr = KerbRandomFill(
  246. OriginalBuffer,
  247. BufferLength
  248. );
  249. if (!KERB_SUCCESS(KerbErr))
  250. {
  251. printf("Failed to init random buffer: 0x%x\n",KerbErr);
  252. goto Exit;
  253. }
  254. #endif
  255. ReqBufferLength = ROUND_UP_COUNT(BufferLength + Overhead, BlockSize);
  256. EncryptedBuffer = (PUCHAR) LocalAlloc(LMEM_ZEROINIT, ReqBufferLength);
  257. if (EncryptedBuffer == NULL)
  258. {
  259. printf("Failed to allocate 0x%x bytes: %d\n",ReqBufferLength, GetLastError());
  260. goto Exit;
  261. }
  262. Status = CDLocateCSystem(
  263. CryptType,
  264. &Crypto
  265. );
  266. if (!NT_SUCCESS(Status))
  267. {
  268. printf("Failed to locate crypt system 0x%x: 0x%x\n",CryptType,Status);
  269. goto Exit;
  270. }
  271. Status = Crypto->Initialize(
  272. Key.keyvalue.value,
  273. (ULONG) Key.keyvalue.length,
  274. 0, // no options
  275. &StateBuffer
  276. );
  277. if (!NT_SUCCESS(Status))
  278. {
  279. printf("failed to initialize crypto system: 0x%x\n",Status);
  280. goto Exit;
  281. }
  282. Status = Crypto->Encrypt(
  283. StateBuffer,
  284. OriginalBuffer,
  285. BufferLength,
  286. EncryptedBuffer,
  287. &ReqBufferLength
  288. );
  289. if (!NT_SUCCESS(Status))
  290. {
  291. printf("Failed to encrypt data: 0x%x\n",Status);
  292. goto Exit;
  293. }
  294. Status = Crypto->Discard(&StateBuffer);
  295. if (!NT_SUCCESS(Status))
  296. {
  297. printf("Failed to discard state buffer: 0x%x\n",Status);
  298. goto Exit;
  299. }
  300. //
  301. // Now turn around and decrypt it.
  302. //
  303. DecryptedBuffer = (PUCHAR) LocalAlloc(LMEM_ZEROINIT, ReqBufferLength);
  304. if (EncryptedBuffer == NULL)
  305. {
  306. printf("Failed to allocate 0x%x bytes: %d\n",ReqBufferLength, GetLastError());
  307. goto Exit;
  308. }
  309. Status = Crypto->Initialize(
  310. Key.keyvalue.value,
  311. (ULONG) Key.keyvalue.length,
  312. 0, // no options
  313. &StateBuffer
  314. );
  315. if (!NT_SUCCESS(Status))
  316. {
  317. printf("failed to initialize crypto system: 0x%x\n",Status);
  318. goto Exit;
  319. }
  320. Status = Crypto->Decrypt(
  321. StateBuffer,
  322. EncryptedBuffer,
  323. ReqBufferLength,
  324. DecryptedBuffer,
  325. &ReqBufferLength
  326. );
  327. if (!NT_SUCCESS(Status))
  328. {
  329. printf("Failed to decrypt data: 0x%x\n",Status);
  330. goto Exit;
  331. }
  332. Status = Crypto->Discard(&StateBuffer);
  333. if (!NT_SUCCESS(Status))
  334. {
  335. printf("Failed to discard state buffer: 0x%x\n",Status);
  336. goto Exit;
  337. }
  338. //
  339. // Now compare
  340. //
  341. if (!RtlEqualMemory(
  342. OriginalBuffer,
  343. DecryptedBuffer,
  344. BufferLength
  345. ))
  346. {
  347. printf("Buffers don't match!\n");
  348. }
  349. else
  350. {
  351. printf("Encryption/decryption succeeded!\n");
  352. }
  353. break;
  354. case ChecksumData:
  355. BufferLength = sizeof(OriginalBuffer);
  356. memset(OriginalBuffer,'A',BufferLength);
  357. DoMd5(OriginalBuffer,BufferLength);
  358. }
  359. Exit:
  360. return;
  361. Cleanup:
  362. printf("Usage: %s { -crypt cryptalg -sum sumtype -hash cryptalg -enum } -pass password\n",
  363. argv[0]);
  364. return;
  365. }