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.

412 lines
9.3 KiB

  1. /*++
  2. Copyright (c) 1991 Microsoft Corporation
  3. Module Name:
  4. cr.c
  5. Abstract:
  6. Local Security Authority - Cipher Routines common to Client and Server
  7. These routines interface the LSA client or server sides with the Cipher
  8. Routines. They perform RPC-style memory allocation.
  9. Author:
  10. Scott Birrell (ScottBi) December 13, 1991
  11. Environment:
  12. Revision History:
  13. --*/
  14. #include <lsacomp.h>
  15. VOID
  16. LsapCrFreeMemoryValue(
  17. IN PVOID MemoryValue
  18. )
  19. /*++
  20. Routine Description:
  21. This function frees the memory allocated for an Cipher Value.
  22. Arguments:
  23. None.
  24. Return Value:
  25. --*/
  26. {
  27. //
  28. // The memory is currently a counted string contained in a UNICODE
  29. // STRING structure in which the buffer follows the structure. A
  30. // single MIDL_user_free will therefore do the trick.
  31. //
  32. MIDL_user_free(MemoryValue);
  33. }
  34. NTSTATUS
  35. LsapCrEncryptValue(
  36. IN OPTIONAL PLSAP_CR_CLEAR_VALUE ClearValue,
  37. IN PLSAP_CR_CIPHER_KEY CipherKey,
  38. OUT PLSAP_CR_CIPHER_VALUE *CipherValue
  39. )
  40. /*++
  41. Routine Description:
  42. This function two-way encrypts a Value with the given Cipher Key
  43. and allocates memory for the output. The memory must be freed after
  44. use by calling LsapCrFreeMemoryValue().
  45. Arguments:
  46. ClearValue - Pointer to structure referencing value to be encrypted.
  47. A NULL pointer may be specified.
  48. CipherKey - Pointer to structure referencing the Cipher Key
  49. CipherValue - Receives a pointer to a structure referencing the
  50. encrypted value or NULL.
  51. Return Value:
  52. --*/
  53. {
  54. NTSTATUS Status;
  55. LSAP_CR_CIPHER_VALUE TempCipherValue;
  56. PLSAP_CR_CIPHER_VALUE OutputCipherValue = NULL;
  57. ULONG CipherValueBufferLength;
  58. LSAP_CR_CLEAR_VALUE LocalFake = { 0 };
  59. //
  60. // If NULL is specified for input, return NULL for output.
  61. //
  62. if (!ARGUMENT_PRESENT(ClearValue)) {
  63. *CipherValue = NULL;
  64. ClearValue = &LocalFake ;
  65. }
  66. //
  67. // Obtain the length of the encrypted value buffer that will be
  68. // required by calling the encryption routine in 'query' mode
  69. // by passing a pointer to a return Cipher Value structure containing
  70. // a MaximumLength of 0.
  71. //
  72. TempCipherValue.MaximumLength = 0;
  73. TempCipherValue.Length = 0;
  74. TempCipherValue.Buffer = NULL;
  75. Status = LsapCrRtlEncryptData(
  76. ClearValue,
  77. CipherKey,
  78. &TempCipherValue
  79. );
  80. if (Status != STATUS_BUFFER_TOO_SMALL) {
  81. goto EncryptValueError;
  82. }
  83. //
  84. // Allocate memory for the output structure followed by buffer.
  85. //
  86. CipherValueBufferLength = TempCipherValue.Length;
  87. Status = STATUS_INSUFFICIENT_RESOURCES;
  88. OutputCipherValue = MIDL_user_allocate(
  89. sizeof (LSAP_CR_CIPHER_VALUE) +
  90. CipherValueBufferLength
  91. );
  92. if (OutputCipherValue == NULL) {
  93. goto EncryptValueError;
  94. }
  95. //
  96. // Initialize Cipher Value structure. The Buffer pointer is set to
  97. // to point to the byte following the structure header.
  98. //
  99. OutputCipherValue->Buffer = (PCHAR)(OutputCipherValue + 1);
  100. OutputCipherValue->MaximumLength = CipherValueBufferLength;
  101. OutputCipherValue->Length = CipherValueBufferLength;
  102. //
  103. // Now call the two-way encryption routine.
  104. //
  105. Status = LsapCrRtlEncryptData(
  106. ClearValue,
  107. CipherKey,
  108. OutputCipherValue
  109. );
  110. if (NT_SUCCESS(Status)) {
  111. *CipherValue = OutputCipherValue;
  112. return(Status);
  113. }
  114. EncryptValueError:
  115. //
  116. // If necessary, free the memory allocated for the output encrypted value.
  117. //
  118. if (OutputCipherValue != NULL) {
  119. MIDL_user_free(OutputCipherValue);
  120. }
  121. *CipherValue = NULL;
  122. return(Status);
  123. }
  124. NTSTATUS
  125. LsapCrDecryptValue(
  126. IN OPTIONAL PLSAP_CR_CIPHER_VALUE CipherValue,
  127. IN PLSAP_CR_CIPHER_KEY CipherKey,
  128. OUT PLSAP_CR_CLEAR_VALUE *ClearValue
  129. )
  130. /*++
  131. Routine Description:
  132. This function decrypts a Value that has been two-way Cipher with the
  133. given Cipher Key and allocates memory for the output. The memory
  134. must be freed after use by calling LsapCrFreeMemoryValue();
  135. Arguments:
  136. CipherValue - Pointer to structure referencing encrypted Value.
  137. CipherKey - Pointer to structure referencing the Cipher Key
  138. ClearValue - Receives a pointer to a structure referencing the
  139. Decrypted Value.
  140. Return Value:
  141. --*/
  142. {
  143. NTSTATUS Status;
  144. LSAP_CR_CLEAR_VALUE TempClearValue;
  145. PLSAP_CR_CLEAR_VALUE OutputClearValue = NULL;
  146. ULONG ClearValueBufferLength;
  147. //
  148. // If NULL is specified for input, return NULL for output.
  149. //
  150. if (!ARGUMENT_PRESENT(CipherValue)) {
  151. *ClearValue = NULL;
  152. } else {
  153. if ( CipherValue->MaximumLength < CipherValue->Length ||
  154. ( CipherValue->Length != 0 && CipherValue->Buffer == NULL ) ) {
  155. return STATUS_INVALID_PARAMETER;
  156. }
  157. }
  158. //
  159. // Obtain the length of the decrypted (clear) value buffer that will be
  160. // required by calling the decryption routine in 'query' mode
  161. // by passing a pointer to a return Clear Value structure containing
  162. // a MaximumLength of 0.
  163. //
  164. TempClearValue.MaximumLength = 0;
  165. TempClearValue.Length = 0;
  166. TempClearValue.Buffer = NULL;
  167. Status = LsapCrRtlDecryptData(
  168. CipherValue,
  169. CipherKey,
  170. &TempClearValue
  171. );
  172. //
  173. // Since we supplied a buffer length of 0, we would normally expect
  174. // to receive STATUS_BUFFER_TOO_SMALL back plus the buffer size required.
  175. // There is one exceptional case and that is where the original
  176. // unencrypted data had length 0. In this case, we expect
  177. // STATUS_SUCCESS and a length required equal to 0 returned.
  178. //
  179. if (Status != STATUS_BUFFER_TOO_SMALL) {
  180. if (!(Status == STATUS_SUCCESS && TempClearValue.Length == 0)) {
  181. goto DecryptValueError;
  182. }
  183. }
  184. //
  185. // Allocate memory for the output structure followed by buffer.
  186. //
  187. ClearValueBufferLength = TempClearValue.Length;
  188. Status = STATUS_INSUFFICIENT_RESOURCES;
  189. OutputClearValue = MIDL_user_allocate(
  190. sizeof (LSAP_CR_CLEAR_VALUE) +
  191. ClearValueBufferLength
  192. );
  193. if (OutputClearValue == NULL) {
  194. goto DecryptValueError;
  195. }
  196. //
  197. // Initialize Clear Value structure. The Buffer pointer is set to
  198. // to point to the byte following the structure header.
  199. //
  200. OutputClearValue->Buffer = (PCHAR)(OutputClearValue + 1);
  201. OutputClearValue->MaximumLength = ClearValueBufferLength;
  202. OutputClearValue->Length = ClearValueBufferLength;
  203. //
  204. // Now call the two-way decryption routine.
  205. //
  206. Status = LsapCrRtlDecryptData(
  207. CipherValue,
  208. CipherKey,
  209. OutputClearValue
  210. );
  211. if (NT_SUCCESS(Status)) {
  212. *ClearValue = OutputClearValue;
  213. return(Status);
  214. }
  215. DecryptValueError:
  216. //
  217. // If necessary, free the memory allocated for the output decrypted value.
  218. //
  219. if (OutputClearValue != NULL) {
  220. MIDL_user_free(OutputClearValue);
  221. }
  222. *ClearValue = NULL;
  223. return(Status);
  224. }
  225. VOID
  226. LsapCrUnicodeToClearValue(
  227. IN OPTIONAL PUNICODE_STRING UnicodeString,
  228. OUT PLSAP_CR_CLEAR_VALUE ClearValue
  229. )
  230. /*++
  231. Routine Description:
  232. This function converts a Unicode structure to a Clear Value structure.
  233. Arguments:
  234. UnicodeString - Optional pointer to Unicode string. If NULL, the
  235. output Clear Value structure is initialized to have zero
  236. length and Maximum length, and with a NULL buffer pointer.
  237. ClearValue - Pointer to Clear Value structure.
  238. Return Value:
  239. None.
  240. --*/
  241. {
  242. UNICODE_STRING IntermediateUnicodeString;
  243. if (ARGUMENT_PRESENT(UnicodeString)) {
  244. IntermediateUnicodeString = *UnicodeString;
  245. ClearValue->Length = (ULONG) IntermediateUnicodeString.Length;
  246. ClearValue->MaximumLength = (ULONG) IntermediateUnicodeString.MaximumLength;
  247. ClearValue->Buffer = (PUCHAR) IntermediateUnicodeString.Buffer;
  248. return;
  249. }
  250. ClearValue->Length = ClearValue->MaximumLength = 0;
  251. ClearValue->Buffer = NULL;
  252. }
  253. VOID
  254. LsapCrClearValueToUnicode(
  255. IN OPTIONAL PLSAP_CR_CLEAR_VALUE ClearValue,
  256. OUT PUNICODE_STRING UnicodeString
  257. )
  258. /*++
  259. Routine Description:
  260. This function converts a Clear Value to a Unicode String. The Clear
  261. Value structure must have valid syntax - no checking will be done.
  262. Arguments:
  263. ClearValue - Optional pointer to Clear Value to be converted. If
  264. NULL is specified, the output Unicode String structure will
  265. be initialized to point to the NULL string.
  266. UnicodeString - Pointer to target Unicode String structure.
  267. Return Value:
  268. None.
  269. --*/
  270. {
  271. LSAP_CR_CLEAR_VALUE IntermediateClearValue;
  272. if (ARGUMENT_PRESENT(ClearValue)) {
  273. IntermediateClearValue = *ClearValue;
  274. UnicodeString->Length = (USHORT) IntermediateClearValue.Length;
  275. UnicodeString->MaximumLength = (USHORT) IntermediateClearValue.MaximumLength;
  276. UnicodeString->Buffer = (PWSTR) IntermediateClearValue.Buffer;
  277. return;
  278. }
  279. UnicodeString->Length = UnicodeString->MaximumLength = 0;
  280. UnicodeString->Buffer = NULL;
  281. }