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.

5131 lines
144 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // FILE : cryptapi.c //
  3. // DESCRIPTION : Crypto API interface //
  4. // AUTHOR : //
  5. // HISTORY : //
  6. // Dec 6 1994 larrys New //
  7. // Jan 16 1995 larrys Added key verify //
  8. // Jan 25 1995 larrys Added thread safe //
  9. // Jan 27 1995 larrys Added Unicode support //
  10. // Feb 21 1995 larrys Added Unicode support for CryptAcquireContext //
  11. // Feb 21 1995 larrys Fixed Unicode problem in CryptAcquireContext //
  12. // Mar 08 1995 larrys Removed CryptGetLastError //
  13. // Mar 20 1995 larrys Removed Certificate APIs //
  14. // Mar 22 1995 larrys #ifdef in WIN95 code //
  15. // Apr 06 1995 larrys Increased signature key to 1024 bits //
  16. // Apr 07 1995 larrys Removed CryptConfigure //
  17. // Jun 14 1995 larrys Removed pointer from RSA key struct //
  18. // Jun 29 1995 larrys Changed AcquireContext //
  19. // Jul 17 1995 larrys Worked on AcquireContext //
  20. // Aug 01 1995 larrys Removed CryptTranslate //
  21. // And CryptDeinstallProvider //
  22. // Changed CryptInstallProvider to //
  23. // CryptSetProvider //
  24. // Aug 03 1995 larrys Cleanup //
  25. // Aug 10 1995 larrys CryptAcquireContext returns error //
  26. // NTE_BAD_KEYSEY_PARAM now //
  27. // Aug 14 1995 larrys Removed key exchange stuff //
  28. // Aug 17 1995 larrys Changed registry entry to decimcal //
  29. // Aug 23 1995 larrys Changed CryptFinishHash to CryptGetHashValue //
  30. // Aug 28 1995 larrys Removed parameter from CryptVerifySignature //
  31. // Aug 31 1995 larrys Remove GenRandom //
  32. // Sep 14 1995 larrys Code review changes //
  33. // Sep 26 1995 larrys Added Microsoft's signing key //
  34. // Sep 27 1995 larrys Updated with more review changes //
  35. // Oct 06 1995 larrys Added more APIs Get/SetHash/ProvParam //
  36. // Oct 12 1995 larrys Remove CryptGetHashValue //
  37. // Oct 20 1995 larrys Changed test key //
  38. // Oct 24 1995 larrys Removed return of KeySet name //
  39. // Oct 30 1995 larrys Removed WIN95 //
  40. // Nov 9 1995 larrys Disable BUILD1057 //
  41. // Nov 10 1995 larrys Fix a problem in EnterHashCritSec //
  42. // May 30 1996 larrys Added hWnd support //
  43. // Oct 10 1996 jeffspel Reordered SetLastErrors and save error on //
  44. // AcquireContext failure //
  45. // Mar 21 1997 jeffspel Added second tier signatures, new APIs //
  46. // Apr 11 1997 jeffspel Replace critical sections with interlocked //
  47. // inc/dec //
  48. // Oct 02 1997 jeffspel Add caching of CSPs to CryptAcquireContext //
  49. // Oct 10 1997 jeffspel Add verification scheme for signature in file //
  50. // //
  51. // Copyright (C) 1993 Microsoft Corporation All Rights Reserved //
  52. /////////////////////////////////////////////////////////////////////////////
  53. #include "advapi.h"
  54. #include "stdlib.h"
  55. #include <wincrypt.h> // Include here, since not included by LEAN_AND_MEAN
  56. #include <cspdk.h>
  57. #include <ntstatus.h>
  58. #include <rsa.h>
  59. #include <md5.h>
  60. #include <rc4.h>
  61. #include <winperf.h>
  62. #include <wtypes.h>
  63. #include <mincrypt.h>
  64. #define IDR_PUBKEY1 102
  65. typedef struct _VTableStruc {
  66. // ******************** WARNING **********************************************
  67. // Do not place anything before these FARPROCs we init the table assuming
  68. // that the first Function to call is the first thing in the table.
  69. // ***************************************************************************
  70. FARPROC FuncAcquireContext;
  71. FARPROC FuncReleaseContext;
  72. FARPROC FuncGenKey;
  73. FARPROC FuncDeriveKey;
  74. FARPROC FuncDestroyKey;
  75. FARPROC FuncSetKeyParam;
  76. FARPROC FuncGetKeyParam;
  77. FARPROC FuncExportKey;
  78. FARPROC FuncImportKey;
  79. FARPROC FuncEncrypt;
  80. FARPROC FuncDecrypt;
  81. FARPROC FuncCreateHash;
  82. FARPROC FuncHashData;
  83. FARPROC FuncHashSessionKey;
  84. FARPROC FuncDestroyHash;
  85. FARPROC FuncSignHash;
  86. FARPROC FuncVerifySignature;
  87. FARPROC FuncGenRandom;
  88. FARPROC FuncGetUserKey;
  89. FARPROC FuncSetProvParam;
  90. FARPROC FuncGetProvParam;
  91. FARPROC FuncSetHashParam;
  92. FARPROC FuncGetHashParam;
  93. FARPROC FuncNULL;
  94. FARPROC OptionalFuncDuplicateKey;
  95. FARPROC OptionalFuncDuplicateHash;
  96. FARPROC OptionalFuncNULL;
  97. HANDLE DllHandle; // Handle to open DLL
  98. HCRYPTPROV hProv; // Handle to provider
  99. DWORD Version;
  100. DWORD Inuse;
  101. LONG RefCnt;
  102. } VTableStruc, *PVTableStruc;
  103. typedef struct _VKeyStruc {
  104. // ******************** WARNING **********************************************
  105. // Do not place anything before these FARPROCs we init the table assuming
  106. // that the first Function to call is the first thing in the table.
  107. // ***************************************************************************
  108. FARPROC FuncGenKey;
  109. FARPROC FuncDeriveKey;
  110. FARPROC FuncDestroyKey;
  111. FARPROC FuncSetKeyParam;
  112. FARPROC FuncGetKeyParam;
  113. FARPROC FuncExportKey;
  114. FARPROC FuncImportKey;
  115. FARPROC FuncEncrypt;
  116. FARPROC FuncDecrypt;
  117. FARPROC OptionalFuncDuplicateKey;
  118. HCRYPTPROV hProv; // Handle to provider
  119. HCRYPTKEY hKey; // Handle to key
  120. DWORD Version;
  121. DWORD Inuse;
  122. } VKeyStruc, *PVKeyStruc;
  123. typedef struct _VHashStruc {
  124. // ******************** WARNING **********************************************
  125. // Do not place anything before these FARPROCs we init the table assuming
  126. // that the first Function to call is the first thing in the table.
  127. // ***************************************************************************
  128. FARPROC FuncCreateHash;
  129. FARPROC FuncHashData;
  130. FARPROC FuncHashSessionKey;
  131. FARPROC FuncDestroyHash;
  132. FARPROC FuncSignHash;
  133. FARPROC FuncVerifySignature;
  134. FARPROC FuncSetHashParam;
  135. FARPROC FuncGetHashParam;
  136. FARPROC OptionalFuncDuplicateHash;
  137. HCRYPTPROV hProv; // Handle to provider
  138. HCRYPTHASH hHash; // Handle to hash
  139. DWORD Version;
  140. DWORD Inuse;
  141. } VHashStruc, *PVHashStruc;
  142. //
  143. // Crypto providers have to have the following entry points:
  144. //
  145. LPCSTR FunctionNames[] = {
  146. "CPAcquireContext",
  147. "CPReleaseContext",
  148. "CPGenKey",
  149. "CPDeriveKey",
  150. "CPDestroyKey",
  151. "CPSetKeyParam",
  152. "CPGetKeyParam",
  153. "CPExportKey",
  154. "CPImportKey",
  155. "CPEncrypt",
  156. "CPDecrypt",
  157. "CPCreateHash",
  158. "CPHashData",
  159. "CPHashSessionKey",
  160. "CPDestroyHash",
  161. "CPSignHash",
  162. "CPVerifySignature",
  163. "CPGenRandom",
  164. "CPGetUserKey",
  165. "CPSetProvParam",
  166. "CPGetProvParam",
  167. "CPSetHashParam",
  168. "CPGetHashParam",
  169. NULL
  170. };
  171. LPCSTR OptionalFunctionNames[] = {
  172. "CPDuplicateKey",
  173. "CPDuplicateHash",
  174. NULL
  175. };
  176. #define CapiExceptionFilter \
  177. (STATUS_ACCESS_VIOLATION == GetExceptionCode() ? \
  178. EXCEPTION_EXECUTE_HANDLER : \
  179. EXCEPTION_CONTINUE_SEARCH)
  180. HWND hWnd = NULL;
  181. BYTE *pbContextInfo = NULL;
  182. DWORD cbContextInfo;
  183. #define KEYSIZE512 0x48
  184. #define KEYSIZE1024 0x88
  185. // designatred resource for in file signatures
  186. #define OLD_CRYPT_SIG_RESOURCE_NUMBER "#666"
  187. typedef struct _SECONDTIER_SIG
  188. {
  189. DWORD dwMagic;
  190. DWORD cbSig;
  191. BSAFE_PUB_KEY Pub;
  192. } SECOND_TIER_SIG, *PSECOND_TIER_SIG;
  193. #ifdef TEST_BUILD_EXPONENT
  194. #pragma message("WARNING: building advapai32.dll with TESTKEY enabled!")
  195. static struct _TESTKEY {
  196. BSAFE_PUB_KEY PUB;
  197. unsigned char pubmodulus[KEYSIZE512];
  198. } TESTKEY = {
  199. {
  200. 0x66b8443b,
  201. 0x6f5fc900,
  202. 0xa12132fe,
  203. 0xff1b06cf,
  204. 0x2f4826eb,
  205. },
  206. {
  207. 0x3e, 0x69, 0x4f, 0x45, 0x31, 0x95, 0x60, 0x6c,
  208. 0x80, 0xa5, 0x41, 0x99, 0x3e, 0xfc, 0x92, 0x2c,
  209. 0x93, 0xf9, 0x86, 0x23, 0x3d, 0x48, 0x35, 0x81,
  210. 0x19, 0xb6, 0x7c, 0x04, 0x43, 0xe6, 0x3e, 0xd4,
  211. 0xd5, 0x43, 0xaf, 0x52, 0xdd, 0x51, 0x20, 0xac,
  212. 0xc3, 0xca, 0xee, 0x21, 0x9b, 0x4a, 0x2d, 0xf7,
  213. 0xd8, 0x5f, 0x32, 0xeb, 0x49, 0x72, 0xb9, 0x8d,
  214. 0x2e, 0x1a, 0x76, 0x7f, 0xde, 0xc6, 0x75, 0xab,
  215. 0xaf, 0x67, 0xe0, 0xf0, 0x8b, 0x30, 0x20, 0x92,
  216. }
  217. };
  218. #endif
  219. #ifdef MS_INTERNAL_KEY
  220. static struct _mskey {
  221. BSAFE_PUB_KEY PUB;
  222. unsigned char pubmodulus[KEYSIZE1024];
  223. } MSKEY = {
  224. {
  225. 0x2bad85ae,
  226. 0x883adacc,
  227. 0xb32ebd68,
  228. 0xa7ec8b06,
  229. 0x58dbeb81,
  230. },
  231. {
  232. 0x42, 0x34, 0xb7, 0xab, 0x45, 0x0f, 0x60, 0xcd,
  233. 0x8f, 0x77, 0xb5, 0xd1, 0x79, 0x18, 0x34, 0xbe,
  234. 0x66, 0xcb, 0x5c, 0x66, 0x4a, 0x9f, 0x03, 0x18,
  235. 0x13, 0x36, 0x8e, 0x88, 0x21, 0x78, 0xb1, 0x94,
  236. 0xa1, 0xd5, 0x8f, 0x8c, 0xa5, 0xd3, 0x9f, 0x86,
  237. 0x43, 0x89, 0x05, 0xa0, 0xe3, 0xee, 0xe2, 0xd0,
  238. 0xe5, 0x1d, 0x5f, 0xaf, 0xff, 0x85, 0x71, 0x7a,
  239. 0x0a, 0xdb, 0x2e, 0xd8, 0xc3, 0x5f, 0x2f, 0xb1,
  240. 0xf0, 0x53, 0x98, 0x3b, 0x44, 0xee, 0x7f, 0xc9,
  241. 0x54, 0x26, 0xdb, 0xdd, 0xfe, 0x1f, 0xd0, 0xda,
  242. 0x96, 0x89, 0xc8, 0x9e, 0x2b, 0x5d, 0x96, 0xd1,
  243. 0xf7, 0x52, 0x14, 0x04, 0xfb, 0xf8, 0xee, 0x4d,
  244. 0x92, 0xd1, 0xb6, 0x37, 0x6a, 0xe0, 0xaf, 0xde,
  245. 0xc7, 0x41, 0x06, 0x7a, 0xe5, 0x6e, 0xb1, 0x8c,
  246. 0x8f, 0x17, 0xf0, 0x63, 0x8d, 0xaf, 0x63, 0xfd,
  247. 0x22, 0xc5, 0xad, 0x1a, 0xb1, 0xe4, 0x7a, 0x6b,
  248. 0x1e, 0x0e, 0xea, 0x60, 0x56, 0xbd, 0x49, 0xd0,
  249. }
  250. };
  251. #endif
  252. static struct _key {
  253. BSAFE_PUB_KEY PUB;
  254. unsigned char pubmodulus[KEYSIZE1024];
  255. } KEY = {
  256. {
  257. 0x3fcbf1a9,
  258. 0x08f597db,
  259. 0xe4aecab4,
  260. 0x75360f90,
  261. 0x9d6c0f00,
  262. },
  263. {
  264. 0x85, 0xdd, 0x9b, 0xf4, 0x4d, 0x0b, 0xc4, 0x96,
  265. 0x3e, 0x79, 0x86, 0x30, 0x6d, 0x27, 0x31, 0xee,
  266. 0x4a, 0x85, 0xf5, 0xff, 0xbb, 0xa9, 0xbd, 0x81,
  267. 0x86, 0xf2, 0x4f, 0x87, 0x6c, 0x57, 0x55, 0x19,
  268. 0xe4, 0xf4, 0x49, 0xa3, 0x19, 0x27, 0x08, 0x82,
  269. 0x9e, 0xf9, 0x8a, 0x8e, 0x41, 0xd6, 0x91, 0x71,
  270. 0x47, 0x48, 0xee, 0xd6, 0x24, 0x2d, 0xdd, 0x22,
  271. 0x72, 0x08, 0xc6, 0xa7, 0x34, 0x6f, 0x93, 0xd2,
  272. 0xe7, 0x72, 0x57, 0x78, 0x7a, 0x96, 0xc1, 0xe1,
  273. 0x47, 0x38, 0x78, 0x43, 0x53, 0xea, 0xf3, 0x88,
  274. 0x82, 0x66, 0x41, 0x43, 0xd4, 0x62, 0x44, 0x01,
  275. 0x7d, 0xb2, 0x16, 0xb3, 0x50, 0x89, 0xdb, 0x0a,
  276. 0x93, 0x17, 0x02, 0x02, 0x46, 0x49, 0x79, 0x76,
  277. 0x59, 0xb6, 0xb1, 0x2b, 0xfc, 0xb0, 0x9a, 0x21,
  278. 0xe6, 0xfa, 0x2d, 0x56, 0x07, 0x36, 0xbc, 0x13,
  279. 0x7f, 0x1c, 0xde, 0x55, 0xfb, 0x0d, 0x67, 0x0f,
  280. 0xc2, 0x17, 0x45, 0x8a, 0x14, 0x2b, 0xba, 0x55,
  281. }
  282. };
  283. static struct _key2 {
  284. BSAFE_PUB_KEY PUB;
  285. unsigned char pubmodulus[KEYSIZE1024];
  286. } KEY2 = {
  287. {
  288. 0x685fc690,
  289. 0x97d49b6b,
  290. 0x1dccd9d2,
  291. 0xa5ec9b52,
  292. 0x64fd29d7,
  293. },
  294. {
  295. 0x03, 0x8c, 0xa3, 0x9e, 0xfb, 0x93, 0xb6, 0x72,
  296. 0x2a, 0xda, 0x6f, 0xa5, 0xec, 0x26, 0x39, 0x58,
  297. 0x41, 0xcd, 0x3f, 0x49, 0x10, 0x4c, 0xcc, 0x7e,
  298. 0x23, 0x94, 0xf9, 0x5d, 0x9b, 0x2b, 0xa3, 0x6b,
  299. 0xe8, 0xec, 0x52, 0xd9, 0x56, 0x64, 0x74, 0x7c,
  300. 0x44, 0x6f, 0x36, 0xb7, 0x14, 0x9d, 0x02, 0x3c,
  301. 0x0e, 0x32, 0xb6, 0x38, 0x20, 0x25, 0xbd, 0x8c,
  302. 0x9b, 0xd1, 0x46, 0xa7, 0xb3, 0x58, 0x4a, 0xb7,
  303. 0xdd, 0x0e, 0x38, 0xb6, 0x16, 0x44, 0xbf, 0xc1,
  304. 0xca, 0x4d, 0x6a, 0x9f, 0xcb, 0x6f, 0x3c, 0x5f,
  305. 0x03, 0xab, 0x7a, 0xb8, 0x16, 0x70, 0xcf, 0x98,
  306. 0xd0, 0xca, 0x8d, 0x25, 0x57, 0x3a, 0x22, 0x8b,
  307. 0x44, 0x96, 0x37, 0x51, 0x30, 0x00, 0x92, 0x1b,
  308. 0x03, 0xb9, 0xf9, 0x0d, 0xb3, 0x1a, 0xe2, 0xb4,
  309. 0xc5, 0x7b, 0xc9, 0x4b, 0xe2, 0x42, 0x25, 0xfe,
  310. 0x3d, 0x42, 0xfa, 0x45, 0xc6, 0x94, 0xc9, 0x8e,
  311. 0x87, 0x7e, 0xf6, 0x68, 0x90, 0x30, 0x65, 0x10,
  312. }
  313. };
  314. #define CACHESIZE 32
  315. static HANDLE gCSPCache[CACHESIZE];
  316. #define TABLEPROV 0x11111111
  317. #define TABLEKEY 0x22222222
  318. #define TABLEHASH 0x33333333
  319. CHAR szreg[] = "SOFTWARE\\Microsoft\\Cryptography\\Providers\\";
  320. CHAR szusertype[] = "SOFTWARE\\Microsoft\\Cryptography\\Providers\\Type ";
  321. CHAR szmachinetype[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider Types\\Type ";
  322. CHAR szprovider[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider\\";
  323. CHAR szenumproviders[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider";
  324. CHAR szprovidertypes[] = "SOFTWARE\\Microsoft\\Cryptography\\Defaults\\Provider Types";
  325. BOOL EnterProviderCritSec(IN PVTableStruc pVTable);
  326. void LeaveProviderCritSec(IN PVTableStruc pVTable);
  327. BOOL EnterKeyCritSec(IN PVKeyStruc pVKey);
  328. void LeaveKeyCritSec(IN PVKeyStruc pVKey);
  329. BOOL EnterHashCritSec(IN PVHashStruc pVHash);
  330. void LeaveHashCritSec(IN PVHashStruc pVHash);
  331. BOOL CheckSignatureInFile(LPCWSTR pszImage);
  332. BOOL CProvVerifyImage(LPCSTR lpszImage,
  333. BYTE *pSigData);
  334. BOOL NewVerifyImage(LPCSTR lpszImage,
  335. BYTE *pSigData,
  336. DWORD cbData,
  337. BOOL fUnknownLen);
  338. BOOL BuildVKey(IN PVKeyStruc *ppVKey,
  339. IN PVTableStruc pVTable);
  340. BOOL BuildVHash(
  341. IN PVHashStruc *ppVKey,
  342. IN PVTableStruc pVTable
  343. );
  344. void CPReturnhWnd(HWND *phWnd);
  345. static void __ltoa(DWORD val, char *buf);
  346. BOOL CSPInCacheCheck(
  347. LPSTR pszValue,
  348. HANDLE *ph
  349. )
  350. {
  351. HANDLE h = 0;
  352. DWORD i;
  353. BOOL fRet = FALSE;
  354. // check if CSP has been loaded
  355. if (0 == (h = GetModuleHandle(pszValue)))
  356. goto Ret;
  357. // check if the CSP is in the cache designating it as signed
  358. for (i=0;i<CACHESIZE;i++)
  359. {
  360. if (h == gCSPCache[i])
  361. {
  362. *ph = h;
  363. fRet = TRUE;
  364. break;
  365. }
  366. }
  367. Ret:
  368. return fRet;
  369. }
  370. void AddHandleToCSPCache(
  371. HANDLE h
  372. )
  373. {
  374. DWORD i;
  375. // check if the CSP is in the cache designating it as signed
  376. for (i=0;i<CACHESIZE;i++)
  377. {
  378. if (0 == gCSPCache[i])
  379. {
  380. gCSPCache[i] = h;
  381. break;
  382. }
  383. }
  384. }
  385. /*
  386. - CryptAcquireContextW
  387. -
  388. * Purpose:
  389. * The CryptAcquireContext function is used to acquire a context
  390. * handle to a cryptograghic service provider (CSP).
  391. *
  392. *
  393. * Parameters:
  394. * OUT phProv - Handle to a CSP
  395. * IN pszIdentity - Pointer to the name of the context's
  396. * keyset.
  397. * IN pszProvider - Pointer to the name of the provider.
  398. * IN dwProvType - Requested CSP type
  399. * IN dwFlags - Flags values
  400. *
  401. * Returns:
  402. */
  403. WINADVAPI
  404. BOOL
  405. WINAPI CryptAcquireContextW(OUT HCRYPTPROV *phProv,
  406. IN LPCWSTR pszIdentity,
  407. IN LPCWSTR pszProvider,
  408. IN DWORD dwProvType,
  409. IN DWORD dwFlags)
  410. {
  411. ANSI_STRING AnsiString1;
  412. ANSI_STRING AnsiString2;
  413. UNICODE_STRING UnicodeString1;
  414. UNICODE_STRING UnicodeString2;
  415. NTSTATUS Status = STATUS_SUCCESS;
  416. BOOL rt;
  417. __try
  418. {
  419. memset(&AnsiString1, 0, sizeof(AnsiString1));
  420. memset(&AnsiString2, 0, sizeof(AnsiString2));
  421. memset(&UnicodeString1, 0, sizeof(UnicodeString1));
  422. memset(&UnicodeString2, 0, sizeof(UnicodeString2));
  423. if (NULL != pszIdentity)
  424. {
  425. RtlInitUnicodeString(&UnicodeString1, pszIdentity);
  426. Status = RtlUnicodeStringToAnsiString(&AnsiString1, &UnicodeString1,
  427. TRUE);
  428. }
  429. if (!NT_SUCCESS(Status))
  430. {
  431. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  432. return(CRYPT_FAILED);
  433. }
  434. if (NULL != pszProvider)
  435. {
  436. RtlInitUnicodeString(&UnicodeString2, pszProvider);
  437. Status = RtlUnicodeStringToAnsiString(&AnsiString2, &UnicodeString2,
  438. TRUE);
  439. }
  440. if (!NT_SUCCESS(Status))
  441. {
  442. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  443. return(CRYPT_FAILED);
  444. }
  445. rt = CryptAcquireContextA(phProv, AnsiString1.Buffer,
  446. AnsiString2.Buffer,
  447. dwProvType, dwFlags);
  448. RtlFreeAnsiString(&AnsiString1);
  449. RtlFreeAnsiString(&AnsiString2);
  450. return(rt);
  451. }
  452. __except (CapiExceptionFilter)
  453. {
  454. SetLastError(ERROR_INVALID_PARAMETER);
  455. goto Try_Error_Return;
  456. }
  457. Try_Error_Return:
  458. return(CRYPT_FAILED);
  459. }
  460. /*
  461. - CryptAcquireContextA
  462. -
  463. * Purpose:
  464. * The CryptAcquireContext function is used to acquire a context
  465. * handle to a cryptograghic service provider (CSP).
  466. *
  467. *
  468. * Parameters:
  469. * OUT phProv - Handle to a CSP
  470. * IN OUT pszIdentity - Pointer to the name of the context's
  471. * keyset.
  472. * IN OUT pszProvName - Pointer to the name of the provider.
  473. * IN dwReqProvider - Requested CSP type
  474. * IN dwFlags - Flags values
  475. *
  476. * Returns:
  477. */
  478. WINADVAPI
  479. BOOL
  480. WINAPI CryptAcquireContextA(OUT HCRYPTPROV *phProv,
  481. IN LPCSTR pszIdentity,
  482. IN LPCSTR pszProvName,
  483. IN DWORD dwReqProvider,
  484. IN DWORD dwFlags)
  485. {
  486. HANDLE handle = 0;
  487. DWORD bufsize;
  488. ULONG_PTR *pTable;
  489. PVTableStruc pVTable = NULL;
  490. LPSTR pszTmpProvName = NULL;
  491. DWORD i;
  492. HKEY hKey = 0;
  493. DWORD cbValue;
  494. DWORD cbTemp;
  495. CHAR *pszValue = NULL;
  496. CHAR *pszDest = NULL;
  497. BYTE *SignatureBuf = NULL;
  498. DWORD provtype;
  499. BOOL rt = CRYPT_FAILED;
  500. DWORD dwType;
  501. LONG err;
  502. DWORD dwErr;
  503. CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  504. HCRYPTPROV hTmpProv = 0;
  505. VTableProvStruc VTableProv;
  506. UNICODE_STRING String ;
  507. BOOL SigInFile ;
  508. __try
  509. {
  510. if (dwReqProvider == 0 || dwReqProvider > 999)
  511. {
  512. SetLastError((DWORD) NTE_BAD_PROV_TYPE);
  513. goto Ret;
  514. }
  515. if (pszProvName != NULL && pszProvName[0] != 0)
  516. {
  517. // Do nothing just check for invalid pointers
  518. ;
  519. }
  520. if (pszProvName != NULL && pszProvName[0] != 0)
  521. {
  522. cbValue = strlen(pszProvName);
  523. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  524. (UINT) cbValue +
  525. strlen(szprovider) + 1)) == NULL)
  526. {
  527. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  528. goto Ret;
  529. }
  530. if ((pszTmpProvName = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
  531. (UINT) cbValue + 1)) == NULL)
  532. {
  533. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  534. goto Ret;
  535. }
  536. strcpy(pszTmpProvName, pszProvName);
  537. strcpy(pszValue, szprovider);
  538. strcat(pszValue, pszProvName);
  539. }
  540. else
  541. {
  542. //
  543. // We no longer look under HKCU for a default csp. We only look
  544. // under HKLM.
  545. //
  546. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  547. 5 + strlen(szmachinetype))) == NULL)
  548. {
  549. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  550. goto Ret;
  551. }
  552. __ltoa(dwReqProvider, typebuf);
  553. strcpy(pszValue, szmachinetype);
  554. strcat(pszValue, &typebuf[5]);
  555. if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  556. (const char *) pszValue, 0L,
  557. KEY_READ, &hKey)) != ERROR_SUCCESS)
  558. {
  559. SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
  560. goto Ret;
  561. }
  562. if ((err = RegQueryValueEx(hKey, "Name", NULL, &dwType,
  563. NULL, &cbValue)) != ERROR_SUCCESS)
  564. {
  565. SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
  566. goto Ret;
  567. }
  568. LocalFree(pszValue);
  569. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  570. cbValue +
  571. strlen(szprovider) + 1)) == NULL)
  572. {
  573. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  574. goto Ret;
  575. }
  576. if ((pszTmpProvName = (LPSTR)LocalAlloc(LMEM_ZEROINIT,
  577. (UINT) cbValue + 1)) == NULL)
  578. {
  579. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  580. goto Ret;
  581. }
  582. strcpy(pszValue, szprovider);
  583. cbTemp = cbValue;
  584. if ((err = RegQueryValueEx(hKey, "Name", NULL, &dwType,
  585. (LPBYTE)pszTmpProvName,
  586. &cbTemp)) != ERROR_SUCCESS)
  587. {
  588. SetLastError((DWORD) NTE_PROV_TYPE_NOT_DEF);
  589. goto Ret;
  590. }
  591. strcat(pszValue, pszTmpProvName);
  592. RegCloseKey(hKey);
  593. hKey = 0;
  594. }
  595. if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  596. (const char *) pszValue,
  597. 0L, KEY_READ, &hKey)) != ERROR_SUCCESS)
  598. {
  599. SetLastError((DWORD) NTE_KEYSET_NOT_DEF);
  600. goto Ret;
  601. }
  602. LocalFree(pszValue);
  603. pszValue = NULL;
  604. cbValue = sizeof(DWORD);
  605. if ((err = RegQueryValueEx(hKey, "Type", NULL, &dwType,
  606. (LPBYTE)&provtype,
  607. &cbValue)) != ERROR_SUCCESS)
  608. {
  609. SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
  610. goto Ret;
  611. }
  612. // Check that requested provider type is same as registry entry
  613. if (provtype != dwReqProvider)
  614. {
  615. SetLastError((DWORD) NTE_PROV_TYPE_NO_MATCH);
  616. goto Ret;
  617. }
  618. // Determine size of path for provider
  619. if ((err = RegQueryValueEx(hKey, "Image Path", NULL,
  620. &dwType, NULL, &cbValue)) != ERROR_SUCCESS)
  621. {
  622. SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
  623. goto Ret;
  624. }
  625. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  626. (UINT) cbValue)) == NULL)
  627. {
  628. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  629. goto Ret;
  630. }
  631. // Get value from registry
  632. if ((err = RegQueryValueEx(hKey, "Image Path", NULL, &dwType,
  633. (LPBYTE)pszValue, &cbValue)) != ERROR_SUCCESS)
  634. {
  635. SetLastError((DWORD) NTE_KEYSET_ENTRY_BAD);
  636. goto Ret;
  637. }
  638. pszDest = NULL;
  639. cbTemp = 0;
  640. if ((cbTemp = ExpandEnvironmentStrings(pszValue, (CHAR *) &pszDest, cbTemp)) == 0)
  641. {
  642. goto Ret;
  643. }
  644. if ((pszDest = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  645. (UINT) cbTemp)) == NULL)
  646. {
  647. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  648. goto Ret;
  649. }
  650. if ((cbTemp = ExpandEnvironmentStrings(pszValue, pszDest,
  651. cbTemp)) == 0)
  652. {
  653. goto Ret;
  654. }
  655. LocalFree(pszValue);
  656. pszValue = pszDest;
  657. pszDest = NULL;
  658. cbValue = cbTemp;
  659. if (!CSPInCacheCheck(pszValue, &handle))
  660. {
  661. if ( RtlCreateUnicodeStringFromAsciiz( &String, pszValue ) )
  662. {
  663. // check if the CSP is registered as having the signature in the file
  664. SigInFile = CheckSignatureInFile( String.Buffer );
  665. RtlFreeUnicodeString( &String );
  666. if (! SigInFile )
  667. {
  668. // Determine size of signature
  669. if ((err = RegQueryValueEx(hKey, "Signature", NULL,
  670. &dwType, NULL, &cbValue)) != ERROR_SUCCESS)
  671. {
  672. SetLastError((DWORD) NTE_BAD_SIGNATURE);
  673. goto Ret;
  674. }
  675. if ((SignatureBuf = (LPBYTE)LocalAlloc(LMEM_ZEROINIT,
  676. (UINT) cbValue)) == NULL)
  677. {
  678. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  679. goto Ret;
  680. }
  681. // Get Digital signature from registry
  682. if ((err = RegQueryValueEx(hKey, "Signature", NULL, &dwType,
  683. SignatureBuf,
  684. &cbValue)) != ERROR_SUCCESS)
  685. {
  686. SetLastError((DWORD) NTE_BAD_SIGNATURE);
  687. goto Ret;
  688. }
  689. if (RCRYPT_FAILED(NewVerifyImage(pszValue, SignatureBuf, cbValue, FALSE)))
  690. {
  691. SetLastError((DWORD) NTE_BAD_SIGNATURE);
  692. goto Ret;
  693. }
  694. }
  695. }
  696. if ((handle = LoadLibrary(pszValue)) == NULL)
  697. {
  698. SetLastError((DWORD) NTE_PROVIDER_DLL_FAIL);
  699. goto Ret;
  700. }
  701. AddHandleToCSPCache(handle);
  702. }
  703. // DLLs exist allocate VTable struct to hold address of entry points
  704. bufsize = sizeof(VTableStruc);
  705. if ((pVTable = (PVTableStruc) LocalAlloc(LMEM_ZEROINIT,
  706. (UINT) bufsize)) == NULL)
  707. {
  708. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  709. goto Ret;
  710. }
  711. pTable = (ULONG_PTR *) pVTable;
  712. // Build table of pointers to Crypto API for this DLL
  713. i = 0;
  714. while (FunctionNames[i] != NULL)
  715. {
  716. *pTable = (ULONG_PTR) GetProcAddress(handle, FunctionNames[i]);
  717. if (*pTable == 0)
  718. {
  719. SetLastError((DWORD) NTE_PROVIDER_DLL_FAIL);
  720. goto Ret;
  721. }
  722. pTable++;
  723. i++;
  724. }
  725. // Build the table of optional pointers to Crypto API for this DLL
  726. i = 0;
  727. pTable++;
  728. while (OptionalFunctionNames[i] != NULL)
  729. {
  730. *pTable = (ULONG_PTR) GetProcAddress(handle, OptionalFunctionNames[i]);
  731. pTable++;
  732. i++;
  733. }
  734. pVTable->DllHandle = handle;
  735. memset(&VTableProv, 0, sizeof(VTableProv));
  736. VTableProv.Version = 3;
  737. VTableProv.FuncVerifyImage = (CRYPT_VERIFY_IMAGE_A)CProvVerifyImage;
  738. VTableProv.FuncReturnhWnd = (CRYPT_RETURN_HWND)CPReturnhWnd;
  739. VTableProv.dwProvType = dwReqProvider;
  740. VTableProv.pszProvName = pszTmpProvName;
  741. VTableProv.pbContextInfo = pbContextInfo;
  742. VTableProv.cbContextInfo = cbContextInfo;
  743. *phProv = (HCRYPTPROV) NULL;
  744. rt = (BOOL)pVTable->FuncAcquireContext(&hTmpProv, pszIdentity, dwFlags,
  745. &VTableProv);
  746. if (RCRYPT_SUCCEEDED(rt) &&
  747. ((dwFlags & CRYPT_DELETEKEYSET) != CRYPT_DELETEKEYSET))
  748. {
  749. pVTable->hProv = hTmpProv;
  750. *phProv = (HCRYPTPROV)pVTable;
  751. pVTable->Version = TABLEPROV;
  752. pVTable->Inuse = 1;
  753. pVTable->RefCnt = 1;
  754. }
  755. }
  756. __except (CapiExceptionFilter)
  757. {
  758. SetLastError(ERROR_INVALID_PARAMETER);
  759. goto Ret;
  760. }
  761. Ret:
  762. dwErr = GetLastError();
  763. if (pszTmpProvName)
  764. LocalFree(pszTmpProvName);
  765. if (pszValue)
  766. LocalFree(pszValue);
  767. if (hKey)
  768. RegCloseKey(hKey);
  769. if (pszDest)
  770. LocalFree(pszDest);
  771. if (SignatureBuf)
  772. LocalFree(SignatureBuf);
  773. if ((CRYPT_SUCCEED != rt) || (dwFlags & CRYPT_DELETEKEYSET))
  774. {
  775. if (pVTable)
  776. LocalFree(pVTable);
  777. SetLastError(dwErr);
  778. }
  779. return rt;
  780. }
  781. /*
  782. - CryptContextAddRef
  783. -
  784. * Purpose:
  785. * Increments the reference counter on the provider handle.
  786. *
  787. * Parameters:
  788. * IN hProv - Handle to a CSP
  789. * IN pdwReserved - Reserved parameter
  790. * IN dwFlags - Flags values
  791. *
  792. * Returns:
  793. * BOOL
  794. * Use get extended error information use GetLastError
  795. */
  796. WINADVAPI
  797. BOOL
  798. WINAPI CryptContextAddRef(
  799. IN HCRYPTPROV hProv,
  800. IN DWORD *pdwReserved,
  801. IN DWORD dwFlags
  802. )
  803. {
  804. PVTableStruc pVTable;
  805. BOOL fRet = CRYPT_FAILED;
  806. __try
  807. {
  808. if ((NULL != pdwReserved) || (0 != dwFlags))
  809. {
  810. SetLastError(ERROR_INVALID_PARAMETER);
  811. goto Ret;
  812. }
  813. pVTable = (PVTableStruc) hProv;
  814. if (pVTable->Version != TABLEPROV)
  815. {
  816. SetLastError(ERROR_INVALID_PARAMETER);
  817. goto Ret;
  818. }
  819. if (InterlockedIncrement(&pVTable->RefCnt) <= 0)
  820. SetLastError(ERROR_INVALID_PARAMETER);
  821. else
  822. fRet = CRYPT_SUCCEED;
  823. }
  824. __except ( CapiExceptionFilter )
  825. {
  826. SetLastError(ERROR_INVALID_PARAMETER);
  827. goto Ret;
  828. }
  829. Ret:
  830. return fRet;
  831. }
  832. /*
  833. - CryptReleaseContext
  834. -
  835. * Purpose:
  836. * The CryptReleaseContext function is used to release a
  837. * context created by CryptAcquireContext.
  838. *
  839. * Parameters:
  840. * IN hProv - Handle to a CSP
  841. * IN dwFlags - Flags values
  842. *
  843. * Returns:
  844. * BOOL
  845. * Use get extended error information use GetLastError
  846. */
  847. WINADVAPI
  848. BOOL
  849. WINAPI CryptReleaseContext(IN HCRYPTPROV hProv,
  850. IN DWORD dwFlags)
  851. {
  852. PVTableStruc pVTable;
  853. BOOL rt;
  854. BOOL fRet = CRYPT_FAILED;
  855. DWORD dwErr = 0;
  856. __try
  857. {
  858. pVTable = (PVTableStruc) hProv;
  859. if (pVTable->Version != TABLEPROV)
  860. {
  861. SetLastError(ERROR_INVALID_PARAMETER);
  862. goto Ret;
  863. }
  864. if (pVTable->RefCnt <= 0)
  865. {
  866. SetLastError(ERROR_INVALID_PARAMETER);
  867. goto Ret;
  868. }
  869. if (0 == InterlockedDecrement(&pVTable->RefCnt))
  870. {
  871. if (0 < InterlockedDecrement((LPLONG)&pVTable->Inuse))
  872. {
  873. InterlockedIncrement((LPLONG)&pVTable->Inuse);
  874. SetLastError(ERROR_BUSY);
  875. goto Ret;
  876. }
  877. InterlockedIncrement((LPLONG)&pVTable->Inuse);
  878. if (FALSE == (rt = (BOOL)pVTable->FuncReleaseContext(pVTable->hProv, dwFlags)))
  879. {
  880. dwErr = GetLastError();
  881. }
  882. pVTable->Version = 0;
  883. LocalFree(pVTable);
  884. if (!rt)
  885. {
  886. SetLastError(dwErr);
  887. goto Ret;
  888. }
  889. }
  890. }
  891. __except ( CapiExceptionFilter )
  892. {
  893. SetLastError(ERROR_INVALID_PARAMETER);
  894. goto Ret;
  895. }
  896. fRet = CRYPT_SUCCEED;
  897. Ret:
  898. return fRet;
  899. }
  900. /*
  901. - CryptGenKey
  902. -
  903. * Purpose:
  904. * Generate cryptographic keys
  905. *
  906. *
  907. * Parameters:
  908. * IN hProv - Handle to a CSP
  909. * IN Algid - Algorithm identifier
  910. * IN dwFlags - Flags values
  911. * OUT phKey - Handle to a generated key
  912. *
  913. * Returns:
  914. */
  915. WINADVAPI
  916. BOOL
  917. WINAPI CryptGenKey(IN HCRYPTPROV hProv,
  918. IN ALG_ID Algid,
  919. IN DWORD dwFlags,
  920. OUT HCRYPTKEY * phKey)
  921. {
  922. PVTableStruc pVTable = NULL;
  923. PVKeyStruc pVKey = NULL;
  924. BOOL fProvCritSec = FALSE;
  925. DWORD dwErr;
  926. BOOL fRet = CRYPT_FAILED;
  927. __try
  928. {
  929. pVTable = (PVTableStruc) hProv;
  930. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  931. {
  932. goto Ret;
  933. }
  934. fProvCritSec = TRUE;
  935. if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
  936. {
  937. goto Ret;
  938. }
  939. if (RCRYPT_FAILED(pVTable->FuncGenKey(pVTable->hProv, Algid, dwFlags,
  940. phKey)))
  941. {
  942. goto Ret;
  943. }
  944. pVKey->hKey = *phKey;
  945. *phKey = (HCRYPTKEY) pVKey;
  946. pVKey->Version = TABLEKEY;
  947. pVKey->hProv = hProv;
  948. pVKey->Inuse = 1;
  949. }
  950. __except ( CapiExceptionFilter )
  951. {
  952. SetLastError(ERROR_INVALID_PARAMETER);
  953. goto Ret;
  954. }
  955. fRet = CRYPT_SUCCEED;
  956. Ret:
  957. dwErr = GetLastError();
  958. if (fProvCritSec)
  959. LeaveProviderCritSec(pVTable);
  960. if (CRYPT_SUCCEED != fRet)
  961. {
  962. if (pVKey)
  963. LocalFree(pVKey);
  964. SetLastError(dwErr);
  965. }
  966. return fRet;
  967. }
  968. /*
  969. - CryptDuplicateKey
  970. -
  971. * Purpose:
  972. * Duplicate a cryptographic key
  973. *
  974. *
  975. * Parameters:
  976. * IN hKey - Handle to the key to be duplicated
  977. * IN pdwReserved - Reserved for later use
  978. * IN dwFlags - Flags values
  979. * OUT phKey - Handle to the new duplicate key
  980. *
  981. * Returns:
  982. */
  983. WINADVAPI
  984. BOOL
  985. WINAPI CryptDuplicateKey(
  986. IN HCRYPTKEY hKey,
  987. IN DWORD *pdwReserved,
  988. IN DWORD dwFlags,
  989. OUT HCRYPTKEY * phKey
  990. )
  991. {
  992. PVTableStruc pVTable = NULL;
  993. PVKeyStruc pVKey;
  994. PVKeyStruc pVNewKey = NULL;
  995. HCRYPTKEY hNewKey;
  996. BOOL fProvCritSecSet = FALSE;
  997. DWORD dwErr = 0;
  998. BOOL fRet = CRYPT_FAILED;
  999. __try
  1000. {
  1001. if (IsBadWritePtr(phKey, sizeof(HCRYPTKEY)))
  1002. {
  1003. SetLastError(ERROR_INVALID_PARAMETER);
  1004. goto Ret;
  1005. }
  1006. pVKey = (PVKeyStruc) hKey;
  1007. if (pVKey->Version != TABLEKEY)
  1008. {
  1009. SetLastError(ERROR_INVALID_PARAMETER);
  1010. goto Ret;
  1011. }
  1012. if (NULL == pVKey->OptionalFuncDuplicateKey)
  1013. {
  1014. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1015. goto Ret;
  1016. }
  1017. pVTable = (PVTableStruc) pVKey->hProv;
  1018. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1019. {
  1020. SetLastError(ERROR_INVALID_PARAMETER);
  1021. goto Ret;
  1022. }
  1023. fProvCritSecSet = TRUE;
  1024. if (RCRYPT_FAILED(BuildVKey(&pVNewKey, pVTable)))
  1025. {
  1026. goto Ret;
  1027. }
  1028. if (RCRYPT_FAILED(pVKey->OptionalFuncDuplicateKey(pVTable->hProv, pVKey->hKey,
  1029. pdwReserved, dwFlags, &hNewKey)))
  1030. {
  1031. goto Ret;
  1032. }
  1033. pVNewKey->hKey = hNewKey;
  1034. pVNewKey->Version = TABLEKEY;
  1035. pVNewKey->hProv = pVKey->hProv;
  1036. pVKey->Inuse = 1;
  1037. *phKey = (HCRYPTKEY) pVNewKey;
  1038. }
  1039. __except ( CapiExceptionFilter )
  1040. {
  1041. SetLastError(ERROR_INVALID_PARAMETER);
  1042. goto Ret;
  1043. }
  1044. fRet = CRYPT_SUCCEED;
  1045. Ret:
  1046. dwErr = GetLastError();
  1047. if (fProvCritSecSet)
  1048. LeaveProviderCritSec(pVTable);
  1049. if (fRet == CRYPT_FAILED)
  1050. {
  1051. if (NULL != pVNewKey)
  1052. LocalFree(pVNewKey);
  1053. SetLastError(dwErr);
  1054. }
  1055. return fRet;
  1056. }
  1057. /*
  1058. - CryptDeriveKey
  1059. -
  1060. * Purpose:
  1061. * Derive cryptographic keys from base data
  1062. *
  1063. *
  1064. * Parameters:
  1065. * IN hProv - Handle to a CSP
  1066. * IN Algid - Algorithm identifier
  1067. * IN hHash - Handle to hash of base data
  1068. * IN dwFlags - Flags values
  1069. * IN OUT phKey - Handle to a generated key
  1070. *
  1071. * Returns:
  1072. */
  1073. WINADVAPI
  1074. BOOL
  1075. WINAPI CryptDeriveKey(IN HCRYPTPROV hProv,
  1076. IN ALG_ID Algid,
  1077. IN HCRYPTHASH hHash,
  1078. IN DWORD dwFlags,
  1079. IN OUT HCRYPTKEY * phKey)
  1080. {
  1081. PVTableStruc pVTable = NULL;
  1082. PVKeyStruc pVKey = NULL;
  1083. PVHashStruc pVHash = NULL;
  1084. BOOL fProvCritSec = FALSE;
  1085. BOOL fKeyCritSec = FALSE;
  1086. BOOL fHashCritSec = FALSE;
  1087. BOOL fUpdate = FALSE;
  1088. DWORD dwErr = 0;
  1089. BOOL fRet = CRYPT_FAILED;
  1090. __try
  1091. {
  1092. pVTable = (PVTableStruc) hProv;
  1093. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1094. {
  1095. goto Ret;
  1096. }
  1097. fProvCritSec = TRUE;
  1098. pVHash = (PVHashStruc) hHash;
  1099. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  1100. {
  1101. goto Ret;
  1102. }
  1103. fHashCritSec = TRUE;
  1104. if (dwFlags & CRYPT_UPDATE_KEY)
  1105. {
  1106. fUpdate = TRUE;
  1107. pVKey = (PVKeyStruc) phKey;
  1108. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1109. {
  1110. SetLastError(ERROR_INVALID_PARAMETER);
  1111. goto Ret;
  1112. }
  1113. fKeyCritSec = TRUE;
  1114. }
  1115. else
  1116. {
  1117. if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
  1118. {
  1119. goto Ret;
  1120. }
  1121. }
  1122. if (RCRYPT_FAILED(pVTable->FuncDeriveKey(pVTable->hProv, Algid,
  1123. pVHash->hHash, dwFlags, phKey)))
  1124. {
  1125. goto Ret;
  1126. }
  1127. if ((dwFlags & CRYPT_UPDATE_KEY) != CRYPT_UPDATE_KEY)
  1128. {
  1129. pVKey->hKey = *phKey;
  1130. *phKey = (HCRYPTKEY)pVKey;
  1131. pVKey->hProv = hProv;
  1132. pVKey->Version = TABLEKEY;
  1133. pVKey->Inuse = 1;
  1134. }
  1135. } __except ( CapiExceptionFilter )
  1136. {
  1137. SetLastError(ERROR_INVALID_PARAMETER);
  1138. goto Ret;
  1139. }
  1140. fRet = CRYPT_SUCCEED;
  1141. Ret:
  1142. if (CRYPT_SUCCEED != fRet)
  1143. dwErr = GetLastError();
  1144. if (fProvCritSec)
  1145. LeaveProviderCritSec(pVTable);
  1146. if (fHashCritSec)
  1147. LeaveHashCritSec(pVHash);
  1148. if (fKeyCritSec)
  1149. LeaveKeyCritSec(pVKey);
  1150. if (CRYPT_SUCCEED != fRet)
  1151. {
  1152. if (pVKey && (!fUpdate))
  1153. LocalFree(pVKey);
  1154. SetLastError(dwErr);
  1155. }
  1156. return fRet;
  1157. }
  1158. /*
  1159. - CryptDestroyKey
  1160. -
  1161. * Purpose:
  1162. * Destroys the cryptographic key that is being referenced
  1163. * with the hKey parameter
  1164. *
  1165. *
  1166. * Parameters:
  1167. * IN hKey - Handle to a key
  1168. *
  1169. * Returns:
  1170. */
  1171. WINADVAPI
  1172. BOOL
  1173. WINAPI CryptDestroyKey(IN HCRYPTKEY hKey)
  1174. {
  1175. PVTableStruc pVTable = NULL;
  1176. PVKeyStruc pVKey;
  1177. BOOL fProvCritSec = FALSE;
  1178. BOOL rt;
  1179. DWORD dwErr = 0;
  1180. BOOL fRet = CRYPT_FAILED;
  1181. __try
  1182. {
  1183. pVKey = (PVKeyStruc) hKey;
  1184. if (pVKey->Version != TABLEKEY)
  1185. {
  1186. SetLastError(ERROR_INVALID_PARAMETER);
  1187. goto Ret;
  1188. }
  1189. if (0 < InterlockedDecrement((LPLONG)&pVKey->Inuse))
  1190. {
  1191. InterlockedIncrement((LPLONG)&pVKey->Inuse);
  1192. SetLastError(ERROR_BUSY);
  1193. goto Ret;
  1194. }
  1195. InterlockedIncrement((LPLONG)&pVKey->Inuse);
  1196. pVTable = (PVTableStruc) pVKey->hProv;
  1197. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1198. {
  1199. goto Ret;
  1200. }
  1201. fProvCritSec = TRUE;
  1202. if (FALSE == (rt = (BOOL)pVKey->FuncDestroyKey(pVTable->hProv, pVKey->hKey)))
  1203. dwErr = GetLastError();
  1204. pVKey->Version = 0;
  1205. LocalFree(pVKey);
  1206. if (!rt)
  1207. {
  1208. SetLastError(dwErr);
  1209. goto Ret;
  1210. }
  1211. } __except ( CapiExceptionFilter )
  1212. {
  1213. SetLastError(ERROR_INVALID_PARAMETER);
  1214. goto Ret;
  1215. }
  1216. fRet = CRYPT_SUCCEED;
  1217. Ret:
  1218. if (CRYPT_SUCCEED != fRet)
  1219. dwErr = GetLastError();
  1220. if (fProvCritSec)
  1221. LeaveProviderCritSec(pVTable);
  1222. if (CRYPT_SUCCEED != fRet)
  1223. SetLastError(dwErr);
  1224. return fRet;
  1225. }
  1226. /*
  1227. - CryptSetKeyParam
  1228. -
  1229. * Purpose:
  1230. * Allows applications to customize various aspects of the
  1231. * operations of a key
  1232. *
  1233. * Parameters:
  1234. * IN hKey - Handle to a key
  1235. * IN dwParam - Parameter number
  1236. * IN pbData - Pointer to data
  1237. * IN dwFlags - Flags values
  1238. *
  1239. * Returns:
  1240. */
  1241. WINADVAPI
  1242. BOOL
  1243. WINAPI CryptSetKeyParam(IN HCRYPTKEY hKey,
  1244. IN DWORD dwParam,
  1245. IN CONST BYTE *pbData,
  1246. IN DWORD dwFlags)
  1247. {
  1248. PVTableStruc pVTable = NULL;
  1249. PVKeyStruc pVKey;
  1250. BOOL rt = CRYPT_FAILED;
  1251. BOOL fCritSec = FALSE;
  1252. __try
  1253. {
  1254. pVKey = (PVKeyStruc) hKey;
  1255. if (pVKey->Version != TABLEKEY)
  1256. {
  1257. SetLastError(ERROR_INVALID_PARAMETER);
  1258. goto Ret;
  1259. }
  1260. if (0 < InterlockedDecrement((LPLONG)&pVKey->Inuse))
  1261. {
  1262. InterlockedIncrement((LPLONG)&pVKey->Inuse);
  1263. SetLastError(ERROR_BUSY);
  1264. goto Ret;
  1265. }
  1266. InterlockedIncrement((LPLONG)&pVKey->Inuse);
  1267. pVTable = (PVTableStruc) pVKey->hProv;
  1268. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1269. {
  1270. goto Ret;
  1271. }
  1272. fCritSec = TRUE;
  1273. rt = (BOOL)pVKey->FuncSetKeyParam(pVTable->hProv, pVKey->hKey,
  1274. dwParam, pbData, dwFlags);
  1275. }
  1276. __except ( CapiExceptionFilter )
  1277. {
  1278. SetLastError(ERROR_INVALID_PARAMETER);
  1279. goto Ret;
  1280. }
  1281. Ret:
  1282. if (fCritSec)
  1283. LeaveProviderCritSec(pVTable);
  1284. return(rt);
  1285. }
  1286. /*
  1287. - CryptGetKeyParam
  1288. -
  1289. * Purpose:
  1290. * Allows applications to get various aspects of the
  1291. * operations of a key
  1292. *
  1293. * Parameters:
  1294. * IN hKey - Handle to a key
  1295. * IN dwParam - Parameter number
  1296. * IN pbData - Pointer to data
  1297. * IN pdwDataLen - Length of parameter data
  1298. * IN dwFlags - Flags values
  1299. *
  1300. * Returns:
  1301. */
  1302. WINADVAPI
  1303. BOOL
  1304. WINAPI CryptGetKeyParam(IN HCRYPTKEY hKey,
  1305. IN DWORD dwParam,
  1306. IN BYTE *pbData,
  1307. IN DWORD *pdwDataLen,
  1308. IN DWORD dwFlags)
  1309. {
  1310. PVTableStruc pVTable = NULL;
  1311. PVKeyStruc pVKey = NULL;
  1312. BOOL rt = CRYPT_FAILED;
  1313. BOOL fKeyCritSec = FALSE;
  1314. BOOL fTableCritSec = FALSE;
  1315. __try
  1316. {
  1317. pVKey = (PVKeyStruc) hKey;
  1318. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1319. {
  1320. goto Ret;
  1321. }
  1322. fKeyCritSec = TRUE;
  1323. pVTable = (PVTableStruc) pVKey->hProv;
  1324. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1325. {
  1326. goto Ret;
  1327. }
  1328. fTableCritSec = TRUE;
  1329. rt = (BOOL)pVKey->FuncGetKeyParam(pVTable->hProv, pVKey->hKey,
  1330. dwParam, pbData, pdwDataLen,
  1331. dwFlags);
  1332. }
  1333. __except ( CapiExceptionFilter )
  1334. {
  1335. SetLastError(ERROR_INVALID_PARAMETER);
  1336. goto Ret;
  1337. }
  1338. Ret:
  1339. if (fKeyCritSec)
  1340. LeaveKeyCritSec(pVKey);
  1341. if (fTableCritSec)
  1342. LeaveProviderCritSec(pVTable);
  1343. return(rt);
  1344. }
  1345. /*
  1346. - CryptGenRandom
  1347. -
  1348. * Purpose:
  1349. * Used to fill a buffer with random bytes
  1350. *
  1351. *
  1352. * Parameters:
  1353. * IN hProv - Handle to the user identifcation
  1354. * IN dwLen - Number of bytes of random data requested
  1355. * OUT pbBuffer - Pointer to the buffer where the random
  1356. * bytes are to be placed
  1357. *
  1358. * Returns:
  1359. */
  1360. WINADVAPI
  1361. BOOL
  1362. WINAPI CryptGenRandom(IN HCRYPTPROV hProv,
  1363. IN DWORD dwLen,
  1364. OUT BYTE *pbBuffer)
  1365. {
  1366. PVTableStruc pVTable = NULL;
  1367. BOOL fTableCritSec = FALSE;
  1368. BOOL rt = CRYPT_FAILED;
  1369. __try
  1370. {
  1371. pVTable = (PVTableStruc) hProv;
  1372. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1373. {
  1374. goto Ret;
  1375. }
  1376. fTableCritSec = TRUE;
  1377. rt = (BOOL)pVTable->FuncGenRandom(pVTable->hProv, dwLen, pbBuffer);
  1378. } __except ( CapiExceptionFilter )
  1379. {
  1380. SetLastError(ERROR_INVALID_PARAMETER);
  1381. goto Ret;
  1382. }
  1383. Ret:
  1384. if (fTableCritSec)
  1385. LeaveProviderCritSec(pVTable);
  1386. return(rt);
  1387. }
  1388. /*
  1389. - CryptGetUserKey
  1390. -
  1391. * Purpose:
  1392. * Gets a handle to a permanent user key
  1393. *
  1394. *
  1395. * Parameters:
  1396. * IN hProv - Handle to the user identifcation
  1397. * IN dwKeySpec - Specification of the key to retrieve
  1398. * OUT phUserKey - Pointer to key handle of retrieved key
  1399. *
  1400. * Returns:
  1401. */
  1402. WINADVAPI
  1403. BOOL
  1404. WINAPI CryptGetUserKey(IN HCRYPTPROV hProv,
  1405. IN DWORD dwKeySpec,
  1406. OUT HCRYPTKEY *phUserKey)
  1407. {
  1408. PVTableStruc pVTable = NULL;
  1409. PVKeyStruc pVKey = NULL;
  1410. BOOL fTableCritSec = FALSE;
  1411. BOOL fRet = CRYPT_FAILED;
  1412. __try
  1413. {
  1414. pVTable = (PVTableStruc) hProv;
  1415. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1416. {
  1417. goto Ret;
  1418. }
  1419. fTableCritSec = TRUE;
  1420. if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
  1421. {
  1422. goto Ret;
  1423. }
  1424. if (RCRYPT_FAILED(pVTable->FuncGetUserKey(pVTable->hProv, dwKeySpec,
  1425. phUserKey)))
  1426. {
  1427. goto Ret;
  1428. }
  1429. pVKey->hKey = *phUserKey;
  1430. pVKey->hProv = hProv;
  1431. *phUserKey = (HCRYPTKEY)pVKey;
  1432. pVKey->Version = TABLEKEY;
  1433. pVKey->Inuse = 1;
  1434. } __except ( CapiExceptionFilter )
  1435. {
  1436. SetLastError(ERROR_INVALID_PARAMETER);
  1437. goto Ret;
  1438. }
  1439. fRet = CRYPT_SUCCEED;
  1440. Ret:
  1441. if (fTableCritSec)
  1442. LeaveProviderCritSec(pVTable);
  1443. if ((CRYPT_SUCCEED != fRet) && pVKey)
  1444. LocalFree(pVKey);
  1445. return fRet;
  1446. }
  1447. /*
  1448. - CryptExportKey
  1449. -
  1450. * Purpose:
  1451. * Export cryptographic keys out of a CSP in a secure manner
  1452. *
  1453. *
  1454. * Parameters:
  1455. * IN hKey - Handle to the key to export
  1456. * IN hPubKey - Handle to the exchange public key value of
  1457. * the destination user
  1458. * IN dwBlobType - Type of key blob to be exported
  1459. * IN dwFlags - Flags values
  1460. * OUT pbData - Key blob data
  1461. * OUT pdwDataLen - Length of key blob in bytes
  1462. *
  1463. * Returns:
  1464. */
  1465. WINADVAPI
  1466. BOOL
  1467. WINAPI CryptExportKey(IN HCRYPTKEY hKey,
  1468. IN HCRYPTKEY hPubKey,
  1469. IN DWORD dwBlobType,
  1470. IN DWORD dwFlags,
  1471. OUT BYTE *pbData,
  1472. OUT DWORD *pdwDataLen)
  1473. {
  1474. PVTableStruc pVTable = NULL;
  1475. PVKeyStruc pVKey = NULL;
  1476. PVKeyStruc pVPublicKey = NULL;
  1477. BOOL fKeyCritSec = FALSE;
  1478. BOOL fPubKeyCritSec = FALSE;
  1479. BOOL fTableCritSec = FALSE;
  1480. BOOL rt = CRYPT_FAILED;
  1481. __try
  1482. {
  1483. pVKey = (PVKeyStruc) hKey;
  1484. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1485. {
  1486. goto Ret;
  1487. }
  1488. fKeyCritSec = TRUE;
  1489. pVTable = (PVTableStruc) pVKey->hProv;
  1490. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1491. {
  1492. goto Ret;
  1493. }
  1494. fTableCritSec = TRUE;
  1495. pVPublicKey = (PVKeyStruc) hPubKey;
  1496. if (pVPublicKey != NULL)
  1497. {
  1498. if (RCRYPT_FAILED(EnterKeyCritSec(pVPublicKey)))
  1499. {
  1500. goto Ret;
  1501. }
  1502. fPubKeyCritSec = TRUE;
  1503. }
  1504. rt = (BOOL)pVKey->FuncExportKey(pVTable->hProv, pVKey->hKey,
  1505. (pVPublicKey == NULL ? 0 : pVPublicKey->hKey),
  1506. dwBlobType, dwFlags, pbData,
  1507. pdwDataLen);
  1508. } __except ( CapiExceptionFilter )
  1509. {
  1510. SetLastError(ERROR_INVALID_PARAMETER);
  1511. goto Ret;
  1512. }
  1513. Ret:
  1514. if (fKeyCritSec)
  1515. LeaveKeyCritSec(pVKey);
  1516. if (fTableCritSec)
  1517. LeaveProviderCritSec(pVTable);
  1518. if (pVPublicKey != NULL)
  1519. {
  1520. if (fPubKeyCritSec)
  1521. LeaveKeyCritSec(pVPublicKey);
  1522. }
  1523. return(rt);
  1524. }
  1525. /*
  1526. - CryptImportKey
  1527. -
  1528. * Purpose:
  1529. * Import cryptographic keys
  1530. *
  1531. *
  1532. * Parameters:
  1533. * IN hProv - Handle to the CSP user
  1534. * IN pbData - Key blob data
  1535. * IN dwDataLen - Length of the key blob data
  1536. * IN hPubKey - Handle to the exchange public key value of
  1537. * the destination user
  1538. * IN dwFlags - Flags values
  1539. * OUT phKey - Pointer to the handle to the key which was
  1540. * Imported
  1541. *
  1542. * Returns:
  1543. */
  1544. WINADVAPI
  1545. BOOL
  1546. WINAPI CryptImportKey(IN HCRYPTPROV hProv,
  1547. IN CONST BYTE *pbData,
  1548. IN DWORD dwDataLen,
  1549. IN HCRYPTKEY hPubKey,
  1550. IN DWORD dwFlags,
  1551. OUT HCRYPTKEY *phKey)
  1552. {
  1553. PVTableStruc pVTable = NULL;
  1554. PVKeyStruc pVKey = NULL;
  1555. PVKeyStruc pVPublicKey = NULL;
  1556. BOOL fKeyCritSec = FALSE;
  1557. BOOL fPubKeyCritSec = FALSE;
  1558. BOOL fTableCritSec = FALSE;
  1559. BOOL fBuiltKey = FALSE;
  1560. BOOL fRet = CRYPT_FAILED;
  1561. __try
  1562. {
  1563. pVTable = (PVTableStruc) hProv;
  1564. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1565. {
  1566. goto Ret;
  1567. }
  1568. fTableCritSec = TRUE;
  1569. pVPublicKey = (PVKeyStruc)hPubKey;
  1570. if (pVPublicKey != NULL)
  1571. {
  1572. if (RCRYPT_FAILED(EnterKeyCritSec(pVPublicKey)))
  1573. {
  1574. goto Ret;
  1575. }
  1576. fPubKeyCritSec = TRUE;
  1577. }
  1578. if (dwFlags & CRYPT_UPDATE_KEY)
  1579. {
  1580. pVKey = (PVKeyStruc) phKey;
  1581. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1582. {
  1583. goto Ret;
  1584. }
  1585. fKeyCritSec = TRUE;
  1586. }
  1587. else
  1588. {
  1589. if (RCRYPT_FAILED(BuildVKey(&pVKey, pVTable)))
  1590. {
  1591. goto Ret;
  1592. }
  1593. fBuiltKey = TRUE;
  1594. }
  1595. if (RCRYPT_FAILED(pVTable->FuncImportKey(pVTable->hProv, pbData,
  1596. dwDataLen,
  1597. (pVPublicKey == NULL ? 0 : pVPublicKey->hKey),
  1598. dwFlags, phKey)))
  1599. {
  1600. goto Ret;
  1601. }
  1602. if ((dwFlags & CRYPT_UPDATE_KEY) != CRYPT_UPDATE_KEY)
  1603. {
  1604. pVKey->hKey = *phKey;
  1605. *phKey = (HCRYPTKEY) pVKey;
  1606. pVKey->hProv = hProv;
  1607. pVKey->Version = TABLEKEY;
  1608. }
  1609. }
  1610. __except ( CapiExceptionFilter )
  1611. {
  1612. SetLastError(ERROR_INVALID_PARAMETER);
  1613. goto Ret;
  1614. }
  1615. fRet = CRYPT_SUCCEED;
  1616. Ret:
  1617. if (fTableCritSec)
  1618. LeaveProviderCritSec(pVTable);
  1619. if (pVPublicKey != NULL)
  1620. {
  1621. if (fPubKeyCritSec)
  1622. LeaveKeyCritSec(pVPublicKey);
  1623. }
  1624. if ((dwFlags & CRYPT_UPDATE_KEY) && fKeyCritSec)
  1625. {
  1626. LeaveKeyCritSec(pVKey);
  1627. }
  1628. else if ((CRYPT_SUCCEED != fRet) && fBuiltKey && pVKey)
  1629. {
  1630. LocalFree(pVKey);
  1631. }
  1632. return fRet;
  1633. }
  1634. /*
  1635. - CryptEncrypt
  1636. -
  1637. * Purpose:
  1638. * Encrypt data
  1639. *
  1640. *
  1641. * Parameters:
  1642. * IN hKey - Handle to the key
  1643. * IN hHash - Optional handle to a hash
  1644. * IN Final - Boolean indicating if this is the final
  1645. * block of plaintext
  1646. * IN dwFlags - Flags values
  1647. * IN OUT pbData - Data to be encrypted
  1648. * IN OUT pdwDataLen - Pointer to the length of the data to be
  1649. * encrypted
  1650. * IN dwBufLen - Size of Data buffer
  1651. *
  1652. * Returns:
  1653. */
  1654. WINADVAPI
  1655. BOOL
  1656. WINAPI CryptEncrypt(IN HCRYPTKEY hKey,
  1657. IN HCRYPTHASH hHash,
  1658. IN BOOL Final,
  1659. IN DWORD dwFlags,
  1660. IN OUT BYTE *pbData,
  1661. IN OUT DWORD *pdwDataLen,
  1662. IN DWORD dwBufLen)
  1663. {
  1664. PVTableStruc pVTable = NULL;
  1665. PVKeyStruc pVKey = NULL;
  1666. PVHashStruc pVHash = NULL;
  1667. BOOL fKeyCritSec = FALSE;
  1668. BOOL fTableCritSec = FALSE;
  1669. BOOL fHashCritSec = FALSE;
  1670. BOOL rt = CRYPT_FAILED;
  1671. __try
  1672. {
  1673. pVKey = (PVKeyStruc) hKey;
  1674. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1675. {
  1676. goto Ret;
  1677. }
  1678. fKeyCritSec = TRUE;
  1679. pVTable = (PVTableStruc) pVKey->hProv;
  1680. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1681. {
  1682. goto Ret;
  1683. }
  1684. fTableCritSec = TRUE;
  1685. pVHash = (PVHashStruc) hHash;
  1686. if (pVHash != NULL)
  1687. {
  1688. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  1689. {
  1690. goto Ret;
  1691. }
  1692. fHashCritSec = TRUE;
  1693. }
  1694. rt = (BOOL)pVKey->FuncEncrypt(pVTable->hProv, pVKey->hKey,
  1695. (pVHash == NULL ? 0 : pVHash->hHash),
  1696. Final, dwFlags, pbData,
  1697. pdwDataLen, dwBufLen);
  1698. }
  1699. __except ( CapiExceptionFilter )
  1700. {
  1701. SetLastError(ERROR_INVALID_PARAMETER);
  1702. goto Ret;
  1703. }
  1704. Ret:
  1705. if (fTableCritSec)
  1706. LeaveProviderCritSec(pVTable);
  1707. if (fKeyCritSec)
  1708. LeaveKeyCritSec(pVKey);
  1709. if (pVHash != NULL)
  1710. {
  1711. if (fHashCritSec)
  1712. LeaveHashCritSec(pVHash);
  1713. }
  1714. return rt;
  1715. }
  1716. /*
  1717. - CryptDecrypt
  1718. -
  1719. * Purpose:
  1720. * Decrypt data
  1721. *
  1722. *
  1723. * Parameters:
  1724. * IN hKey - Handle to the key
  1725. * IN hHash - Optional handle to a hash
  1726. * IN Final - Boolean indicating if this is the final
  1727. * block of ciphertext
  1728. * IN dwFlags - Flags values
  1729. * IN OUT pbData - Data to be decrypted
  1730. * IN OUT pdwDataLen - Pointer to the length of the data to be
  1731. * decrypted
  1732. *
  1733. * Returns:
  1734. */
  1735. WINADVAPI
  1736. BOOL
  1737. WINAPI CryptDecrypt(IN HCRYPTKEY hKey,
  1738. IN HCRYPTHASH hHash,
  1739. IN BOOL Final,
  1740. IN DWORD dwFlags,
  1741. IN OUT BYTE *pbData,
  1742. IN OUT DWORD *pdwDataLen)
  1743. {
  1744. PVTableStruc pVTable = NULL;
  1745. PVKeyStruc pVKey = NULL;
  1746. PVHashStruc pVHash = NULL;
  1747. BOOL fKeyCritSec = FALSE;
  1748. BOOL fTableCritSec = FALSE;
  1749. BOOL fHashCritSec = FALSE;
  1750. BOOL rt = CRYPT_FAILED;
  1751. __try
  1752. {
  1753. pVKey = (PVKeyStruc) hKey;
  1754. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1755. {
  1756. goto Ret;
  1757. }
  1758. fKeyCritSec = TRUE;
  1759. pVTable = (PVTableStruc) pVKey->hProv;
  1760. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1761. {
  1762. goto Ret;
  1763. }
  1764. fTableCritSec = TRUE;
  1765. pVHash = (PVHashStruc) hHash;
  1766. if (pVHash != NULL)
  1767. {
  1768. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  1769. {
  1770. goto Ret;
  1771. }
  1772. fHashCritSec = TRUE;
  1773. }
  1774. rt = (BOOL)pVKey->FuncDecrypt(pVTable->hProv, pVKey->hKey,
  1775. (pVHash == NULL ? 0 : pVHash->hHash),
  1776. Final, dwFlags, pbData, pdwDataLen);
  1777. }
  1778. __except ( CapiExceptionFilter )
  1779. {
  1780. SetLastError(ERROR_INVALID_PARAMETER);
  1781. goto Ret;
  1782. }
  1783. Ret:
  1784. if (fTableCritSec)
  1785. LeaveProviderCritSec(pVTable);
  1786. if (fKeyCritSec)
  1787. LeaveKeyCritSec(pVKey);
  1788. if (pVHash != NULL)
  1789. {
  1790. if (fHashCritSec)
  1791. LeaveHashCritSec(pVHash);
  1792. }
  1793. return(rt);
  1794. }
  1795. /*
  1796. - CryptCreateHash
  1797. -
  1798. * Purpose:
  1799. * initate the hashing of a stream of data
  1800. *
  1801. *
  1802. * Parameters:
  1803. * IN hProv - Handle to the user identifcation
  1804. * IN Algid - Algorithm identifier of the hash algorithm
  1805. * to be used
  1806. * IN hKey - Optional key for MAC algorithms
  1807. * IN dwFlags - Flags values
  1808. * OUT pHash - Handle to hash object
  1809. *
  1810. * Returns:
  1811. */
  1812. WINADVAPI
  1813. BOOL
  1814. WINAPI CryptCreateHash(IN HCRYPTPROV hProv,
  1815. IN ALG_ID Algid,
  1816. IN HCRYPTKEY hKey,
  1817. IN DWORD dwFlags,
  1818. OUT HCRYPTHASH *phHash)
  1819. {
  1820. PVTableStruc pVTable = NULL;
  1821. DWORD bufsize;
  1822. PVKeyStruc pVKey = NULL;
  1823. PVHashStruc pVHash = NULL;
  1824. BOOL fTableCritSec = FALSE;
  1825. BOOL fKeyCritSec = FALSE;
  1826. BOOL fRet = CRYPT_FAILED;
  1827. __try
  1828. {
  1829. pVTable = (PVTableStruc) hProv;
  1830. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1831. {
  1832. SetLastError(ERROR_INVALID_PARAMETER);
  1833. goto Ret;
  1834. }
  1835. fTableCritSec = TRUE;
  1836. pVKey = (PVKeyStruc) hKey;
  1837. if (pVKey != NULL)
  1838. {
  1839. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  1840. {
  1841. SetLastError(ERROR_INVALID_PARAMETER);
  1842. goto Ret;
  1843. }
  1844. fKeyCritSec = TRUE;
  1845. }
  1846. bufsize = sizeof(VHashStruc);
  1847. if (!BuildVHash(&pVHash, pVTable))
  1848. {
  1849. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  1850. goto Ret;
  1851. }
  1852. if (RCRYPT_FAILED(pVTable->FuncCreateHash(pVTable->hProv, Algid,
  1853. (pVKey == NULL ? 0 : pVKey->hKey),
  1854. dwFlags, phHash)))
  1855. {
  1856. goto Ret;
  1857. }
  1858. pVHash->hHash = *phHash;
  1859. *phHash = (HCRYPTHASH) pVHash;
  1860. pVHash->Version = TABLEHASH;
  1861. pVHash->Inuse = 1;
  1862. }
  1863. __except ( CapiExceptionFilter )
  1864. {
  1865. SetLastError(ERROR_INVALID_PARAMETER);
  1866. goto Ret;
  1867. }
  1868. fRet = CRYPT_SUCCEED;
  1869. Ret:
  1870. if (fTableCritSec)
  1871. LeaveProviderCritSec(pVTable);
  1872. if (pVKey != NULL)
  1873. {
  1874. if (fKeyCritSec)
  1875. LeaveKeyCritSec(pVKey);
  1876. }
  1877. if ((CRYPT_SUCCEED != fRet) && pVHash)
  1878. LocalFree(pVHash);
  1879. return fRet;
  1880. }
  1881. /*
  1882. - CryptDuplicateHash
  1883. -
  1884. * Purpose:
  1885. * Duplicate a cryptographic hash
  1886. *
  1887. *
  1888. * Parameters:
  1889. * IN hHash - Handle to the hash to be duplicated
  1890. * IN pdwReserved - Reserved for later use
  1891. * IN dwFlags - Flags values
  1892. * OUT phHash - Handle to the new duplicate hash
  1893. *
  1894. * Returns:
  1895. */
  1896. WINADVAPI
  1897. BOOL
  1898. WINAPI CryptDuplicateHash(
  1899. IN HCRYPTHASH hHash,
  1900. IN DWORD *pdwReserved,
  1901. IN DWORD dwFlags,
  1902. OUT HCRYPTHASH * phHash
  1903. )
  1904. {
  1905. PVTableStruc pVTable = NULL;
  1906. PVHashStruc pVHash;
  1907. PVHashStruc pVNewHash = NULL;
  1908. HCRYPTHASH hNewHash;
  1909. BOOL fProvCritSecSet = FALSE;
  1910. DWORD dwErr = 0;
  1911. BOOL fRet = CRYPT_FAILED;
  1912. __try
  1913. {
  1914. if (IsBadWritePtr(phHash, sizeof(HCRYPTHASH)))
  1915. {
  1916. SetLastError(ERROR_INVALID_PARAMETER);
  1917. goto Ret;
  1918. }
  1919. pVHash = (PVHashStruc) hHash;
  1920. if (pVHash->Version != TABLEHASH)
  1921. {
  1922. SetLastError(ERROR_INVALID_PARAMETER);
  1923. goto Ret;
  1924. }
  1925. if (NULL == pVHash->OptionalFuncDuplicateHash)
  1926. {
  1927. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  1928. goto Ret;
  1929. }
  1930. pVTable = (PVTableStruc) pVHash->hProv;
  1931. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  1932. {
  1933. SetLastError(ERROR_INVALID_PARAMETER);
  1934. goto Ret;
  1935. }
  1936. fProvCritSecSet = TRUE;
  1937. if (RCRYPT_FAILED(BuildVHash(&pVNewHash, pVTable)))
  1938. {
  1939. goto Ret;
  1940. }
  1941. if (RCRYPT_FAILED(pVHash->OptionalFuncDuplicateHash(pVTable->hProv, pVHash->hHash,
  1942. pdwReserved, dwFlags, &hNewHash)))
  1943. {
  1944. goto Ret;
  1945. }
  1946. pVNewHash->hHash = hNewHash;
  1947. pVNewHash->Version = TABLEHASH;
  1948. pVNewHash->hProv = pVHash->hProv;
  1949. pVHash->Inuse = 1;
  1950. *phHash = (HCRYPTHASH) pVNewHash;
  1951. }
  1952. __except ( CapiExceptionFilter )
  1953. {
  1954. SetLastError(ERROR_INVALID_PARAMETER);
  1955. goto Ret;
  1956. }
  1957. fRet = CRYPT_SUCCEED;
  1958. Ret:
  1959. if (CRYPT_SUCCEED != fRet)
  1960. dwErr = GetLastError();
  1961. if ((fRet == CRYPT_FAILED) && (NULL != pVNewHash))
  1962. LocalFree(pVNewHash);
  1963. if (fProvCritSecSet)
  1964. LeaveProviderCritSec(pVTable);
  1965. if (CRYPT_SUCCEED != fRet)
  1966. SetLastError(dwErr);
  1967. return fRet;
  1968. }
  1969. /*
  1970. - CryptHashData
  1971. -
  1972. * Purpose:
  1973. * Compute the cryptograghic hash on a stream of data
  1974. *
  1975. *
  1976. * Parameters:
  1977. * IN hHash - Handle to hash object
  1978. * IN pbData - Pointer to data to be hashed
  1979. * IN dwDataLen - Length of the data to be hashed
  1980. * IN dwFlags - Flags values
  1981. *
  1982. *
  1983. * Returns:
  1984. */
  1985. WINADVAPI
  1986. BOOL
  1987. WINAPI CryptHashData(IN HCRYPTHASH hHash,
  1988. IN CONST BYTE *pbData,
  1989. IN DWORD dwDataLen,
  1990. IN DWORD dwFlags)
  1991. {
  1992. PVTableStruc pVTable = NULL;
  1993. PVHashStruc pVHash = NULL;
  1994. BOOL fProvCritSec = FALSE;
  1995. BOOL fHashCritSec = FALSE;
  1996. DWORD dwErr = 0;
  1997. BOOL fRet = CRYPT_FAILED;
  1998. __try
  1999. {
  2000. pVHash = (PVHashStruc) hHash;
  2001. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  2002. {
  2003. goto Ret;
  2004. }
  2005. fHashCritSec = TRUE;
  2006. pVTable = (PVTableStruc) pVHash->hProv;
  2007. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2008. {
  2009. goto Ret;
  2010. }
  2011. fProvCritSec = TRUE;
  2012. if (!pVHash->FuncHashData(pVTable->hProv,
  2013. pVHash->hHash,
  2014. pbData, dwDataLen, dwFlags))
  2015. goto Ret;
  2016. } __except ( CapiExceptionFilter )
  2017. {
  2018. SetLastError(ERROR_INVALID_PARAMETER);
  2019. goto Ret;
  2020. }
  2021. fRet = CRYPT_SUCCEED;
  2022. Ret:
  2023. if (CRYPT_SUCCEED != fRet)
  2024. dwErr = GetLastError();
  2025. if (fHashCritSec)
  2026. LeaveHashCritSec(pVHash);
  2027. if (fProvCritSec)
  2028. LeaveProviderCritSec(pVTable);
  2029. if (CRYPT_SUCCEED != fRet)
  2030. SetLastError(dwErr);
  2031. return fRet;
  2032. }
  2033. /*
  2034. - CryptHashSessionKey
  2035. -
  2036. * Purpose:
  2037. * Compute the cryptograghic hash on a key object
  2038. *
  2039. *
  2040. * Parameters:
  2041. * IN hHash - Handle to hash object
  2042. * IN hKey - Handle to a key object
  2043. * IN dwFlags - Flags values
  2044. *
  2045. * Returns:
  2046. * CRYPT_FAILED
  2047. * CRYPT_SUCCEED
  2048. */
  2049. WINADVAPI
  2050. BOOL
  2051. WINAPI CryptHashSessionKey(IN HCRYPTHASH hHash,
  2052. IN HCRYPTKEY hKey,
  2053. IN DWORD dwFlags)
  2054. {
  2055. PVTableStruc pVTable = NULL;
  2056. PVHashStruc pVHash = NULL;
  2057. PVKeyStruc pVKey = NULL;
  2058. BOOL fHashCritSec = FALSE;
  2059. BOOL fProvCritSec = FALSE;
  2060. BOOL fKeyCritSec = FALSE;
  2061. BOOL rt = CRYPT_FAILED;
  2062. __try
  2063. {
  2064. pVHash = (PVHashStruc) hHash;
  2065. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  2066. {
  2067. goto Ret;
  2068. }
  2069. fHashCritSec = TRUE;
  2070. pVTable = (PVTableStruc) pVHash->hProv;
  2071. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2072. {
  2073. goto Ret;
  2074. }
  2075. fProvCritSec = TRUE;
  2076. pVKey = (PVKeyStruc) hKey;
  2077. if (pVKey != NULL)
  2078. {
  2079. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  2080. {
  2081. goto Ret;
  2082. }
  2083. fKeyCritSec = TRUE;
  2084. }
  2085. rt = (BOOL)pVHash->FuncHashSessionKey(pVTable->hProv,
  2086. pVHash->hHash,
  2087. pVKey->hKey,
  2088. dwFlags);
  2089. } __except ( CapiExceptionFilter )
  2090. {
  2091. SetLastError(ERROR_INVALID_PARAMETER);
  2092. goto Ret;
  2093. }
  2094. Ret:
  2095. if (fHashCritSec)
  2096. LeaveHashCritSec(pVHash);
  2097. if (fProvCritSec)
  2098. LeaveProviderCritSec(pVTable);
  2099. if (pVKey != NULL)
  2100. {
  2101. if (fKeyCritSec)
  2102. LeaveKeyCritSec(pVKey);
  2103. }
  2104. return rt;
  2105. }
  2106. /*
  2107. - CryptDestoryHash
  2108. -
  2109. * Purpose:
  2110. * Destory the hash object
  2111. *
  2112. *
  2113. * Parameters:
  2114. * IN hHash - Handle to hash object
  2115. *
  2116. * Returns:
  2117. */
  2118. WINADVAPI
  2119. BOOL
  2120. WINAPI CryptDestroyHash(IN HCRYPTHASH hHash)
  2121. {
  2122. PVTableStruc pVTable = NULL;
  2123. PVHashStruc pVHash;
  2124. BOOL fProvCritSec = FALSE;
  2125. BOOL rt = CRYPT_FAILED;
  2126. __try
  2127. {
  2128. pVHash = (PVHashStruc) hHash;
  2129. if (pVHash->Version != TABLEHASH)
  2130. {
  2131. SetLastError(ERROR_INVALID_PARAMETER);
  2132. goto Ret;
  2133. }
  2134. if (0 < InterlockedDecrement((LPLONG)&pVHash->Inuse))
  2135. {
  2136. InterlockedIncrement((LPLONG)&pVHash->Inuse);
  2137. SetLastError(ERROR_BUSY);
  2138. goto Ret;
  2139. }
  2140. InterlockedIncrement((LPLONG)&pVHash->Inuse);
  2141. pVTable = (PVTableStruc) pVHash->hProv;
  2142. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2143. {
  2144. goto Ret;
  2145. }
  2146. fProvCritSec = TRUE;
  2147. rt = (BOOL)pVHash->FuncDestroyHash(pVTable->hProv, pVHash->hHash);
  2148. pVHash->Version = 0;
  2149. LocalFree(pVHash);
  2150. }
  2151. __except ( CapiExceptionFilter )
  2152. {
  2153. SetLastError(ERROR_INVALID_PARAMETER);
  2154. goto Ret;
  2155. }
  2156. Ret:
  2157. if (fProvCritSec)
  2158. LeaveProviderCritSec(pVTable);
  2159. return rt;
  2160. }
  2161. WINADVAPI
  2162. BOOL
  2163. WINAPI LocalSignHashW(IN HCRYPTHASH hHash,
  2164. IN DWORD dwKeySpec,
  2165. IN LPCWSTR sDescription,
  2166. IN DWORD dwFlags,
  2167. OUT BYTE *pbSignature,
  2168. OUT DWORD *pdwSigLen)
  2169. {
  2170. PVTableStruc pVTable = NULL;
  2171. PVHashStruc pVHash = NULL;
  2172. BOOL fHashCritSec = FALSE;
  2173. BOOL fProvCritSec = FALSE;
  2174. BOOL rt = CRYPT_FAILED;
  2175. __try
  2176. {
  2177. pVHash = (PVHashStruc) hHash;
  2178. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  2179. {
  2180. goto Ret;
  2181. }
  2182. fHashCritSec = TRUE;
  2183. pVTable = (PVTableStruc) pVHash->hProv;
  2184. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2185. {
  2186. goto Ret;
  2187. }
  2188. fProvCritSec = TRUE;
  2189. rt = (BOOL)pVHash->FuncSignHash(pVTable->hProv, pVHash->hHash,
  2190. dwKeySpec,
  2191. sDescription, dwFlags,
  2192. pbSignature, pdwSigLen);
  2193. }
  2194. __except ( CapiExceptionFilter )
  2195. {
  2196. SetLastError(ERROR_INVALID_PARAMETER);
  2197. goto Ret;
  2198. }
  2199. Ret:
  2200. if (fHashCritSec)
  2201. LeaveHashCritSec(pVHash);
  2202. if (fProvCritSec)
  2203. LeaveProviderCritSec(pVTable);
  2204. return rt;
  2205. }
  2206. /*
  2207. - CryptSignHashW
  2208. -
  2209. * Purpose:
  2210. * Create a digital signature from a hash
  2211. *
  2212. *
  2213. * Parameters:
  2214. * IN hHash - Handle to hash object
  2215. * IN dwKeySpec - Key pair that is used to sign with
  2216. * algorithm to be used
  2217. * IN sDescription - Description of data to be signed
  2218. * IN dwFlags - Flags values
  2219. * OUT pbSignture - Pointer to signature data
  2220. * OUT pdwSigLen - Pointer to the len of the signature data
  2221. *
  2222. * Returns:
  2223. */
  2224. WINADVAPI
  2225. BOOL
  2226. WINAPI CryptSignHashW(IN HCRYPTHASH hHash,
  2227. IN DWORD dwKeySpec,
  2228. IN LPCWSTR sDescription,
  2229. IN DWORD dwFlags,
  2230. OUT BYTE *pbSignature,
  2231. OUT DWORD *pdwSigLen)
  2232. {
  2233. return LocalSignHashW(hHash, dwKeySpec, sDescription,
  2234. dwFlags, pbSignature, pdwSigLen);
  2235. }
  2236. /*
  2237. - CryptSignHashA
  2238. -
  2239. * Purpose:
  2240. * Create a digital signature from a hash
  2241. *
  2242. *
  2243. * Parameters:
  2244. * IN hHash - Handle to hash object
  2245. * IN dwKeySpec - Key pair that is used to sign with
  2246. * algorithm to be used
  2247. * IN sDescription - Description of data to be signed
  2248. * IN dwFlags - Flags values
  2249. * OUT pbSignture - Pointer to signature data
  2250. * OUT pdwSigLen - Pointer to the len of the signature data
  2251. *
  2252. * Returns:
  2253. */
  2254. WINADVAPI
  2255. BOOL
  2256. WINAPI CryptSignHashA(IN HCRYPTHASH hHash,
  2257. IN DWORD dwKeySpec,
  2258. IN LPCSTR sDescription,
  2259. IN DWORD dwFlags,
  2260. OUT BYTE *pbSignature,
  2261. OUT DWORD *pdwSigLen)
  2262. {
  2263. ANSI_STRING AnsiString;
  2264. UNICODE_STRING UnicodeString;
  2265. NTSTATUS Status;
  2266. BOOL rt = CRYPT_FAILED;
  2267. __try
  2268. {
  2269. memset(&AnsiString, 0, sizeof(AnsiString));
  2270. memset(&UnicodeString, 0, sizeof(UnicodeString));
  2271. if (NULL != sDescription)
  2272. {
  2273. RtlInitAnsiString(&AnsiString, sDescription);
  2274. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  2275. if ( !NT_SUCCESS(Status) )
  2276. {
  2277. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2278. goto Ret;
  2279. }
  2280. }
  2281. rt = LocalSignHashW(hHash, dwKeySpec, UnicodeString.Buffer,
  2282. dwFlags, pbSignature, pdwSigLen);
  2283. RtlFreeUnicodeString(&UnicodeString);
  2284. } __except ( CapiExceptionFilter )
  2285. {
  2286. SetLastError(ERROR_INVALID_PARAMETER);
  2287. goto Ret;
  2288. }
  2289. Ret:
  2290. return rt;
  2291. }
  2292. WINADVAPI
  2293. BOOL
  2294. WINAPI LocalVerifySignatureW(IN HCRYPTHASH hHash,
  2295. IN CONST BYTE *pbSignature,
  2296. IN DWORD dwSigLen,
  2297. IN HCRYPTKEY hPubKey,
  2298. IN LPCWSTR sDescription,
  2299. IN DWORD dwFlags)
  2300. {
  2301. PVTableStruc pVTable = NULL;
  2302. PVHashStruc pVHash = NULL;
  2303. PVKeyStruc pVKey = NULL;
  2304. BOOL fHashCritSec = FALSE;
  2305. BOOL fProvCritSec = FALSE;
  2306. BOOL fKeyCritSec = FALSE;
  2307. BOOL rt = CRYPT_FAILED;
  2308. __try
  2309. {
  2310. pVHash = (PVHashStruc) hHash;
  2311. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  2312. {
  2313. goto Ret;
  2314. }
  2315. fHashCritSec = TRUE;
  2316. pVTable = (PVTableStruc) pVHash->hProv;
  2317. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2318. {
  2319. goto Ret;
  2320. }
  2321. fProvCritSec = TRUE;
  2322. pVKey = (PVKeyStruc) hPubKey;
  2323. if (RCRYPT_FAILED(EnterKeyCritSec(pVKey)))
  2324. {
  2325. goto Ret;
  2326. }
  2327. fKeyCritSec = TRUE;
  2328. rt = (BOOL)pVHash->FuncVerifySignature(pVTable->hProv,
  2329. pVHash->hHash, pbSignature,
  2330. dwSigLen,
  2331. (pVKey == NULL ? 0 : pVKey->hKey),
  2332. sDescription, dwFlags);
  2333. }
  2334. __except ( CapiExceptionFilter )
  2335. {
  2336. SetLastError(ERROR_INVALID_PARAMETER);
  2337. goto Ret;
  2338. }
  2339. Ret:
  2340. if (fHashCritSec)
  2341. LeaveHashCritSec(pVHash);
  2342. if (fProvCritSec)
  2343. LeaveProviderCritSec(pVTable);
  2344. if (fKeyCritSec)
  2345. LeaveKeyCritSec(pVKey);
  2346. return rt;
  2347. }
  2348. /*
  2349. - CryptVerifySignatureW
  2350. -
  2351. * Purpose:
  2352. * Used to verify a signature against a hash object
  2353. *
  2354. *
  2355. * Parameters:
  2356. * IN hHash - Handle to hash object
  2357. * IN pbSignture - Pointer to signature data
  2358. * IN dwSigLen - Length of the signature data
  2359. * IN hPubKey - Handle to the public key for verifying
  2360. * the signature
  2361. * IN sDescription - String describing the signed data
  2362. * IN dwFlags - Flags values
  2363. *
  2364. * Returns:
  2365. */
  2366. WINADVAPI
  2367. BOOL
  2368. WINAPI CryptVerifySignatureW(IN HCRYPTHASH hHash,
  2369. IN CONST BYTE *pbSignature,
  2370. IN DWORD dwSigLen,
  2371. IN HCRYPTKEY hPubKey,
  2372. IN LPCWSTR sDescription,
  2373. IN DWORD dwFlags)
  2374. {
  2375. return LocalVerifySignatureW(hHash, pbSignature, dwSigLen,
  2376. hPubKey, sDescription, dwFlags);
  2377. }
  2378. /*
  2379. - CryptVerifySignatureA
  2380. -
  2381. * Purpose:
  2382. * Used to verify a signature against a hash object
  2383. *
  2384. *
  2385. * Parameters:
  2386. * IN hHash - Handle to hash object
  2387. * IN pbSignture - Pointer to signature data
  2388. * IN dwSigLen - Length of the signature data
  2389. * IN hPubKey - Handle to the public key for verifying
  2390. * the signature
  2391. * IN sDescription - String describing the signed data
  2392. * IN dwFlags - Flags values
  2393. *
  2394. * Returns:
  2395. */
  2396. WINADVAPI
  2397. BOOL
  2398. WINAPI CryptVerifySignatureA(IN HCRYPTHASH hHash,
  2399. IN CONST BYTE *pbSignature,
  2400. IN DWORD dwSigLen,
  2401. IN HCRYPTKEY hPubKey,
  2402. IN LPCSTR sDescription,
  2403. IN DWORD dwFlags)
  2404. {
  2405. ANSI_STRING AnsiString;
  2406. UNICODE_STRING UnicodeString;
  2407. NTSTATUS Status;
  2408. BOOL rt = CRYPT_FAILED;
  2409. __try
  2410. {
  2411. memset(&AnsiString, 0, sizeof(AnsiString));
  2412. memset(&UnicodeString, 0, sizeof(UnicodeString));
  2413. if (NULL != sDescription)
  2414. {
  2415. RtlInitAnsiString(&AnsiString, sDescription);
  2416. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  2417. if ( !NT_SUCCESS(Status) )
  2418. {
  2419. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2420. goto Ret;
  2421. }
  2422. }
  2423. rt = LocalVerifySignatureW(hHash, pbSignature, dwSigLen,
  2424. hPubKey, UnicodeString.Buffer, dwFlags);
  2425. RtlFreeUnicodeString(&UnicodeString);
  2426. }
  2427. __except ( CapiExceptionFilter )
  2428. {
  2429. SetLastError(ERROR_INVALID_PARAMETER);
  2430. goto Ret;
  2431. }
  2432. Ret:
  2433. return rt;
  2434. }
  2435. /*
  2436. - CryptSetProvParam
  2437. -
  2438. * Purpose:
  2439. * Allows applications to customize various aspects of the
  2440. * operations of a provider
  2441. *
  2442. * Parameters:
  2443. * IN hProv - Handle to a provider
  2444. * IN dwParam - Parameter number
  2445. * IN pbData - Pointer to data
  2446. * IN dwFlags - Flags values
  2447. *
  2448. * Returns:
  2449. */
  2450. WINADVAPI
  2451. BOOL
  2452. WINAPI CryptSetProvParam(IN HCRYPTPROV hProv,
  2453. IN DWORD dwParam,
  2454. IN CONST BYTE *pbData,
  2455. IN DWORD dwFlags)
  2456. {
  2457. PVTableStruc pVTable;
  2458. BYTE *pbTmp;
  2459. CRYPT_DATA_BLOB *pBlob;
  2460. BOOL rt = CRYPT_FAILED;
  2461. __try
  2462. {
  2463. if (dwParam == PP_CLIENT_HWND)
  2464. {
  2465. hWnd = *((HWND *) pbData);
  2466. rt = CRYPT_SUCCEED;
  2467. goto Ret;
  2468. }
  2469. else if (dwParam == PP_CONTEXT_INFO)
  2470. {
  2471. pBlob = (CRYPT_DATA_BLOB*)pbData;
  2472. // allocate space for the new context info
  2473. if (NULL == (pbTmp = (BYTE*)LocalAlloc(LMEM_ZEROINIT, pBlob->cbData)))
  2474. {
  2475. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2476. goto Ret;
  2477. }
  2478. memcpy(pbTmp, pBlob->pbData, pBlob->cbData);
  2479. // free any previously allocated context info
  2480. if (NULL != pbContextInfo)
  2481. {
  2482. LocalFree(pbContextInfo);
  2483. }
  2484. cbContextInfo = pBlob->cbData;
  2485. pbContextInfo = pbTmp;
  2486. rt = CRYPT_SUCCEED;
  2487. goto Ret;
  2488. }
  2489. pVTable = (PVTableStruc) hProv;
  2490. if (pVTable->Version != TABLEPROV)
  2491. {
  2492. SetLastError(ERROR_INVALID_PARAMETER);
  2493. goto Ret;
  2494. }
  2495. if (0 < InterlockedDecrement((LPLONG)&pVTable->Inuse))
  2496. {
  2497. InterlockedIncrement((LPLONG)&pVTable->Inuse);
  2498. SetLastError(ERROR_BUSY);
  2499. goto Ret;
  2500. }
  2501. InterlockedIncrement((LPLONG)&pVTable->Inuse);
  2502. rt = (BOOL)pVTable->FuncSetProvParam(pVTable->hProv, dwParam, pbData,
  2503. dwFlags);
  2504. }
  2505. __except ( CapiExceptionFilter )
  2506. {
  2507. SetLastError(ERROR_INVALID_PARAMETER);
  2508. goto Ret;
  2509. }
  2510. Ret:
  2511. return(rt);
  2512. }
  2513. /*
  2514. - CryptGetProvParam
  2515. -
  2516. * Purpose:
  2517. * Allows applications to get various aspects of the
  2518. * operations of a provider
  2519. *
  2520. * Parameters:
  2521. * IN hProv - Handle to a proivder
  2522. * IN dwParam - Parameter number
  2523. * IN pbData - Pointer to data
  2524. * IN pdwDataLen - Length of parameter data
  2525. * IN dwFlags - Flags values
  2526. *
  2527. * Returns:
  2528. */
  2529. WINADVAPI
  2530. BOOL
  2531. WINAPI CryptGetProvParam(IN HCRYPTPROV hProv,
  2532. IN DWORD dwParam,
  2533. IN BYTE *pbData,
  2534. IN DWORD *pdwDataLen,
  2535. IN DWORD dwFlags)
  2536. {
  2537. PVTableStruc pVTable = NULL;
  2538. BOOL fProvCritSec = FALSE;
  2539. BOOL rt = CRYPT_FAILED;
  2540. __try
  2541. {
  2542. pVTable = (PVTableStruc) hProv;
  2543. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2544. {
  2545. goto Ret;
  2546. }
  2547. fProvCritSec = TRUE;
  2548. rt = (BOOL)pVTable->FuncGetProvParam(pVTable->hProv, dwParam, pbData,
  2549. pdwDataLen, dwFlags);
  2550. }
  2551. __except ( CapiExceptionFilter )
  2552. {
  2553. SetLastError(ERROR_INVALID_PARAMETER);
  2554. goto Ret;
  2555. }
  2556. Ret:
  2557. if (fProvCritSec)
  2558. LeaveProviderCritSec(pVTable);
  2559. return rt;
  2560. }
  2561. /*
  2562. - CryptSetHashParam
  2563. -
  2564. * Purpose:
  2565. * Allows applications to customize various aspects of the
  2566. * operations of a hash
  2567. *
  2568. * Parameters:
  2569. * IN hHash - Handle to a hash
  2570. * IN dwParam - Parameter number
  2571. * IN pbData - Pointer to data
  2572. * IN dwFlags - Flags values
  2573. *
  2574. * Returns:
  2575. */
  2576. WINADVAPI
  2577. BOOL
  2578. WINAPI CryptSetHashParam(IN HCRYPTHASH hHash,
  2579. IN DWORD dwParam,
  2580. IN CONST BYTE *pbData,
  2581. IN DWORD dwFlags)
  2582. {
  2583. PVTableStruc pVTable = NULL;
  2584. PVHashStruc pVHash;
  2585. BOOL fProvCritSec = FALSE;
  2586. BOOL rt = CRYPT_FAILED;
  2587. __try
  2588. {
  2589. pVHash = (PVHashStruc) hHash;
  2590. if (pVHash->Version != TABLEHASH)
  2591. {
  2592. SetLastError(ERROR_INVALID_PARAMETER);
  2593. goto Ret;
  2594. }
  2595. if (0 < InterlockedDecrement((LPLONG)&pVHash->Inuse))
  2596. {
  2597. InterlockedIncrement((LPLONG)&pVHash->Inuse);
  2598. SetLastError(ERROR_BUSY);
  2599. goto Ret;
  2600. }
  2601. InterlockedIncrement((LPLONG)&pVHash->Inuse);
  2602. pVTable = (PVTableStruc) pVHash->hProv;
  2603. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2604. {
  2605. goto Ret;
  2606. }
  2607. fProvCritSec = TRUE;
  2608. rt = (BOOL)pVHash->FuncSetHashParam(pVTable->hProv, pVHash->hHash,
  2609. dwParam, pbData, dwFlags);
  2610. }
  2611. __except ( CapiExceptionFilter )
  2612. {
  2613. SetLastError(ERROR_INVALID_PARAMETER);
  2614. goto Ret;
  2615. }
  2616. Ret:
  2617. if (fProvCritSec)
  2618. LeaveProviderCritSec(pVTable);
  2619. return rt;
  2620. }
  2621. /*
  2622. - CryptGetHashParam
  2623. -
  2624. * Purpose:
  2625. * Allows applications to get various aspects of the
  2626. * operations of a hash
  2627. *
  2628. * Parameters:
  2629. * IN hHash - Handle to a hash
  2630. * IN dwParam - Parameter number
  2631. * IN pbData - Pointer to data
  2632. * IN pdwDataLen - Length of parameter data
  2633. * IN dwFlags - Flags values
  2634. *
  2635. * Returns:
  2636. */
  2637. WINADVAPI
  2638. BOOL
  2639. WINAPI CryptGetHashParam(IN HCRYPTKEY hHash,
  2640. IN DWORD dwParam,
  2641. IN BYTE *pbData,
  2642. IN DWORD *pdwDataLen,
  2643. IN DWORD dwFlags)
  2644. {
  2645. PVTableStruc pVTable = NULL;
  2646. PVHashStruc pVHash = NULL;
  2647. BOOL fHashCritSec = FALSE;
  2648. BOOL fProvCritSec = FALSE;
  2649. BOOL rt = CRYPT_FAILED;
  2650. __try
  2651. {
  2652. pVHash = (PVHashStruc) hHash;
  2653. if (RCRYPT_FAILED(EnterHashCritSec(pVHash)))
  2654. {
  2655. goto Ret;
  2656. }
  2657. fHashCritSec = TRUE;
  2658. pVTable = (PVTableStruc) pVHash->hProv;
  2659. if (RCRYPT_FAILED(EnterProviderCritSec(pVTable)))
  2660. {
  2661. goto Ret;
  2662. }
  2663. fProvCritSec = TRUE;
  2664. rt = (BOOL)pVHash->FuncGetHashParam(pVTable->hProv, pVHash->hHash,
  2665. dwParam, pbData, pdwDataLen,
  2666. dwFlags);
  2667. }
  2668. __except ( CapiExceptionFilter )
  2669. {
  2670. SetLastError(ERROR_INVALID_PARAMETER);
  2671. goto Ret;
  2672. }
  2673. Ret:
  2674. if (fHashCritSec)
  2675. LeaveHashCritSec(pVHash);
  2676. if (fProvCritSec)
  2677. LeaveProviderCritSec(pVTable);
  2678. return rt;
  2679. }
  2680. /*
  2681. - CryptSetProviderW
  2682. -
  2683. * Purpose:
  2684. * Set a cryptography provider
  2685. *
  2686. *
  2687. * Parameters:
  2688. *
  2689. * IN pszProvName - Name of the provider to install
  2690. * IN dwProvType - Type of the provider to install
  2691. *
  2692. * Returns:
  2693. * BOOL
  2694. * Use get extended error information use GetLastError
  2695. */
  2696. WINADVAPI
  2697. BOOL
  2698. WINAPI CryptSetProviderW(IN LPCWSTR pszProvName,
  2699. IN DWORD dwProvType)
  2700. {
  2701. ANSI_STRING AnsiString;
  2702. UNICODE_STRING UnicodeString;
  2703. NTSTATUS Status;
  2704. BOOL rt = FALSE;
  2705. __try
  2706. {
  2707. RtlInitUnicodeString(&UnicodeString, pszProvName);
  2708. Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
  2709. if (!NT_SUCCESS(Status))
  2710. {
  2711. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2712. goto Ret;
  2713. }
  2714. rt = CryptSetProviderA((LPCSTR) AnsiString.Buffer,
  2715. dwProvType);
  2716. RtlFreeAnsiString(&AnsiString);
  2717. }
  2718. __except ( CapiExceptionFilter )
  2719. {
  2720. SetLastError(ERROR_INVALID_PARAMETER);
  2721. goto Ret;
  2722. }
  2723. Ret:
  2724. return(rt);
  2725. }
  2726. /*
  2727. - CryptSetProviderA
  2728. -
  2729. * Purpose:
  2730. * Set a cryptography provider
  2731. *
  2732. *
  2733. * Parameters:
  2734. *
  2735. * IN pszProvName - Name of the provider to install
  2736. * IN dwProvType - Type of the provider to install
  2737. *
  2738. * Returns:
  2739. * BOOL
  2740. * Use get extended error information use GetLastError
  2741. */
  2742. WINADVAPI
  2743. BOOL
  2744. WINAPI CryptSetProviderA(IN LPCSTR pszProvName,
  2745. IN DWORD dwProvType)
  2746. {
  2747. BOOL fRet = CRYPT_FAILED;
  2748. LPSTR pszCurrent = NULL;
  2749. DWORD cbCurrent = 0;
  2750. __try
  2751. {
  2752. if (dwProvType == 0 || dwProvType > 999 || pszProvName == NULL)
  2753. {
  2754. SetLastError(ERROR_INVALID_PARAMETER);
  2755. goto Ret;
  2756. }
  2757. //
  2758. // We don't support setting the user default provider any more. See
  2759. // if the current default provider of the specified type matches the
  2760. // caller's. If it does, we'll let the call "succeed".
  2761. //
  2762. if (! CryptGetDefaultProvider(
  2763. dwProvType,
  2764. NULL,
  2765. CRYPT_MACHINE_DEFAULT,
  2766. NULL,
  2767. &cbCurrent))
  2768. {
  2769. goto Ret;
  2770. }
  2771. pszCurrent = (LPSTR) HeapAlloc(
  2772. GetProcessHeap(), HEAP_ZERO_MEMORY, cbCurrent);
  2773. if (NULL == pszCurrent)
  2774. {
  2775. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2776. goto Ret;
  2777. }
  2778. if (! CryptGetDefaultProvider(
  2779. dwProvType,
  2780. NULL,
  2781. CRYPT_MACHINE_DEFAULT,
  2782. pszCurrent,
  2783. &cbCurrent))
  2784. {
  2785. goto Ret;
  2786. }
  2787. if (0 != strcmp(pszProvName, pszCurrent))
  2788. {
  2789. SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
  2790. goto Ret;
  2791. }
  2792. }
  2793. __except ( CapiExceptionFilter )
  2794. {
  2795. SetLastError(ERROR_INVALID_PARAMETER);
  2796. goto Ret;
  2797. }
  2798. fRet = CRYPT_SUCCEED;
  2799. Ret:
  2800. if (pszCurrent)
  2801. HeapFree(GetProcessHeap(), 0, pszCurrent);
  2802. return fRet;
  2803. }
  2804. /*
  2805. - CryptSetProviderExW
  2806. -
  2807. * Purpose:
  2808. * Set the cryptographic provider as the default
  2809. * either for machine or for user.
  2810. *
  2811. *
  2812. * Parameters:
  2813. *
  2814. * IN pszProvName - Name of the provider to install
  2815. * IN dwProvType - Type of the provider to install
  2816. * IN pdwReserved - Reserved for future use
  2817. * IN dwFlags - Flags parameter (for machine or for user)
  2818. *
  2819. *
  2820. * Returns:
  2821. * BOOL
  2822. * Use get extended error information use GetLastError
  2823. */
  2824. WINADVAPI
  2825. BOOL
  2826. WINAPI CryptSetProviderExW(
  2827. IN LPCWSTR pszProvName,
  2828. IN DWORD dwProvType,
  2829. IN DWORD *pdwReserved,
  2830. IN DWORD dwFlags
  2831. )
  2832. {
  2833. ANSI_STRING AnsiString;
  2834. UNICODE_STRING UnicodeString;
  2835. NTSTATUS Status;
  2836. BOOL fRet = CRYPT_FAILED;
  2837. __try
  2838. {
  2839. RtlInitUnicodeString(&UnicodeString, pszProvName);
  2840. Status = RtlUnicodeStringToAnsiString(&AnsiString, &UnicodeString, TRUE);
  2841. if (!NT_SUCCESS(Status))
  2842. {
  2843. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2844. goto Ret;
  2845. }
  2846. fRet = CryptSetProviderExA((LPCSTR) AnsiString.Buffer,
  2847. dwProvType,
  2848. pdwReserved,
  2849. dwFlags);
  2850. RtlFreeAnsiString(&AnsiString);
  2851. }
  2852. __except ( CapiExceptionFilter )
  2853. {
  2854. SetLastError(ERROR_INVALID_PARAMETER);
  2855. goto Ret;
  2856. }
  2857. Ret:
  2858. return fRet;
  2859. }
  2860. /*
  2861. - CryptSetProviderExA
  2862. -
  2863. * Purpose:
  2864. * Set the cryptographic provider as the default
  2865. * either for machine or for user.
  2866. *
  2867. *
  2868. * Parameters:
  2869. *
  2870. * IN pszProvName - Name of the provider to install
  2871. * IN dwProvType - Type of the provider to install
  2872. * IN pdwReserved - Reserved for future use
  2873. * IN dwFlags - Flags parameter (for machine or for user)
  2874. *
  2875. * Returns:
  2876. * BOOL
  2877. * Use get extended error information use GetLastError
  2878. */
  2879. WINADVAPI
  2880. BOOL
  2881. WINAPI CryptSetProviderExA(
  2882. IN LPCSTR pszProvName,
  2883. IN DWORD dwProvType,
  2884. IN DWORD *pdwReserved,
  2885. IN DWORD dwFlags
  2886. )
  2887. {
  2888. HKEY hCurrUser = 0;
  2889. HKEY hRegKey = 0;
  2890. LONG err;
  2891. DWORD dwDisp;
  2892. DWORD cbValue;
  2893. CHAR *pszValue = NULL;
  2894. CHAR *pszFullName = NULL;
  2895. DWORD cbFullName;
  2896. CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  2897. DWORD dwKeyType;
  2898. DWORD dw;
  2899. DWORD cbProvType;
  2900. BOOL fRet = CRYPT_FAILED;
  2901. __try
  2902. {
  2903. if ((dwProvType == 0) || (dwProvType > 999) ||
  2904. (pszProvName == NULL) || (pdwReserved != NULL))
  2905. {
  2906. SetLastError(ERROR_INVALID_PARAMETER);
  2907. goto Ret;
  2908. }
  2909. if ((dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT | CRYPT_DELETE_DEFAULT)) ||
  2910. ((dwFlags & CRYPT_MACHINE_DEFAULT) && (dwFlags & CRYPT_USER_DEFAULT)))
  2911. {
  2912. SetLastError((DWORD)NTE_BAD_FLAGS);
  2913. goto Ret;
  2914. }
  2915. cbValue = strlen(pszProvName);
  2916. // check if the CSP has been installed
  2917. cbFullName = cbValue + sizeof(szenumproviders) + sizeof(CHAR);
  2918. if (NULL == (pszFullName = (CHAR *) LocalAlloc(LMEM_ZEROINIT, cbFullName)))
  2919. {
  2920. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2921. goto Ret;
  2922. }
  2923. strcpy(pszFullName, szenumproviders);
  2924. pszFullName[sizeof(szenumproviders) - 1] = '\\';
  2925. strcpy(pszFullName + sizeof(szenumproviders), pszProvName);
  2926. if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  2927. (const char *) pszFullName,
  2928. 0L, KEY_READ, &hRegKey)) != ERROR_SUCCESS)
  2929. {
  2930. SetLastError(ERROR_INVALID_PARAMETER);
  2931. goto Ret;
  2932. }
  2933. cbProvType = sizeof(dw);
  2934. if (ERROR_SUCCESS != (err = RegQueryValueEx(hRegKey,
  2935. (const char *) "Type",
  2936. NULL, &dwKeyType, (BYTE*)&dw,
  2937. &cbProvType)))
  2938. {
  2939. SetLastError(err);
  2940. goto Ret;
  2941. }
  2942. if (dwProvType != dw)
  2943. {
  2944. SetLastError(ERROR_INVALID_PARAMETER);
  2945. goto Ret;
  2946. }
  2947. if (ERROR_SUCCESS != (err = RegCloseKey(hRegKey)))
  2948. {
  2949. SetLastError(err);
  2950. goto Ret;
  2951. }
  2952. hRegKey = NULL;
  2953. if (dwFlags & CRYPT_MACHINE_DEFAULT)
  2954. {
  2955. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  2956. strlen(szmachinetype) + 5 + 1)) == NULL)
  2957. {
  2958. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2959. goto Ret;
  2960. }
  2961. strcpy(pszValue, szmachinetype);
  2962. __ltoa(dwProvType, typebuf);
  2963. strcat(pszValue, &typebuf[5]);
  2964. if ((err = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
  2965. (const char *) pszValue,
  2966. 0L, NULL, REG_OPTION_NON_VOLATILE,
  2967. KEY_READ | KEY_WRITE, NULL, &hRegKey, &dwDisp)) != ERROR_SUCCESS)
  2968. {
  2969. SetLastError(ERROR_INVALID_PARAMETER);
  2970. goto Ret;
  2971. }
  2972. // check the delete flag
  2973. if (dwFlags & CRYPT_DELETE_DEFAULT)
  2974. {
  2975. if (ERROR_SUCCESS != (err = RegDeleteValue(hRegKey, "Name")))
  2976. {
  2977. SetLastError(err);
  2978. goto Ret;
  2979. }
  2980. fRet = CRYPT_SUCCEED;
  2981. goto Ret;
  2982. }
  2983. }
  2984. else if (dwFlags & CRYPT_USER_DEFAULT)
  2985. {
  2986. if (dwFlags & CRYPT_DELETE_DEFAULT)
  2987. {
  2988. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  2989. strlen(szusertype) + 5 + 1)) == NULL)
  2990. {
  2991. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2992. goto Ret;
  2993. }
  2994. strcpy(pszValue, szusertype);
  2995. __ltoa(dwProvType, typebuf);
  2996. strcat(pszValue, &typebuf[5]);
  2997. if (!NT_SUCCESS(RtlOpenCurrentUser(KEY_READ | KEY_WRITE, &hCurrUser)))
  2998. {
  2999. SetLastError(ERROR_INVALID_PARAMETER);
  3000. goto Ret;
  3001. }
  3002. if (ERROR_SUCCESS != (err = RegDeleteKey(hCurrUser,
  3003. (const char *)pszValue)))
  3004. {
  3005. NtClose(hCurrUser);
  3006. SetLastError(err);
  3007. goto Ret;
  3008. }
  3009. fRet = CRYPT_SUCCEED;
  3010. NtClose(hCurrUser);
  3011. goto Ret;
  3012. }
  3013. else
  3014. {
  3015. // The User flag is set, but Delete is not. Handle this case
  3016. // in CryptSetProvider.
  3017. fRet = CryptSetProviderA(pszProvName, dwProvType);
  3018. goto Ret;
  3019. }
  3020. }
  3021. if (ERROR_SUCCESS != (err = RegSetValueEx(hRegKey, "Name", 0L, REG_SZ,
  3022. (const LPBYTE) pszProvName, cbValue)))
  3023. {
  3024. SetLastError(err);
  3025. goto Ret;
  3026. }
  3027. }
  3028. __except ( CapiExceptionFilter )
  3029. {
  3030. SetLastError(ERROR_INVALID_PARAMETER);
  3031. goto Ret;
  3032. }
  3033. fRet = CRYPT_SUCCEED;
  3034. Ret:
  3035. if (pszFullName)
  3036. LocalFree(pszFullName);
  3037. if (pszValue)
  3038. LocalFree(pszValue);
  3039. if (hRegKey)
  3040. RegCloseKey(hRegKey);
  3041. return fRet;
  3042. }
  3043. /*
  3044. - CryptGetDefaultProviderW
  3045. -
  3046. * Purpose:
  3047. * Get the default cryptographic provider of the specified
  3048. * type for either the machine or for the user.
  3049. *
  3050. * Parameters:
  3051. * IN dwProvType - Type of the provider to install
  3052. * IN pdwReserved - Reserved for future use
  3053. * IN dwFlags - Flags parameter (for machine or for user)
  3054. * OUT pszProvName - Name of the default provider
  3055. * IN OUT pcbProvName - Length in bytes of the provider name
  3056. *
  3057. *
  3058. * Returns:
  3059. * BOOL
  3060. * Use get extended error information use GetLastError
  3061. */
  3062. WINADVAPI
  3063. BOOL
  3064. WINAPI CryptGetDefaultProviderW(
  3065. IN DWORD dwProvType,
  3066. IN DWORD *pdwReserved,
  3067. IN DWORD dwFlags,
  3068. OUT LPWSTR pszProvName,
  3069. IN OUT DWORD *pcbProvName
  3070. )
  3071. {
  3072. ANSI_STRING AnsiString;
  3073. UNICODE_STRING UnicodeString;
  3074. LPSTR pszName = NULL;
  3075. DWORD cbName;
  3076. NTSTATUS Status;
  3077. BOOL fRet = CRYPT_FAILED;
  3078. memset(&UnicodeString, 0, sizeof(UnicodeString));
  3079. __try
  3080. {
  3081. memset(&AnsiString, 0, sizeof(AnsiString));
  3082. if (!CryptGetDefaultProviderA(dwProvType,
  3083. pdwReserved,
  3084. dwFlags,
  3085. NULL,
  3086. &cbName))
  3087. goto Ret;
  3088. if (NULL == (pszName = LocalAlloc(LMEM_ZEROINIT, cbName)))
  3089. {
  3090. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3091. goto Ret;
  3092. }
  3093. if (!CryptGetDefaultProviderA(dwProvType,
  3094. pdwReserved,
  3095. dwFlags,
  3096. pszName,
  3097. &cbName))
  3098. goto Ret;
  3099. RtlInitAnsiString(&AnsiString, pszName);
  3100. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  3101. if (!NT_SUCCESS(Status))
  3102. {
  3103. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3104. goto Ret;
  3105. }
  3106. if (NULL == pszProvName)
  3107. {
  3108. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3109. fRet = CRYPT_SUCCEED;
  3110. goto Ret;
  3111. }
  3112. if (*pcbProvName < UnicodeString.Length + sizeof(WCHAR))
  3113. {
  3114. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3115. SetLastError(ERROR_MORE_DATA);
  3116. goto Ret;
  3117. }
  3118. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3119. memset(pszProvName, 0, *pcbProvName);
  3120. memcpy(pszProvName, UnicodeString.Buffer, UnicodeString.Length);
  3121. }
  3122. __except ( CapiExceptionFilter )
  3123. {
  3124. SetLastError(ERROR_INVALID_PARAMETER);
  3125. goto Ret;
  3126. }
  3127. fRet = CRYPT_SUCCEED;
  3128. Ret:
  3129. if (UnicodeString.Buffer)
  3130. RtlFreeUnicodeString(&UnicodeString);
  3131. if (pszName)
  3132. LocalFree(pszName);
  3133. return fRet;
  3134. }
  3135. /*
  3136. - CryptGetDefaultProviderA
  3137. -
  3138. * Purpose:
  3139. * Get the default cryptographic provider of the specified
  3140. * type for either the machine or for the user.
  3141. *
  3142. *
  3143. * Parameters:
  3144. * IN dwProvType - Type of the provider to install
  3145. * IN pdwReserved - Reserved for future use
  3146. * IN dwFlags - Flags parameter (for machine or for user)
  3147. * OUT pszProvName - Name of the default provider
  3148. * IN OUT pcbProvName - Length in bytes of the provider name
  3149. * including the NULL terminator
  3150. *
  3151. * Returns:
  3152. * BOOL
  3153. * Use get extended error information use GetLastError
  3154. */
  3155. WINAPI CryptGetDefaultProviderA(
  3156. IN DWORD dwProvType,
  3157. IN DWORD *pdwReserved,
  3158. IN DWORD dwFlags,
  3159. OUT LPSTR pszProvName,
  3160. IN OUT DWORD *pcbProvName
  3161. )
  3162. {
  3163. HKEY hRegKey = 0;
  3164. LONG err;
  3165. CHAR *pszValue = NULL;
  3166. DWORD dwValType;
  3167. CHAR typebuf[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
  3168. DWORD cbProvName = 0;
  3169. BOOL fRet = CRYPT_FAILED;
  3170. __try
  3171. {
  3172. if (dwProvType == 0 || dwProvType > 999 || pdwReserved != NULL)
  3173. {
  3174. SetLastError(ERROR_INVALID_PARAMETER);
  3175. goto Ret;
  3176. }
  3177. if ((dwFlags & ~(CRYPT_MACHINE_DEFAULT | CRYPT_USER_DEFAULT)) ||
  3178. ((dwFlags & CRYPT_MACHINE_DEFAULT) && (dwFlags & CRYPT_USER_DEFAULT)))
  3179. {
  3180. SetLastError((DWORD)NTE_BAD_FLAGS);
  3181. goto Ret;
  3182. }
  3183. //
  3184. // We no longer look for a User default, but instead treat the USER_
  3185. // and MACHINE_ flags as identical, and only look in HKLM.
  3186. //
  3187. if ((pszValue = (CHAR *) LocalAlloc(LMEM_ZEROINIT,
  3188. strlen(szmachinetype) + 5 + 1)) == NULL)
  3189. {
  3190. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3191. goto Ret;
  3192. }
  3193. strcpy(pszValue, szmachinetype);
  3194. __ltoa(dwProvType, typebuf);
  3195. strcat(pszValue, &typebuf[5]);
  3196. if ((err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3197. (const char *) pszValue,
  3198. 0L, KEY_READ, &hRegKey)) != ERROR_SUCCESS)
  3199. {
  3200. SetLastError(ERROR_INVALID_PARAMETER);
  3201. goto Ret;
  3202. }
  3203. if ((err = RegQueryValueEx(hRegKey, "Name", 0L, &dwValType,
  3204. NULL,
  3205. &cbProvName)) != ERROR_SUCCESS)
  3206. {
  3207. SetLastError(ERROR_INVALID_PARAMETER);
  3208. goto Ret;
  3209. }
  3210. if (NULL == pszProvName)
  3211. {
  3212. *pcbProvName = cbProvName;
  3213. fRet = CRYPT_SUCCEED;
  3214. goto Ret;
  3215. }
  3216. if (cbProvName > *pcbProvName)
  3217. {
  3218. *pcbProvName = cbProvName;
  3219. SetLastError(ERROR_MORE_DATA);
  3220. goto Ret;
  3221. }
  3222. if ((err = RegQueryValueEx(hRegKey, "Name", 0L, &dwValType,
  3223. (BYTE*)pszProvName,
  3224. &cbProvName)) != ERROR_SUCCESS)
  3225. {
  3226. SetLastError(ERROR_INVALID_PARAMETER);
  3227. goto Ret;
  3228. }
  3229. *pcbProvName = cbProvName;
  3230. }
  3231. __except ( CapiExceptionFilter )
  3232. {
  3233. SetLastError(ERROR_INVALID_PARAMETER);
  3234. goto Ret;
  3235. }
  3236. fRet = CRYPT_SUCCEED;
  3237. Ret:
  3238. if (hRegKey)
  3239. RegCloseKey(hRegKey);
  3240. if (pszValue)
  3241. LocalFree(pszValue);
  3242. return fRet;
  3243. }
  3244. /*
  3245. - CryptEnumProviderTypesW
  3246. -
  3247. * Purpose:
  3248. * Enumerate the provider types.
  3249. *
  3250. * Parameters:
  3251. * IN dwIndex - Index to the provider types to enumerate
  3252. * IN pdwReserved - Reserved for future use
  3253. * IN dwFlags - Flags parameter
  3254. * OUT pdwProvType - Pointer to the provider type
  3255. * OUT pszTypeName - Name of the enumerated provider type
  3256. * IN OUT pcbTypeName - Length of the enumerated provider type
  3257. *
  3258. * Returns:
  3259. * BOOL
  3260. * Use get extended error information use GetLastError
  3261. */
  3262. WINADVAPI
  3263. BOOL
  3264. WINAPI CryptEnumProviderTypesW(
  3265. IN DWORD dwIndex,
  3266. IN DWORD *pdwReserved,
  3267. IN DWORD dwFlags,
  3268. OUT DWORD *pdwProvType,
  3269. OUT LPWSTR pszTypeName,
  3270. IN OUT DWORD *pcbTypeName
  3271. )
  3272. {
  3273. ANSI_STRING AnsiString;
  3274. UNICODE_STRING UnicodeString;
  3275. LPSTR pszTmpTypeName = NULL;
  3276. DWORD cbTmpTypeName = 0;
  3277. NTSTATUS Status;
  3278. BOOL fRet = CRYPT_FAILED;
  3279. memset(&UnicodeString, 0, sizeof(UnicodeString));
  3280. __try
  3281. {
  3282. memset(&AnsiString, 0, sizeof(AnsiString));
  3283. if (!CryptEnumProviderTypesA(dwIndex,
  3284. pdwReserved,
  3285. dwFlags,
  3286. pdwProvType,
  3287. NULL,
  3288. &cbTmpTypeName))
  3289. goto Ret;
  3290. if (NULL == (pszTmpTypeName = LocalAlloc(LMEM_ZEROINIT, cbTmpTypeName)))
  3291. {
  3292. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3293. goto Ret;
  3294. }
  3295. if (!CryptEnumProviderTypesA(dwIndex,
  3296. pdwReserved,
  3297. dwFlags,
  3298. pdwProvType,
  3299. pszTmpTypeName,
  3300. &cbTmpTypeName))
  3301. goto Ret;
  3302. if (0 != cbTmpTypeName)
  3303. {
  3304. RtlInitAnsiString(&AnsiString, pszTmpTypeName);
  3305. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  3306. if ( !NT_SUCCESS(Status))
  3307. {
  3308. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3309. goto Ret;
  3310. }
  3311. // check if caller is asking for length, in addition the name of the provider
  3312. // may not be available, in this case a name length of 0 is returned
  3313. if ((NULL == pszTypeName) || (0 == cbTmpTypeName))
  3314. {
  3315. *pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
  3316. fRet = CRYPT_SUCCEED;
  3317. goto Ret;
  3318. }
  3319. if (*pcbTypeName < UnicodeString.Length + sizeof(WCHAR))
  3320. {
  3321. *pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
  3322. SetLastError(ERROR_MORE_DATA);
  3323. goto Ret;
  3324. }
  3325. *pcbTypeName = UnicodeString.Length + sizeof(WCHAR);
  3326. memset(pszTypeName, 0, *pcbTypeName);
  3327. memcpy(pszTypeName, UnicodeString.Buffer, UnicodeString.Length);
  3328. }
  3329. }
  3330. __except ( CapiExceptionFilter )
  3331. {
  3332. SetLastError(ERROR_INVALID_PARAMETER);
  3333. goto Ret;
  3334. }
  3335. fRet = CRYPT_SUCCEED;
  3336. Ret:
  3337. if (UnicodeString.Buffer)
  3338. RtlFreeUnicodeString(&UnicodeString);
  3339. if (pszTmpTypeName)
  3340. LocalFree(pszTmpTypeName);
  3341. return fRet;
  3342. }
  3343. /*
  3344. - CryptEnumProviderTypesA
  3345. -
  3346. * Purpose:
  3347. * Enumerate the provider types.
  3348. *
  3349. * Parameters:
  3350. * IN dwIndex - Index to the provider types to enumerate
  3351. * IN pdwReserved - Reserved for future use
  3352. * IN dwFlags - Flags parameter
  3353. * OUT pdwProvType - Pointer to the provider type
  3354. * OUT pszTypeName - Name of the enumerated provider type
  3355. * IN OUT pcbTypeName - Length of the enumerated provider type
  3356. *
  3357. * Returns:
  3358. * BOOL
  3359. * Use get extended error information use GetLastError
  3360. */
  3361. WINADVAPI
  3362. BOOL
  3363. WINAPI CryptEnumProviderTypesA(
  3364. IN DWORD dwIndex,
  3365. IN DWORD *pdwReserved,
  3366. IN DWORD dwFlags,
  3367. OUT DWORD *pdwProvType,
  3368. OUT LPSTR pszTypeName,
  3369. IN OUT DWORD *pcbTypeName
  3370. )
  3371. {
  3372. HKEY hRegKey = 0;
  3373. HKEY hTypeKey = 0;
  3374. LONG err;
  3375. CHAR *pszRegKeyName = NULL;
  3376. DWORD cbClass;
  3377. FILETIME ft;
  3378. CHAR rgcType[] = {'T', 'y', 'p', 'e', ' '};
  3379. LPSTR pszValue;
  3380. long Type;
  3381. DWORD cSubKeys;
  3382. DWORD cbMaxKeyName;
  3383. DWORD cbMaxClass;
  3384. DWORD cValues;
  3385. DWORD cbMaxValName;
  3386. DWORD cbMaxValData;
  3387. DWORD cbTmpTypeName = 0;
  3388. DWORD dwValType;
  3389. BOOL fRet = CRYPT_FAILED;
  3390. __try
  3391. {
  3392. if (NULL != pdwReserved)
  3393. {
  3394. SetLastError(ERROR_INVALID_PARAMETER);
  3395. goto Ret;
  3396. }
  3397. if (0 != dwFlags)
  3398. {
  3399. SetLastError((DWORD)NTE_BAD_FLAGS);
  3400. goto Ret;
  3401. }
  3402. if (ERROR_SUCCESS != (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3403. (const char *) szprovidertypes,
  3404. 0L,
  3405. KEY_READ,
  3406. &hRegKey)))
  3407. {
  3408. SetLastError((DWORD)NTE_FAIL);
  3409. goto Ret;
  3410. }
  3411. if (ERROR_SUCCESS != (err = RegQueryInfoKey(hRegKey,
  3412. NULL,
  3413. NULL,
  3414. NULL,
  3415. &cSubKeys,
  3416. &cbMaxKeyName,
  3417. &cbMaxClass,
  3418. &cValues,
  3419. &cbMaxValName,
  3420. &cbMaxValData,
  3421. NULL,
  3422. &ft)))
  3423. {
  3424. SetLastError((DWORD)NTE_FAIL);
  3425. goto Ret;
  3426. }
  3427. cbMaxKeyName += sizeof(CHAR);
  3428. if (NULL == (pszRegKeyName = LocalAlloc(LMEM_ZEROINIT, cbMaxKeyName)))
  3429. {
  3430. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3431. goto Ret;
  3432. }
  3433. if (ERROR_SUCCESS != (err = RegEnumKeyEx(hRegKey,
  3434. dwIndex, pszRegKeyName, &cbMaxKeyName, NULL,
  3435. NULL, &cbClass, &ft)))
  3436. {
  3437. if (ERROR_NO_MORE_ITEMS == err)
  3438. {
  3439. SetLastError((DWORD)err);
  3440. }
  3441. else
  3442. {
  3443. SetLastError((DWORD)NTE_FAIL);
  3444. }
  3445. goto Ret;
  3446. }
  3447. if (memcmp(pszRegKeyName, rgcType, sizeof(rgcType)))
  3448. {
  3449. SetLastError((DWORD)NTE_FAIL);
  3450. goto Ret;
  3451. }
  3452. pszValue = pszRegKeyName + sizeof(rgcType);
  3453. if (0 == (Type = atol(pszValue)))
  3454. {
  3455. SetLastError((DWORD)NTE_FAIL);
  3456. goto Ret;
  3457. }
  3458. *pdwProvType = (DWORD)Type;
  3459. // check for the type name
  3460. if (ERROR_SUCCESS != (err = RegOpenKeyEx(hRegKey,
  3461. (const char *)pszRegKeyName,
  3462. 0L,
  3463. KEY_READ,
  3464. &hTypeKey)))
  3465. {
  3466. SetLastError((DWORD)NTE_FAIL);
  3467. goto Ret;
  3468. }
  3469. if ((err = RegQueryValueEx(hTypeKey, "TypeName", 0L, &dwValType,
  3470. NULL, &cbTmpTypeName)) != ERROR_SUCCESS)
  3471. {
  3472. fRet = CRYPT_SUCCEED;
  3473. goto Ret;
  3474. }
  3475. if (NULL == pszTypeName)
  3476. {
  3477. *pcbTypeName = cbTmpTypeName;
  3478. fRet = CRYPT_SUCCEED;
  3479. goto Ret;
  3480. }
  3481. else if (*pcbTypeName < cbTmpTypeName)
  3482. {
  3483. *pcbTypeName = cbTmpTypeName;
  3484. SetLastError(ERROR_MORE_DATA);
  3485. goto Ret;
  3486. }
  3487. if ((err = RegQueryValueEx(hTypeKey, "TypeName", 0L, &dwValType,
  3488. (BYTE*)pszTypeName, &cbTmpTypeName)) != ERROR_SUCCESS)
  3489. {
  3490. SetLastError(ERROR_INVALID_PARAMETER);
  3491. goto Ret;
  3492. }
  3493. *pcbTypeName = cbTmpTypeName;
  3494. }
  3495. __except ( CapiExceptionFilter )
  3496. {
  3497. SetLastError(ERROR_INVALID_PARAMETER);
  3498. goto Ret;
  3499. }
  3500. fRet = CRYPT_SUCCEED;
  3501. Ret:
  3502. if (hRegKey)
  3503. RegCloseKey(hRegKey);
  3504. if (hTypeKey)
  3505. RegCloseKey(hTypeKey);
  3506. if (pszRegKeyName)
  3507. LocalFree(pszRegKeyName);
  3508. return fRet;
  3509. }
  3510. /*
  3511. - CryptEnumProvidersW
  3512. -
  3513. * Purpose:
  3514. * Enumerate the providers.
  3515. *
  3516. * Parameters:
  3517. * IN dwIndex - Index to the providers to enumerate
  3518. * IN pdwReserved - Reserved for future use
  3519. * IN dwFlags - Flags parameter
  3520. * OUT pdwProvType - The type of the provider
  3521. * OUT pszProvName - Name of the enumerated provider
  3522. * IN OUT pcbProvName - Length of the enumerated provider
  3523. *
  3524. * Returns:
  3525. * BOOL
  3526. * Use get extended error information use GetLastError
  3527. */
  3528. WINADVAPI
  3529. BOOL
  3530. WINAPI CryptEnumProvidersW(
  3531. IN DWORD dwIndex,
  3532. IN DWORD *pdwReserved,
  3533. IN DWORD dwFlags,
  3534. OUT DWORD *pdwProvType,
  3535. OUT LPWSTR pszProvName,
  3536. IN OUT DWORD *pcbProvName
  3537. )
  3538. {
  3539. ANSI_STRING AnsiString;
  3540. UNICODE_STRING UnicodeString;
  3541. LPSTR pszTmpProvName = NULL;
  3542. DWORD cbTmpProvName;
  3543. NTSTATUS Status;
  3544. BOOL fRet = CRYPT_FAILED;
  3545. memset(&UnicodeString, 0, sizeof(UnicodeString));
  3546. __try
  3547. {
  3548. memset(&AnsiString, 0, sizeof(AnsiString));
  3549. if (!CryptEnumProvidersA(dwIndex,
  3550. pdwReserved,
  3551. dwFlags,
  3552. pdwProvType,
  3553. NULL,
  3554. &cbTmpProvName))
  3555. goto Ret;
  3556. if (NULL == (pszTmpProvName = LocalAlloc(LMEM_ZEROINIT, cbTmpProvName)))
  3557. {
  3558. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3559. goto Ret;
  3560. }
  3561. if (!CryptEnumProvidersA(dwIndex,
  3562. pdwReserved,
  3563. dwFlags,
  3564. pdwProvType,
  3565. pszTmpProvName,
  3566. &cbTmpProvName))
  3567. goto Ret;
  3568. RtlInitAnsiString(&AnsiString, pszTmpProvName);
  3569. Status = RtlAnsiStringToUnicodeString(&UnicodeString, &AnsiString, TRUE);
  3570. if ( !NT_SUCCESS(Status))
  3571. {
  3572. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3573. goto Ret;
  3574. }
  3575. if (NULL == pszProvName)
  3576. {
  3577. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3578. fRet = CRYPT_SUCCEED;
  3579. goto Ret;
  3580. }
  3581. if (*pcbProvName < UnicodeString.Length + sizeof(WCHAR))
  3582. {
  3583. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3584. SetLastError(ERROR_MORE_DATA);
  3585. goto Ret;
  3586. }
  3587. *pcbProvName = UnicodeString.Length + sizeof(WCHAR);
  3588. memset(pszProvName, 0, *pcbProvName);
  3589. memcpy(pszProvName, UnicodeString.Buffer, UnicodeString.Length);
  3590. }
  3591. __except ( CapiExceptionFilter )
  3592. {
  3593. SetLastError(ERROR_INVALID_PARAMETER);
  3594. goto Ret;
  3595. }
  3596. fRet = CRYPT_SUCCEED;
  3597. Ret:
  3598. if (UnicodeString.Buffer)
  3599. RtlFreeUnicodeString(&UnicodeString);
  3600. if (pszTmpProvName)
  3601. LocalFree(pszTmpProvName);
  3602. return fRet;
  3603. }
  3604. /*
  3605. - CryptEnumProvidersA
  3606. -
  3607. * Purpose:
  3608. * Enumerate the providers.
  3609. *
  3610. * Parameters:
  3611. * IN dwIndex - Index to the providers to enumerate
  3612. * IN pdwReserved - Reserved for future use
  3613. * IN dwFlags - Flags parameter
  3614. * OUT pdwProvType - The type of the provider
  3615. * OUT pszProvName - Name of the enumerated provider
  3616. * IN OUT pcbProvName - Length of the enumerated provider
  3617. *
  3618. * Returns:
  3619. * BOOL
  3620. * Use get extended error information use GetLastError
  3621. */
  3622. WINADVAPI
  3623. BOOL
  3624. WINAPI CryptEnumProvidersA(
  3625. IN DWORD dwIndex,
  3626. IN DWORD *pdwReserved,
  3627. IN DWORD dwFlags,
  3628. OUT DWORD *pdwProvType,
  3629. OUT LPSTR pszProvName,
  3630. IN OUT DWORD *pcbProvName
  3631. )
  3632. {
  3633. HKEY hRegKey = 0;
  3634. HKEY hProvRegKey = 0;
  3635. LONG err;
  3636. DWORD cbClass;
  3637. FILETIME ft;
  3638. DWORD dwKeyType;
  3639. DWORD cbProvType;
  3640. DWORD dw;
  3641. DWORD cSubKeys;
  3642. DWORD cbMaxKeyName;
  3643. DWORD cbMaxClass;
  3644. DWORD cValues;
  3645. DWORD cbMaxValName;
  3646. DWORD cbMaxValData;
  3647. LPSTR pszTmpProvName = NULL;
  3648. DWORD cbTmpProvName;
  3649. BOOL fRet = CRYPT_FAILED;
  3650. __try
  3651. {
  3652. if (NULL != pdwReserved)
  3653. {
  3654. SetLastError(ERROR_INVALID_PARAMETER);
  3655. goto Ret;
  3656. }
  3657. if (0 != dwFlags)
  3658. {
  3659. SetLastError((DWORD)NTE_BAD_FLAGS);
  3660. goto Ret;
  3661. }
  3662. if (ERROR_SUCCESS != (err = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  3663. (const char *) szenumproviders,
  3664. 0L, KEY_READ, &hRegKey)))
  3665. {
  3666. SetLastError((DWORD)NTE_FAIL);
  3667. goto Ret;
  3668. }
  3669. if (ERROR_SUCCESS != (err = RegQueryInfoKey(hRegKey,
  3670. NULL,
  3671. NULL,
  3672. NULL,
  3673. &cSubKeys,
  3674. &cbMaxKeyName,
  3675. &cbMaxClass,
  3676. &cValues,
  3677. &cbMaxValName,
  3678. &cbMaxValData,
  3679. NULL,
  3680. &ft)))
  3681. {
  3682. SetLastError((DWORD)NTE_FAIL);
  3683. goto Ret;
  3684. }
  3685. cbMaxKeyName += sizeof(CHAR);
  3686. if (NULL == (pszTmpProvName = LocalAlloc(LMEM_ZEROINIT, cbMaxKeyName)))
  3687. {
  3688. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3689. goto Ret;
  3690. }
  3691. if (ERROR_SUCCESS != (err = RegEnumKeyEx(hRegKey, dwIndex, pszTmpProvName,
  3692. &cbMaxKeyName, NULL,
  3693. NULL, &cbClass, &ft)))
  3694. {
  3695. SetLastError((DWORD)err);
  3696. goto Ret;
  3697. }
  3698. if (ERROR_SUCCESS != (err = RegOpenKeyEx(hRegKey,
  3699. (const char *) pszTmpProvName,
  3700. 0L, KEY_READ, &hProvRegKey)))
  3701. {
  3702. SetLastError((DWORD)NTE_FAIL);
  3703. goto Ret;
  3704. }
  3705. cbProvType = sizeof(dw);
  3706. if (ERROR_SUCCESS != (err = RegQueryValueEx(hProvRegKey,
  3707. (const char *) "Type",
  3708. NULL, &dwKeyType, (BYTE*)&dw,
  3709. &cbProvType)))
  3710. {
  3711. SetLastError((DWORD)NTE_FAIL);
  3712. goto Ret;
  3713. }
  3714. *pdwProvType = dw;
  3715. cbTmpProvName = strlen(pszTmpProvName) + sizeof(CHAR);
  3716. if (NULL != pszProvName)
  3717. {
  3718. if (*pcbProvName < cbTmpProvName)
  3719. {
  3720. *pcbProvName = cbTmpProvName;
  3721. SetLastError(ERROR_MORE_DATA);
  3722. goto Ret;
  3723. }
  3724. strcpy(pszProvName, pszTmpProvName);
  3725. }
  3726. *pcbProvName = cbTmpProvName;
  3727. }
  3728. __except ( CapiExceptionFilter )
  3729. {
  3730. SetLastError(ERROR_INVALID_PARAMETER);
  3731. goto Ret;
  3732. }
  3733. fRet = CRYPT_SUCCEED;
  3734. Ret:
  3735. if (pszTmpProvName)
  3736. LocalFree(pszTmpProvName);
  3737. if (hRegKey)
  3738. RegCloseKey(hRegKey);
  3739. if (hProvRegKey)
  3740. RegCloseKey(hProvRegKey);
  3741. return fRet;
  3742. }
  3743. BOOL EnterProviderCritSec(IN PVTableStruc pVTable)
  3744. {
  3745. __try
  3746. {
  3747. if (pVTable->Version != TABLEPROV)
  3748. {
  3749. SetLastError(ERROR_INVALID_PARAMETER);
  3750. goto Try_Error_Return;
  3751. }
  3752. InterlockedIncrement((LPLONG)&pVTable->Inuse);
  3753. }
  3754. __except ( CapiExceptionFilter )
  3755. {
  3756. SetLastError(ERROR_INVALID_PARAMETER);
  3757. goto Try_Error_Return;
  3758. }
  3759. return(CRYPT_SUCCEED);
  3760. Try_Error_Return:
  3761. return(CRYPT_FAILED);
  3762. }
  3763. void LeaveProviderCritSec(IN PVTableStruc pVTable)
  3764. {
  3765. InterlockedDecrement((LPLONG)&pVTable->Inuse);
  3766. }
  3767. BOOL EnterKeyCritSec(IN PVKeyStruc pVKey)
  3768. {
  3769. __try
  3770. {
  3771. if (pVKey->Version != TABLEKEY)
  3772. {
  3773. SetLastError(ERROR_INVALID_PARAMETER);
  3774. goto Try_Error_Return;
  3775. }
  3776. InterlockedIncrement((LPLONG)&pVKey->Inuse);
  3777. }
  3778. __except ( CapiExceptionFilter )
  3779. {
  3780. SetLastError(ERROR_INVALID_PARAMETER);
  3781. goto Try_Error_Return;
  3782. }
  3783. return(CRYPT_SUCCEED);
  3784. Try_Error_Return:
  3785. return(CRYPT_FAILED);
  3786. }
  3787. void LeaveKeyCritSec(IN PVKeyStruc pVKey)
  3788. {
  3789. InterlockedDecrement((LPLONG)&pVKey->Inuse);
  3790. }
  3791. BOOL EnterHashCritSec(IN PVHashStruc pVHash)
  3792. {
  3793. __try
  3794. {
  3795. if (pVHash->Version != TABLEHASH)
  3796. {
  3797. SetLastError(ERROR_INVALID_PARAMETER);
  3798. goto Try_Error_Return;
  3799. }
  3800. InterlockedIncrement((LPLONG)&pVHash->Inuse);
  3801. }
  3802. __except ( CapiExceptionFilter )
  3803. {
  3804. SetLastError(ERROR_INVALID_PARAMETER);
  3805. goto Try_Error_Return;
  3806. }
  3807. return(CRYPT_SUCCEED);
  3808. Try_Error_Return:
  3809. return(CRYPT_FAILED);
  3810. }
  3811. void LeaveHashCritSec(IN PVHashStruc pVHash)
  3812. {
  3813. InterlockedDecrement((LPLONG)&pVHash->Inuse);
  3814. }
  3815. BOOL BuildVKey(IN PVKeyStruc *ppVKey,
  3816. IN PVTableStruc pVTable)
  3817. {
  3818. DWORD bufsize;
  3819. PVKeyStruc pVKey;
  3820. bufsize = sizeof(VKeyStruc);
  3821. if ((pVKey = (PVKeyStruc) LocalAlloc(LMEM_ZEROINIT,
  3822. (UINT) bufsize)) == NULL)
  3823. {
  3824. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3825. return(CRYPT_FAILED);
  3826. }
  3827. pVKey->FuncGenKey = pVTable->FuncGenKey;
  3828. pVKey->FuncDeriveKey = pVTable->FuncDeriveKey;
  3829. pVKey->FuncDestroyKey = pVTable->FuncDestroyKey;
  3830. pVKey->FuncSetKeyParam = pVTable->FuncSetKeyParam;
  3831. pVKey->FuncGetKeyParam = pVTable->FuncGetKeyParam;
  3832. pVKey->FuncExportKey = pVTable->FuncExportKey;
  3833. pVKey->FuncImportKey = pVTable->FuncImportKey;
  3834. pVKey->FuncEncrypt = pVTable->FuncEncrypt;
  3835. pVKey->FuncDecrypt = pVTable->FuncDecrypt;
  3836. pVKey->OptionalFuncDuplicateKey = pVTable->OptionalFuncDuplicateKey;
  3837. pVKey->hProv = pVTable->hProv;
  3838. *ppVKey = pVKey;
  3839. return(CRYPT_SUCCEED);
  3840. }
  3841. BOOL BuildVHash(
  3842. IN PVHashStruc *ppVHash,
  3843. IN PVTableStruc pVTable
  3844. )
  3845. {
  3846. DWORD bufsize;
  3847. PVHashStruc pVHash;
  3848. bufsize = sizeof(VHashStruc);
  3849. if ((pVHash = (PVHashStruc) LocalAlloc(LMEM_ZEROINIT, (UINT) bufsize)) == NULL)
  3850. {
  3851. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  3852. return(CRYPT_FAILED);
  3853. }
  3854. pVHash->FuncCreateHash = pVTable->FuncCreateHash;
  3855. pVHash->FuncHashData = pVTable->FuncHashData;
  3856. pVHash->FuncHashSessionKey = pVTable->FuncHashSessionKey;
  3857. pVHash->FuncDestroyHash = pVTable->FuncDestroyHash;
  3858. pVHash->FuncSignHash = pVTable->FuncSignHash;
  3859. pVHash->FuncVerifySignature = pVTable->FuncVerifySignature;
  3860. pVHash->FuncGetHashParam = pVTable->FuncGetHashParam;
  3861. pVHash->FuncSetHashParam = pVTable->FuncSetHashParam;
  3862. pVHash->OptionalFuncDuplicateHash = pVTable->OptionalFuncDuplicateHash;
  3863. pVHash->hProv = (HCRYPTPROV)pVTable;
  3864. *ppVHash = pVHash;
  3865. return(CRYPT_SUCCEED);
  3866. }
  3867. #define RC4_KEYSIZE 5
  3868. void EncryptKey(BYTE *pdata, DWORD size, BYTE val)
  3869. {
  3870. RC4_KEYSTRUCT key;
  3871. BYTE RealKey[RC4_KEYSIZE] = {0xa2, 0x17, 0x9c, 0x98, 0xca};
  3872. DWORD index;
  3873. for (index = 0; index < RC4_KEYSIZE; index++)
  3874. {
  3875. RealKey[index] ^= val;
  3876. }
  3877. rc4_key(&key, RC4_KEYSIZE, RealKey);
  3878. rc4(&key, size, pdata);
  3879. }
  3880. void MD5HashData(
  3881. BYTE *pb,
  3882. DWORD cb,
  3883. BYTE *pbHash
  3884. )
  3885. {
  3886. MD5_CTX HashState;
  3887. MD5Init(&HashState);
  3888. __try
  3889. {
  3890. MD5Update(&HashState, pb, cb);
  3891. } __except ( CapiExceptionFilter )
  3892. {
  3893. SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
  3894. return;
  3895. }
  3896. // Finish the hash
  3897. MD5Final(&HashState);
  3898. memcpy(pbHash, HashState.digest, 16);
  3899. }
  3900. BOOL CheckSignature(
  3901. BYTE *pbKey,
  3902. DWORD cbKey,
  3903. BYTE *pbSig,
  3904. DWORD cbSig,
  3905. BYTE *pbHash,
  3906. BOOL fUnknownLen)
  3907. {
  3908. BYTE rgbResult[KEYSIZE1024];
  3909. BYTE rgbSig[KEYSIZE1024];
  3910. BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  3911. BYTE rgbKeyHash[16];
  3912. BYTE *pbSecondKey;
  3913. DWORD cbSecondKey;
  3914. BYTE *pbKeySig;
  3915. PSECOND_TIER_SIG pSecondTierSig;
  3916. LPBSAFE_PUB_KEY pTmp;
  3917. BOOL fRet = FALSE;
  3918. memset(rgbResult, 0, KEYSIZE1024);
  3919. memset(rgbSig, 0, KEYSIZE1024);
  3920. // just check the straight signature if version is 1
  3921. pTmp = (LPBSAFE_PUB_KEY)pbKey;
  3922. // check if sig length is the same as the key length
  3923. if (fUnknownLen || (cbSig == pTmp->keylen))
  3924. {
  3925. memcpy(rgbSig, pbSig, pTmp->keylen);
  3926. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  3927. if (RtlEqualMemory(pbHash, rgbResult, 16) &&
  3928. rgbResult[cbKey-1] == 0 &&
  3929. rgbResult[cbKey-2] == 1 &&
  3930. rgbResult[16] == 0 &&
  3931. rgbResult[17] == 0xFF)
  3932. {
  3933. fRet = TRUE;
  3934. goto Ret;
  3935. }
  3936. }
  3937. // check the the second tier signature if the magic equals 2
  3938. pSecondTierSig = (PSECOND_TIER_SIG)pbSig;
  3939. if (0x00000002 != pSecondTierSig->dwMagic)
  3940. goto Ret;
  3941. if (0x31415352 != pSecondTierSig->Pub.magic)
  3942. goto Ret;
  3943. if (pSecondTierSig->Pub.keylen > KEYSIZE1024)
  3944. goto Ret;
  3945. // assign the pointers
  3946. cbSecondKey = sizeof(BSAFE_PUB_KEY) + pSecondTierSig->Pub.keylen;
  3947. pbSecondKey = pbSig + (sizeof(SECOND_TIER_SIG) - sizeof(BSAFE_PUB_KEY));
  3948. pbKeySig = pbSecondKey + cbSecondKey;
  3949. // hash the second tier key
  3950. MD5HashData(pbSecondKey, cbSecondKey, rgbKeyHash);
  3951. // Decrypt the signature data on the second tier key
  3952. memset(rgbResult, 0, sizeof(rgbResult));
  3953. memset(rgbSig, 0, sizeof(rgbSig));
  3954. if (pSecondTierSig->cbSig > sizeof(rgbSig))
  3955. goto Ret;
  3956. memcpy(rgbSig, pbKeySig, pSecondTierSig->cbSig);
  3957. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  3958. if ((FALSE == RtlEqualMemory(rgbKeyHash, rgbResult, 16)) ||
  3959. rgbResult[cbKey-1] != 0 ||
  3960. rgbResult[cbKey-2] != 1 ||
  3961. rgbResult[16] != 0 ||
  3962. rgbResult[17] != 0)
  3963. {
  3964. goto Ret;
  3965. }
  3966. // Decrypt the signature data on the CSP
  3967. memset(rgbResult, 0, sizeof(rgbResult));
  3968. memset(rgbSig, 0, sizeof(rgbSig));
  3969. memset(rgbKey, 0, sizeof(rgbKey));
  3970. memcpy(rgbSig, pbKeySig + pSecondTierSig->cbSig, pSecondTierSig->cbSig);
  3971. memcpy(rgbKey, pbSecondKey, cbSecondKey);
  3972. pTmp = (LPBSAFE_PUB_KEY)rgbKey;
  3973. BSafeEncPublic(pTmp, rgbSig, rgbResult);
  3974. if (RtlEqualMemory(pbHash, rgbResult, 16) &&
  3975. rgbResult[pTmp->keylen-1] == 0 &&
  3976. rgbResult[pTmp->keylen-2] == 1 &&
  3977. rgbResult[16] == 0)
  3978. {
  3979. fRet = TRUE;
  3980. }
  3981. Ret:
  3982. return fRet;
  3983. }
  3984. // Given hInst, allocs and returns pointers to signature pulled from
  3985. // resource
  3986. BOOL GetCryptSigResourcePtr(
  3987. HMODULE hInst,
  3988. BYTE **ppbRsrcSig,
  3989. DWORD *pcbRsrcSig
  3990. )
  3991. {
  3992. HRSRC hRsrc;
  3993. BOOL fRet = FALSE;
  3994. // Nab resource handle for our signature
  3995. if (NULL == (hRsrc = FindResource(hInst, OLD_CRYPT_SIG_RESOURCE_NUMBER,
  3996. RT_RCDATA)))
  3997. goto Ret;
  3998. // get a pointer to the actual signature data
  3999. if (NULL == (*ppbRsrcSig = (PBYTE)LoadResource(hInst, hRsrc)))
  4000. goto Ret;
  4001. // determine the size of the resource
  4002. if (0 == (*pcbRsrcSig = SizeofResource(hInst, hRsrc)))
  4003. goto Ret;
  4004. fRet = TRUE;
  4005. Ret:
  4006. return fRet;
  4007. }
  4008. #define CSP_TO_BE_HASHED_CHUNK 4096
  4009. // Given hFile, reads the specified number of bytes (cbToBeHashed) from the file
  4010. // and hashes these bytes. The function does this in chunks.
  4011. BOOL HashBytesOfFile(
  4012. IN HANDLE hFile,
  4013. IN DWORD cbToBeHashed,
  4014. IN OUT MD5_CTX *pMD5Hash
  4015. )
  4016. {
  4017. BYTE rgbChunk[CSP_TO_BE_HASHED_CHUNK];
  4018. DWORD cbRemaining = cbToBeHashed;
  4019. DWORD cbToRead;
  4020. DWORD dwBytesRead;
  4021. BOOL fRet = FALSE;
  4022. //
  4023. // loop over the file for the specified number of bytes
  4024. // updating the hash as we go.
  4025. //
  4026. while (cbRemaining > 0)
  4027. {
  4028. if (cbRemaining < CSP_TO_BE_HASHED_CHUNK)
  4029. cbToRead = cbRemaining;
  4030. else
  4031. cbToRead = CSP_TO_BE_HASHED_CHUNK;
  4032. if(!ReadFile(hFile, rgbChunk, cbToRead, &dwBytesRead, NULL))
  4033. goto Ret;
  4034. if (dwBytesRead != cbToRead)
  4035. goto Ret;
  4036. MD5Update(pMD5Hash, rgbChunk, dwBytesRead);
  4037. cbRemaining -= cbToRead;
  4038. }
  4039. fRet = TRUE;
  4040. Ret:
  4041. return fRet;
  4042. }
  4043. BOOL HashTheFile(
  4044. LPCWSTR pszImage,
  4045. DWORD cbImage,
  4046. BYTE **ppbSig,
  4047. DWORD *pcbSig,
  4048. BYTE *pbHash
  4049. )
  4050. {
  4051. HMODULE hInst;
  4052. MEMORY_BASIC_INFORMATION MemInfo;
  4053. BYTE *pbRsrcSig;
  4054. DWORD cbRsrcSig;
  4055. BYTE *pbStart = NULL;
  4056. BYTE *pbZeroSig = NULL;
  4057. MD5_CTX MD5Hash;
  4058. BYTE *pbPostCRC; // pointer to just after CRC
  4059. DWORD cbCRCToSig; // number of bytes from CRC to sig
  4060. DWORD cbPostSig; // size - (already hashed + signature size)
  4061. BYTE *pbPostSig;
  4062. DWORD *pdwSigInFileVer;
  4063. DWORD *pdwCRCOffset;
  4064. DWORD dwCRCOffset;
  4065. DWORD dwZeroCRC = 0;
  4066. HANDLE File = INVALID_HANDLE_VALUE ;
  4067. HANDLE hMapping = NULL;
  4068. BOOL fRet = FALSE;
  4069. memset(&MD5Hash, 0, sizeof(MD5Hash));
  4070. memset(&MemInfo, 0, sizeof(MemInfo));
  4071. // Load the file
  4072. File = CreateFileW(
  4073. pszImage,
  4074. GENERIC_READ,
  4075. FILE_SHARE_READ,
  4076. NULL,
  4077. OPEN_EXISTING,
  4078. FILE_ATTRIBUTE_NORMAL,
  4079. NULL );
  4080. if ( File == INVALID_HANDLE_VALUE )
  4081. {
  4082. goto Ret ;
  4083. }
  4084. hMapping = CreateFileMapping( File,
  4085. NULL,
  4086. PAGE_READONLY,
  4087. 0,
  4088. 0,
  4089. NULL);
  4090. if(hMapping == NULL)
  4091. {
  4092. goto Ret;
  4093. }
  4094. pbStart = MapViewOfFile(hMapping,
  4095. FILE_MAP_READ,
  4096. 0,
  4097. 0,
  4098. 0);
  4099. if(pbStart == NULL)
  4100. {
  4101. goto Ret;
  4102. }
  4103. // Convert pointer to HMODULE, using the same scheme as
  4104. // LoadLibrary (windows\base\client\module.c).
  4105. hInst = (HMODULE)((ULONG_PTR)pbStart | 0x00000001);
  4106. // the resources signature
  4107. if (!GetCryptSigResourcePtr(hInst, &pbRsrcSig, &cbRsrcSig))
  4108. goto Ret;
  4109. if (cbRsrcSig < (sizeof(DWORD) * 2))
  4110. goto Ret;
  4111. // check the sig in file version and get the CRC offset
  4112. pdwSigInFileVer = (DWORD*)pbRsrcSig;
  4113. pdwCRCOffset = (DWORD*)(pbRsrcSig + sizeof(DWORD));
  4114. dwCRCOffset = *pdwCRCOffset;
  4115. if ((0x00000100 != *pdwSigInFileVer) || (dwCRCOffset > cbImage))
  4116. goto Ret;
  4117. // create a zero byte signature
  4118. if (NULL == (pbZeroSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, cbRsrcSig)))
  4119. goto Ret;
  4120. memcpy(pbZeroSig, pbRsrcSig, sizeof(DWORD) * 2);
  4121. pbPostCRC = pbStart + *pdwCRCOffset + sizeof(DWORD);
  4122. cbCRCToSig = (DWORD)(pbRsrcSig - pbPostCRC);
  4123. pbPostSig = pbRsrcSig + cbRsrcSig;
  4124. cbPostSig = (cbImage - (DWORD)(pbPostSig - pbStart));
  4125. // allocate the real signature and copy the resource sig into the real sig
  4126. *pcbSig = cbRsrcSig - (sizeof(DWORD) * 2);
  4127. if (NULL == (*ppbSig = (BYTE*)LocalAlloc(LMEM_ZEROINIT, *pcbSig)))
  4128. goto Ret;
  4129. memcpy(*ppbSig, pbRsrcSig + (sizeof(DWORD) * 2), *pcbSig);
  4130. // hash over the relevant data
  4131. MD5Init(&MD5Hash);
  4132. // hash up to the CRC
  4133. if (!HashBytesOfFile(File, dwCRCOffset, &MD5Hash))
  4134. goto Ret;
  4135. // pretend CRC is zeroed
  4136. MD5Update(&MD5Hash, (BYTE*)&dwZeroCRC, sizeof(DWORD));
  4137. if (!SetFilePointer(File, sizeof(DWORD), NULL, FILE_CURRENT))
  4138. {
  4139. goto Ret;
  4140. }
  4141. // hash from CRC to sig resource
  4142. if (!HashBytesOfFile(File, cbCRCToSig, &MD5Hash))
  4143. goto Ret;
  4144. // pretend image has zeroed sig
  4145. MD5Update(&MD5Hash, pbZeroSig, cbRsrcSig);
  4146. if (!SetFilePointer(File, cbRsrcSig, NULL, FILE_CURRENT))
  4147. {
  4148. goto Ret;
  4149. }
  4150. // hash after the sig resource
  4151. if (!HashBytesOfFile(File, cbPostSig, &MD5Hash))
  4152. goto Ret;
  4153. // Finish the hash
  4154. MD5Final(&MD5Hash);
  4155. memcpy(pbHash, MD5Hash.digest, MD5DIGESTLEN);
  4156. fRet = TRUE;
  4157. Ret:
  4158. if (pbZeroSig)
  4159. LocalFree(pbZeroSig);
  4160. if(pbStart)
  4161. UnmapViewOfFile(pbStart);
  4162. if(hMapping)
  4163. CloseHandle(hMapping);
  4164. if ( File != INVALID_HANDLE_VALUE )
  4165. {
  4166. CloseHandle( File );
  4167. }
  4168. return fRet;
  4169. }
  4170. /*
  4171. - CheckAllSignatures
  4172. -
  4173. * Purpose:
  4174. * Check signature against all keys
  4175. *
  4176. *
  4177. * Returns:
  4178. * BOOL
  4179. */
  4180. BOOL CheckAllSignatures(
  4181. BYTE *pbSig,
  4182. DWORD cbSig,
  4183. BYTE *pbHash,
  4184. BOOL fUnknownLen
  4185. )
  4186. {
  4187. BYTE rgbKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  4188. BYTE rgbKey2[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  4189. #ifdef MS_INTERNAL_KEY
  4190. BYTE rgbMSKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE1024];
  4191. #endif
  4192. #ifdef TEST_BUILD_EXPONENT
  4193. BYTE rgbTestKey[sizeof(BSAFE_PUB_KEY) + KEYSIZE512];
  4194. #endif
  4195. BOOL fRet = FALSE;
  4196. // decrypt the keys once for each process
  4197. memcpy(rgbKey, (BYTE*)&KEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  4198. EncryptKey(rgbKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 0);
  4199. #ifdef MS_INTERNAL_KEY
  4200. memcpy(rgbMSKey, (BYTE*)&MSKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  4201. EncryptKey(rgbMSKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 1);
  4202. #endif
  4203. memcpy(rgbKey2, (BYTE*)&KEY2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024);
  4204. EncryptKey(rgbKey2, sizeof(BSAFE_PUB_KEY) + KEYSIZE1024, 2);
  4205. #ifdef TEST_BUILD_EXPONENT
  4206. memcpy(rgbTestKey, (BYTE*)&TESTKEY, sizeof(BSAFE_PUB_KEY) + KEYSIZE512);
  4207. EncryptKey(rgbTestKey, sizeof(BSAFE_PUB_KEY) + KEYSIZE512, 3);
  4208. #endif // TEST_BUILD_EXPONENT
  4209. if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbKey, 128, pbSig,
  4210. cbSig, pbHash, fUnknownLen)))
  4211. {
  4212. fRet = TRUE;
  4213. goto Ret;
  4214. }
  4215. #ifdef MS_INTERNAL_KEY
  4216. if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbMSKey, 128, pbSig,
  4217. cbSig, pbHash, fUnknownLen)))
  4218. {
  4219. fRet = TRUE;
  4220. goto Ret;
  4221. }
  4222. #endif
  4223. if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbKey2, 128, pbSig,
  4224. cbSig, pbHash, fUnknownLen)))
  4225. {
  4226. fRet = TRUE;
  4227. goto Ret;
  4228. }
  4229. #ifdef TEST_BUILD_EXPONENT
  4230. if (CRYPT_SUCCEED == (fRet = CheckSignature(rgbTestKey, 64, pbSig,
  4231. cbSig, pbHash, fUnknownLen)))
  4232. {
  4233. fRet = TRUE;
  4234. goto Ret;
  4235. }
  4236. #endif // TEST_BUILD_EXPONENT
  4237. Ret:
  4238. return fRet;
  4239. }
  4240. /*
  4241. - CheckSignatureInFile
  4242. -
  4243. * Purpose:
  4244. * Check signature which is in the resource in the file
  4245. *
  4246. *
  4247. * Parameters:
  4248. * IN pszImage - address of file
  4249. *
  4250. * Returns:
  4251. * BOOL
  4252. */
  4253. BOOL CheckSignatureInFile(
  4254. LPCWSTR pszImage)
  4255. {
  4256. DWORD cbImage;
  4257. BYTE *pbSig = NULL;
  4258. DWORD cbSig;
  4259. BYTE rgbHash[MD5DIGESTLEN];
  4260. BOOL fRet = FALSE;
  4261. WIN32_FILE_ATTRIBUTE_DATA FileData ;
  4262. WCHAR FullName[ MAX_PATH ];
  4263. PWSTR FilePart ;
  4264. SYSTEM_KERNEL_DEBUGGER_INFORMATION KdInfo;
  4265. BYTE rgbMincryptHash[MINCRYPT_MAX_HASH_LEN];
  4266. DWORD cbMincryptHash = MINCRYPT_MAX_HASH_LEN;
  4267. CRYPT_HASH_BLOB HashBlob;
  4268. DWORD dwErr = ERROR_SUCCESS;
  4269. NtQuerySystemInformation(
  4270. SystemKernelDebuggerInformation,
  4271. &KdInfo,
  4272. sizeof(KdInfo),
  4273. NULL);
  4274. // Allow any CSP to load if a Kd is attached
  4275. // and "responsive"
  4276. if ( TRUE == KdInfo.KernelDebuggerEnabled &&
  4277. FALSE == KdInfo.KernelDebuggerNotPresent)
  4278. return TRUE;
  4279. if ( !SearchPathW(NULL,
  4280. pszImage,
  4281. NULL,
  4282. MAX_PATH,
  4283. FullName,
  4284. &FilePart ) )
  4285. {
  4286. goto Ret ;
  4287. }
  4288. //
  4289. // Try new signature check. Use "mincrypt"
  4290. // functionality.
  4291. //
  4292. // Look for valid embedded "signcode" signature
  4293. // in the CSP.
  4294. //
  4295. if (ERROR_SUCCESS == MinCryptVerifySignedFile(
  4296. MINCRYPT_FILE_NAME,
  4297. (PVOID) FullName,
  4298. 0, NULL, NULL, NULL))
  4299. {
  4300. // Valid signature was found.
  4301. return TRUE;
  4302. }
  4303. //
  4304. // The new signcode-style signature checks failed,
  4305. // so revert to legacy resource-based signature check.
  4306. //
  4307. if ( !GetFileAttributesExW( FullName,
  4308. GetFileExInfoStandard,
  4309. &FileData ) )
  4310. {
  4311. goto Ret ;
  4312. }
  4313. if ( FileData.nFileSizeHigh )
  4314. {
  4315. goto Ret ;
  4316. }
  4317. cbImage = FileData.nFileSizeLow ;
  4318. if (!HashTheFile(FullName, cbImage, &pbSig, &cbSig, rgbHash))
  4319. goto Ret;
  4320. // check signature against all public keys
  4321. if (!CheckAllSignatures(pbSig, cbSig, rgbHash, FALSE))
  4322. goto Ret;
  4323. fRet = TRUE;
  4324. Ret:
  4325. if (pbSig)
  4326. LocalFree(pbSig);
  4327. return fRet;
  4328. }
  4329. /*
  4330. - NewVerifyImage
  4331. -
  4332. * Purpose:
  4333. * Check signature of file
  4334. *
  4335. *
  4336. * Parameters:
  4337. * IN lpszImage - address of file
  4338. * IN pSigData - address of signature data
  4339. * IN cbSig - length of signature data
  4340. * IN fUnknownLen - BOOL to tell if length is not passed in
  4341. *
  4342. * Returns:
  4343. * BOOL
  4344. */
  4345. BOOL NewVerifyImage(LPCSTR lpszImage,
  4346. BYTE *pSigData,
  4347. DWORD cbSig,
  4348. BOOL fUnknownLen)
  4349. {
  4350. HFILE hFileProv = HFILE_ERROR;
  4351. DWORD NumBytes;
  4352. DWORD lpdwFileSizeHigh;
  4353. MD5_CTX HashState;
  4354. OFSTRUCT ImageInfoBuf;
  4355. BOOL fRet = CRYPT_FAILED;
  4356. memset(&HashState, 0, sizeof(HashState));
  4357. if (HFILE_ERROR == (hFileProv = OpenFile(lpszImage, &ImageInfoBuf,
  4358. OF_READ)))
  4359. {
  4360. SetLastError((DWORD) NTE_PROV_DLL_NOT_FOUND);
  4361. goto Ret;
  4362. }
  4363. if (0xffffffff == (NumBytes = GetFileSize((HANDLE)IntToPtr(hFileProv),
  4364. &lpdwFileSizeHigh)))
  4365. {
  4366. SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
  4367. goto Ret;
  4368. }
  4369. MD5Init(&HashState);
  4370. if (!HashBytesOfFile((HANDLE)IntToPtr(hFileProv), NumBytes, &HashState))
  4371. {
  4372. SetLastError((DWORD) NTE_SIGNATURE_FILE_BAD);
  4373. goto Ret;
  4374. }
  4375. MD5Final(&HashState);
  4376. // check the signature against all keys
  4377. if (!CheckAllSignatures(pSigData, cbSig, HashState.digest, fUnknownLen))
  4378. {
  4379. SetLastError((DWORD) NTE_BAD_SIGNATURE);
  4380. goto Ret;
  4381. }
  4382. fRet = TRUE;
  4383. Ret:
  4384. if (HFILE_ERROR != hFileProv)
  4385. _lclose(hFileProv);
  4386. return fRet;
  4387. }
  4388. /*
  4389. - CProvVerifyImage
  4390. -
  4391. * Purpose:
  4392. * Check signature of file
  4393. *
  4394. *
  4395. * Parameters:
  4396. * IN lpszImage - address of file
  4397. * IN lpSigData - address of signature data
  4398. *
  4399. * Returns:
  4400. * BOOL
  4401. */
  4402. BOOL CProvVerifyImage(LPCSTR lpszImage,
  4403. BYTE *pSigData)
  4404. {
  4405. UNICODE_STRING String ;
  4406. BOOL Result ;
  4407. if (NULL == pSigData)
  4408. {
  4409. if ( RtlCreateUnicodeStringFromAsciiz( &String, lpszImage ) )
  4410. {
  4411. Result = CheckSignatureInFile( String.Buffer );
  4412. RtlFreeUnicodeString( &String );
  4413. }
  4414. else
  4415. {
  4416. Result = FALSE ;
  4417. }
  4418. }
  4419. else
  4420. {
  4421. Result = NewVerifyImage(lpszImage, pSigData, 0, TRUE);
  4422. }
  4423. return Result;
  4424. }
  4425. /*
  4426. - CPReturnhWnd
  4427. -
  4428. * Purpose:
  4429. * Return a window handle back to a CSP
  4430. *
  4431. *
  4432. * Parameters:
  4433. * OUT phWnd - pointer to a hWnd to return
  4434. *
  4435. * Returns:
  4436. * void
  4437. */
  4438. void CPReturnhWnd(HWND *phWnd)
  4439. {
  4440. __try
  4441. {
  4442. *phWnd = hWnd;
  4443. } __except ( CapiExceptionFilter )
  4444. { ; }
  4445. return;
  4446. }
  4447. static void __ltoa(DWORD val, char *buf)
  4448. {
  4449. char *p; /* pointer to traverse string */
  4450. char *firstdig; /* pointer to first digit */
  4451. char temp; /* temp char */
  4452. unsigned digval; /* value of digit */
  4453. int i;
  4454. p = buf;
  4455. firstdig = p; /* save pointer to first digit */
  4456. for (i = 0; i < 8; i++) {
  4457. digval = (unsigned) (val % 10);
  4458. val /= 10; /* get next digit */
  4459. /* convert to ascii and store */
  4460. *p++ = (char) (digval + '0'); /* a digit */
  4461. }
  4462. /* We now have the digit of the number in the buffer, but in reverse
  4463. order. Thus we reverse them now. */
  4464. *p-- = '\0'; /* terminate string; p points to last digit */
  4465. do {
  4466. temp = *p;
  4467. *p = *firstdig;
  4468. *firstdig = temp; /* swap *p and *firstdig */
  4469. --p;
  4470. ++firstdig; /* advance to next two digits */
  4471. } while (firstdig < p); /* repeat until halfway */
  4472. }