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.

1034 lines
31 KiB

  1. //+-------------------------------------------------------------------------
  2. // Microsoft Windows
  3. //
  4. // Copyright (C) Microsoft Corporation, 1995 - 1999
  5. //
  6. // File: crypttls.cpp
  7. //
  8. // Contents: Crypt Thread Local Storage (TLS) and OssGlobal "world"
  9. // installation and allocation functions
  10. //
  11. // Functions: I_CryptTlsDllMain
  12. // I_CryptAllocTls
  13. // I_CryptFreeTls
  14. // I_CryptGetTls
  15. // I_CryptSetTls
  16. // I_CryptDetachTls
  17. // I_CryptInstallOssGlobal
  18. // I_CryptUninstallOssGlobal
  19. // I_CryptGetOssGlobal
  20. //
  21. // I_CryptInstallAsn1Module
  22. // I_CryptUninstallAsn1Module
  23. // I_CryptGetAsn1Encoder
  24. // I_CryptGetAsn1Decoder
  25. //
  26. // Assumption:
  27. // For PROCESS_ATTACH or THREAD_ATTACH, I_CryptTlsDllMain is called
  28. // first. For PROCESS_DETACH or THREAD_DETACH, I_CryptTlsDllMain
  29. // is called last.
  30. //
  31. // History: 17-Nov-96 philh created
  32. //--------------------------------------------------------------------------
  33. #include "global.hxx"
  34. #include <dbgdef.h>
  35. #include <asn1code.h>
  36. #ifdef STATIC
  37. #undef STATIC
  38. #endif
  39. #define STATIC
  40. // CryptTls Entry types
  41. #define FREE_CRYPTTLS 0
  42. #define USER_CRYPTTLS 1
  43. #define OSS_CRYPTTLS 2
  44. #define ASN1_CRYPTTLS 3
  45. typedef struct _ASN1_TLS_ENTRY {
  46. ASN1encoding_t pEnc;
  47. ASN1decoding_t pDec;
  48. } ASN1_TLS_ENTRY, *PASN1_TLS_ENTRY;
  49. // The following is reallocated and updated for each I_CryptAllocTls or
  50. // I_CryptInstallOssGlobal. For I_CryptAllocTls, dwType is set to
  51. // USER_CRYPTTLS and dwNext is zeroed. For I_CryptInstallOssGlobal, dwType
  52. // is set to OSS_CRYPTTLS and pvCtlTbl is updated with pvCtlTbl.
  53. // For I_CryptFreeTls, dwType is set to FREE_CRYPTTLS and dwNext is
  54. // updated with previous dwFreeProcessTlsHead.
  55. //
  56. // The array is indexed via hCryptTls -1 or hOssGlobal -1.
  57. typedef struct _CRYPTTLS_PROCESS_ENTRY {
  58. DWORD dwType;
  59. union {
  60. void *pvCtlTbl;
  61. ASN1module_t pMod;
  62. // Following is applicable to I_CryptFreeTls'ed entries.
  63. // Its the array index + 1 of the next free entry. A dwNext
  64. // of zero terminates.
  65. DWORD dwNext;
  66. };
  67. } CRYPTTLS_PROCESS_ENTRY, *PCRYPTTLS_PROCESS_ENTRY;
  68. static DWORD cProcessTls;
  69. static PCRYPTTLS_PROCESS_ENTRY pProcessTls;
  70. // The head of the entries freed by I_CryptFreeTls are indexed by the following.
  71. // A 0 index indicates an empty free list.
  72. //
  73. // I_CryptAllocTls first checks this list before reallocating pProcessTls.
  74. static DWORD dwFreeProcessTlsHead;
  75. // The kernel32.dll Thread Local Storage (TLS) slot index
  76. static DWORD iCryptTLS = 0xFFFFFFFF;
  77. // The Thread Local Storage (TLS) referenced by iCryptTLS points to the
  78. // following structure allocated for each thread. Once allocated, not
  79. // reallocated.
  80. typedef struct _CRYPTTLS_THREAD_HDR CRYPTTLS_THREAD_HDR, *PCRYPTTLS_THREAD_HDR;
  81. struct _CRYPTTLS_THREAD_HDR {
  82. DWORD cTls;
  83. void **ppvTls; // reallocated
  84. PCRYPTTLS_THREAD_HDR pNext;
  85. PCRYPTTLS_THREAD_HDR pPrev;
  86. };
  87. // Linked list of all threads having CRYPTTLS
  88. static PCRYPTTLS_THREAD_HDR pThreadTlsHead;
  89. // Minimum number of entries allocated for pProcessTls and the ppvTls
  90. //
  91. // realloc optimization (MIN value is 1)
  92. #define MIN_TLS_ALLOC_COUNT 16
  93. // Used to protect the allocation of TLS and installation of OssGlobals
  94. static CRITICAL_SECTION CryptTlsCriticalSection;
  95. #define OSS_INIT_PROC_IDX 0
  96. #define OSS_TERM_PROC_IDX 1
  97. #define OSS_GET_OSS_GLOBAL_SIZE_PROC_IDX 2
  98. #define OSS_SET_ENCODING_RULES_PROC_IDX 3
  99. #define OSS_SET_DECODING_FLAGS_PROC_IDX 4
  100. #define OSS_SET_ENCODING_FLAGS_PROC_IDX 5
  101. #define OSS_PROC_CNT 6
  102. static LPSTR rgpszOssProc[OSS_PROC_CNT] = {
  103. "ossinit", // 0
  104. "ossterm", // 1
  105. "ossGetOssGlobalSize", // 2
  106. "ossSetEncodingRules", // 3
  107. "ossSetDecodingFlags", // 4
  108. "ossSetEncodingFlags" // 5
  109. };
  110. static void *rgpvOssProc[OSS_PROC_CNT];
  111. static HMODULE hmsossDll = NULL;
  112. static BOOL fLoadedOss = FALSE;
  113. static void OssUnload()
  114. {
  115. if (hmsossDll) {
  116. FreeLibrary(hmsossDll);
  117. hmsossDll = NULL;
  118. }
  119. }
  120. static void OssLoad()
  121. {
  122. DWORD i;
  123. if (fLoadedOss)
  124. return;
  125. EnterCriticalSection(&CryptTlsCriticalSection);
  126. if (fLoadedOss)
  127. goto LeaveReturn;
  128. if (NULL == (hmsossDll = LoadLibraryA("msoss.dll")))
  129. goto msossLoadLibraryError;
  130. for (i = 0; i < OSS_PROC_CNT; i++) {
  131. if (NULL == (rgpvOssProc[i] = GetProcAddress(
  132. hmsossDll, rgpszOssProc[i])))
  133. goto msossGetProcAddressError;
  134. }
  135. LeaveReturn:
  136. LeaveCriticalSection(&CryptTlsCriticalSection);
  137. CommonReturn:
  138. fLoadedOss = TRUE;
  139. return;
  140. ErrorReturn:
  141. LeaveCriticalSection(&CryptTlsCriticalSection);
  142. OssUnload();
  143. goto CommonReturn;
  144. TRACE_ERROR(msossLoadLibraryError)
  145. TRACE_ERROR(msossGetProcAddressError)
  146. }
  147. // nonstandard extension used : redefined extern to static
  148. #pragma warning (disable: 4211)
  149. typedef int (DLL_ENTRY* pfnossinit)(struct ossGlobal *world,
  150. void *ctl_tbl);
  151. static int DLL_ENTRY ossinit(struct ossGlobal *world,
  152. void *ctl_tbl)
  153. {
  154. if (hmsossDll)
  155. return ((pfnossinit) rgpvOssProc[OSS_INIT_PROC_IDX])(
  156. world,
  157. ctl_tbl);
  158. else
  159. return API_DLL_NOT_LINKED;
  160. }
  161. typedef void (DLL_ENTRY* pfnossterm)(struct ossGlobal *world);
  162. static void DLL_ENTRY ossterm(struct ossGlobal *world)
  163. {
  164. if (hmsossDll)
  165. ((pfnossterm) rgpvOssProc[OSS_TERM_PROC_IDX])(world);
  166. }
  167. typedef int (DLL_ENTRY* pfnossGetOssGlobalSize)(void);
  168. static int DLL_ENTRY ossGetOssGlobalSize(void)
  169. {
  170. if (hmsossDll)
  171. return ((pfnossGetOssGlobalSize)
  172. rgpvOssProc[OSS_GET_OSS_GLOBAL_SIZE_PROC_IDX])();
  173. else
  174. return 0;
  175. }
  176. typedef int (DLL_ENTRY* pfnossSetEncodingRules)(struct ossGlobal *world,
  177. ossEncodingRules rules);
  178. static int DLL_ENTRY ossSetEncodingRules(struct ossGlobal *world,
  179. ossEncodingRules rules)
  180. {
  181. if (hmsossDll)
  182. return ((pfnossSetEncodingRules)
  183. rgpvOssProc[OSS_SET_ENCODING_RULES_PROC_IDX])(
  184. world,
  185. rules);
  186. else
  187. return API_DLL_NOT_LINKED;
  188. }
  189. #if !DBG
  190. typedef int (DLL_ENTRY* pfnossSetDecodingFlags)(struct ossGlobal *world,
  191. unsigned long flags);
  192. static int DLL_ENTRY ossSetDecodingFlags(struct ossGlobal *world,
  193. unsigned long flags)
  194. {
  195. if (hmsossDll)
  196. return ((pfnossSetDecodingFlags)
  197. rgpvOssProc[OSS_SET_DECODING_FLAGS_PROC_IDX])(
  198. world,
  199. flags);
  200. else
  201. return API_DLL_NOT_LINKED;
  202. }
  203. typedef int (DLL_ENTRY* pfnossSetEncodingFlags)(struct ossGlobal *world,
  204. unsigned long flags);
  205. static int DLL_ENTRY ossSetEncodingFlags(struct ossGlobal *world,
  206. unsigned long flags)
  207. {
  208. if (hmsossDll)
  209. return ((pfnossSetEncodingFlags)
  210. rgpvOssProc[OSS_SET_ENCODING_FLAGS_PROC_IDX])(
  211. world,
  212. flags);
  213. else
  214. return API_DLL_NOT_LINKED;
  215. }
  216. #endif
  217. //+-------------------------------------------------------------------------
  218. // Free the thread's CRYPT TLS
  219. //
  220. // Upon entry/exit, in CryptTlsCriticalSection
  221. //--------------------------------------------------------------------------
  222. static void FreeCryptTls(
  223. IN PCRYPTTLS_THREAD_HDR pTlsHdr
  224. )
  225. {
  226. if (pTlsHdr->pNext)
  227. pTlsHdr->pNext->pPrev = pTlsHdr->pPrev;
  228. if (pTlsHdr->pPrev)
  229. pTlsHdr->pPrev->pNext = pTlsHdr->pNext;
  230. else if (pTlsHdr == pThreadTlsHead)
  231. pThreadTlsHead = pTlsHdr->pNext;
  232. else {
  233. assert(pTlsHdr == pThreadTlsHead);
  234. }
  235. if (pTlsHdr->ppvTls)
  236. free(pTlsHdr->ppvTls);
  237. free(pTlsHdr);
  238. }
  239. //+-------------------------------------------------------------------------
  240. // Dll initialization
  241. //--------------------------------------------------------------------------
  242. BOOL
  243. WINAPI
  244. I_CryptTlsDllMain(
  245. HMODULE hInst,
  246. ULONG ulReason,
  247. LPVOID lpReserved)
  248. {
  249. BOOL fRet;
  250. PCRYPTTLS_THREAD_HDR pTlsHdr;
  251. switch (ulReason) {
  252. case DLL_PROCESS_ATTACH:
  253. if (!Pki_InitializeCriticalSection(&CryptTlsCriticalSection))
  254. goto InitCritSectionError;
  255. if ((iCryptTLS = TlsAlloc()) == 0xFFFFFFFF) {
  256. DeleteCriticalSection(&CryptTlsCriticalSection);
  257. goto TlsAllocError;
  258. }
  259. break;
  260. case DLL_PROCESS_DETACH:
  261. case DLL_THREAD_DETACH:
  262. if (pTlsHdr = (PCRYPTTLS_THREAD_HDR) TlsGetValue(iCryptTLS)) {
  263. DWORD cTls;
  264. DWORD cDetach = 0;
  265. DWORD i;
  266. cTls = pTlsHdr->cTls;
  267. EnterCriticalSection(&CryptTlsCriticalSection);
  268. assert(cTls <= cProcessTls);
  269. for (i = 0; i < cTls; i++) {
  270. void *pvTls;
  271. if (pvTls = pTlsHdr->ppvTls[i]) {
  272. switch (pProcessTls[i].dwType) {
  273. case OSS_CRYPTTLS:
  274. // Following API is in delay loaded msoss.dll.
  275. __try {
  276. ossterm((POssGlobal) pvTls);
  277. } __except(EXCEPTION_EXECUTE_HANDLER) {
  278. }
  279. free(pvTls);
  280. pTlsHdr->ppvTls[i] = NULL;
  281. break;
  282. case ASN1_CRYPTTLS:
  283. {
  284. PASN1_TLS_ENTRY pAsn1TlsEntry =
  285. (PASN1_TLS_ENTRY) pvTls;
  286. if (pAsn1TlsEntry->pEnc)
  287. ASN1_CloseEncoder(pAsn1TlsEntry->pEnc);
  288. if (pAsn1TlsEntry->pDec)
  289. ASN1_CloseDecoder(pAsn1TlsEntry->pDec);
  290. free(pvTls);
  291. pTlsHdr->ppvTls[i] = NULL;
  292. }
  293. break;
  294. case USER_CRYPTTLS:
  295. cDetach++;
  296. break;
  297. default:
  298. assert(FREE_CRYPTTLS == pProcessTls[i].dwType);
  299. }
  300. }
  301. }
  302. FreeCryptTls(pTlsHdr);
  303. TlsSetValue(iCryptTLS, 0);
  304. LeaveCriticalSection(&CryptTlsCriticalSection);
  305. assert(cDetach == 0);
  306. }
  307. if (ulReason == DLL_PROCESS_DETACH) {
  308. while(pThreadTlsHead)
  309. FreeCryptTls(pThreadTlsHead);
  310. if (pProcessTls) {
  311. free(pProcessTls);
  312. pProcessTls = NULL;
  313. }
  314. cProcessTls = 0;
  315. dwFreeProcessTlsHead = 0;
  316. OssUnload();
  317. DeleteCriticalSection(&CryptTlsCriticalSection);
  318. TlsFree(iCryptTLS);
  319. iCryptTLS = 0xFFFFFFFF;
  320. }
  321. break;
  322. default:
  323. break;
  324. }
  325. fRet = TRUE;
  326. CommonReturn:
  327. return fRet;
  328. ErrorReturn:
  329. fRet = FALSE;
  330. goto CommonReturn;
  331. TRACE_ERROR(InitCritSectionError)
  332. TRACE_ERROR(TlsAllocError)
  333. }
  334. //+-------------------------------------------------------------------------
  335. // Get a pointer to the Crypt TLS entries. Check that the hCryptTls is
  336. // included in the list of entries. If hCryptTls isn't included and
  337. // allocation isn't inhibited, alloc/realloc the array of TLS entries.
  338. //
  339. // Also verifies the hCryptTls handle.
  340. //--------------------------------------------------------------------------
  341. STATIC void **GetCryptTls(
  342. IN HCRYPTTLS hCryptTls,
  343. IN BOOL fInhibitAlloc // TRUE for I_CryptDetachTls
  344. )
  345. {
  346. PCRYPTTLS_THREAD_HDR pTlsHdr;
  347. DWORD cTls;
  348. void **ppvTls;
  349. DWORD i;
  350. if (0 == hCryptTls--) {
  351. SetLastError((DWORD) E_INVALIDARG);
  352. return NULL;
  353. }
  354. pTlsHdr = (PCRYPTTLS_THREAD_HDR) TlsGetValue(iCryptTLS);
  355. cTls = pTlsHdr ? pTlsHdr->cTls : 0;
  356. if (hCryptTls < cTls)
  357. return pTlsHdr->ppvTls;
  358. if (fInhibitAlloc)
  359. return NULL;
  360. EnterCriticalSection(&CryptTlsCriticalSection);
  361. if (hCryptTls >= cProcessTls)
  362. goto InvalidArg;
  363. assert(cTls < cProcessTls);
  364. // Note for !DBG: realloc is mapped to LocalReAlloc. For LocalRealloc()
  365. // the previous memory pointer can't be NULL.
  366. if (pTlsHdr) {
  367. if (cProcessTls > MIN_TLS_ALLOC_COUNT) {
  368. if (NULL == (ppvTls = (void **) realloc(pTlsHdr->ppvTls,
  369. cProcessTls * sizeof(void *))))
  370. goto OutOfMemory;
  371. } else {
  372. ppvTls = pTlsHdr->ppvTls;
  373. assert(ppvTls);
  374. }
  375. } else {
  376. DWORD cAllocTls = (cProcessTls > MIN_TLS_ALLOC_COUNT) ?
  377. cProcessTls : MIN_TLS_ALLOC_COUNT;
  378. if (NULL == (ppvTls = (void **) malloc(cAllocTls * sizeof(void *))))
  379. goto OutOfMemory;
  380. if (NULL == (pTlsHdr = (PCRYPTTLS_THREAD_HDR) malloc(
  381. sizeof(CRYPTTLS_THREAD_HDR)))) {
  382. free(ppvTls);
  383. goto OutOfMemory;
  384. }
  385. if (!TlsSetValue(iCryptTLS, pTlsHdr)) {
  386. free(pTlsHdr);
  387. free(ppvTls);
  388. goto TlsSetValueError;
  389. }
  390. pTlsHdr->pPrev = NULL;
  391. pTlsHdr->pNext = pThreadTlsHead;
  392. if (pThreadTlsHead)
  393. pThreadTlsHead->pPrev = pTlsHdr;
  394. pThreadTlsHead = pTlsHdr;
  395. }
  396. for (i = cTls; i < cProcessTls; i++)
  397. ppvTls[i] = NULL;
  398. pTlsHdr->ppvTls = ppvTls;
  399. pTlsHdr->cTls = cProcessTls;
  400. CommonReturn:
  401. LeaveCriticalSection(&CryptTlsCriticalSection);
  402. return ppvTls;
  403. ErrorReturn:
  404. ppvTls = NULL;
  405. goto CommonReturn;
  406. SET_ERROR(InvalidArg, E_INVALIDARG)
  407. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  408. TRACE_ERROR(TlsSetValueError)
  409. }
  410. //+-------------------------------------------------------------------------
  411. // Install a thread local storage entry and return a handle for future access.
  412. //--------------------------------------------------------------------------
  413. HCRYPTTLS
  414. WINAPI
  415. I_CryptAllocTls()
  416. {
  417. HCRYPTTLS hCryptTls;
  418. EnterCriticalSection(&CryptTlsCriticalSection);
  419. if (dwFreeProcessTlsHead) {
  420. PCRYPTTLS_PROCESS_ENTRY pEntry;
  421. hCryptTls = (HCRYPTTLS) dwFreeProcessTlsHead;
  422. assert(hCryptTls <= cProcessTls);
  423. pEntry = &pProcessTls[dwFreeProcessTlsHead - 1];
  424. assert(FREE_CRYPTTLS == pEntry->dwType);
  425. assert(pEntry->dwNext <= cProcessTls);
  426. pEntry->dwType = USER_CRYPTTLS;
  427. dwFreeProcessTlsHead = pEntry->dwNext;
  428. pEntry->dwNext = 0;
  429. } else {
  430. PCRYPTTLS_PROCESS_ENTRY pNewProcessTls;
  431. // Note for !DBG: realloc is mapped to LocalReAlloc. For LocalRealloc()
  432. // the previous memory pointer can't be NULL.
  433. if (pProcessTls) {
  434. if (cProcessTls + 1 > MIN_TLS_ALLOC_COUNT)
  435. pNewProcessTls = (PCRYPTTLS_PROCESS_ENTRY) realloc(pProcessTls,
  436. (cProcessTls + 1) * sizeof(CRYPTTLS_PROCESS_ENTRY));
  437. else
  438. pNewProcessTls = pProcessTls;
  439. } else
  440. pNewProcessTls = (PCRYPTTLS_PROCESS_ENTRY) malloc(
  441. (MIN_TLS_ALLOC_COUNT) * sizeof(CRYPTTLS_PROCESS_ENTRY));
  442. if (pNewProcessTls) {
  443. pNewProcessTls[cProcessTls].dwType = USER_CRYPTTLS;
  444. pNewProcessTls[cProcessTls].dwNext = 0;
  445. hCryptTls = (HCRYPTTLS) ++cProcessTls;
  446. pProcessTls = pNewProcessTls;
  447. } else {
  448. SetLastError((DWORD) E_OUTOFMEMORY);
  449. hCryptTls = 0;
  450. }
  451. }
  452. LeaveCriticalSection(&CryptTlsCriticalSection);
  453. return hCryptTls;
  454. }
  455. //+-------------------------------------------------------------------------
  456. // Called at DLL_PROCESS_DETACH to free a thread local storage entry.
  457. // Optionally, calls the callback for each thread having a non-NULL pvTls.
  458. //--------------------------------------------------------------------------
  459. BOOL
  460. WINAPI
  461. I_CryptFreeTls(
  462. IN HCRYPTTLS hCryptTls,
  463. IN OPTIONAL PFN_CRYPT_FREE pfnFree
  464. )
  465. {
  466. BOOL fResult;
  467. DWORD dwType;
  468. PCRYPTTLS_THREAD_HDR pThreadTls;
  469. if (0 == hCryptTls--) {
  470. SetLastError((DWORD) E_INVALIDARG);
  471. return FALSE;
  472. }
  473. EnterCriticalSection(&CryptTlsCriticalSection);
  474. if (hCryptTls >= cProcessTls)
  475. goto InvalidArg;
  476. dwType = pProcessTls[hCryptTls].dwType;
  477. if (!(OSS_CRYPTTLS == dwType || USER_CRYPTTLS == dwType ||
  478. ASN1_CRYPTTLS == dwType))
  479. goto InvalidArg;
  480. // Iterate through the threads having CRYPTTLS
  481. pThreadTls = pThreadTlsHead;
  482. while (pThreadTls) {
  483. PCRYPTTLS_THREAD_HDR pThreadTlsNext;
  484. pThreadTlsNext = pThreadTls->pNext;
  485. if (pThreadTls->cTls > hCryptTls) {
  486. void *pvTls = pThreadTls->ppvTls[hCryptTls];
  487. if (pvTls) {
  488. pThreadTls->ppvTls[hCryptTls] = NULL;
  489. if (OSS_CRYPTTLS == dwType) {
  490. // Following API is in delay loaded msoss.dll.
  491. __try {
  492. ossterm((POssGlobal) pvTls);
  493. } __except(EXCEPTION_EXECUTE_HANDLER) {
  494. }
  495. free(pvTls);
  496. } else if (ASN1_CRYPTTLS == dwType) {
  497. PASN1_TLS_ENTRY pAsn1TlsEntry =
  498. (PASN1_TLS_ENTRY) pvTls;
  499. if (pAsn1TlsEntry->pEnc)
  500. ASN1_CloseEncoder(pAsn1TlsEntry->pEnc);
  501. if (pAsn1TlsEntry->pDec)
  502. ASN1_CloseDecoder(pAsn1TlsEntry->pDec);
  503. free(pvTls);
  504. } else if (pfnFree) {
  505. // Don't call the callback holding the critical section
  506. LeaveCriticalSection(&CryptTlsCriticalSection);
  507. pfnFree(pvTls);
  508. EnterCriticalSection(&CryptTlsCriticalSection);
  509. // In case this thread gets deleted, start over at
  510. // the beginning.
  511. pThreadTlsNext = pThreadTlsHead;
  512. }
  513. }
  514. }
  515. pThreadTls = pThreadTlsNext;
  516. }
  517. // Insert in beginning of process free list
  518. pProcessTls[hCryptTls].dwType = FREE_CRYPTTLS;
  519. pProcessTls[hCryptTls].dwNext = dwFreeProcessTlsHead;
  520. dwFreeProcessTlsHead = hCryptTls + 1;
  521. fResult = TRUE;
  522. CommonReturn:
  523. LeaveCriticalSection(&CryptTlsCriticalSection);
  524. return fResult;
  525. ErrorReturn:
  526. fResult = FALSE;
  527. goto CommonReturn;
  528. SET_ERROR(InvalidArg, E_INVALIDARG)
  529. }
  530. //+-------------------------------------------------------------------------
  531. // Get the thread specific pointer specified by the
  532. // hCryptTls returned by I_CryptAllocTls().
  533. //
  534. // Returns NULL for an error or uninitialized or NULL pointer.
  535. //--------------------------------------------------------------------------
  536. void *
  537. WINAPI
  538. I_CryptGetTls(
  539. IN HCRYPTTLS hCryptTls
  540. )
  541. {
  542. void **ppvTls;
  543. void *pvTls;
  544. if (ppvTls = GetCryptTls(
  545. hCryptTls,
  546. FALSE)) { // fInhibitAlloc
  547. if (NULL == (pvTls = ppvTls[hCryptTls - 1]))
  548. SetLastError(NO_ERROR);
  549. } else
  550. pvTls = NULL;
  551. return pvTls;
  552. }
  553. //+-------------------------------------------------------------------------
  554. // Set the thread specific pointer specified by the
  555. // hCryptTls returned by I_CryptAllocTls().
  556. //
  557. // Returns FALSE for an invalid handle or unable to allocate memory.
  558. //--------------------------------------------------------------------------
  559. BOOL
  560. WINAPI
  561. I_CryptSetTls(
  562. IN HCRYPTTLS hCryptTls,
  563. IN void *pvTls
  564. )
  565. {
  566. void **ppvTls;
  567. if (ppvTls = GetCryptTls(
  568. hCryptTls,
  569. FALSE)) { // fInhibitAlloc
  570. ppvTls[hCryptTls - 1] = pvTls;
  571. return TRUE;
  572. } else
  573. return FALSE;
  574. }
  575. //+-------------------------------------------------------------------------
  576. // Called at DLL_THREAD_DETACH to free the thread's
  577. // TLS entry specified by the hCryptTls. Returns the thread specific pointer
  578. // to be freed by the caller.
  579. //
  580. // Note, at DLL_PROCESS_DETACH, I_CryptFreeTls should be called instead.
  581. //--------------------------------------------------------------------------
  582. void *
  583. WINAPI
  584. I_CryptDetachTls(
  585. IN HCRYPTTLS hCryptTls
  586. )
  587. {
  588. void **ppvTls;
  589. void *pvTls;
  590. if (ppvTls = GetCryptTls(
  591. hCryptTls,
  592. TRUE)) { // fInhibitAlloc
  593. if (pvTls = ppvTls[hCryptTls - 1])
  594. ppvTls[hCryptTls - 1] = NULL;
  595. else
  596. SetLastError(NO_ERROR);
  597. } else
  598. pvTls = NULL;
  599. return pvTls;
  600. }
  601. //+-------------------------------------------------------------------------
  602. // Install an OssGlobal entry and return a handle for future access.
  603. //
  604. // Each thread has its own copy of OssGlobal. Allocation and
  605. // initialization are deferred until first referenced by the thread.
  606. //
  607. // The parameter, pvCtlTbl is passed to ossinit() to initialize the OssGlobal.
  608. //
  609. // I_CryptGetOssGlobal must be called with the handled returned by
  610. // I_CryptInstallOssGlobal to get the thread specific OssGlobal.
  611. //
  612. // Currently, dwFlags and pvReserved aren't used and must be set to 0.
  613. //--------------------------------------------------------------------------
  614. HCRYPTOSSGLOBAL
  615. WINAPI
  616. I_CryptInstallOssGlobal(
  617. IN void *pvCtlTbl,
  618. IN DWORD dwFlags,
  619. IN void *pvReserved
  620. )
  621. {
  622. HCRYPTOSSGLOBAL hOssGlobal;
  623. if (hOssGlobal = (HCRYPTOSSGLOBAL) I_CryptAllocTls()) {
  624. // Since pProcessTls can be reallocated in another thread
  625. // need CriticalSection
  626. EnterCriticalSection(&CryptTlsCriticalSection);
  627. pProcessTls[hOssGlobal - 1].dwType = OSS_CRYPTTLS;
  628. pProcessTls[hOssGlobal - 1].pvCtlTbl = pvCtlTbl;
  629. LeaveCriticalSection(&CryptTlsCriticalSection);
  630. }
  631. return hOssGlobal;
  632. }
  633. //+-------------------------------------------------------------------------
  634. // Called at DLL_PROCESS_DETACH to uninstall an OssGlobal entry. Iterate
  635. // through the threads and frees their allocated copy of OssGlobal.
  636. //--------------------------------------------------------------------------
  637. BOOL
  638. WINAPI
  639. I_CryptUninstallOssGlobal(
  640. IN HCRYPTOSSGLOBAL hOssGlobal
  641. )
  642. {
  643. return I_CryptFreeTls(
  644. (HCRYPTTLS) hOssGlobal,
  645. NULL // pfnFree
  646. );
  647. }
  648. //+-------------------------------------------------------------------------
  649. // Get the thread specific pointer to the OssGlobal specified by the
  650. // hOssGlobal returned by CryptInstallOssGlobal. If the
  651. // OssGlobal doesn't exist, then, its allocated and initialized using
  652. // the pvCtlTbl associated with hOssGlobal.
  653. //--------------------------------------------------------------------------
  654. POssGlobal
  655. WINAPI
  656. I_CryptGetOssGlobal(
  657. IN HCRYPTOSSGLOBAL hOssGlobal
  658. )
  659. {
  660. POssGlobal pog;
  661. void **ppvTls;
  662. DWORD iOssGlobal;
  663. DWORD dwType;
  664. void *pvCtlTbl;
  665. DWORD dwExceptionCode;
  666. int cbOssGlobalSize;
  667. if (NULL == (ppvTls = GetCryptTls(
  668. (HCRYPTTLS) hOssGlobal,
  669. FALSE))) // fInhibitAlloc
  670. return NULL;
  671. iOssGlobal = (DWORD) hOssGlobal - 1;
  672. if (pog = (POssGlobal) ppvTls[iOssGlobal])
  673. return pog;
  674. // Since pProcessTls can be reallocated in another thread
  675. // need CriticalSection
  676. EnterCriticalSection(&CryptTlsCriticalSection);
  677. dwType = pProcessTls[iOssGlobal].dwType;
  678. pvCtlTbl = pProcessTls[iOssGlobal].pvCtlTbl;
  679. LeaveCriticalSection(&CryptTlsCriticalSection);
  680. if (OSS_CRYPTTLS != dwType || NULL == pvCtlTbl)
  681. goto InvalidArg;
  682. __try {
  683. // Attempt to do delay, demand loading of msoss.dll
  684. OssLoad();
  685. if (0 >= (cbOssGlobalSize = ossGetOssGlobalSize()))
  686. goto ossGetOssGlobalSizeError;
  687. if (NULL == (pog = (POssGlobal) malloc(cbOssGlobalSize)))
  688. goto OutOfMemory;
  689. if (0 != ossinit(pog, pvCtlTbl))
  690. goto ossinitError;
  691. if (0 != ossSetEncodingRules(pog, OSS_DER))
  692. goto SetEncodingRulesError;
  693. #if DBG
  694. if (!DbgInitOSS(pog))
  695. goto DbgInitOSSError;
  696. #else
  697. if (0 != ossSetEncodingFlags(pog, NOTRAPPING | FRONT_ALIGN))
  698. goto SetEncodingFlagsError;
  699. if (0 != ossSetDecodingFlags(pog, NOTRAPPING | RELAXBER))
  700. goto SetDecodingFlagsError;
  701. #endif
  702. } __except(EXCEPTION_EXECUTE_HANDLER) {
  703. dwExceptionCode = GetExceptionCode();
  704. goto msossLoadLibraryException;
  705. }
  706. ppvTls[iOssGlobal] = pog;
  707. CommonReturn:
  708. return pog;
  709. ErrorReturn:
  710. if (pog) {
  711. free(pog);
  712. pog = NULL;
  713. }
  714. goto CommonReturn;
  715. SET_ERROR(ossGetOssGlobalSizeError, ERROR_MOD_NOT_FOUND)
  716. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  717. SET_ERROR(InvalidArg, E_INVALIDARG)
  718. TRACE_ERROR(ossinitError)
  719. TRACE_ERROR(SetEncodingRulesError)
  720. #if DBG
  721. TRACE_ERROR(DbgInitOSSError)
  722. #else
  723. TRACE_ERROR(SetEncodingFlagsError)
  724. TRACE_ERROR(SetDecodingFlagsError)
  725. #endif
  726. SET_ERROR_VAR(msossLoadLibraryException, dwExceptionCode)
  727. }
  728. //+-------------------------------------------------------------------------
  729. // Install an Asn1 module entry and return a handle for future access.
  730. //
  731. // Each thread has its own copy of the decoder and encoder associated
  732. // with the Asn1 module. Creation is deferred until first referenced by
  733. // the thread.
  734. //
  735. // I_CryptGetAsn1Encoder or I_CryptGetAsn1Decoder must be called with the
  736. // handle returned by I_CryptInstallAsn1Module to get the thread specific
  737. // Asn1 encoder or decoder.
  738. //
  739. // Currently, dwFlags and pvReserved aren't used and must be set to 0.
  740. //--------------------------------------------------------------------------
  741. HCRYPTASN1MODULE
  742. WINAPI
  743. I_CryptInstallAsn1Module(
  744. IN ASN1module_t pMod,
  745. IN DWORD dwFlags,
  746. IN void *pvReserved
  747. )
  748. {
  749. HCRYPTASN1MODULE hAsn1Module;
  750. if (hAsn1Module = (HCRYPTOSSGLOBAL) I_CryptAllocTls()) {
  751. // Since pProcessTls can be reallocated in another thread
  752. // need CriticalSection
  753. EnterCriticalSection(&CryptTlsCriticalSection);
  754. pProcessTls[hAsn1Module - 1].dwType = ASN1_CRYPTTLS;
  755. pProcessTls[hAsn1Module - 1].pMod = pMod;
  756. LeaveCriticalSection(&CryptTlsCriticalSection);
  757. }
  758. return hAsn1Module;
  759. }
  760. //+-------------------------------------------------------------------------
  761. // Called at DLL_PROCESS_DETACH to uninstall an hAsn1Module entry. Iterates
  762. // through the threads and frees their created Asn1 encoders and decoders.
  763. //--------------------------------------------------------------------------
  764. BOOL
  765. WINAPI
  766. I_CryptUninstallAsn1Module(
  767. IN HCRYPTASN1MODULE hAsn1Module
  768. )
  769. {
  770. return I_CryptFreeTls(
  771. (HCRYPTTLS) hAsn1Module,
  772. NULL // pfnFree
  773. );
  774. }
  775. STATIC
  776. PASN1_TLS_ENTRY
  777. WINAPI
  778. I_CryptGetAsn1Tls(
  779. IN HCRYPTASN1MODULE hAsn1Module
  780. )
  781. {
  782. PASN1_TLS_ENTRY pAsn1TlsEntry;
  783. void **ppvTls;
  784. DWORD iAsn1Module;
  785. if (NULL == (ppvTls = GetCryptTls(
  786. (HCRYPTTLS) hAsn1Module,
  787. FALSE))) // fInhibitAlloc
  788. return NULL;
  789. iAsn1Module = (DWORD) hAsn1Module - 1;
  790. if (pAsn1TlsEntry = (PASN1_TLS_ENTRY) ppvTls[iAsn1Module])
  791. return pAsn1TlsEntry;
  792. if (NULL == (pAsn1TlsEntry = (PASN1_TLS_ENTRY) malloc(
  793. sizeof(ASN1_TLS_ENTRY))))
  794. goto OutOfMemory;
  795. memset(pAsn1TlsEntry, 0, sizeof(ASN1_TLS_ENTRY));
  796. ppvTls[iAsn1Module] = pAsn1TlsEntry;
  797. CommonReturn:
  798. return pAsn1TlsEntry;
  799. ErrorReturn:
  800. goto CommonReturn;
  801. SET_ERROR(OutOfMemory, E_OUTOFMEMORY)
  802. }
  803. //+-------------------------------------------------------------------------
  804. // Get the thread specific pointer to the Asn1 encoder specified by the
  805. // hAsn1Module returned by CryptInstallAsn1Module. If the
  806. // encoder doesn't exist, then, its created using the Asn1 module
  807. // associated with hAsn1Module.
  808. //--------------------------------------------------------------------------
  809. ASN1encoding_t
  810. WINAPI
  811. I_CryptGetAsn1Encoder(
  812. IN HCRYPTASN1MODULE hAsn1Module
  813. )
  814. {
  815. PASN1_TLS_ENTRY pAsn1TlsEntry;
  816. ASN1encoding_t pEnc;
  817. DWORD iAsn1Module;
  818. DWORD dwType;
  819. ASN1module_t pMod;
  820. ASN1error_e Asn1Err;
  821. if (NULL == (pAsn1TlsEntry = I_CryptGetAsn1Tls(hAsn1Module)))
  822. return NULL;
  823. if (pEnc = pAsn1TlsEntry->pEnc)
  824. return pEnc;
  825. iAsn1Module = (DWORD) hAsn1Module - 1;
  826. // Since pProcessTls can be reallocated in another thread
  827. // need CriticalSection
  828. EnterCriticalSection(&CryptTlsCriticalSection);
  829. dwType = pProcessTls[iAsn1Module].dwType;
  830. pMod = pProcessTls[iAsn1Module].pMod;
  831. LeaveCriticalSection(&CryptTlsCriticalSection);
  832. if (ASN1_CRYPTTLS != dwType || NULL == pMod)
  833. goto InvalidArg;
  834. Asn1Err = ASN1_CreateEncoder(
  835. pMod,
  836. &pEnc,
  837. NULL, // pbBuf
  838. 0, // cbBufSize
  839. NULL // pParent
  840. );
  841. if (ASN1_SUCCESS != Asn1Err)
  842. goto CreateEncoderError;
  843. pAsn1TlsEntry->pEnc = pEnc;
  844. CommonReturn:
  845. return pEnc;
  846. ErrorReturn:
  847. pEnc = NULL;
  848. goto CommonReturn;
  849. SET_ERROR_VAR(CreateEncoderError, PkiAsn1ErrToHr(Asn1Err))
  850. SET_ERROR(InvalidArg, E_INVALIDARG)
  851. }
  852. //+-------------------------------------------------------------------------
  853. // Get the thread specific pointer to the Asn1 decoder specified by the
  854. // hAsn1Module returned by CryptInstallAsn1Module. If the
  855. // decoder doesn't exist, then, its created using the Asn1 module
  856. // associated with hAsn1Module.
  857. //--------------------------------------------------------------------------
  858. ASN1decoding_t
  859. WINAPI
  860. I_CryptGetAsn1Decoder(
  861. IN HCRYPTASN1MODULE hAsn1Module
  862. )
  863. {
  864. PASN1_TLS_ENTRY pAsn1TlsEntry;
  865. ASN1decoding_t pDec;
  866. DWORD iAsn1Module;
  867. DWORD dwType;
  868. ASN1module_t pMod;
  869. ASN1error_e Asn1Err;
  870. if (NULL == (pAsn1TlsEntry = I_CryptGetAsn1Tls(hAsn1Module)))
  871. return NULL;
  872. if (pDec = pAsn1TlsEntry->pDec)
  873. return pDec;
  874. iAsn1Module = (DWORD) hAsn1Module - 1;
  875. // Since pProcessTls can be reallocated in another thread
  876. // need CriticalSection
  877. EnterCriticalSection(&CryptTlsCriticalSection);
  878. dwType = pProcessTls[iAsn1Module].dwType;
  879. pMod = pProcessTls[iAsn1Module].pMod;
  880. LeaveCriticalSection(&CryptTlsCriticalSection);
  881. if (ASN1_CRYPTTLS != dwType || NULL == pMod)
  882. goto InvalidArg;
  883. Asn1Err = ASN1_CreateDecoder(
  884. pMod,
  885. &pDec,
  886. NULL, // pbBuf
  887. 0, // cbBufSize
  888. NULL // pParent
  889. );
  890. if (ASN1_SUCCESS != Asn1Err)
  891. goto CreateDecoderError;
  892. pAsn1TlsEntry->pDec = pDec;
  893. CommonReturn:
  894. return pDec;
  895. ErrorReturn:
  896. pDec = NULL;
  897. goto CommonReturn;
  898. SET_ERROR_VAR(CreateDecoderError, PkiAsn1ErrToHr(Asn1Err))
  899. SET_ERROR(InvalidArg, E_INVALIDARG)
  900. }