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.

827 lines
18 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // File: rc4crypt.c
  4. //
  5. // Contents: CryptoSystem wrapper functions for RC4 hmac
  6. //
  7. //
  8. // History: 02-Nov-1998 MikeSw Created
  9. //
  10. //------------------------------------------------------------------------
  11. #ifndef KERNEL_MODE
  12. #include <nt.h>
  13. #include <ntrtl.h>
  14. #include <nturtl.h>
  15. #include <windows.h>
  16. #else
  17. #include <ntifs.h>
  18. #endif
  19. #include <string.h>
  20. #include <malloc.h>
  21. #include <kerbcon.h>
  22. #include <security.h>
  23. #include <cryptdll.h>
  24. #include <rc4.h>
  25. #include <md4.h>
  26. #include <md5.h>
  27. typedef struct RC4_KEYSTRUCT RC4KEY;
  28. #define RC4_CONFOUNDER_LEN 8
  29. typedef struct _RC4_MDx_HEADER {
  30. UCHAR Checksum[MD5_LEN];
  31. UCHAR Confounder[RC4_CONFOUNDER_LEN];
  32. } RC4_MDx_HEADER, *PRC4_MDx_HEADER;
  33. typedef struct _RC4_STATE_BUFFER {
  34. UCHAR BaseKey[MD5_LEN];
  35. RC4KEY Key;
  36. } RC4_STATE_BUFFER, *PRC4_STATE_BUFFER;
  37. typedef struct _RC4_HMAC_STATE_BUFFER {
  38. UCHAR Key[MD5_LEN];
  39. } RC4_HMAC_STATE_BUFFER, *PRC4_HMAC_STATE_BUFFER;
  40. NTSTATUS NTAPI rc4PlainInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  41. NTSTATUS NTAPI rc4PlainExpInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  42. NTSTATUS NTAPI rc4HmacInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  43. NTSTATUS NTAPI rc4HmacExpInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  44. NTSTATUS NTAPI rc4HmacEncrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  45. NTSTATUS NTAPI rc4HmacDecrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  46. NTSTATUS NTAPI rc4HmacPlainEncrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  47. NTSTATUS NTAPI rc4HmacPlainDecrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  48. NTSTATUS NTAPI rc4HmacFinish(PCRYPT_STATE_BUFFER *);
  49. NTSTATUS NTAPI rc4HmacControl(ULONG, PCRYPT_STATE_BUFFER, PUCHAR, ULONG);
  50. NTSTATUS NTAPI rc4HmacPlainControl(ULONG, PCRYPT_STATE_BUFFER, PUCHAR, ULONG);
  51. NTSTATUS NTAPI rc4HmacRandomKey(PUCHAR, ULONG, PUCHAR);
  52. NTSTATUS NTAPI rc4HmacHashPassword(PSECURITY_STRING, PUCHAR );
  53. #ifdef KERNEL_MODE
  54. #pragma alloc_text(PAGEMSG, rc4PlainInitialize)
  55. #pragma alloc_text(PAGEMSG, rc4PlainExpInitialize )
  56. #pragma alloc_text(PAGEMSG, rc4HmacInitialize )
  57. #pragma alloc_text(PAGEMSG, rc4HmacExpInitialize )
  58. #pragma alloc_text(PAGEMSG, rc4HmacEncrypt )
  59. #pragma alloc_text(PAGEMSG, rc4HmacDecrypt )
  60. #pragma alloc_text(PAGEMSG, rc4HmacPlainEncrypt )
  61. #pragma alloc_text(PAGEMSG, rc4HmacPlainDecrypt )
  62. #pragma alloc_text(PAGEMSG, rc4HmacFinish )
  63. #pragma alloc_text(PAGEMSG, rc4HmacControl )
  64. #pragma alloc_text(PAGEMSG, rc4HmacPlainControl )
  65. #pragma alloc_text(PAGEMSG, rc4HmacRandomKey )
  66. #pragma alloc_text(PAGEMSG, rc4HmacHashPassword )
  67. #endif
  68. CRYPTO_SYSTEM csRC4_HMAC = {
  69. KERB_ETYPE_RC4_HMAC_NT, // Etype
  70. 1, // Blocksize (stream)
  71. KERB_ETYPE_RC4_HMAC_NT_EXP, // Exportable version
  72. MD4_LEN, // Key size, in bytes
  73. sizeof(RC4_MDx_HEADER), // header size
  74. KERB_CHECKSUM_MD4, // Preferred Checksum
  75. CSYSTEM_INTEGRITY_PROTECTED, // attributes
  76. L"RSADSI RC4-HMAC", // Text name
  77. rc4HmacInitialize,
  78. rc4HmacEncrypt,
  79. rc4HmacDecrypt,
  80. rc4HmacFinish,
  81. rc4HmacHashPassword,
  82. rc4HmacRandomKey,
  83. rc4HmacControl
  84. };
  85. //
  86. // This is not actually export strength - it is a signal that the
  87. // plain version is export strength
  88. //
  89. CRYPTO_SYSTEM csRC4_HMAC_EXP = {
  90. KERB_ETYPE_RC4_HMAC_NT_EXP, // Etype
  91. 1, // Blocksize (stream)
  92. KERB_ETYPE_RC4_HMAC_NT_EXP, // Exportable version
  93. MD4_LEN, // Key size, in bytes
  94. sizeof(RC4_MDx_HEADER), // header size
  95. KERB_CHECKSUM_MD4, // Preferred Checksum
  96. CSYSTEM_INTEGRITY_PROTECTED | CSYSTEM_EXPORT_STRENGTH, // attributes
  97. L"RSADSI RC4-HMAC", // Text name
  98. rc4HmacInitialize,
  99. rc4HmacEncrypt,
  100. rc4HmacDecrypt,
  101. rc4HmacFinish,
  102. rc4HmacHashPassword,
  103. rc4HmacRandomKey,
  104. rc4HmacControl
  105. };
  106. CRYPTO_SYSTEM csRC4_PLAIN = {
  107. KERB_ETYPE_RC4_PLAIN, // Etype
  108. 1, // Blocksize (stream)
  109. KERB_ETYPE_RC4_PLAIN_EXP, // exportable version
  110. MD4_LEN, // Key size, in bytes
  111. 0, // header size
  112. KERB_CHECKSUM_MD4, // Preferred Checksum
  113. 0, // no attributes
  114. L"RSADSI RC4", // Text name
  115. rc4PlainInitialize,
  116. rc4HmacPlainEncrypt,
  117. rc4HmacPlainDecrypt,
  118. rc4HmacFinish,
  119. rc4HmacHashPassword,
  120. rc4HmacRandomKey,
  121. rc4HmacPlainControl
  122. };
  123. CRYPTO_SYSTEM csRC4_PLAIN_EXP = {
  124. KERB_ETYPE_RC4_PLAIN_EXP, // Etype
  125. 1, // Blocksize (stream)
  126. KERB_ETYPE_RC4_PLAIN_EXP, // exportable version
  127. MD4_LEN, // Key size, in bytes
  128. 0, // header size
  129. KERB_CHECKSUM_MD4, // Preferred Checksum
  130. CSYSTEM_EXPORT_STRENGTH, // no attributes
  131. L"RSADSI RC4-EXP", // Text name
  132. rc4PlainExpInitialize,
  133. rc4HmacPlainEncrypt,
  134. rc4HmacPlainDecrypt,
  135. rc4HmacFinish,
  136. rc4HmacHashPassword,
  137. rc4HmacRandomKey,
  138. rc4HmacPlainControl
  139. };
  140. NTSTATUS NTAPI
  141. rc4HmacHashPassword(
  142. IN PSECURITY_STRING Password,
  143. OUT PUCHAR Key
  144. )
  145. {
  146. PCHECKSUM_FUNCTION SumFunction;
  147. PCHECKSUM_BUFFER Buffer;
  148. NTSTATUS Status;
  149. Status = CDLocateCheckSum(KERB_CHECKSUM_MD4, &SumFunction);
  150. if (!NT_SUCCESS(Status))
  151. {
  152. return(SEC_E_CHECKSUM_NOT_SUPP);
  153. }
  154. Status = SumFunction->Initialize(0, &Buffer);
  155. if (!NT_SUCCESS(Status))
  156. {
  157. return(Status);
  158. }
  159. (void) SumFunction->Sum(Buffer, Password->Length, (PUCHAR) Password->Buffer);
  160. (void) SumFunction->Finalize(Buffer, Key);
  161. (void) SumFunction->Finish(&Buffer);
  162. return(STATUS_SUCCESS);
  163. }
  164. //////////////////////////////////////////////////////////////////////////
  165. //
  166. // RC4 HMAC crypt type
  167. //
  168. //////////////////////////////////////////////////////////////////////////
  169. BOOLEAN static
  170. md5Hmac(
  171. IN PUCHAR pbKeyMaterial,
  172. IN ULONG cbKeyMaterial,
  173. IN PUCHAR pbData,
  174. IN ULONG cbData,
  175. IN PUCHAR pbData2,
  176. IN ULONG cbData2,
  177. OUT PUCHAR HmacData
  178. )
  179. {
  180. BOOLEAN fRet = FALSE;
  181. #define HMAC_K_PADSIZE 64
  182. UCHAR Kipad[HMAC_K_PADSIZE];
  183. UCHAR Kopad[HMAC_K_PADSIZE];
  184. UCHAR HMACTmp[HMAC_K_PADSIZE+MD5_LEN];
  185. ULONG dwBlock;
  186. MD5_CTX Md5Hash;
  187. // truncate
  188. if (cbKeyMaterial > HMAC_K_PADSIZE)
  189. cbKeyMaterial = HMAC_K_PADSIZE;
  190. RtlZeroMemory(Kipad, HMAC_K_PADSIZE);
  191. RtlCopyMemory(Kipad, pbKeyMaterial, cbKeyMaterial);
  192. RtlZeroMemory(Kopad, HMAC_K_PADSIZE);
  193. RtlCopyMemory(Kopad, pbKeyMaterial, cbKeyMaterial);
  194. //
  195. // Kipad, Kopad are padded sMacKey. Now XOR across...
  196. //
  197. for(dwBlock=0; dwBlock<HMAC_K_PADSIZE/sizeof(ULONG); dwBlock++)
  198. {
  199. ((ULONG*)Kipad)[dwBlock] ^= 0x36363636;
  200. ((ULONG*)Kopad)[dwBlock] ^= 0x5C5C5C5C;
  201. }
  202. //
  203. // prepend Kipad to data, Hash to get H1
  204. //
  205. MD5Init(&Md5Hash);
  206. MD5Update(&Md5Hash, Kipad, HMAC_K_PADSIZE);
  207. if (cbData != 0)
  208. {
  209. MD5Update(&Md5Hash, pbData, cbData);
  210. }
  211. if (cbData2 != 0)
  212. {
  213. MD5Update(&Md5Hash, pbData2, cbData2);
  214. }
  215. // Finish off the hash
  216. MD5Final(&Md5Hash);
  217. // prepend Kopad to H1, hash to get HMAC
  218. RtlCopyMemory(HMACTmp, Kopad, HMAC_K_PADSIZE);
  219. RtlCopyMemory(HMACTmp+HMAC_K_PADSIZE, Md5Hash.digest, MD5_LEN);
  220. // final hash: output value into passed-in buffer
  221. MD5Init(&Md5Hash);
  222. MD5Update(&Md5Hash,HMACTmp, sizeof(HMACTmp));
  223. MD5Final(&Md5Hash);
  224. RtlCopyMemory(
  225. HmacData,
  226. Md5Hash.digest,
  227. MD5_LEN
  228. );
  229. return TRUE;
  230. }
  231. NTSTATUS NTAPI
  232. rc4HmacBaseInitialize(
  233. IN PUCHAR pbKey,
  234. IN ULONG KeySize,
  235. IN ULONG MessageType,
  236. IN BOOLEAN Exportable,
  237. OUT PCRYPT_STATE_BUFFER * psbBuffer
  238. )
  239. {
  240. PRC4_HMAC_STATE_BUFFER StateBuffer = NULL;
  241. ULONG LocalKeySize = 0;
  242. //
  243. // Compute the HMAC pad
  244. //
  245. #ifdef KERNEL_MODE
  246. StateBuffer = (PRC4_HMAC_STATE_BUFFER) ExAllocatePool(NonPagedPool, sizeof(RC4_HMAC_STATE_BUFFER));
  247. #else
  248. StateBuffer = (PRC4_HMAC_STATE_BUFFER) LocalAlloc(0, sizeof(RC4_HMAC_STATE_BUFFER));
  249. #endif
  250. if (StateBuffer == NULL)
  251. {
  252. return(STATUS_INSUFFICIENT_RESOURCES);
  253. }
  254. //
  255. // If the key is not exportable, shrink it first
  256. //
  257. if (!Exportable)
  258. {
  259. md5Hmac(
  260. pbKey,
  261. KeySize,
  262. (PUCHAR) &MessageType,
  263. sizeof(ULONG),
  264. NULL,
  265. 0,
  266. StateBuffer->Key
  267. );
  268. LocalKeySize = MD5_LEN;
  269. }
  270. else
  271. {
  272. md5Hmac(
  273. pbKey,
  274. KeySize,
  275. "fiftysixbits",
  276. sizeof("fiftysixbits"),
  277. (PUCHAR) &MessageType,
  278. sizeof(ULONG),
  279. StateBuffer->Key
  280. );
  281. LocalKeySize = 5; // 40 bits
  282. }
  283. //
  284. // Pad exportable keys with 0xababab
  285. //
  286. ASSERT(MD5_LEN >= LocalKeySize);
  287. memset(
  288. StateBuffer->Key+LocalKeySize,
  289. 0xab,
  290. MD5_LEN-LocalKeySize
  291. );
  292. *psbBuffer = StateBuffer;
  293. return(STATUS_SUCCESS);
  294. }
  295. NTSTATUS NTAPI
  296. rc4HmacInitialize(
  297. IN PUCHAR pbKey,
  298. IN ULONG KeySize,
  299. IN ULONG MessageType,
  300. OUT PCRYPT_STATE_BUFFER * psbBuffer
  301. )
  302. {
  303. return(rc4HmacBaseInitialize(
  304. pbKey,
  305. KeySize,
  306. MessageType,
  307. FALSE, // not exportable
  308. psbBuffer
  309. ));
  310. }
  311. NTSTATUS NTAPI
  312. rc4HmacPlainBaseInitialize(
  313. IN PUCHAR pbKey,
  314. IN ULONG KeySize,
  315. IN ULONG MessageType,
  316. IN BOOLEAN Exportable,
  317. OUT PCRYPT_STATE_BUFFER * psbBuffer
  318. )
  319. {
  320. PRC4_STATE_BUFFER StateBuffer = NULL;
  321. ULONG LocalKeySize = 0;
  322. //
  323. // Compute the HMAC pad
  324. //
  325. #ifdef KERNEL_MODE
  326. StateBuffer = (PRC4_STATE_BUFFER) ExAllocatePool(NonPagedPool, sizeof(RC4_STATE_BUFFER));
  327. #else
  328. StateBuffer = (PRC4_STATE_BUFFER) LocalAlloc(0, sizeof(RC4_STATE_BUFFER));
  329. #endif
  330. if (StateBuffer == NULL)
  331. {
  332. return(STATUS_INSUFFICIENT_RESOURCES);
  333. }
  334. //
  335. // If the key is not exportable, shrink it first
  336. //
  337. if (!Exportable)
  338. {
  339. md5Hmac(
  340. pbKey,
  341. KeySize,
  342. (PUCHAR) &MessageType,
  343. sizeof(ULONG),
  344. NULL,
  345. 0,
  346. StateBuffer->BaseKey
  347. );
  348. LocalKeySize = MD5_LEN;
  349. }
  350. else
  351. {
  352. md5Hmac(
  353. pbKey,
  354. KeySize,
  355. "fortybits",
  356. sizeof("fortybits"),
  357. (PUCHAR) &MessageType,
  358. sizeof(ULONG),
  359. StateBuffer->BaseKey
  360. );
  361. LocalKeySize = 7; // 56 bits
  362. }
  363. //
  364. // Pad exportable keys with 0xababab
  365. //
  366. ASSERT(MD5_LEN >= LocalKeySize);
  367. memset(
  368. StateBuffer->BaseKey+LocalKeySize,
  369. 0xab,
  370. MD5_LEN-LocalKeySize
  371. );
  372. //
  373. // Create the encryption key
  374. //
  375. rc4_key(
  376. &StateBuffer->Key,
  377. MD5_LEN,
  378. StateBuffer->BaseKey
  379. );
  380. *psbBuffer = StateBuffer;
  381. return(STATUS_SUCCESS);
  382. }
  383. NTSTATUS NTAPI
  384. rc4PlainInitialize(
  385. IN PUCHAR pbKey,
  386. IN ULONG KeySize,
  387. IN ULONG MessageType,
  388. OUT PCRYPT_STATE_BUFFER * psbBuffer
  389. )
  390. {
  391. return(rc4HmacPlainBaseInitialize(
  392. pbKey,
  393. KeySize,
  394. MessageType,
  395. FALSE, // not exportable
  396. psbBuffer
  397. ));
  398. }
  399. NTSTATUS NTAPI
  400. rc4PlainExpInitialize(
  401. IN PUCHAR pbKey,
  402. IN ULONG KeySize,
  403. IN ULONG MessageType,
  404. OUT PCRYPT_STATE_BUFFER * psbBuffer
  405. )
  406. {
  407. return(rc4HmacPlainBaseInitialize(
  408. pbKey,
  409. KeySize, // only use 40 bites
  410. MessageType,
  411. TRUE, // exportable
  412. psbBuffer
  413. ));
  414. }
  415. NTSTATUS NTAPI
  416. rc4HmacControl(
  417. IN ULONG Function,
  418. IN PCRYPT_STATE_BUFFER StateBuffer,
  419. IN PUCHAR InputBuffer,
  420. IN ULONG InputBufferSize
  421. )
  422. {
  423. PRC4_HMAC_STATE_BUFFER HmacStateBuffer = (PRC4_HMAC_STATE_BUFFER) StateBuffer;
  424. if (Function == CRYPT_CONTROL_SET_INIT_VECT)
  425. {
  426. md5Hmac(
  427. HmacStateBuffer->Key,
  428. MD5_LEN,
  429. InputBuffer,
  430. InputBufferSize,
  431. NULL,
  432. 0,
  433. HmacStateBuffer->Key
  434. );
  435. }
  436. else
  437. {
  438. return(STATUS_INVALID_PARAMETER);
  439. }
  440. return(STATUS_SUCCESS);
  441. }
  442. NTSTATUS NTAPI
  443. rc4HmacPlainControl(
  444. IN ULONG Function,
  445. IN PCRYPT_STATE_BUFFER StateBuffer,
  446. IN PUCHAR InputBuffer,
  447. IN ULONG InputBufferSize
  448. )
  449. {
  450. PRC4_STATE_BUFFER HmacStateBuffer = (PRC4_STATE_BUFFER) StateBuffer;
  451. if (Function == CRYPT_CONTROL_SET_INIT_VECT)
  452. {
  453. //
  454. // create the new initial key
  455. //
  456. md5Hmac(
  457. HmacStateBuffer->BaseKey,
  458. MD5_LEN,
  459. InputBuffer,
  460. InputBufferSize,
  461. NULL,
  462. 0,
  463. HmacStateBuffer->BaseKey
  464. );
  465. //
  466. // Create the encryption key
  467. //
  468. rc4_key(
  469. &HmacStateBuffer->Key,
  470. MD5_LEN,
  471. HmacStateBuffer->BaseKey
  472. );
  473. }
  474. else
  475. {
  476. return(STATUS_INVALID_PARAMETER);
  477. }
  478. return(STATUS_SUCCESS);
  479. }
  480. NTSTATUS NTAPI
  481. rc4HmacEncrypt(
  482. IN PCRYPT_STATE_BUFFER psbBuffer,
  483. IN PUCHAR pbInput,
  484. IN ULONG cbInput,
  485. OUT PUCHAR pbOutput,
  486. OUT PULONG cbOutput
  487. )
  488. {
  489. PRC4_HMAC_STATE_BUFFER StateBuffer = (PRC4_HMAC_STATE_BUFFER) psbBuffer;
  490. PRC4_MDx_HEADER CryptHeader = (PRC4_MDx_HEADER) pbOutput;
  491. UCHAR LocalKey[MD5_LEN];
  492. ULONG Offset = 0;
  493. RC4KEY Rc4Key;
  494. Offset = sizeof(RC4_MDx_HEADER);
  495. RtlMoveMemory(
  496. pbOutput + Offset,
  497. pbInput,
  498. cbInput
  499. );
  500. *cbOutput = cbInput + Offset;
  501. //
  502. // Create the header - the confounder & checksum
  503. //
  504. RtlZeroMemory(
  505. CryptHeader->Checksum,
  506. MD5_LEN
  507. );
  508. CDGenerateRandomBits(
  509. CryptHeader->Confounder,
  510. RC4_CONFOUNDER_LEN
  511. );
  512. //
  513. // Checksum everything but the checksum
  514. //
  515. md5Hmac(
  516. StateBuffer->Key,
  517. MD5_LEN,
  518. pbOutput+MD5_LEN,
  519. *cbOutput-MD5_LEN,
  520. NULL,
  521. 0,
  522. CryptHeader->Checksum
  523. );
  524. //
  525. // HMAC the checksum into the key
  526. //
  527. md5Hmac(
  528. StateBuffer->Key,
  529. MD5_LEN,
  530. CryptHeader->Checksum,
  531. MD5_LEN,
  532. NULL,
  533. 0,
  534. LocalKey
  535. );
  536. rc4_key(
  537. &Rc4Key,
  538. MD5_LEN,
  539. LocalKey
  540. );
  541. //
  542. // Encrypt everything but the checksum
  543. //
  544. rc4(&Rc4Key, *cbOutput-MD5_LEN, pbOutput+MD5_LEN);
  545. return(STATUS_SUCCESS);
  546. }
  547. NTSTATUS NTAPI
  548. rc4HmacDecrypt( PCRYPT_STATE_BUFFER psbBuffer,
  549. PUCHAR pbInput,
  550. ULONG cbInput,
  551. PUCHAR pbOutput,
  552. PULONG cbOutput)
  553. {
  554. PRC4_HMAC_STATE_BUFFER StateBuffer = (PRC4_HMAC_STATE_BUFFER) psbBuffer;
  555. RC4_MDx_HEADER TempHeader;
  556. UCHAR TempChecksum[MD5_LEN];
  557. ULONG Offset = sizeof(RC4_MDx_HEADER);
  558. UCHAR LocalKey[MD5_LEN];
  559. RC4KEY Rc4Key;
  560. if (cbInput < Offset)
  561. {
  562. return(STATUS_INVALID_PARAMETER);
  563. }
  564. //
  565. // Copy the input to the output before decrypting
  566. //
  567. RtlCopyMemory(
  568. &TempHeader,
  569. pbInput,
  570. Offset
  571. );
  572. *cbOutput = cbInput - Offset;
  573. RtlMoveMemory(
  574. pbOutput,
  575. pbInput + Offset,
  576. *cbOutput
  577. );
  578. //
  579. // Build the decryption key from the checksum and the
  580. // real key
  581. //
  582. md5Hmac(
  583. StateBuffer->Key,
  584. MD5_LEN,
  585. TempHeader.Checksum,
  586. MD5_LEN,
  587. NULL,
  588. 0,
  589. LocalKey
  590. );
  591. rc4_key(
  592. &Rc4Key,
  593. MD5_LEN,
  594. LocalKey
  595. );
  596. //
  597. // Now decrypt the two buffers
  598. //
  599. rc4(
  600. &Rc4Key,
  601. Offset - MD5_LEN,
  602. TempHeader.Confounder
  603. );
  604. rc4(
  605. &Rc4Key,
  606. *cbOutput,
  607. pbOutput
  608. );
  609. //
  610. // Now verify the checksum. First copy it out of the way, zero the
  611. // header
  612. //
  613. md5Hmac(
  614. StateBuffer->Key,
  615. MD5_LEN,
  616. TempHeader.Confounder,
  617. Offset-MD5_LEN,
  618. pbOutput,
  619. *cbOutput,
  620. TempChecksum
  621. );
  622. if (RtlEqualMemory(
  623. TempHeader.Checksum,
  624. TempChecksum,
  625. MD5_LEN
  626. ) != TRUE)
  627. {
  628. return(STATUS_UNSUCCESSFUL);
  629. }
  630. return(STATUS_SUCCESS);
  631. }
  632. NTSTATUS NTAPI
  633. rc4HmacPlainEncrypt(
  634. IN PCRYPT_STATE_BUFFER psbBuffer,
  635. IN PUCHAR pbInput,
  636. IN ULONG cbInput,
  637. OUT PUCHAR pbOutput,
  638. OUT PULONG cbOutput
  639. )
  640. {
  641. PRC4_STATE_BUFFER StateBuffer = (PRC4_STATE_BUFFER) psbBuffer;
  642. *cbOutput = cbInput;
  643. rc4(
  644. &StateBuffer->Key,
  645. cbInput,
  646. pbInput
  647. );
  648. return(STATUS_SUCCESS);
  649. }
  650. NTSTATUS NTAPI
  651. rc4HmacPlainDecrypt(
  652. IN PCRYPT_STATE_BUFFER psbBuffer,
  653. IN PUCHAR pbInput,
  654. IN ULONG cbInput,
  655. OUT PUCHAR pbOutput,
  656. OUT PULONG cbOutput
  657. )
  658. {
  659. PRC4_STATE_BUFFER StateBuffer = (PRC4_STATE_BUFFER) psbBuffer;
  660. *cbOutput = cbInput;
  661. rc4(
  662. &StateBuffer->Key,
  663. *cbOutput,
  664. pbOutput
  665. );
  666. return(STATUS_SUCCESS);
  667. }
  668. NTSTATUS NTAPI
  669. rc4HmacFinish( PCRYPT_STATE_BUFFER * psbBuffer)
  670. {
  671. #ifdef KERNEL_MODE
  672. ExFreePool(*psbBuffer);
  673. #else
  674. LocalFree(*psbBuffer);
  675. #endif
  676. *psbBuffer = NULL;
  677. return(STATUS_SUCCESS);
  678. }
  679. NTSTATUS NTAPI
  680. rc4HmacRandomKey(
  681. IN OPTIONAL PUCHAR Seed,
  682. IN ULONG SeedLength,
  683. OUT PUCHAR pbKey
  684. )
  685. {
  686. CDGenerateRandomBits(pbKey,MD5_LEN);
  687. return(STATUS_SUCCESS);
  688. }