1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <pthread.h>
30#include <security/cryptoki.h>
31#include "pkcs11Global.h"
32#include "pkcs11Session.h"
33#include "pkcs11Slot.h"
34#include "metaGlobal.h"
35
36/*
37 * C_OpenSession will need to create a pseudo session associated
38 * with the session created by the plugged in provider.  Only
39 * minimal argument checking is done here, as we rely on the
40 * underlying provider to catch most errors.
41 */
42CK_RV
43C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
44    CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
45{
46
47	CK_RV rv;
48	CK_SLOT_ID true_id;
49	CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
50	CK_SESSION_HANDLE prov_sess;
51
52	if (!pkcs11_initialized) {
53		return (CKR_CRYPTOKI_NOT_INITIALIZED);
54	}
55
56	/* Check for a fastpath */
57	if (purefastpath || policyfastpath) {
58		if (metaslot_enabled) {
59			/*
60			 * if metaslot is enabled and we are in fastpath
61			 * mode, only one other slot is in the framework
62			 * so, need to go to that slot's entry
63			 * to look up the true slot ID for the slot
64			 */
65			return (fast_funcs->C_OpenSession(TRUEID(slotID+1),
66			    flags, pApplication, Notify, phSession));
67		} else {
68			return (fast_funcs->C_OpenSession(slotID, flags,
69			    pApplication, Notify, phSession));
70		}
71	}
72
73
74	if (slotID == METASLOT_FRAMEWORK_ID) {
75		rv = meta_OpenSession(METASLOT_SLOTID, flags,
76		    pApplication, Notify, &prov_sess);
77	} else {
78		/* Check that slotID is valid */
79		if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id)
80		    != CKR_OK) {
81			return (CKR_SLOT_ID_INVALID);
82		}
83		true_id = TRUEID(fw_st_id);
84		rv = FUNCLIST(fw_st_id)->C_OpenSession(true_id, flags,
85		    pApplication, Notify, &prov_sess);
86	}
87
88	/* Present consistent interface for framework */
89	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
90		return (CKR_FUNCTION_FAILED);
91	} else if (rv != CKR_OK) {
92		/* could not create session with provider, return now */
93		return (rv);
94	}
95
96	/* Provider was successful, now create session in framework */
97	if (slotID == METASLOT_FRAMEWORK_ID) {
98		rv = pkcs11_session_add(
99		    slottable->st_slots[METASLOT_FRAMEWORK_ID],
100		    METASLOT_FRAMEWORK_ID, phSession, prov_sess);
101	} else {
102		rv = pkcs11_session_add(slottable->st_slots[fw_st_id],
103		    fw_st_id, phSession, prov_sess);
104	}
105
106	if (rv != CKR_OK) {
107		/* Trouble in the framework, clean up provider session */
108		FUNCLIST(slotID)->C_CloseSession(prov_sess);
109	}
110	return (rv);
111}
112
113/*
114 * C_CloseSession will close a session with the underlying provider,
115 * and if that's successful will close it in the framework.
116 */
117CK_RV
118C_CloseSession(CK_SESSION_HANDLE hSession)
119{
120	CK_RV rv;
121	pkcs11_session_t *sessp;
122
123	/* Check for a fastpath */
124	if (purefastpath || policyfastpath) {
125		return (fast_funcs->C_CloseSession(hSession));
126	}
127
128	if (!pkcs11_initialized) {
129		return (CKR_CRYPTOKI_NOT_INITIALIZED);
130	}
131
132	/* Obtain the session pointer */
133	HANDLE2SESSION(hSession, sessp, rv);
134
135	if (rv != CKR_OK) {
136		return (rv);
137	}
138
139	/* Delete the session with the provider */
140	rv = FUNCLIST(sessp->se_slotid)->C_CloseSession(sessp->se_handle);
141
142	/* Present consistent interface for framework */
143	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
144		return (CKR_FUNCTION_FAILED);
145	} else if (rv != CKR_OK) {
146		/* could not delete session with provider, return now */
147		return (rv);
148	}
149
150	/* Delete session from the framework */
151	pkcs11_session_delete(slottable->st_slots[sessp->se_slotid], sessp);
152
153	return (rv);
154}
155
156/*
157 * C_CloseAllSessions will close all sessions associated with this
158 * slot with the underlying provider.  If that is successful, will
159 * close the associated sessions in the framework.  If the provider
160 * has not implemented C_CloseAllSessions, then we will loop through
161 * the list of sessions and individually call C_CloseSession.
162 */
163CK_RV
164C_CloseAllSessions(CK_SLOT_ID slotID)
165{
166
167	CK_RV rv, rv1;
168
169	CK_SLOT_ID true_id;
170	CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
171	pkcs11_session_t *sessp, *sess_nextp;
172	pkcs11_slot_t *slotp;
173
174	if (!pkcs11_initialized) {
175		return (CKR_CRYPTOKI_NOT_INITIALIZED);
176	}
177
178	/* Check for a fastpath */
179	if (purefastpath || policyfastpath) {
180		if (metaslot_enabled) {
181			/*
182			 * if metaslot is enabled and we are in fastpath
183			 * mode, only one other slot is in the framework
184			 * so, need to go to that slot's entry
185			 * to look up the true slot ID for the slot
186			 */
187			return (fast_funcs->C_CloseAllSessions(
188			    TRUEID(slotID+1)));
189		} else {
190			return (fast_funcs->C_CloseAllSessions(slotID));
191		}
192	}
193
194	/* Check that slotID is valid */
195	if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) {
196		return (CKR_SLOT_ID_INVALID);
197	}
198
199	slotp = slottable->st_slots[fw_st_id];
200	true_id = TRUEID(fw_st_id);
201
202	rv = FUNCLIST(fw_st_id)->C_CloseAllSessions(true_id);
203
204	/* Present consistent interface for framework */
205	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
206		/* Need to attempt to individually delete sessions */
207
208		/* reset rv */
209		rv = CKR_OK;
210
211		(void) pthread_mutex_lock(&slotp->sl_mutex);
212		sessp = slotp->sl_sess_list;
213
214		while (sessp) {
215			sess_nextp = sessp->se_next;
216
217			rv1 = FUNCLIST(fw_st_id)->
218			    C_CloseSession(sessp->se_handle);
219
220			/* Record the first error encountered */
221			if ((rv == CKR_OK) && (rv1 != CKR_OK)) {
222				rv = rv1;
223			}
224
225			sessp = sess_nextp;
226		}
227
228		(void) pthread_mutex_unlock(&slotp->sl_mutex);
229	}
230
231	if (rv != CKR_OK) {
232		/* could not delete sessionlist with provider, return now */
233		return (rv);
234	}
235
236	/* Delete sessions from the framework */
237	pkcs11_sessionlist_delete(slotp);
238
239	return (rv);
240}
241
242/*
243 * C_GetSessionInfo is a pure wrapper to the underlying provider.
244 * The only argument checked is whether or not hSession is valid.
245 */
246CK_RV
247C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
248{
249
250	CK_RV rv;
251	CK_SLOT_ID slot_id;
252	pkcs11_session_t *sessp;
253
254	/* Check for a fastpath */
255	if (purefastpath || policyfastpath) {
256		rv = fast_funcs->C_GetSessionInfo(hSession, pInfo);
257
258		/*
259		 * If metaslot is enabled, and we are here, that
260		 * that means there's only 1 other slot in the
261		 * framework, and that slot should be hidden.
262		 * so, override value of slot id to be metaslot's
263		 * slot id.
264		 */
265		if (metaslot_enabled) {
266			pInfo->slotID = METASLOT_FRAMEWORK_ID;
267		}
268		return (rv);
269	}
270
271	if (!pkcs11_initialized) {
272		return (CKR_CRYPTOKI_NOT_INITIALIZED);
273	}
274
275	/* Obtain the session pointer */
276	HANDLE2SESSION(hSession, sessp, rv);
277
278	if (rv != CKR_OK) {
279		return (rv);
280	}
281
282	/* Find the slot id for the framework */
283	slot_id = sessp->se_slotid;
284
285	/* Get session info from the provider */
286	rv = FUNCLIST(slot_id)->
287	    C_GetSessionInfo(sessp->se_handle, pInfo);
288
289	/* Present consistent interface to the application */
290	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
291		return (CKR_FUNCTION_FAILED);
292	}
293
294	/* Override value of slot id to framework's */
295	pInfo->slotID = slot_id;
296
297	return (rv);
298}
299
300/*
301 * C_GetOperationState is a pure wrapper to the underlying provider.
302 * The only argument checked is whether or not hSession is valid.
303 */
304CK_RV
305C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
306    CK_ULONG_PTR pulOperationStateLen)
307{
308
309	CK_RV rv;
310	pkcs11_session_t *sessp;
311
312	/* Check for a fastpath */
313	if (purefastpath || policyfastpath) {
314		return (fast_funcs->C_GetOperationState(hSession,
315			    pOperationState, pulOperationStateLen));
316	}
317
318	if (!pkcs11_initialized) {
319		return (CKR_CRYPTOKI_NOT_INITIALIZED);
320	}
321
322	/* Obtain the session pointer */
323	HANDLE2SESSION(hSession, sessp, rv);
324
325	if (rv != CKR_OK) {
326		return (rv);
327	}
328
329	/* Get the operation state with the provider */
330	rv = FUNCLIST(sessp->se_slotid)->C_GetOperationState(sessp->se_handle,
331		pOperationState, pulOperationStateLen);
332
333	/* Present consistent interface to the application */
334	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
335		return (CKR_FUNCTION_FAILED);
336	}
337
338	return (rv);
339}
340
341
342/*
343 * C_SetOperationState is a pure wrapper to the underlying provider.
344 * The only argument checked is whether or not hSession is valid.
345 */
346CK_RV
347C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
348    CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
349    CK_OBJECT_HANDLE hAuthenticationKey)
350{
351	CK_RV rv;
352	pkcs11_session_t *sessp;
353
354	/* Check for a fastpath */
355	if (purefastpath || policyfastpath) {
356		return (fast_funcs->C_SetOperationState(hSession,
357			    pOperationState, ulOperationStateLen,
358			    hEncryptionKey, hAuthenticationKey));
359	}
360
361	if (!pkcs11_initialized) {
362		return (CKR_CRYPTOKI_NOT_INITIALIZED);
363	}
364
365	/* Obtain the session pointer */
366	HANDLE2SESSION(hSession, sessp, rv);
367
368	if (rv != CKR_OK) {
369		return (rv);
370	}
371
372	/* Set the operation state with the provider */
373	rv = FUNCLIST(sessp->se_slotid)->C_SetOperationState(sessp->se_handle,
374		pOperationState, ulOperationStateLen, hEncryptionKey,
375		hAuthenticationKey);
376
377	/* Present consistent interface to the application */
378	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
379		return (CKR_FUNCTION_FAILED);
380	}
381
382	return (rv);
383}
384
385
386/*
387 * C_Login is a pure wrapper to the underlying provider.
388 * The only argument checked is whether or not hSession is valid.
389 */
390CK_RV
391C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
392	CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
393{
394	CK_RV rv;
395	pkcs11_session_t *sessp;
396
397	/* Check for a fastpath */
398	if (purefastpath || policyfastpath) {
399		return (fast_funcs->C_Login(hSession, userType, pPin,
400			    ulPinLen));
401	}
402
403	if (!pkcs11_initialized) {
404		return (CKR_CRYPTOKI_NOT_INITIALIZED);
405	}
406
407	/* Obtain the session pointer */
408	HANDLE2SESSION(hSession, sessp, rv);
409
410	if (rv != CKR_OK) {
411		return (rv);
412	}
413
414	/* Login with the provider */
415	rv = FUNCLIST(sessp->se_slotid)->C_Login(sessp->se_handle,
416	    userType, pPin, ulPinLen);
417
418	/* Present consistent interface to the application */
419	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
420		return (CKR_FUNCTION_FAILED);
421	}
422
423	return (rv);
424}
425
426/*
427 * C_Logout is a pure wrapper to the underlying provider.
428 * The only argument checked is whether or not hSession is valid.
429 */
430CK_RV
431C_Logout(CK_SESSION_HANDLE hSession)
432{
433	CK_RV rv;
434	pkcs11_session_t *sessp;
435
436	/* Check for a fastpath */
437	if (purefastpath || policyfastpath) {
438		return (fast_funcs->C_Logout(hSession));
439	}
440
441	if (!pkcs11_initialized) {
442		return (CKR_CRYPTOKI_NOT_INITIALIZED);
443	}
444
445	/* Obtain the session pointer */
446	HANDLE2SESSION(hSession, sessp, rv);
447
448	if (rv != CKR_OK) {
449		return (rv);
450	}
451
452	rv = FUNCLIST(sessp->se_slotid)->C_Logout(sessp->se_handle);
453
454	/* Present consistent interface to the application */
455	if (rv == CKR_FUNCTION_NOT_SUPPORTED) {
456		return (CKR_FUNCTION_FAILED);
457	}
458
459	return (rv);
460}
461