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.

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