1/*
2 * Copyright (c) 2000-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
20 * ModuleAttacher.c
21 *
22 * Process-wide class which loads and attaches to {CSP, TP, CL} at most
23 * once, and detaches and unloads the modules when this code is unloaded.
24 */
25
26#include "ssl.h"
27#if USE_CDSA_CRYPTO
28
29#include "ModuleAttacher.h"
30#include "sslDebug.h"
31#include "appleCdsa.h"
32#include <Security/cssmapple.h>
33#include <Security/cssmtype.h>
34#include <Security/cssmapi.h>
35
36#include <pthread.h>
37
38static pthread_mutex_t gAttachLock = PTHREAD_MUTEX_INITIALIZER;
39static CSSM_CSP_HANDLE gCSPHandle = CSSM_INVALID_HANDLE;
40static CSSM_CL_HANDLE gCLHandle = CSSM_INVALID_HANDLE;
41static CSSM_TP_HANDLE gTPHandle = CSSM_INVALID_HANDLE;
42
43static const CSSM_API_MEMORY_FUNCS CA_memFuncs = {
44	stAppMalloc,
45	stAppFree,
46	stAppRealloc,
47 	stAppCalloc,
48 	NULL
49};
50static const CSSM_VERSION cssmVers = {2, 0};
51static const CSSM_GUID testGuid = { 0xFADE, 0, 0, { 1,2,3,4,5,6,7,0 }};
52
53static CSSM_HANDLE loadModule(
54	CSSM_SERVICE_TYPE svcType,	// CSSM_SERVICE_CSP, etc.
55	const CSSM_GUID *guid,
56	const char *modName)
57{
58	CSSM_RETURN crtn;
59	CSSM_HANDLE hand;
60
61	crtn = CSSM_ModuleLoad(guid,
62		CSSM_KEY_HIERARCHY_NONE,
63		NULL,			// eventHandler
64		NULL);			// AppNotifyCallbackCtx
65	if(crtn) {
66		#ifndef NDEBUG
67		sslErrorLog("loadModule: error (%lu) loading %s\n",
68			(unsigned long)crtn, modName);
69		#endif
70		return CSSM_INVALID_HANDLE;
71	}
72	crtn = CSSM_ModuleAttach (guid,
73		&cssmVers,
74		&CA_memFuncs,			// memFuncs
75		0,						// SubserviceID
76		svcType,				// SubserviceFlags
77		0,						// AttachFlags
78		CSSM_KEY_HIERARCHY_NONE,
79		NULL,					// FunctionTable
80		0,						// NumFuncTable
81		NULL,					// reserved
82		&hand);
83	if(crtn) {
84		#ifndef NDEBUG
85		sslErrorLog("loadModule: error (%lu) attaching to %s\n",
86			(unsigned long)crtn, modName);
87		#endif
88		return CSSM_INVALID_HANDLE;
89	}
90	return hand;
91}
92
93
94static CSSM_RETURN doAttachToModules(void)
95{
96	CSSM_RETURN  crtn;
97    CSSM_PVC_MODE pvcPolicy = CSSM_PVC_NONE;
98	CSSM_HANDLE cspHandle, clHandle, tpHandle;
99
100	/* Check if we got the lock after some other thread did the
101	   initialization. */
102	if (gCSPHandle)
103		return CSSM_OK;
104
105	crtn = CSSM_Init (&cssmVers,
106		CSSM_PRIVILEGE_SCOPE_NONE,
107		&testGuid,
108		CSSM_KEY_HIERARCHY_NONE,
109		&pvcPolicy,
110		NULL /* reserved */);
111	if(crtn != CSSM_OK) {
112		#ifndef NDEBUG
113		sslErrorLog("CSSM_Init returned %lu", (unsigned long)crtn);
114		#endif
115		return crtn;
116	}
117
118	cspHandle = loadModule(CSSM_SERVICE_CSP, &gGuidAppleCSP, "AppleCSP");
119	if (cspHandle == CSSM_INVALID_HANDLE)
120		return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
121	clHandle = loadModule(CSSM_SERVICE_CL, &gGuidAppleX509CL, "AppleCL");
122	if (clHandle == CSSM_INVALID_HANDLE)
123		return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
124	tpHandle = loadModule(CSSM_SERVICE_TP, &gGuidAppleX509TP, "AppleTP");
125	if (tpHandle == CSSM_INVALID_HANDLE)
126		return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
127
128	gCSPHandle = cspHandle;
129	gCLHandle = clHandle;
130	gTPHandle = tpHandle;
131
132	return CSSM_OK;
133}
134
135/* Public C function to load and attach to all three modules. */
136CSSM_RETURN attachToModules(
137	CSSM_CSP_HANDLE		*cspHand,
138	CSSM_CL_HANDLE		*clHand,
139	CSSM_TP_HANDLE		*tpHand)
140{
141	CSSM_RETURN result;
142	if (gCSPHandle && gCLHandle && gTPHandle)
143		result = CSSM_OK;
144	else
145	{
146		pthread_mutex_lock(&gAttachLock);
147		result = doAttachToModules();
148		pthread_mutex_unlock(&gAttachLock);
149	}
150
151	*cspHand = gCSPHandle;
152	*clHand = gCLHandle;
153	*tpHand = gTPHandle;
154
155	return result;
156}
157
158#endif	/* USE_CDSA_CRYPTO */
159
160