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