1/*
2 * Copyright (c) 2000-2001 Apple Computer, 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 * CSPAttacher.cpp - process-wide class which loads and attaches to CSP at most
21 *				     once, and detaches and unloads the CSP when this code is
22 *	 			     unloaded.
23 */
24
25#include "CSPAttacher.h"
26#include "cldebugging.h"
27#include <security_utilities/globalizer.h>
28#include <security_utilities/threading.h>
29#include <security_utilities/alloc.h>
30#include <security_cdsa_utilities/cssmerrors.h>
31#include <Security/cssmapple.h>
32#include <Security/cssmtype.h>
33#include <Security/cssmapi.h>
34
35class CSPAttacher
36{
37public:
38	CSPAttacher() :
39		mCspHand(CSSM_INVALID_HANDLE),
40		mCspDlHand(CSSM_INVALID_HANDLE)
41			{ }
42	~CSPAttacher();
43	CSSM_CSP_HANDLE			getCspHand(bool bareCsp);
44
45private:
46	/* connection to CSP and CSPDL, evaluated lazily */
47	CSSM_HANDLE				mCspHand;
48	CSSM_HANDLE				mCspDlHand;
49	Mutex					mLock;
50};
51
52/* the single global thing */
53static ModuleNexus<CSPAttacher> cspAttacher;
54
55static void *CL_malloc(
56	 CSSM_SIZE size,
57     void *allocref)
58{
59	return Allocator::standard().malloc(size);
60}
61
62static void CL_free(
63     void *memblock,
64     void *allocref)
65{
66	Allocator::standard().free(memblock);
67}
68
69static void *CL_realloc(
70     void *memblock,
71     CSSM_SIZE size,
72     void *allocref)
73{
74	return Allocator::standard().realloc(memblock, size);
75}
76
77static void *CL_calloc(
78     uint32 num,
79     CSSM_SIZE size,
80     void *allocref)
81{
82	return Allocator::standard().calloc(num, size);
83}
84
85static const CSSM_API_MEMORY_FUNCS CL_memFuncs = {
86	CL_malloc,
87	CL_free,
88	CL_realloc,
89 	CL_calloc,
90 	NULL
91 };
92
93
94/*
95 * This only gets called when cspAttacher get deleted, i.e., when this code
96 * is actually unloaded from the process's address space.
97 */
98CSPAttacher::~CSPAttacher()
99{
100	StLock<Mutex> 	_(mLock);
101
102	if(mCspHand != CSSM_INVALID_HANDLE) {
103		CSSM_ModuleDetach(mCspHand);
104		CSSM_ModuleUnload(&gGuidAppleCSP, NULL, NULL);
105	}
106	if(mCspDlHand != CSSM_INVALID_HANDLE) {
107		CSSM_ModuleDetach(mCspDlHand);
108		CSSM_ModuleUnload(&gGuidAppleCSPDL, NULL, NULL);
109	}
110}
111
112CSSM_CSP_HANDLE CSPAttacher::getCspHand(bool bareCsp)
113{
114	const char 		*modName;
115	CSSM_RETURN		crtn;
116	const CSSM_GUID *guid;
117	CSSM_VERSION 	vers = {2, 0};
118	StLock<Mutex> 	_(mLock);
119	CSSM_CSP_HANDLE	cspHand;
120
121	if(bareCsp) {
122		if(mCspHand != CSSM_INVALID_HANDLE) {
123			/* already connected */
124			return mCspHand;
125		}
126		guid = &gGuidAppleCSP;
127		modName = "AppleCSP";
128	}
129	else {
130		if(mCspDlHand != CSSM_INVALID_HANDLE) {
131			/* already connected */
132			return mCspDlHand;
133		}
134		guid = &gGuidAppleCSPDL;
135		modName = "AppleCSPDL";
136	}
137	crtn = CSSM_ModuleLoad(guid,
138		CSSM_KEY_HIERARCHY_NONE,
139		NULL,			// eventHandler
140		NULL);			// AppNotifyCallbackCtx
141	if(crtn) {
142		clErrorLog("AppleX509CLSession::cspAttach: error (%d) loading %s",
143			(int)crtn, modName);
144		CssmError::throwMe(crtn);
145	}
146	crtn = CSSM_ModuleAttach (guid,
147		&vers,
148		&CL_memFuncs,			// memFuncs
149		0,						// SubserviceID
150		CSSM_SERVICE_CSP,		// SubserviceFlags
151		0,						// AttachFlags
152		CSSM_KEY_HIERARCHY_NONE,
153		NULL,					// FunctionTable
154		0,						// NumFuncTable
155		NULL,					// reserved
156		&cspHand);
157	if(crtn) {
158		clErrorLog("AppleX509CLSession::cspAttach: error (%d) attaching to %s",
159			(int)crtn, modName);
160		CssmError::throwMe(crtn);
161	}
162	if(bareCsp) {
163		mCspHand = cspHand;
164	}
165	else {
166		mCspDlHand = cspHand;
167	}
168	return cspHand;
169}
170
171/*
172 * Just one public function - "give me a CSP handle".
173 *   bareCsp true: AppleCSP
174 *   bareCsp false: AppleCSPDL
175 */
176CSSM_CSP_HANDLE	getGlobalCspHand(bool bareCsp)
177{
178	return cspAttacher().getCspHand(bareCsp);
179}
180
181