dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_softtoken / common / softSession.c
blob7b0901508a37d8f87d34f069671b6bd7f4d4520f
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <pthread.h>
26 #include <security/cryptoki.h>
27 #include "softGlobal.h"
28 #include "softSession.h"
29 #include "softObject.h"
30 #include "softKeystore.h"
31 #include "softKeystoreUtil.h"
34 CK_RV
35 C_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication,
36 CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession)
39 CK_RV rv = CKR_OK;
41 if (!softtoken_initialized)
42 return (CKR_CRYPTOKI_NOT_INITIALIZED);
45 * For legacy reasons, the CKF_SERIAL_SESSION bit must always
46 * be set.
48 if (!(flags & CKF_SERIAL_SESSION))
49 return (CKR_SESSION_PARALLEL_NOT_SUPPORTED);
51 if (slotID != SOFTTOKEN_SLOTID)
52 return (CKR_SLOT_ID_INVALID);
54 if (phSession == NULL)
55 return (CKR_ARGUMENTS_BAD);
58 * softtoken has no limit on the number of concurrent sessions
59 * that the token allows. No need to check to see if the
60 * token has too many sessions already open.
63 /* Create a new session */
64 rv = soft_add_session(flags, pApplication, Notify, phSession);
66 return (rv);
70 CK_RV
71 C_CloseSession(CK_SESSION_HANDLE hSession)
74 CK_RV rv;
76 soft_session_t *session_p;
77 boolean_t lock_held = B_TRUE;
79 if (!softtoken_initialized)
80 return (CKR_CRYPTOKI_NOT_INITIALIZED);
83 * Obtain the session pointer. Also, increment the session
84 * reference count.
86 rv = handle2session(hSession, &session_p);
87 if (rv != CKR_OK)
88 return (rv);
90 (void) pthread_mutex_lock(&session_p->session_mutex);
92 * Set SESSION_IS_CLOSING flag so any access to this
93 * session will be rejected.
95 if (session_p->ses_close_sync & SESSION_IS_CLOSING) {
96 SES_REFRELE(session_p, lock_held);
97 return (CKR_SESSION_CLOSED);
99 session_p->ses_close_sync |= SESSION_IS_CLOSING;
102 * Decrement the session reference count.
103 * We hold the session lock, and SES_REFRELE()
104 * will release the session lock for us.
106 SES_REFRELE(session_p, lock_held);
109 * Delete a session by calling soft_delete_session() with
110 * a session pointer and a boolean arguments. Boolean
111 * value FALSE is used to indicate that the caller does not
112 * hold the lock on the global session list and also that
113 * this is not a forced session close but an explicit request.
115 * soft_delete_session() will reset SESSION_IS_CLOSING
116 * flag after it is done.
118 rv = soft_delete_session(session_p, B_FALSE, B_FALSE);
120 if (soft_session_cnt == 0) {
121 /* Clean up private token objects from the token object list */
122 soft_delete_all_in_core_token_objects(PRIVATE_TOKEN);
124 * Invalidate public token object handles instead of
125 * deleting them.
127 soft_validate_token_objects(B_FALSE);
128 (void) pthread_mutex_lock(&soft_giant_mutex);
129 soft_slot.authenticated = 0;
130 soft_slot.userpin_change_needed = 0;
131 (void) pthread_mutex_unlock(&soft_giant_mutex);
134 return (rv);
138 CK_RV
139 C_CloseAllSessions(CK_SLOT_ID slotID)
142 CK_RV rv = CKR_OK;
144 if (!softtoken_initialized)
145 return (CKR_CRYPTOKI_NOT_INITIALIZED);
147 if (slotID != SOFTTOKEN_SLOTID)
148 return (CKR_SLOT_ID_INVALID);
150 /* Acquire the global session list lock */
151 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
153 * Set all_sessions_closing flag so any access to any
154 * existing sessions will be rejected.
156 all_sessions_closing = 1;
157 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
159 /* Delete all the sessions and release the allocated resources */
160 rv = soft_delete_all_sessions(B_FALSE);
162 /* Clean up private token objects from the token object list */
163 soft_delete_all_in_core_token_objects(PRIVATE_TOKEN);
165 /* Invalidate public token object handles instead of deleting them */
166 soft_validate_token_objects(B_FALSE);
168 (void) pthread_mutex_lock(&soft_giant_mutex);
169 soft_slot.authenticated = 0;
170 soft_slot.userpin_change_needed = 0;
171 (void) pthread_mutex_unlock(&soft_giant_mutex);
173 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
174 /* Reset all_sessions_closing flag. */
175 all_sessions_closing = 0;
176 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
178 return (rv);
181 CK_RV
182 C_GetSessionInfo(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo)
185 soft_session_t *session_p;
186 CK_RV rv;
187 boolean_t lock_held = B_TRUE;
189 if (!softtoken_initialized)
190 return (CKR_CRYPTOKI_NOT_INITIALIZED);
193 * Obtain the session pointer. Also, increment the session
194 * reference count.
196 rv = handle2session(hSession, &session_p);
197 if (rv != CKR_OK)
198 return (rv);
200 if (pInfo == NULL) {
201 lock_held = B_FALSE;
202 rv = CKR_ARGUMENTS_BAD;
203 goto clean_exit;
206 (void) pthread_mutex_lock(&session_p->session_mutex);
208 /* Provide information for the specified session */
209 pInfo->slotID = SOFTTOKEN_SLOTID;
210 pInfo->state = session_p->state;
211 pInfo->flags = session_p->flags;
212 pInfo->ulDeviceError = 0;
214 clean_exit:
216 * Decrement the session reference count.
217 * We hold the session lock, and SES_REFRELE()
218 * will release the session lock for us.
220 SES_REFRELE(session_p, lock_held);
222 return (rv);
226 CK_RV
227 C_GetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
228 CK_ULONG_PTR pulOperationStateLen)
230 soft_session_t *session_p;
231 CK_RV rv;
232 boolean_t lock_held = B_FALSE;
234 if (!softtoken_initialized)
235 return (CKR_CRYPTOKI_NOT_INITIALIZED);
238 * Obtain the session pointer. Also, increment the session
239 * reference count.
241 rv = handle2session(hSession, &session_p);
242 if (rv != CKR_OK)
243 return (rv);
246 * Only check if pulOperationStateLen is NULL_PTR.
247 * No need to check if pOperationState is NULL_PTR because
248 * application might just ask for the length of buffer to hold
249 * the OperationState.
251 if (pulOperationStateLen == NULL_PTR) {
252 rv = CKR_ARGUMENTS_BAD;
253 goto clean_exit;
256 rv = soft_get_operationstate(session_p, pOperationState,
257 pulOperationStateLen);
259 clean_exit:
260 SES_REFRELE(session_p, lock_held);
261 return (rv);
266 CK_RV
267 C_SetOperationState(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState,
268 CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey,
269 CK_OBJECT_HANDLE hAuthenticationKey)
271 soft_session_t *session_p;
272 CK_RV rv;
273 boolean_t lock_held = B_FALSE;
275 if (!softtoken_initialized)
276 return (CKR_CRYPTOKI_NOT_INITIALIZED);
279 * Obtain the session pointer. Also, increment the session
280 * reference count.
282 rv = handle2session(hSession, &session_p);
283 if (rv != CKR_OK)
284 return (rv);
286 if ((pOperationState == NULL_PTR) ||
287 (ulOperationStateLen == 0)) {
288 rv = CKR_ARGUMENTS_BAD;
289 goto clean_exit;
292 rv = soft_set_operationstate(session_p, pOperationState,
293 ulOperationStateLen, hEncryptionKey, hAuthenticationKey);
295 clean_exit:
296 SES_REFRELE(session_p, lock_held);
297 return (rv);
300 CK_RV
301 C_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin,
302 CK_ULONG ulPinLen)
305 soft_session_t *session_p, *sp;
306 CK_RV rv;
307 boolean_t lock_held = B_FALSE;
309 if (!softtoken_initialized)
310 return (CKR_CRYPTOKI_NOT_INITIALIZED);
313 * Obtain the session pointer. Also, increment the session
314 * reference count.
316 rv = handle2session(hSession, &session_p);
317 if (rv != CKR_OK)
318 return (rv);
320 /* Check the load status of keystore */
321 if (!soft_keystore_status(KEYSTORE_LOAD)) {
322 SES_REFRELE(session_p, lock_held);
323 return (CKR_DEVICE_REMOVED);
326 if (userType != CKU_USER) {
327 SES_REFRELE(session_p, lock_held);
328 return (CKR_USER_TYPE_INVALID);
331 if ((ulPinLen < MIN_PIN_LEN) || (ulPinLen > MAX_PIN_LEN)) {
332 SES_REFRELE(session_p, lock_held);
333 return (CKR_PIN_LEN_RANGE);
336 if (pPin == NULL_PTR) {
338 * We don't support CKF_PROTECTED_AUTHENTICATION_PATH
340 SES_REFRELE(session_p, lock_held);
341 return (CKR_ARGUMENTS_BAD);
344 (void) pthread_mutex_lock(&soft_giant_mutex);
345 if (soft_slot.authenticated) {
346 (void) pthread_mutex_unlock(&soft_giant_mutex);
347 SES_REFRELE(session_p, lock_held);
348 return (CKR_USER_ALREADY_LOGGED_IN);
351 rv = soft_login(pPin, ulPinLen);
352 if (rv == CKR_OK) {
353 if (soft_slot.userpin_change_needed) {
355 * This is the special case when the PIN is never
356 * initialized in the keystore, which will always
357 * return CKR_OK with "userpin_change_needed" set.
359 (void) pthread_mutex_unlock(&soft_giant_mutex);
360 SES_REFRELE(session_p, lock_held);
361 return (rv);
364 soft_slot.authenticated = 1;
365 (void) pthread_mutex_unlock(&soft_giant_mutex);
366 } else {
367 (void) pthread_mutex_unlock(&soft_giant_mutex);
368 SES_REFRELE(session_p, lock_held);
369 return (rv);
373 * Load all the private token objects from keystore.
375 rv = soft_get_token_objects_from_keystore(PRI_TOKENOBJS);
376 if (rv != CKR_OK) {
377 SES_REFRELE(session_p, lock_held);
378 return (rv);
381 /* Acquire the global session list lock */
382 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
384 sp = soft_session_list;
386 while (sp) {
387 (void) pthread_mutex_lock(&sp->session_mutex);
389 if (sp->flags & CKF_RW_SESSION) {
390 sp->state = CKS_RW_USER_FUNCTIONS;
391 } else {
392 sp->state = CKS_RO_USER_FUNCTIONS;
394 (void) pthread_mutex_unlock(&sp->session_mutex);
395 sp = sp->next;
398 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
400 SES_REFRELE(session_p, lock_held);
401 return (rv);
405 CK_RV
406 C_Logout(CK_SESSION_HANDLE hSession)
409 soft_session_t *session_p, *sp;
410 CK_RV rv;
411 boolean_t lock_held = B_FALSE;
413 if (!softtoken_initialized)
414 return (CKR_CRYPTOKI_NOT_INITIALIZED);
417 * Obtain the session pointer. Also, increment the session
418 * reference count.
420 rv = handle2session(hSession, &session_p);
421 if (rv != CKR_OK)
422 return (rv);
424 (void) pthread_mutex_lock(&soft_giant_mutex);
425 if (!soft_slot.authenticated) {
426 if (!soft_slot.userpin_change_needed) {
428 * Only if the PIN has been initialized in the keystore.
430 (void) pthread_mutex_unlock(&soft_giant_mutex);
431 SES_REFRELE(session_p, lock_held);
432 return (CKR_USER_NOT_LOGGED_IN);
433 } else {
434 soft_slot.userpin_change_needed = 0;
435 (void) pthread_mutex_unlock(&soft_giant_mutex);
436 SES_REFRELE(session_p, lock_held);
437 return (CKR_OK);
441 soft_logout();
442 soft_slot.authenticated = 0;
443 (void) pthread_mutex_unlock(&soft_giant_mutex);
445 /* Acquire the global session list lock */
446 (void) pthread_mutex_lock(&soft_sessionlist_mutex);
448 sp = soft_session_list;
450 while (sp) {
451 (void) pthread_mutex_lock(&sp->session_mutex);
453 if (sp->flags & CKF_RW_SESSION) {
454 sp->state = CKS_RW_PUBLIC_SESSION;
455 } else {
456 sp->state = CKS_RO_PUBLIC_SESSION;
458 (void) pthread_mutex_unlock(&sp->session_mutex);
459 sp = sp->next;
462 (void) pthread_mutex_unlock(&soft_sessionlist_mutex);
464 SES_REFRELE(session_p, lock_held);
465 return (rv);