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.

484 lines
9.1 KiB

  1. //#include <StdAfx.h>
  2. #include "AdmtCrypt.h"
  3. #include <NtSecApi.h>
  4. #pragma comment( lib, "AdvApi32.lib" )
  5. namespace AdmtCrypt2
  6. {
  7. #define SESSION_KEY_SIZE 16 // in bytes
  8. HCRYPTKEY __stdcall DeriveEncryptionKey(HCRYPTPROV hProvider);
  9. bool __stdcall IsDataMatchHash(HCRYPTPROV hProvider, const _variant_t& vntData, const _variant_t& vntHash);
  10. // Provider Methods
  11. HCRYPTKEY __stdcall DeriveKey(HCRYPTPROV hProvider, const _variant_t& vntBytes);
  12. HCRYPTHASH __stdcall CreateHash(HCRYPTPROV hProvider);
  13. bool __stdcall GenRandom(HCRYPTPROV hProvider, BYTE* pbData, DWORD cbData);
  14. // Key Methods
  15. void __stdcall DestroyKey(HCRYPTKEY hKey);
  16. bool __stdcall Decrypt(HCRYPTKEY hKey, const _variant_t& vntEncrypted, _variant_t& vntDecrypted);
  17. // Hash Methods
  18. void __stdcall DestroyHash(HCRYPTHASH hHash);
  19. bool __stdcall HashData(HCRYPTHASH hHash, const _variant_t& vntData);
  20. // Miscellaneous Helpers
  21. bool __stdcall RetrieveEncryptionBytes(_variant_t& vntBytes);
  22. // Variant Helpers
  23. bool __stdcall CreateByteArray(DWORD cb, _variant_t& vntByteArray);
  24. }
  25. using namespace AdmtCrypt2;
  26. //---------------------------------------------------------------------------
  27. // Source Crypt API
  28. //---------------------------------------------------------------------------
  29. // AdmtAcquireContext Method
  30. HCRYPTPROV __stdcall AdmtAcquireContext()
  31. {
  32. HCRYPTPROV hProvider = 0;
  33. BOOL bAcquire = CryptAcquireContext(
  34. &hProvider,
  35. NULL,
  36. MS_ENHANCED_PROV,
  37. PROV_RSA_FULL,
  38. CRYPT_MACHINE_KEYSET|CRYPT_VERIFYCONTEXT
  39. );
  40. if (!bAcquire)
  41. {
  42. hProvider = 0;
  43. }
  44. return hProvider;
  45. }
  46. // AdmtReleaseContext Method
  47. void __stdcall AdmtReleaseContext(HCRYPTPROV hProvider)
  48. {
  49. if (hProvider)
  50. {
  51. CryptReleaseContext(hProvider, 0);
  52. }
  53. }
  54. // AdmtImportSessionKey Method
  55. HCRYPTKEY __stdcall AdmtImportSessionKey(HCRYPTPROV hProvider, const _variant_t& vntEncryptedSessionBytes)
  56. {
  57. HCRYPTKEY hSessionKey = 0;
  58. if (hProvider && (vntEncryptedSessionBytes.vt == (VT_UI1|VT_ARRAY)) && ((vntEncryptedSessionBytes.parray != NULL)))
  59. {
  60. HCRYPTKEY hEncryptionKey = DeriveEncryptionKey(hProvider);
  61. if (hEncryptionKey)
  62. {
  63. _variant_t vntDecryptedSessionBytes;
  64. if (Decrypt(hEncryptionKey, vntEncryptedSessionBytes, vntDecryptedSessionBytes))
  65. {
  66. if (vntDecryptedSessionBytes.parray->rgsabound[0].cElements > SESSION_KEY_SIZE)
  67. {
  68. // extract session key bytes
  69. _variant_t vntBytes;
  70. if (CreateByteArray(SESSION_KEY_SIZE, vntBytes))
  71. {
  72. memcpy(vntBytes.parray->pvData, vntDecryptedSessionBytes.parray->pvData, SESSION_KEY_SIZE);
  73. // extract hash of session key bytes
  74. _variant_t vntHashValue;
  75. DWORD cbHashValue = vntDecryptedSessionBytes.parray->rgsabound[0].cElements - SESSION_KEY_SIZE;
  76. if (CreateByteArray(cbHashValue, vntHashValue))
  77. {
  78. memcpy(vntHashValue.parray->pvData, (BYTE*)vntDecryptedSessionBytes.parray->pvData + SESSION_KEY_SIZE, cbHashValue);
  79. if (IsDataMatchHash(hProvider, vntBytes, vntHashValue))
  80. {
  81. hSessionKey = DeriveKey(hProvider, vntBytes);
  82. }
  83. }
  84. }
  85. }
  86. else
  87. {
  88. SetLastError(ERROR_INVALID_PARAMETER);
  89. }
  90. }
  91. DestroyKey(hEncryptionKey);
  92. }
  93. }
  94. else
  95. {
  96. SetLastError(ERROR_INVALID_PARAMETER);
  97. }
  98. return hSessionKey;
  99. }
  100. // AdmtDecrypt Method
  101. _bstr_t __stdcall AdmtDecrypt(HCRYPTKEY hSessionKey, const _variant_t& vntEncrypted)
  102. {
  103. BSTR bstr = NULL;
  104. _variant_t vntDecrypted;
  105. if (Decrypt(hSessionKey, vntEncrypted, vntDecrypted))
  106. {
  107. HRESULT hr = BstrFromVector(vntDecrypted.parray, &bstr);
  108. if (FAILED(hr))
  109. {
  110. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  111. }
  112. }
  113. return bstr;
  114. }
  115. // AdmtDestroyKey Method
  116. void __stdcall AdmtDestroyKey(HCRYPTKEY hKey)
  117. {
  118. DestroyKey(hKey);
  119. }
  120. //---------------------------------------------------------------------------
  121. // Private Helpers
  122. //---------------------------------------------------------------------------
  123. namespace AdmtCrypt2
  124. {
  125. HCRYPTKEY __stdcall DeriveEncryptionKey(HCRYPTPROV hProvider)
  126. {
  127. HCRYPTKEY hKey = 0;
  128. _variant_t vntBytes;
  129. if (RetrieveEncryptionBytes(vntBytes))
  130. {
  131. hKey = DeriveKey(hProvider, vntBytes);
  132. }
  133. return hKey;
  134. }
  135. bool __stdcall IsDataMatchHash(HCRYPTPROV hProvider, const _variant_t& vntData, const _variant_t& vntHash)
  136. {
  137. bool bMatch = false;
  138. HCRYPTHASH hHash = CreateHash(hProvider);
  139. if (hHash)
  140. {
  141. if (HashData(hHash, vntData))
  142. {
  143. DWORD dwSizeA;
  144. DWORD cbSize = sizeof(DWORD);
  145. if (CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&dwSizeA, &cbSize, 0))
  146. {
  147. DWORD dwSizeB = vntHash.parray->rgsabound[0].cElements;
  148. if (dwSizeA == dwSizeB)
  149. {
  150. try
  151. {
  152. BYTE* pbA = (BYTE*) _alloca(dwSizeA);
  153. if (CryptGetHashParam(hHash, HP_HASHVAL, pbA, &dwSizeA, 0))
  154. {
  155. BYTE* pbB = (BYTE*) vntHash.parray->pvData;
  156. if (memcmp(pbA, pbB, dwSizeA) == 0)
  157. {
  158. bMatch = true;
  159. }
  160. }
  161. }
  162. catch (...)
  163. {
  164. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  165. }
  166. }
  167. }
  168. }
  169. }
  170. return bMatch;
  171. }
  172. // Provider Methods
  173. HCRYPTKEY __stdcall DeriveKey(HCRYPTPROV hProvider, const _variant_t& vntBytes)
  174. {
  175. HCRYPTKEY hKey = 0;
  176. HCRYPTHASH hHash = CreateHash(hProvider);
  177. if (hHash)
  178. {
  179. if (HashData(hHash, vntBytes))
  180. {
  181. if (!CryptDeriveKey(hProvider, CALG_3DES, hHash, 0, &hKey))
  182. {
  183. hKey = 0;
  184. }
  185. }
  186. DestroyHash(hHash);
  187. }
  188. return hKey;
  189. }
  190. HCRYPTHASH __stdcall CreateHash(HCRYPTPROV hProvider)
  191. {
  192. HCRYPTHASH hHash;
  193. if (!CryptCreateHash(hProvider, CALG_SHA1, 0, 0, &hHash))
  194. {
  195. hHash = 0;
  196. }
  197. return hHash;
  198. }
  199. bool __stdcall GenRandom(HCRYPTPROV hProvider, BYTE* pbData, DWORD cbData)
  200. {
  201. return CryptGenRandom(hProvider, cbData, pbData) ? true : false;
  202. }
  203. // Key Methods --------------------------------------------------------------
  204. // DestroyKey Method
  205. void __stdcall DestroyKey(HCRYPTKEY hKey)
  206. {
  207. if (hKey)
  208. {
  209. CryptDestroyKey(hKey);
  210. }
  211. }
  212. // Decrypt Method
  213. bool __stdcall Decrypt(HCRYPTKEY hKey, const _variant_t& vntEncrypted, _variant_t& vntDecrypted)
  214. {
  215. bool bDecrypted = false;
  216. _variant_t vnt = vntEncrypted;
  217. if ((vnt.vt == (VT_UI1|VT_ARRAY)) && (vnt.parray != NULL))
  218. {
  219. // decrypt data
  220. BYTE* pb = (BYTE*) vnt.parray->pvData;
  221. DWORD cb = vnt.parray->rgsabound[0].cElements;
  222. if (CryptDecrypt(hKey, NULL, TRUE, 0, pb, &cb))
  223. {
  224. // create decrypted byte array
  225. // the number of decrypted bytes may be less than
  226. // the number of encrypted bytes
  227. vntDecrypted.parray = SafeArrayCreateVector(VT_UI1, 0, cb);
  228. if (vntDecrypted.parray != NULL)
  229. {
  230. vntDecrypted.vt = VT_UI1|VT_ARRAY;
  231. memcpy(vntDecrypted.parray->pvData, vnt.parray->pvData, cb);
  232. bDecrypted = true;
  233. }
  234. else
  235. {
  236. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  237. }
  238. }
  239. }
  240. else
  241. {
  242. SetLastError(ERROR_INVALID_PARAMETER);
  243. }
  244. return bDecrypted;
  245. }
  246. // Hash Methods -------------------------------------------------------------
  247. // DestroyHash Method
  248. void __stdcall DestroyHash(HCRYPTHASH hHash)
  249. {
  250. if (hHash)
  251. {
  252. CryptDestroyHash(hHash);
  253. }
  254. }
  255. // HashData Method
  256. bool __stdcall HashData(HCRYPTHASH hHash, const _variant_t& vntData)
  257. {
  258. bool bHash = false;
  259. if ((vntData.vt == (VT_UI1|VT_ARRAY)) && ((vntData.parray != NULL)))
  260. {
  261. if (CryptHashData(hHash, (BYTE*)vntData.parray->pvData, vntData.parray->rgsabound[0].cElements, 0))
  262. {
  263. bHash = true;
  264. }
  265. }
  266. else
  267. {
  268. SetLastError(ERROR_INVALID_PARAMETER);
  269. }
  270. return bHash;
  271. }
  272. // Miscellaneous Helpers ----------------------------------------------------
  273. // RetrieveEncryptionBytes Method
  274. bool __stdcall RetrieveEncryptionBytes(_variant_t& vntBytes)
  275. {
  276. // private data key identifier
  277. _TCHAR c_szIdPrefix[] = _T("L$6A2899C0-CECE-459A-B5EB-7ED04DE61388");
  278. const USHORT c_cbIdPrefix = sizeof(c_szIdPrefix) - sizeof(_TCHAR);
  279. bool bRetrieve = false;
  280. // open policy object
  281. LSA_HANDLE hPolicy;
  282. LSA_OBJECT_ATTRIBUTES lsaoa = { sizeof(LSA_OBJECT_ATTRIBUTES), NULL, NULL, 0, NULL, NULL };
  283. NTSTATUS ntsStatus = LsaOpenPolicy(NULL, &lsaoa, POLICY_GET_PRIVATE_INFORMATION, &hPolicy);
  284. if (LSA_SUCCESS(ntsStatus))
  285. {
  286. // retrieve data
  287. LSA_UNICODE_STRING lsausKey = { c_cbIdPrefix, c_cbIdPrefix, c_szIdPrefix };
  288. PLSA_UNICODE_STRING plsausData;
  289. ntsStatus = LsaRetrievePrivateData(hPolicy, &lsausKey, &plsausData);
  290. if (LSA_SUCCESS(ntsStatus))
  291. {
  292. vntBytes.Clear();
  293. vntBytes.parray = SafeArrayCreateVector(VT_UI1, 0, plsausData->Length);
  294. if (vntBytes.parray != NULL)
  295. {
  296. vntBytes.vt = VT_UI1|VT_ARRAY;
  297. memcpy(vntBytes.parray->pvData, plsausData->Buffer, plsausData->Length);
  298. bRetrieve = true;
  299. }
  300. else
  301. {
  302. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  303. }
  304. LsaFreeMemory(plsausData);
  305. }
  306. else
  307. {
  308. SetLastError(LsaNtStatusToWinError(ntsStatus));
  309. }
  310. // close policy object
  311. LsaClose(hPolicy);
  312. }
  313. else
  314. {
  315. SetLastError(LsaNtStatusToWinError(ntsStatus));
  316. }
  317. return bRetrieve;
  318. }
  319. // Variant Helpers ----------------------------------------------------------
  320. // CreateByteArray Method
  321. bool __stdcall CreateByteArray(DWORD cb, _variant_t& vntByteArray)
  322. {
  323. bool bCreate = false;
  324. vntByteArray.Clear();
  325. vntByteArray.parray = SafeArrayCreateVector(VT_UI1, 0, cb);
  326. if (vntByteArray.parray)
  327. {
  328. bCreate = true;
  329. }
  330. else
  331. {
  332. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  333. }
  334. vntByteArray.vt = VT_UI1|VT_ARRAY;
  335. return bCreate;
  336. }
  337. }