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.

1702 lines
37 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // File: DESWRAP.C
  4. //
  5. // Contents: CryptoSystem wrapper functions for DES
  6. //
  7. //
  8. // History: 06-Sep-1996 MikeSw Created
  9. //
  10. //------------------------------------------------------------------------
  11. //
  12. // Portions of this code (the key generation code) were taken from the
  13. // MIT kerberos distribution.
  14. //
  15. /*
  16. *
  17. * Copyright 1989,1990 by the Massachusetts Institute of Technology.
  18. * All Rights Reserved.
  19. *
  20. * Export of this software from the United States of America may
  21. * require a specific license from the United States Government.
  22. * It is the responsibility of any person or organization contemplating
  23. * export to obtain such a license before exporting.
  24. *
  25. * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
  26. * distribute this software and its documentation for any purpose and
  27. * without fee is hereby granted, provided that the above copyright
  28. * notice appear in all copies and that both that copyright notice and
  29. * this permission notice appear in supporting documentation, and that
  30. * the name of M.I.T. not be used in advertising or publicity pertaining
  31. * to distribution of the software without specific, written prior
  32. * permission. M.I.T. makes no representations about the suitability of
  33. * this software for any purpose. It is provided "as is" without express
  34. * or implied warranty.
  35. *
  36. *
  37. * Under U.S. law, this software may not be exported outside the US
  38. * without license from the U.S. Commerce department.
  39. *
  40. * These routines form the library interface to the DES facilities.
  41. *
  42. * Originally written 8/85 by Steve Miller, MIT Project Athena.
  43. */
  44. /* des.c - Routines for implementing the FIPS Data Encryption Standard (DES).
  45. *
  46. * Allan Bjorklund, University of Michigan, ITD/RS/DD.
  47. * July 24, 1993.
  48. *
  49. * Revisions for PC memory model portability, July 11, 1994.
  50. *
  51. * Removed model portability header and added Win95 DLL
  52. * declarations, May 31, 1995.
  53. *
  54. * Made all declarations Win95 and NT specific, September 18, 1995.
  55. *
  56. * Added quad_cksum, October 9, 1995.
  57. *
  58. * Copyright (c) 1995,1996 Regents of The University of Michigan.
  59. * All Rights Reserved.
  60. *
  61. * Permission to use, copy, modify, and distribute this software and
  62. * its documentation for any purpose and without fee is hereby granted,
  63. * provided that the above copyright notice appears in all copies and
  64. * that both that copyright notice and this permission notice appear
  65. * in supporting documentation, and that the name of The University
  66. * of Michigan not be used in advertising or publicity pertaining to
  67. * distribution of the software without specific, written prior
  68. * permission. This software is supplied as is without expressed or
  69. * implied warranties of any kind.
  70. *
  71. * Research Systems Unix Group
  72. * The University of Michigan
  73. * c/o Allan Bjorklund
  74. * 535 W. William Street
  75. * Ann Arbor, Michigan
  76. * kerb95@umich.edu
  77. */
  78. #ifndef KERNEL_MODE
  79. #include <nt.h>
  80. #include <ntrtl.h>
  81. #include <nturtl.h>
  82. #include <windows.h>
  83. #else
  84. #include <ntifs.h>
  85. #include <winerror.h>
  86. #endif
  87. #include <string.h>
  88. #include <malloc.h>
  89. #include <align.h>
  90. #include <kerbcon.h>
  91. #include <security.h>
  92. #include <cryptdll.h>
  93. #ifdef WIN32_CHICAGO
  94. #include <assert.h>
  95. #undef ASSERT
  96. #define ASSERT(x) assert(x)
  97. VOID MyRtlFreeOemString( POEM_STRING OemString );
  98. #define RtlFreeOemString(x) MyRtlFreeOemString(x)
  99. NTSTATUS MyRtlUnicodeStringToOemString(
  100. OUT POEM_STRING DestinationString,
  101. IN PUNICODE_STRING SourceString,
  102. IN BOOLEAN AllocateDestinationString
  103. );
  104. #define RtlUnicodeStringToOemString(x, y, z) MyRtlUnicodeStringToOemString(x, y, z)
  105. #endif // WIN32_CHICAGO
  106. #include "modes.h"
  107. #include "des.h"
  108. #include "md5.h"
  109. BOOLEAN
  110. md5Hmac(
  111. IN PUCHAR pbKeyMaterial,
  112. IN ULONG cbKeyMaterial,
  113. IN PUCHAR pbData,
  114. IN ULONG cbData,
  115. IN PUCHAR pbData2,
  116. IN ULONG cbData2,
  117. OUT PUCHAR HmacData
  118. );
  119. #define DES_CONFOUNDER_LEN 8
  120. typedef struct _DES_HEADER {
  121. UCHAR Confounder[DES_CONFOUNDER_LEN];
  122. UCHAR Checksum[MD5_LEN];
  123. } DES_HEADER, *PDES_HEADER;
  124. typedef struct _DES_STATE_BUFFER {
  125. PCHECKSUM_FUNCTION ChecksumFunction;
  126. DESTable KeyTable;
  127. UCHAR InitializationVector[DES_BLOCKLEN];
  128. } DES_STATE_BUFFER, *PDES_STATE_BUFFER;
  129. typedef struct _DES_MAC_STATE_BUFFER {
  130. DESTable KeyTable;
  131. UCHAR Confounder[DES_BLOCKLEN];
  132. UCHAR InitializationVector[DES_BLOCKLEN];
  133. } DES_MAC_STATE_BUFFER, *PDES_MAC_STATE_BUFFER;
  134. typedef struct _DES_MAC_1510_STATE_BUFFER {
  135. DESTable KeyTable;
  136. UCHAR InitializationVector[DES_BLOCKLEN];
  137. UCHAR Confounder[DES_BLOCKLEN];
  138. DESTable FinalKeyTable;
  139. } DES_MAC_1510_STATE_BUFFER, *PDES_MAC_1510_STATE_BUFFER;
  140. NTSTATUS NTAPI desPlainInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  141. NTSTATUS NTAPI desPlainExpInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  142. NTSTATUS NTAPI desMd5Initialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  143. NTSTATUS NTAPI desMd5ExpInitialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  144. NTSTATUS NTAPI desCrc32Initialize(PUCHAR, ULONG, ULONG, PCRYPT_STATE_BUFFER *);
  145. NTSTATUS NTAPI desEncrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  146. NTSTATUS NTAPI desDecrypt(PCRYPT_STATE_BUFFER, PUCHAR, ULONG, PUCHAR, PULONG);
  147. NTSTATUS NTAPI desFinish(PCRYPT_STATE_BUFFER *);
  148. NTSTATUS NTAPI desHashPassword(PSECURITY_STRING, PUCHAR);
  149. NTSTATUS NTAPI desInitRandom(ULONG);
  150. NTSTATUS NTAPI desRandomKey(PUCHAR, ULONG, PUCHAR);
  151. NTSTATUS NTAPI desFinishRandom(void);
  152. NTSTATUS NTAPI desControl(ULONG, PCRYPT_STATE_BUFFER, PUCHAR, ULONG);
  153. NTSTATUS NTAPI desMacGeneralInitializeEx(PUCHAR, ULONG, PUCHAR, ULONG, PCHECKSUM_BUFFER *);
  154. NTSTATUS NTAPI desMacInitialize(ULONG, PCHECKSUM_BUFFER *);
  155. NTSTATUS NTAPI desMacInitializeEx(PUCHAR,ULONG, ULONG, PCHECKSUM_BUFFER *);
  156. NTSTATUS NTAPI desMacKInitializeEx(PUCHAR,ULONG, ULONG, PCHECKSUM_BUFFER *);
  157. NTSTATUS NTAPI desMac1510Initialize(ULONG, PCHECKSUM_BUFFER *);
  158. NTSTATUS NTAPI desMac1510InitializeEx(PUCHAR,ULONG, ULONG, PCHECKSUM_BUFFER *);
  159. NTSTATUS NTAPI desMac1510InitializeEx2(PUCHAR,ULONG, PUCHAR, ULONG, PCHECKSUM_BUFFER *);
  160. NTSTATUS NTAPI desMac1510Finalize(PCHECKSUM_BUFFER, PUCHAR);
  161. NTSTATUS NTAPI desMacSum(PCHECKSUM_BUFFER, ULONG, PUCHAR);
  162. NTSTATUS NTAPI desMacFinalize(PCHECKSUM_BUFFER, PUCHAR);
  163. NTSTATUS NTAPI desMacFinish(PCHECKSUM_BUFFER *);
  164. #ifdef KERNEL_MODE
  165. #pragma alloc_text( PAGEMSG, desPlainInitialize )
  166. #pragma alloc_text( PAGEMSG, desPlainExpInitialize )
  167. #pragma alloc_text( PAGEMSG, desMd5Initialize )
  168. #pragma alloc_text( PAGEMSG, desMd5ExpInitialize )
  169. #pragma alloc_text( PAGEMSG, desCrc32Initialize )
  170. #pragma alloc_text( PAGEMSG, desEncrypt )
  171. #pragma alloc_text( PAGEMSG, desDecrypt )
  172. #pragma alloc_text( PAGEMSG, desFinish )
  173. #pragma alloc_text( PAGEMSG, desHashPassword )
  174. #pragma alloc_text( PAGEMSG, desInitRandom )
  175. #pragma alloc_text( PAGEMSG, desRandomKey )
  176. #pragma alloc_text( PAGEMSG, desFinishRandom )
  177. #pragma alloc_text( PAGEMSG, desControl )
  178. #pragma alloc_text( PAGEMSG, desMacInitialize )
  179. #pragma alloc_text( PAGEMSG, desMacInitializeEx )
  180. #pragma alloc_text( PAGEMSG, desMacSum )
  181. #pragma alloc_text( PAGEMSG, desMacFinalize )
  182. #pragma alloc_text( PAGEMSG, desMacFinish )
  183. #pragma alloc_text( PAGEMSG, desMacGeneralInitializeEx )
  184. #pragma alloc_text( PAGEMSG, desMacKInitializeEx )
  185. #pragma alloc_text( PAGEMSG, desMac1510Initialize )
  186. #pragma alloc_text( PAGEMSG, desMac1510InitializeEx )
  187. #pragma alloc_text( PAGEMSG, desMac1510InitializeEx2 )
  188. #pragma alloc_text( PAGEMSG, desMac1510Finalize )
  189. #endif
  190. CRYPTO_SYSTEM csDES_MD5 = {
  191. KERB_ETYPE_DES_CBC_MD5, // Etype
  192. DES_BLOCKLEN, // Blocksize
  193. KERB_ETYPE_DES_CBC_MD5, // exportable version
  194. DES_KEYSIZE, // Key size, in bytes
  195. sizeof(DES_HEADER), // header size
  196. KERB_CHECKSUM_MD5, // Preferred Checksum
  197. CSYSTEM_USE_PRINCIPAL_NAME |
  198. CSYSTEM_INTEGRITY_PROTECTED |
  199. CSYSTEM_EXPORT_STRENGTH, // Attributes
  200. L"Kerberos DES-CBC-MD5", // Text name
  201. desMd5Initialize,
  202. desEncrypt,
  203. desDecrypt,
  204. desFinish,
  205. desHashPassword,
  206. desRandomKey,
  207. desControl
  208. };
  209. CRYPTO_SYSTEM csDES_CRC32 = {
  210. KERB_ETYPE_DES_CBC_CRC, // Etype
  211. DES_BLOCKLEN, // Blocksize (stream)
  212. KERB_ETYPE_DES_CBC_CRC, // exportable version
  213. DES_KEYSIZE, // Key size, in bytes
  214. sizeof(DES_HEADER), // header size
  215. KERB_CHECKSUM_CRC32, // Preferred Checksum
  216. CSYSTEM_USE_PRINCIPAL_NAME |
  217. CSYSTEM_INTEGRITY_PROTECTED |
  218. CSYSTEM_EXPORT_STRENGTH, // Attributes
  219. L"Kerberos DES-CBC-CRC", // Text name
  220. desCrc32Initialize,
  221. desEncrypt,
  222. desDecrypt,
  223. desFinish,
  224. desHashPassword,
  225. desRandomKey,
  226. desControl
  227. };
  228. CRYPTO_SYSTEM csDES_PLAIN = {
  229. KERB_ETYPE_DES_PLAIN, // Etype
  230. DES_BLOCKLEN, // Blocksize
  231. KERB_ETYPE_DES_PLAIN, // exportable version
  232. DES_KEYSIZE, // Key size, in bytes
  233. 0, // header size
  234. KERB_CHECKSUM_CRC32, // Preferred Checksum
  235. CSYSTEM_USE_PRINCIPAL_NAME | CSYSTEM_EXPORT_STRENGTH, // Attributes
  236. L"Kerberos DES-Plain", // Text name
  237. desPlainInitialize,
  238. desEncrypt,
  239. desDecrypt,
  240. desFinish,
  241. desHashPassword,
  242. desRandomKey,
  243. desControl
  244. };
  245. CHECKSUM_FUNCTION csfDesMac = {
  246. KERB_CHECKSUM_DES_MAC, // Checksum type
  247. DES_BLOCKLEN, // Checksum length
  248. CKSUM_KEYED,
  249. desMacInitialize,
  250. desMacSum,
  251. desMacFinalize,
  252. desMacFinish,
  253. desMacInitializeEx,
  254. NULL};
  255. CHECKSUM_FUNCTION csfDesMacK = {
  256. KERB_CHECKSUM_KRB_DES_MAC_K, // Checksum type
  257. DES_BLOCKLEN, // Checksum length
  258. CKSUM_KEYED,
  259. desMacInitialize,
  260. desMacSum,
  261. desMacFinalize,
  262. desMacFinish,
  263. desMacKInitializeEx,
  264. NULL};
  265. CHECKSUM_FUNCTION csfDesMac1510 = {
  266. KERB_CHECKSUM_KRB_DES_MAC, // Checksum type
  267. DES_BLOCKLEN * 2, // Checksum length
  268. CKSUM_KEYED,
  269. desMac1510Initialize,
  270. desMacSum,
  271. desMac1510Finalize,
  272. desMacFinish, // just frees the buffer
  273. desMac1510InitializeEx,
  274. desMac1510InitializeEx2};
  275. #define SMASK(step) ((1<<step)-1)
  276. #define PSTEP(x,step) (((x)&SMASK(step))^(((x)>>step)&SMASK(step)))
  277. #define PARITY_CHAR(x, y) \
  278. {\
  279. UCHAR _tmp1_, _tmp2_; \
  280. _tmp1_ = (UCHAR) PSTEP((x),4); \
  281. _tmp2_ = (UCHAR) PSTEP(_tmp1_,2); \
  282. *(y) = (UCHAR) PSTEP(_tmp2_, 1); \
  283. } \
  284. VOID
  285. desFixupKeyParity(
  286. PUCHAR Key
  287. )
  288. {
  289. ULONG Index;
  290. UCHAR TempChar;
  291. for (Index=0; Index < DES_BLOCKLEN; Index++)
  292. {
  293. Key[Index] &= 0xfe;
  294. PARITY_CHAR(Key[Index], &TempChar);
  295. Key[Index] |= 1 ^ TempChar;
  296. }
  297. }
  298. typedef UCHAR DES_KEYBLOCK[8];
  299. DES_KEYBLOCK desWeakKeys[] = {
  300. /* weak keys */
  301. {0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01},
  302. {0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe},
  303. {0x1f,0x1f,0x1f,0x1f,0x0e,0x0e,0x0e,0x0e},
  304. {0xe0,0xe0,0xe0,0xe0,0xf1,0xf1,0xf1,0xf1},
  305. /* semi-weak */
  306. {0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe},
  307. {0xfe,0x01,0xfe,0x01,0xfe,0x01,0xfe,0x01},
  308. {0x1f,0xe0,0x1f,0xe0,0x0e,0xf1,0x0e,0xf1},
  309. {0xe0,0x1f,0xe0,0x1f,0xf1,0x0e,0xf1,0x0e},
  310. {0x01,0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1},
  311. {0xe0,0x01,0xe0,0x01,0xf1,0x01,0xf1,0x01},
  312. {0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e,0xfe},
  313. {0xfe,0x1f,0xfe,0x1f,0xfe,0x0e,0xfe,0x0e},
  314. {0x01,0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e},
  315. {0x1f,0x01,0x1f,0x01,0x0e,0x01,0x0e,0x01},
  316. {0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1,0xfe},
  317. {0xfe,0xe0,0xfe,0xe0,0xfe,0xf1,0xfe,0xf1}
  318. };
  319. /*
  320. * mit_des_is_weak_key: returns true iff key is a [semi-]weak des key.
  321. *
  322. * Requires: key has correct odd parity.
  323. */
  324. BOOLEAN
  325. desIsWeakKey(
  326. PUCHAR Key
  327. )
  328. {
  329. ULONG Index;
  330. DES_KEYBLOCK * WeakKey = desWeakKeys;
  331. for (Index = 0; Index < sizeof(desWeakKeys)/DES_BLOCKLEN; Index++) {
  332. if (RtlEqualMemory(
  333. WeakKey++,
  334. Key,
  335. DES_BLOCKLEN
  336. ))
  337. {
  338. return( TRUE );
  339. }
  340. }
  341. return(FALSE);
  342. }
  343. NTSTATUS NTAPI
  344. desInitialize( PUCHAR pbKey,
  345. ULONG KeySize,
  346. ULONG MessageType,
  347. ULONG Checksum,
  348. PCRYPT_STATE_BUFFER * psbBuffer)
  349. {
  350. NTSTATUS Status;
  351. UCHAR LocalKey[DES_KEYSIZE];
  352. PDES_STATE_BUFFER DesKey = NULL;
  353. PCHECKSUM_FUNCTION ChecksumFunction = NULL;
  354. //
  355. // Make sure we were passed an appropriate keytable
  356. //
  357. if (KeySize != DES_KEYSIZE)
  358. {
  359. return(STATUS_INVALID_PARAMETER);
  360. }
  361. RtlCopyMemory(
  362. LocalKey,
  363. pbKey,
  364. KeySize
  365. );
  366. //
  367. // Get the appropriate checksum here.
  368. //
  369. if (Checksum != 0)
  370. {
  371. Status = CDLocateCheckSum(
  372. Checksum,
  373. &ChecksumFunction
  374. );
  375. if (!NT_SUCCESS(Status))
  376. {
  377. return(Status);
  378. }
  379. }
  380. else
  381. {
  382. ChecksumFunction = NULL;
  383. }
  384. //
  385. // Create the key buffer
  386. //
  387. #ifdef KERNEL_MODE
  388. DesKey = ExAllocatePool (NonPagedPool, sizeof(DES_STATE_BUFFER));
  389. #else
  390. DesKey = LocalAlloc(0, sizeof(DES_STATE_BUFFER));
  391. #endif
  392. if (DesKey == NULL)
  393. {
  394. return(STATUS_INSUFFICIENT_RESOURCES);
  395. }
  396. deskey(&DesKey->KeyTable, LocalKey);
  397. //
  398. // Initialize the checksum function
  399. //
  400. DesKey->ChecksumFunction = ChecksumFunction;
  401. //
  402. // DES-CBC-CRC uses the key as the ivec, MD5 and MD4 user zero
  403. //
  404. if (Checksum == KERB_CHECKSUM_CRC32)
  405. {
  406. RtlCopyMemory(
  407. DesKey->InitializationVector,
  408. LocalKey,
  409. DES_BLOCKLEN
  410. );
  411. }
  412. else
  413. {
  414. RtlZeroMemory(
  415. DesKey->InitializationVector,
  416. DES_BLOCKLEN
  417. );
  418. }
  419. *psbBuffer = (PCRYPT_STATE_BUFFER) DesKey;
  420. return(STATUS_SUCCESS);
  421. }
  422. #if DBG
  423. void
  424. DumpBuf(
  425. IN PUCHAR Buf,
  426. IN ULONG BufSize
  427. )
  428. {
  429. ULONG Index;
  430. for (Index = 0; Index < BufSize ;Index++ )
  431. {
  432. DbgPrint("%0.2x ",Buf[Index]);
  433. }
  434. }
  435. #endif
  436. NTSTATUS NTAPI
  437. desMd5Initialize(
  438. IN PUCHAR pbKey,
  439. IN ULONG KeySize,
  440. IN ULONG MessageType,
  441. OUT PCRYPT_STATE_BUFFER * psbBuffer
  442. )
  443. {
  444. return(desInitialize(
  445. pbKey,
  446. KeySize,
  447. MessageType,
  448. KERB_CHECKSUM_MD5,
  449. psbBuffer
  450. ));
  451. }
  452. NTSTATUS NTAPI
  453. desCrc32Initialize(
  454. IN PUCHAR pbKey,
  455. IN ULONG KeySize,
  456. IN ULONG MessageType,
  457. OUT PCRYPT_STATE_BUFFER * psbBuffer
  458. )
  459. {
  460. return(desInitialize(
  461. pbKey,
  462. KeySize,
  463. MessageType,
  464. KERB_CHECKSUM_CRC32,
  465. psbBuffer
  466. ));
  467. }
  468. NTSTATUS NTAPI
  469. desPlainInitialize(
  470. IN PUCHAR pbKey,
  471. IN ULONG KeySize,
  472. IN ULONG MessageType,
  473. OUT PCRYPT_STATE_BUFFER * psbBuffer
  474. )
  475. {
  476. return(desInitialize(
  477. pbKey,
  478. KeySize,
  479. MessageType,
  480. 0, // no checksum
  481. psbBuffer
  482. ));
  483. }
  484. //+-------------------------------------------------------------------------
  485. //
  486. // Function: BlockDecrypt
  487. //
  488. // Synopsis: Encrypts a data buffer using DES
  489. //
  490. // Effects:
  491. //
  492. // Arguments:
  493. //
  494. // Requires:
  495. //
  496. // Returns:
  497. //
  498. // Notes: stolen from windows\base\ntcyrpto\scp\nt_crypt.c
  499. //
  500. //
  501. //--------------------------------------------------------------------------
  502. NTSTATUS
  503. BlockEncrypt(
  504. IN PDES_STATE_BUFFER pKey,
  505. IN PUCHAR pbData,
  506. OUT PULONG pdwDataLen,
  507. IN ULONG dwBufLen
  508. )
  509. {
  510. ULONG cbPartial, dwPadVal, dwDataLen;
  511. UCHAR pbBuf[DES_BLOCKLEN];
  512. UCHAR FeedBack[DES_BLOCKLEN];
  513. dwDataLen = *pdwDataLen;
  514. //
  515. // Initialize the feedback buffer to the initialization vector
  516. //
  517. memcpy(
  518. FeedBack,
  519. pKey->InitializationVector,
  520. DES_BLOCKLEN
  521. );
  522. //
  523. // check length of the buffer and calculate the pad
  524. // (if multiple of DES_BLOCKLEN, do a full block of pad)
  525. //
  526. cbPartial = (dwDataLen % DES_BLOCKLEN);
  527. //
  528. // The original code here put in 8 bytes of padding
  529. // on an aligned buffer. That is a waste.
  530. //
  531. if (cbPartial != 0)
  532. {
  533. dwPadVal = DES_BLOCKLEN - cbPartial;
  534. }
  535. else
  536. {
  537. dwPadVal = 0;
  538. }
  539. if (pbData == NULL || dwBufLen < dwDataLen + dwPadVal)
  540. {
  541. //
  542. // set what we need
  543. //
  544. *pdwDataLen = dwDataLen + dwPadVal;
  545. if (pbData == NULL)
  546. {
  547. return (STATUS_SUCCESS);
  548. }
  549. return(STATUS_BUFFER_OVERFLOW);
  550. }
  551. //
  552. // allocate memory for a temporary buffer
  553. //
  554. //
  555. // Will this cause MIT clients/servers to flail? The caller
  556. // should pass in only buffers that are already padded to
  557. // make MIT clients work.
  558. //
  559. if (dwPadVal)
  560. {
  561. // Fill the pad with a value equal to the
  562. // length of the padding, so decrypt will
  563. // know the length of the original data
  564. // and as a simple integrity check.
  565. memset(
  566. pbData + dwDataLen,
  567. dwPadVal,
  568. dwPadVal
  569. );
  570. }
  571. dwDataLen += dwPadVal;
  572. *pdwDataLen = dwDataLen;
  573. ASSERT((dwDataLen % DES_BLOCKLEN) == 0);
  574. //
  575. // pump the full blocks of data through
  576. //
  577. while (dwDataLen)
  578. {
  579. ASSERT(dwDataLen >= DES_BLOCKLEN);
  580. //
  581. // put the plaintext into a temporary
  582. // buffer, then encrypt the data
  583. // back into the caller's buffer
  584. //
  585. memcpy(pbBuf, pbData, DES_BLOCKLEN);
  586. CBC( des,
  587. DES_BLOCKLEN,
  588. pbData,
  589. pbBuf,
  590. &pKey->KeyTable,
  591. ENCRYPT,
  592. FeedBack
  593. );
  594. pbData += DES_BLOCKLEN;
  595. dwDataLen -= DES_BLOCKLEN;
  596. }
  597. memcpy(
  598. pKey->InitializationVector,
  599. pbData - DES_BLOCKLEN,
  600. DES_BLOCKLEN
  601. );
  602. return(STATUS_SUCCESS);
  603. }
  604. //+-------------------------------------------------------------------------
  605. //
  606. // Function: BlockDecrypt
  607. //
  608. // Synopsis: Decrypt a block of data encrypted with BlockEncrypt
  609. //
  610. // Effects:
  611. //
  612. // Arguments:
  613. //
  614. // Requires:
  615. //
  616. // Returns:
  617. //
  618. // Notes:
  619. //
  620. //
  621. //--------------------------------------------------------------------------
  622. NTSTATUS
  623. BlockDecrypt(
  624. IN PDES_STATE_BUFFER pKey,
  625. IN OUT PUCHAR pbData,
  626. IN OUT PULONG pdwDataLen
  627. )
  628. {
  629. UCHAR pbBuf[DES_BLOCKLEN];
  630. ULONG dwDataLen, BytePos;
  631. UCHAR FeedBack[DES_BLOCKLEN];
  632. dwDataLen = *pdwDataLen;
  633. //
  634. // Check to see if we are decrypting something already
  635. //
  636. memcpy(
  637. FeedBack,
  638. pKey->InitializationVector,
  639. DES_BLOCKLEN
  640. );
  641. //
  642. // The data length must be a multiple of the algorithm
  643. // pad size.
  644. //
  645. if (dwDataLen % DES_BLOCKLEN)
  646. {
  647. return(STATUS_INVALID_PARAMETER);
  648. }
  649. //
  650. // pump the data through the decryption, including padding
  651. // NOTE: the total length is a multiple of DES_BLOCKLEN
  652. //
  653. for (BytePos = 0; (BytePos + DES_BLOCKLEN) <= dwDataLen; BytePos += DES_BLOCKLEN)
  654. {
  655. //
  656. // put the encrypted text into a temp buffer
  657. //
  658. memcpy (pbBuf, pbData + BytePos, DES_BLOCKLEN);
  659. CBC(
  660. des,
  661. DES_BLOCKLEN,
  662. pbData + BytePos,
  663. pbBuf,
  664. &pKey->KeyTable,
  665. DECRYPT,
  666. FeedBack
  667. );
  668. }
  669. memcpy(
  670. pKey->InitializationVector,
  671. pbBuf,
  672. DES_BLOCKLEN
  673. );
  674. return STATUS_SUCCESS;
  675. }
  676. NTSTATUS NTAPI
  677. desEncrypt(
  678. IN PCRYPT_STATE_BUFFER psbBuffer,
  679. IN PUCHAR pbInput,
  680. IN ULONG cbInput,
  681. OUT PUCHAR OutputBuffer,
  682. OUT PULONG OutputLength
  683. )
  684. {
  685. NTSTATUS Status = STATUS_SUCCESS;
  686. PDES_STATE_BUFFER StateBuffer = (PDES_STATE_BUFFER) psbBuffer;
  687. PDES_HEADER CryptHeader = (PDES_HEADER) OutputBuffer;
  688. PCHECKSUM_BUFFER SumBuffer = NULL;
  689. ULONG LocalOutputLength;
  690. //
  691. // If we aren't doing raw DES, prepare a header structure
  692. //
  693. if (StateBuffer->ChecksumFunction != NULL)
  694. {
  695. //
  696. // Relocate the buffer and inserat the header
  697. //
  698. RtlMoveMemory(
  699. OutputBuffer + DES_CONFOUNDER_LEN + StateBuffer->ChecksumFunction->CheckSumSize,
  700. pbInput,
  701. cbInput
  702. );
  703. LocalOutputLength = cbInput + DES_CONFOUNDER_LEN + StateBuffer->ChecksumFunction->CheckSumSize;
  704. //
  705. // Zero fill the padding space
  706. //
  707. RtlZeroMemory(
  708. OutputBuffer+LocalOutputLength,
  709. ROUND_UP_COUNT(LocalOutputLength,DES_BLOCKLEN) - LocalOutputLength
  710. );
  711. LocalOutputLength = ROUND_UP_COUNT(LocalOutputLength,DES_BLOCKLEN);
  712. RtlZeroMemory(
  713. CryptHeader->Checksum,
  714. StateBuffer->ChecksumFunction->CheckSumSize
  715. );
  716. CDGenerateRandomBits(
  717. CryptHeader->Confounder,
  718. DES_CONFOUNDER_LEN
  719. );
  720. //
  721. // Checksum the buffer.
  722. //
  723. Status = StateBuffer->ChecksumFunction->Initialize(0, &SumBuffer);
  724. if (!NT_SUCCESS(Status))
  725. {
  726. goto Cleanup;
  727. }
  728. StateBuffer->ChecksumFunction->Sum(
  729. SumBuffer,
  730. LocalOutputLength,
  731. OutputBuffer
  732. );
  733. StateBuffer->ChecksumFunction->Finalize(
  734. SumBuffer,
  735. CryptHeader->Checksum
  736. );
  737. StateBuffer->ChecksumFunction->Finish(
  738. &SumBuffer
  739. );
  740. }
  741. else
  742. {
  743. //
  744. // Just copy the buffer
  745. //
  746. RtlCopyMemory(
  747. OutputBuffer,
  748. pbInput,
  749. cbInput
  750. );
  751. LocalOutputLength = ROUND_UP_COUNT(cbInput,DES_BLOCKLEN);
  752. //
  753. // Zero fill the padding space
  754. //
  755. RtlZeroMemory(
  756. OutputBuffer+cbInput,
  757. LocalOutputLength - cbInput
  758. );
  759. }
  760. //
  761. // Encrypt the buffer.
  762. //
  763. *OutputLength = LocalOutputLength;
  764. Status = BlockEncrypt(
  765. StateBuffer,
  766. OutputBuffer,
  767. OutputLength,
  768. LocalOutputLength
  769. );
  770. Cleanup:
  771. return(Status);
  772. }
  773. NTSTATUS NTAPI
  774. desDecrypt( PCRYPT_STATE_BUFFER psbBuffer,
  775. PUCHAR pbInput,
  776. ULONG cbInput,
  777. PUCHAR pbOutput,
  778. PULONG cbOutput)
  779. {
  780. NTSTATUS Status = STATUS_SUCCESS;
  781. PDES_STATE_BUFFER StateBuffer = (PDES_STATE_BUFFER) psbBuffer;
  782. PDES_HEADER CryptHeader;
  783. UCHAR Checksum[MD5_LEN];
  784. PCHECKSUM_BUFFER SumBuffer = NULL;
  785. //
  786. // First decrypt the whole buffer
  787. //
  788. if (*cbOutput < cbInput)
  789. {
  790. *cbOutput = cbInput;
  791. return(STATUS_BUFFER_TOO_SMALL);
  792. }
  793. RtlCopyMemory(
  794. pbOutput,
  795. pbInput,
  796. cbInput
  797. );
  798. Status = BlockDecrypt(
  799. StateBuffer,
  800. pbOutput,
  801. &cbInput
  802. );
  803. if (!NT_SUCCESS(Status))
  804. {
  805. goto Cleanup;
  806. }
  807. if (StateBuffer->ChecksumFunction != NULL)
  808. {
  809. //
  810. // Now verify the checksum
  811. //
  812. CryptHeader = (PDES_HEADER) pbOutput;
  813. RtlCopyMemory(
  814. Checksum,
  815. CryptHeader->Checksum,
  816. MD5_LEN
  817. );
  818. //
  819. // Zero the checksum field before computing the checksum of the buffer
  820. //
  821. RtlZeroMemory(
  822. CryptHeader->Checksum,
  823. StateBuffer->ChecksumFunction->CheckSumSize
  824. );
  825. //
  826. // Checksum the buffer.
  827. //
  828. Status = StateBuffer->ChecksumFunction->Initialize(0, &SumBuffer);
  829. if (!NT_SUCCESS(Status))
  830. {
  831. goto Cleanup;
  832. }
  833. StateBuffer->ChecksumFunction->Sum(
  834. SumBuffer,
  835. cbInput,
  836. pbOutput
  837. );
  838. StateBuffer->ChecksumFunction->Finalize(
  839. SumBuffer,
  840. CryptHeader->Checksum
  841. );
  842. StateBuffer->ChecksumFunction->Finish(
  843. &SumBuffer
  844. );
  845. if (!RtlEqualMemory(
  846. CryptHeader->Checksum,
  847. Checksum,
  848. StateBuffer->ChecksumFunction->CheckSumSize
  849. ))
  850. {
  851. Status = SEC_E_MESSAGE_ALTERED;
  852. goto Cleanup;
  853. }
  854. //
  855. // Copy the input to the output without the header
  856. *cbOutput = cbInput - (DES_CONFOUNDER_LEN + StateBuffer->ChecksumFunction->CheckSumSize);
  857. RtlMoveMemory(
  858. pbOutput,
  859. pbOutput + DES_CONFOUNDER_LEN + StateBuffer->ChecksumFunction->CheckSumSize,
  860. *cbOutput
  861. );
  862. }
  863. else
  864. {
  865. *cbOutput = cbInput;
  866. }
  867. Cleanup:
  868. return(Status);
  869. }
  870. NTSTATUS NTAPI
  871. desFinish( PCRYPT_STATE_BUFFER * psbBuffer)
  872. {
  873. PDES_STATE_BUFFER StateBuffer = (PDES_STATE_BUFFER) *psbBuffer;
  874. #ifdef KERNEL_MODE
  875. ExFreePool(StateBuffer);
  876. #else
  877. LocalFree(StateBuffer);
  878. #endif
  879. *psbBuffer = NULL;
  880. return(S_OK);
  881. }
  882. #define MIN(x,y) (((x) < (y)) ? (x) : (y))
  883. #define XORBLOCK(x,y) \
  884. { \
  885. PULONG tx = (PULONG) x; \
  886. PULONG ty = (PULONG) y; \
  887. *tx++ ^= *ty++; \
  888. *tx++ ^= *ty++; \
  889. }
  890. VOID
  891. desCbcChecksum(
  892. IN PUCHAR Password,
  893. IN ULONG PasswordLength,
  894. IN PUCHAR InitialVector,
  895. IN DESTable * KeyTable,
  896. OUT PUCHAR OutputKey
  897. )
  898. {
  899. ULONG Offset;
  900. UCHAR Feedback[DES_BLOCKLEN];
  901. UCHAR Block[DES_BLOCKLEN];
  902. RtlCopyMemory(
  903. Feedback,
  904. InitialVector,
  905. DES_BLOCKLEN
  906. );
  907. for (Offset = 0; Offset < PasswordLength ; Offset+= 8 )
  908. {
  909. RtlZeroMemory(
  910. Block,
  911. DES_BLOCKLEN
  912. );
  913. RtlCopyMemory(
  914. Block,
  915. Password+Offset,
  916. MIN(DES_BLOCKLEN, PasswordLength - Offset)
  917. );
  918. XORBLOCK(Block, Feedback);
  919. des(
  920. Feedback,
  921. Block,
  922. KeyTable,
  923. ENCRYPT
  924. );
  925. }
  926. RtlCopyMemory(
  927. OutputKey,
  928. Feedback,
  929. DES_BLOCKLEN
  930. );
  931. }
  932. #define BITREVERSE(c) ((UCHAR)((((c & 0x01) ? 0x80 : 0x00)\
  933. |((c & 0x02) ? 0x40 : 0x00)\
  934. |((c & 0x04) ? 0x20 : 0x00)\
  935. |((c & 0x08) ? 0x10 : 0x00)\
  936. |((c & 0x10) ? 0x08 : 0x00)\
  937. |((c & 0x20) ? 0x04 : 0x00)\
  938. |((c & 0x40) ? 0x02 : 0x00))\
  939. & 0xFE))
  940. //
  941. // This is the core routine that converts a buffer into a key. It is called
  942. // by desHashPassword and desRandomKey
  943. //
  944. VOID
  945. desHashBuffer(
  946. IN PUCHAR LocalPassword,
  947. IN ULONG PasswordLength,
  948. IN OUT PUCHAR Key
  949. )
  950. {
  951. ULONG Index;
  952. BOOLEAN Forward;
  953. PUCHAR KeyPointer = Key;
  954. DESTable KeyTable;
  955. RtlZeroMemory(
  956. Key,
  957. DES_BLOCKLEN
  958. );
  959. //
  960. // Initialize our temporary parity vector
  961. //
  962. //
  963. // Start fanfolding the bytes into the key
  964. //
  965. Forward = TRUE;
  966. KeyPointer = Key;
  967. for (Index = 0; Index < PasswordLength ; Index++ )
  968. {
  969. if (!Forward)
  970. {
  971. *(--KeyPointer) ^= BITREVERSE(LocalPassword[Index] & 0x7F);
  972. }
  973. else
  974. {
  975. *KeyPointer++ ^= (LocalPassword[Index] & 0x7F) << 1;
  976. }
  977. if (((Index+1) & 0x07) == 0) /* When MOD 8 equals 0 */
  978. {
  979. Forward = !Forward; /* Change direction. */
  980. }
  981. }
  982. //
  983. // Fix key parity
  984. //
  985. desFixupKeyParity(Key);
  986. //
  987. // Check for weak keys.
  988. //
  989. if (desIsWeakKey(Key))
  990. {
  991. Key[7] ^= 0xf0;
  992. }
  993. //
  994. // Now calculate the des-cbc-mac of the original string
  995. //
  996. deskey(&KeyTable, Key);
  997. //
  998. // Now compute the CBC checksum of the string
  999. //
  1000. desCbcChecksum(
  1001. LocalPassword,
  1002. PasswordLength,
  1003. Key, // initial vector
  1004. &KeyTable,
  1005. Key // output key
  1006. );
  1007. //
  1008. // Fix key parity
  1009. //
  1010. desFixupKeyParity(Key);
  1011. //
  1012. // Check for weak keys.
  1013. //
  1014. if (desIsWeakKey(Key))
  1015. {
  1016. Key[7] ^= 0xf0;
  1017. }
  1018. }
  1019. NTSTATUS NTAPI
  1020. desHashPassword(
  1021. IN PSECURITY_STRING Password,
  1022. OUT PUCHAR Key
  1023. )
  1024. {
  1025. PUCHAR LocalPassword = NULL;
  1026. ULONG PasswordLength;
  1027. OEM_STRING OemPassword;
  1028. NTSTATUS Status;
  1029. //
  1030. // First convert the UNICODE string to an OEM string
  1031. //
  1032. Status = RtlUnicodeStringToOemString(
  1033. &OemPassword,
  1034. Password,
  1035. TRUE // allocate destination
  1036. );
  1037. if (!NT_SUCCESS(Status))
  1038. {
  1039. return(Status);
  1040. }
  1041. //
  1042. // We hash the password according to RFC1510
  1043. //
  1044. // This code is derived from the MIT Kerberos code in string2key.c
  1045. //
  1046. PasswordLength = ROUND_UP_COUNT(OemPassword.Length,8);
  1047. #ifdef KERNEL_MODE
  1048. LocalPassword = (PUCHAR) ExAllocatePool(NonPagedPool, PasswordLength);
  1049. #else
  1050. LocalPassword = (PUCHAR) LocalAlloc(0, PasswordLength);
  1051. #endif
  1052. if (LocalPassword == NULL)
  1053. {
  1054. RtlFreeOemString( &OemPassword );
  1055. return(STATUS_INSUFFICIENT_RESOURCES);
  1056. }
  1057. RtlCopyMemory(
  1058. LocalPassword,
  1059. OemPassword.Buffer,
  1060. OemPassword.Length
  1061. );
  1062. //
  1063. // Zero extend the password
  1064. //
  1065. RtlZeroMemory(
  1066. LocalPassword + OemPassword.Length,
  1067. PasswordLength - OemPassword.Length
  1068. );
  1069. //
  1070. // Initialize our temporary parity vector
  1071. //
  1072. desHashBuffer(
  1073. LocalPassword,
  1074. PasswordLength,
  1075. Key
  1076. );
  1077. RtlFreeOemString( &OemPassword );
  1078. #ifdef KERNEL_MODE
  1079. ExFreePool(LocalPassword);
  1080. #else
  1081. LocalFree(LocalPassword);
  1082. #endif
  1083. return(STATUS_SUCCESS);
  1084. }
  1085. NTSTATUS NTAPI
  1086. desRandomKey(
  1087. IN OPTIONAL PUCHAR Seed,
  1088. IN ULONG SeedLength,
  1089. OUT PUCHAR pbKey)
  1090. {
  1091. UCHAR Buffer[16];
  1092. do
  1093. {
  1094. CDGenerateRandomBits(Buffer,16);
  1095. desHashBuffer(
  1096. Buffer,
  1097. 16,
  1098. pbKey
  1099. );
  1100. } while (desIsWeakKey(pbKey));
  1101. return(STATUS_SUCCESS);
  1102. }
  1103. NTSTATUS NTAPI
  1104. desControl(
  1105. IN ULONG Function,
  1106. IN PCRYPT_STATE_BUFFER StateBuffer,
  1107. IN PUCHAR InputBuffer,
  1108. IN ULONG InputBufferSize
  1109. )
  1110. {
  1111. PDES_STATE_BUFFER DesStateBuffer = (PDES_STATE_BUFFER) StateBuffer;
  1112. if (Function != CRYPT_CONTROL_SET_INIT_VECT)
  1113. {
  1114. return(STATUS_INVALID_PARAMETER);
  1115. }
  1116. if (InputBufferSize != DES_BLOCKLEN)
  1117. {
  1118. return(STATUS_INVALID_PARAMETER);
  1119. }
  1120. memcpy(
  1121. DesStateBuffer->InitializationVector,
  1122. InputBuffer,
  1123. DES_BLOCKLEN
  1124. );
  1125. return(STATUS_SUCCESS);
  1126. }
  1127. ///////////////////////////////////////////////////////////////////////////
  1128. NTSTATUS NTAPI
  1129. desMacGeneralInitializeEx(
  1130. PUCHAR Key,
  1131. ULONG KeySize,
  1132. PUCHAR IV,
  1133. ULONG MessageType,
  1134. PCHECKSUM_BUFFER * ppcsBuffer
  1135. )
  1136. {
  1137. PDES_MAC_STATE_BUFFER DesKey = NULL;
  1138. //
  1139. // Make sure we were passed an appropriate keytable
  1140. //
  1141. if (KeySize != DES_KEYSIZE)
  1142. {
  1143. return(STATUS_INVALID_PARAMETER);
  1144. }
  1145. #ifdef KERNEL_MODE
  1146. DesKey = ExAllocatePool(NonPagedPool, sizeof(DES_MAC_STATE_BUFFER));
  1147. #else
  1148. DesKey = LocalAlloc(0, sizeof(DES_MAC_STATE_BUFFER));
  1149. #endif
  1150. if (DesKey == NULL)
  1151. {
  1152. return(STATUS_INSUFFICIENT_RESOURCES);
  1153. }
  1154. //
  1155. // Create the key buffer
  1156. //
  1157. deskey(&DesKey->KeyTable, Key);
  1158. RtlCopyMemory(
  1159. DesKey->InitializationVector,
  1160. IV,
  1161. DES_BLOCKLEN
  1162. );
  1163. *ppcsBuffer = (PCHECKSUM_BUFFER) DesKey;
  1164. return(STATUS_SUCCESS);
  1165. }
  1166. NTSTATUS NTAPI
  1167. desMacInitializeEx(
  1168. PUCHAR Key,
  1169. ULONG KeySize,
  1170. ULONG MessageType,
  1171. PCHECKSUM_BUFFER * ppcsBuffer
  1172. )
  1173. {
  1174. UCHAR IV[DES_BLOCKLEN];
  1175. RtlZeroMemory(
  1176. IV,
  1177. DES_BLOCKLEN
  1178. );
  1179. return desMacGeneralInitializeEx(
  1180. Key,
  1181. KeySize,
  1182. IV,
  1183. MessageType,
  1184. ppcsBuffer
  1185. );
  1186. }
  1187. NTSTATUS NTAPI
  1188. desMacKInitializeEx(
  1189. PUCHAR Key,
  1190. ULONG KeySize,
  1191. ULONG MessageType,
  1192. PCHECKSUM_BUFFER * ppcsBuffer
  1193. )
  1194. {
  1195. return desMacGeneralInitializeEx(
  1196. Key,
  1197. KeySize,
  1198. Key,
  1199. MessageType,
  1200. ppcsBuffer
  1201. );
  1202. }
  1203. NTSTATUS NTAPI
  1204. desMacInitialize(ULONG dwSeed,
  1205. PCHECKSUM_BUFFER * ppcsBuffer)
  1206. {
  1207. return(STATUS_NOT_IMPLEMENTED);
  1208. }
  1209. //
  1210. // NOTE - This function is used with both DES_MAC_STATE_BUFFER and
  1211. // DES_MAC_1510_STATE_BUFFER as the pcsBuffer parameter, since the
  1212. // DES_MAC_1510_STATE_BUFFER is the same as DES_MAC_STATE_BUFFER
  1213. // except with an added confounder this should be OK.
  1214. //
  1215. NTSTATUS NTAPI
  1216. desMacSum(
  1217. PCHECKSUM_BUFFER pcsBuffer,
  1218. ULONG cbData,
  1219. PUCHAR pbData)
  1220. {
  1221. PDES_MAC_STATE_BUFFER DesKey = (PDES_MAC_STATE_BUFFER) pcsBuffer;
  1222. UCHAR FeedBack[DES_BLOCKLEN];
  1223. UCHAR TempBuffer[DES_BLOCKLEN];
  1224. UCHAR OutputBuffer[DES_BLOCKLEN];
  1225. ULONG Index;
  1226. //
  1227. // Set up the IV for this round - it may be zero or the output of
  1228. // a previous MAC
  1229. //
  1230. memcpy(
  1231. FeedBack,
  1232. DesKey->InitializationVector,
  1233. DES_BLOCKLEN
  1234. );
  1235. for (Index = 0; Index < cbData ; Index += DES_BLOCKLEN )
  1236. {
  1237. //
  1238. // Compute the input buffer, with padding
  1239. //
  1240. if (Index+DES_BLOCKLEN > cbData)
  1241. {
  1242. memset(
  1243. TempBuffer,
  1244. 0,
  1245. DES_BLOCKLEN
  1246. );
  1247. memcpy(
  1248. TempBuffer,
  1249. pbData,
  1250. Index & (DES_BLOCKLEN-1)
  1251. );
  1252. }
  1253. else
  1254. {
  1255. memcpy(
  1256. TempBuffer,
  1257. pbData+Index,
  1258. DES_BLOCKLEN
  1259. );
  1260. }
  1261. CBC( des,
  1262. DES_BLOCKLEN,
  1263. TempBuffer,
  1264. OutputBuffer,
  1265. &DesKey->KeyTable,
  1266. ENCRYPT,
  1267. FeedBack
  1268. );
  1269. }
  1270. //
  1271. // Copy the feedback back into the IV for the next round
  1272. //
  1273. memcpy(
  1274. DesKey->InitializationVector,
  1275. FeedBack,
  1276. DES_BLOCKLEN
  1277. );
  1278. return(STATUS_SUCCESS);
  1279. }
  1280. NTSTATUS NTAPI
  1281. desMacFinalize(
  1282. PCHECKSUM_BUFFER pcsBuffer,
  1283. PUCHAR pbSum)
  1284. {
  1285. PDES_MAC_STATE_BUFFER DesKey = (PDES_MAC_STATE_BUFFER) pcsBuffer;
  1286. memcpy(pbSum, DesKey->InitializationVector, DES_BLOCKLEN);
  1287. return(STATUS_SUCCESS);
  1288. }
  1289. NTSTATUS NTAPI
  1290. desMacFinish( PCHECKSUM_BUFFER * ppcsBuffer)
  1291. {
  1292. #ifdef KERNEL_MODE
  1293. ExFreePool(*ppcsBuffer);
  1294. #else
  1295. LocalFree(*ppcsBuffer);
  1296. #endif
  1297. *ppcsBuffer = 0;
  1298. return(STATUS_SUCCESS);
  1299. }
  1300. NTSTATUS NTAPI
  1301. desMac1510Initialize(ULONG dwSeed,
  1302. PCHECKSUM_BUFFER * ppcsBuffer)
  1303. {
  1304. return(STATUS_NOT_IMPLEMENTED);
  1305. }
  1306. NTSTATUS NTAPI
  1307. desMac1510InitializeEx(
  1308. PUCHAR Key,
  1309. ULONG KeySize,
  1310. ULONG MessageType,
  1311. PCHECKSUM_BUFFER * ppcsBuffer
  1312. )
  1313. {
  1314. return(STATUS_NOT_IMPLEMENTED);
  1315. }
  1316. NTSTATUS NTAPI
  1317. desMac1510InitializeEx2(
  1318. PUCHAR Key,
  1319. ULONG KeySize,
  1320. PUCHAR ChecksumToVerify,
  1321. ULONG MessageType,
  1322. PCHECKSUM_BUFFER * ppcsBuffer
  1323. )
  1324. {
  1325. ULONG *pul;
  1326. ULONG *pul2;
  1327. UCHAR FinalKey[DES_KEYSIZE];
  1328. PDES_MAC_1510_STATE_BUFFER DesKey = NULL;
  1329. //
  1330. // Make sure we were passed an appropriate keytable
  1331. //
  1332. if (KeySize != DES_KEYSIZE)
  1333. {
  1334. return(STATUS_INVALID_PARAMETER);
  1335. }
  1336. #ifdef KERNEL_MODE
  1337. DesKey = ExAllocatePool(NonPagedPool, sizeof(DES_MAC_1510_STATE_BUFFER));
  1338. #else
  1339. DesKey = LocalAlloc(0, sizeof(DES_MAC_1510_STATE_BUFFER));
  1340. #endif
  1341. if (DesKey == NULL)
  1342. {
  1343. return(STATUS_INSUFFICIENT_RESOURCES);
  1344. }
  1345. //
  1346. // create the final key table
  1347. //
  1348. pul = (ULONG*)FinalKey;
  1349. pul2 = (ULONG*)Key;
  1350. *pul = *pul2 ^ 0xf0f0f0f0;
  1351. pul = (ULONG*)(FinalKey + sizeof(ULONG));
  1352. pul2 = (ULONG*)(Key + sizeof(ULONG));
  1353. *pul = *pul2 ^ 0xf0f0f0f0;
  1354. deskey(&DesKey->FinalKeyTable, FinalKey);
  1355. //
  1356. // Checksum was not passed in so generate a confounder
  1357. //
  1358. if (NULL == ChecksumToVerify)
  1359. {
  1360. CDGenerateRandomBits(DesKey->Confounder,DES_BLOCKLEN);
  1361. }
  1362. else
  1363. {
  1364. // the IV is all zero so no need to use CBC on first block
  1365. des(DesKey->Confounder, ChecksumToVerify, &DesKey->FinalKeyTable, DECRYPT);
  1366. }
  1367. //
  1368. // Create the key buffer
  1369. //
  1370. deskey(&DesKey->KeyTable, Key);
  1371. // the IV is all zero so no need to use CBC on first block, but the
  1372. // ecncrypted confounder becomes the next IV
  1373. des(DesKey->InitializationVector, DesKey->Confounder, &DesKey->KeyTable, ENCRYPT);
  1374. *ppcsBuffer = (PCHECKSUM_BUFFER) DesKey;
  1375. return(STATUS_SUCCESS);
  1376. }
  1377. NTSTATUS NTAPI
  1378. desMac1510Finalize(
  1379. PCHECKSUM_BUFFER pcsBuffer,
  1380. PUCHAR pbSum)
  1381. {
  1382. UCHAR Feedback[DES_BLOCKLEN];
  1383. PDES_MAC_1510_STATE_BUFFER DesKey = (PDES_MAC_1510_STATE_BUFFER) pcsBuffer;
  1384. // the IV is all zero so no need to use CBC on first block
  1385. des(Feedback, DesKey->Confounder, &DesKey->FinalKeyTable, ENCRYPT);
  1386. memcpy(pbSum, Feedback, DES_BLOCKLEN);
  1387. // use CBC on second block
  1388. CBC( des,
  1389. DES_BLOCKLEN,
  1390. pbSum + DES_BLOCKLEN,
  1391. DesKey->InitializationVector,
  1392. &DesKey->FinalKeyTable,
  1393. ENCRYPT,
  1394. Feedback
  1395. );
  1396. return(STATUS_SUCCESS);
  1397. }