xref: /illumos-gate/usr/src/lib/pkcs11/libpkcs11/common/pkcs11Session.c (revision 4c87aefe8930bd07275b8dd2e96ea5f24d93a52e)
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  */
42 CK_RV
43 C_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  */
117 CK_RV
118 C_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  */
163 CK_RV
164 C_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  */
246 CK_RV
247 C_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  */
304 CK_RV
305 C_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  */
346 CK_RV
347 C_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  */
390 CK_RV
391 C_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  */
430 CK_RV
431 C_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