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.

394 lines
8.9 KiB

  1. //+-----------------------------------------------------------------------
  2. //
  3. // File: crypt.c
  4. //
  5. // Contents: cryptography routines for building EncryptedData structs
  6. //
  7. //
  8. // History: 17-Dec-91, RichardW Created
  9. // 25-Feb-92, RichardW Revised for CryptoSystems
  10. //
  11. //------------------------------------------------------------------------
  12. #ifndef WIN32_CHICAGO
  13. #include "krbprgma.h"
  14. #include <nt.h>
  15. #include <ntrtl.h>
  16. #include <nturtl.h>
  17. #include <kerbcomm.h>
  18. #include <kerberr.h>
  19. #include <kerbcon.h>
  20. #else // WIN32_CHICAGO
  21. #include <kerb.hxx>
  22. #include <kerbp.h>
  23. #endif // WIN32_CHICAGO
  24. #define CONFOUNDER_SIZE 8
  25. #define CHECKSUM_SIZE sizeof(CheckSum)
  26. //+-------------------------------------------------------------------------
  27. //
  28. // Function: KerbEncryptData
  29. //
  30. // Synopsis: shim for KerbEncryptDataEx
  31. //
  32. // Effects:
  33. //
  34. // Arguments:
  35. //
  36. // Requires:
  37. //
  38. // Returns:
  39. //
  40. // Notes:
  41. //
  42. //
  43. //--------------------------------------------------------------------------
  44. KERBERR NTAPI
  45. KerbEncryptData(
  46. OUT PKERB_ENCRYPTED_DATA EncryptedData,
  47. IN ULONG DataSize,
  48. IN PUCHAR Data,
  49. IN ULONG Algorithm,
  50. IN PKERB_ENCRYPTION_KEY Key
  51. )
  52. {
  53. return KerbEncryptDataEx(
  54. EncryptedData,
  55. DataSize,
  56. Data,
  57. KERB_NO_KEY_VERSION,
  58. 0, // no usage flags
  59. Key
  60. );
  61. }
  62. //+---------------------------------------------------------------------------
  63. //
  64. // Function: KerbEncryptDataEx
  65. //
  66. // Synopsis: Turns cleartext into cipher text
  67. //
  68. // Effects: In place encryption of data
  69. //
  70. // Arguments: Data - Contains data to be encrypted
  71. // DataSize - Contains length of data in bytes
  72. // KeyVersion - KERB_NO_KEY_VERSION for no key version or kvno for KERB_ENCRYPTED_DATA
  73. // Algorithm - Algorithm to be used for encryption/checksum
  74. // UsageFlags - Flags indicating usage (client/serve, encryption/authentication)
  75. // Key - Key to use for encryption
  76. //
  77. //
  78. //
  79. // Notes:
  80. //
  81. //----------------------------------------------------------------------------
  82. KERBERR NTAPI
  83. KerbEncryptDataEx(
  84. OUT PKERB_ENCRYPTED_DATA EncryptedData,
  85. IN ULONG DataSize,
  86. IN PUCHAR Data,
  87. IN ULONG KeyVersion,
  88. IN ULONG UsageFlags,
  89. IN PKERB_ENCRYPTION_KEY Key
  90. )
  91. {
  92. PCRYPTO_SYSTEM pcsCrypt = NULL;
  93. PCRYPT_STATE_BUFFER psbCryptBuffer = NULL;
  94. NTSTATUS Status = STATUS_SUCCESS;
  95. Status = CDLocateCSystem(Key->keytype, &pcsCrypt);
  96. if (!NT_SUCCESS(Status))
  97. {
  98. return(KDC_ERR_ETYPE_NOTSUPP);
  99. }
  100. //
  101. // Initialize header
  102. //
  103. EncryptedData->encryption_type = Key->keytype;
  104. Status = pcsCrypt->Initialize(
  105. (PUCHAR) Key->keyvalue.value,
  106. Key->keyvalue.length,
  107. UsageFlags,
  108. &psbCryptBuffer
  109. );
  110. if (!NT_SUCCESS(Status))
  111. {
  112. return(KRB_ERR_GENERIC);
  113. }
  114. Status = pcsCrypt->Encrypt(
  115. psbCryptBuffer,
  116. Data,
  117. DataSize,
  118. EncryptedData->cipher_text.value,
  119. &EncryptedData->cipher_text.length
  120. );
  121. (void) pcsCrypt->Discard(&psbCryptBuffer);
  122. if (!NT_SUCCESS(Status))
  123. {
  124. return(KRB_ERR_GENERIC);
  125. }
  126. if (KeyVersion != KERB_NO_KEY_VERSION)
  127. {
  128. EncryptedData->version = KeyVersion;
  129. EncryptedData->bit_mask |= version_present;
  130. }
  131. return(KDC_ERR_NONE);
  132. }
  133. //+-------------------------------------------------------------------------
  134. //
  135. // Function: KerbDecryptData
  136. //
  137. // Synopsis: Shim for KerbDecryptDataEx with no usage flags
  138. //
  139. // Effects:
  140. //
  141. // Arguments:
  142. //
  143. // Requires:
  144. //
  145. // Returns:
  146. //
  147. // Notes:
  148. //
  149. //
  150. //--------------------------------------------------------------------------
  151. KERBERR NTAPI
  152. KerbDecryptData(
  153. IN PKERB_ENCRYPTED_DATA EncryptedData,
  154. IN PKERB_ENCRYPTION_KEY pkKey,
  155. OUT PULONG DataSize,
  156. OUT PUCHAR Data
  157. )
  158. {
  159. return(KerbDecryptDataEx(
  160. EncryptedData,
  161. pkKey,
  162. 0, // no usage flags
  163. DataSize,
  164. Data
  165. ) );
  166. }
  167. //+---------------------------------------------------------------------------
  168. //
  169. // Function: KerbDecryptDataEx
  170. //
  171. // Synopsis: Decrypts an EncryptedData structure
  172. //
  173. // Effects:
  174. //
  175. // Arguments: [pedData] -- EncryptedData
  176. // [pkKey] -- Key to use
  177. //
  178. // History: 4-16-93 RichardW Created Comment
  179. //
  180. //----------------------------------------------------------------------------
  181. KERBERR NTAPI
  182. KerbDecryptDataEx(
  183. IN PKERB_ENCRYPTED_DATA EncryptedData,
  184. IN PKERB_ENCRYPTION_KEY pkKey,
  185. IN ULONG UsageFlags,
  186. OUT PULONG DataSize,
  187. OUT PUCHAR Data
  188. )
  189. {
  190. PCRYPTO_SYSTEM pcsCrypt = NULL;
  191. PCRYPT_STATE_BUFFER psbCryptBuffer = NULL;
  192. NTSTATUS Status = STATUS_SUCCESS;
  193. Status = CDLocateCSystem(
  194. EncryptedData->encryption_type,
  195. &pcsCrypt
  196. );
  197. if (!NT_SUCCESS(Status))
  198. {
  199. return(KDC_ERR_ETYPE_NOTSUPP);
  200. }
  201. if (EncryptedData->cipher_text.length & (pcsCrypt->BlockSize - 1))
  202. {
  203. return(KRB_ERR_GENERIC);
  204. }
  205. Status = pcsCrypt->Initialize(
  206. (PUCHAR) pkKey->keyvalue.value,
  207. pkKey->keyvalue.length,
  208. UsageFlags,
  209. &psbCryptBuffer
  210. );
  211. if (!NT_SUCCESS(Status))
  212. {
  213. return(KRB_ERR_GENERIC);
  214. }
  215. Status = pcsCrypt->Decrypt(
  216. psbCryptBuffer,
  217. EncryptedData->cipher_text.value,
  218. EncryptedData->cipher_text.length,
  219. Data,
  220. DataSize
  221. );
  222. (VOID) pcsCrypt->Discard(&psbCryptBuffer);
  223. if (!NT_SUCCESS(Status))
  224. {
  225. return(KRB_AP_ERR_MODIFIED);
  226. }
  227. else
  228. {
  229. return(KDC_ERR_NONE);
  230. }
  231. }
  232. //+-------------------------------------------------------------------------
  233. //
  234. // Function: KerbGetEncryptionOverhead
  235. //
  236. // Synopsis: Gets the extra space required for encryption to store the ckecksum
  237. //
  238. // Effects:
  239. //
  240. // Arguments: Algorithm - the algorithm to use
  241. // Overhead - receives the overhead in bytes
  242. //
  243. // Requires:
  244. //
  245. // Returns: STATUS_SUCCESS or KRB_E_ETYPE_NOSUPP
  246. //
  247. // Notes:
  248. //
  249. //
  250. //--------------------------------------------------------------------------
  251. KERBERR
  252. KerbGetEncryptionOverhead(
  253. IN ULONG Algorithm,
  254. OUT PULONG Overhead,
  255. OUT OPTIONAL PULONG BlockSize
  256. )
  257. {
  258. PCRYPTO_SYSTEM pcsCrypt;
  259. NTSTATUS Status = STATUS_SUCCESS;
  260. Status = CDLocateCSystem(Algorithm, &pcsCrypt);
  261. if (!NT_SUCCESS(Status))
  262. {
  263. return(KDC_ERR_ETYPE_NOTSUPP);
  264. }
  265. *Overhead = pcsCrypt->HeaderSize;
  266. if (ARGUMENT_PRESENT(BlockSize))
  267. {
  268. *BlockSize = pcsCrypt->BlockSize;
  269. }
  270. return(KDC_ERR_NONE);
  271. }
  272. //+-------------------------------------------------------------------------
  273. //
  274. // Function: KerbAllocateEncryptionBuffer
  275. //
  276. // Synopsis: Allocates the space required for encryption with a given
  277. // key
  278. //
  279. // Effects:
  280. //
  281. // Arguments:
  282. //
  283. // Requires:
  284. //
  285. // Returns:
  286. //
  287. // Notes:
  288. //
  289. //
  290. //--------------------------------------------------------------------------
  291. KERBERR
  292. KerbAllocateEncryptionBuffer(
  293. IN ULONG EncryptionType,
  294. IN ULONG BufferSize,
  295. OUT PUINT EncryptionBufferSize,
  296. OUT PBYTE * EncryptionBuffer
  297. )
  298. {
  299. KERBERR KerbErr = KDC_ERR_NONE;
  300. ULONG EncryptionOverhead = 0;
  301. ULONG BlockSize = 0;
  302. KerbErr = KerbGetEncryptionOverhead(
  303. EncryptionType,
  304. &EncryptionOverhead,
  305. &BlockSize
  306. );
  307. if (!KERB_SUCCESS(KerbErr))
  308. {
  309. goto Cleanup;
  310. }
  311. *EncryptionBufferSize = (UINT) ROUND_UP_COUNT(EncryptionOverhead + BufferSize, BlockSize);
  312. *EncryptionBuffer = (PBYTE) MIDL_user_allocate(*EncryptionBufferSize);
  313. if (*EncryptionBuffer == NULL)
  314. {
  315. KerbErr = KRB_ERR_GENERIC;
  316. }
  317. Cleanup:
  318. return(KerbErr);
  319. }
  320. KERBERR
  321. KerbAllocateEncryptionBufferWrapper(
  322. IN ULONG EncryptionType,
  323. IN ULONG BufferSize,
  324. OUT unsigned long * EncryptionBufferSize,
  325. OUT PBYTE * EncryptionBuffer
  326. )
  327. {
  328. KERBERR KerbErr = KDC_ERR_NONE;
  329. unsigned int tempInt = 0;
  330. KerbErr = KerbAllocateEncryptionBuffer(
  331. EncryptionType,
  332. BufferSize,
  333. &tempInt,
  334. EncryptionBuffer
  335. );
  336. if (!KERB_SUCCESS(KerbErr))
  337. {
  338. goto Cleanup;
  339. }
  340. *EncryptionBufferSize = tempInt;
  341. Cleanup:
  342. return (KerbErr);
  343. }