Leaked source code of windows server 2003
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.

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