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]
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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"
35 C_OpenSession(CK_SLOT_ID slotID
, CK_FLAGS flags
, CK_VOID_PTR pApplication
,
36 CK_NOTIFY Notify
, CK_SESSION_HANDLE_PTR phSession
)
41 if (!softtoken_initialized
)
42 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
45 * For legacy reasons, the CKF_SERIAL_SESSION bit must always
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
);
71 C_CloseSession(CK_SESSION_HANDLE hSession
)
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
86 rv
= handle2session(hSession
, &session_p
);
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
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
);
139 C_CloseAllSessions(CK_SLOT_ID slotID
)
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
);
182 C_GetSessionInfo(CK_SESSION_HANDLE hSession
, CK_SESSION_INFO_PTR pInfo
)
185 soft_session_t
*session_p
;
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
196 rv
= handle2session(hSession
, &session_p
);
202 rv
= CKR_ARGUMENTS_BAD
;
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;
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
);
227 C_GetOperationState(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pOperationState
,
228 CK_ULONG_PTR pulOperationStateLen
)
230 soft_session_t
*session_p
;
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
241 rv
= handle2session(hSession
, &session_p
);
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
;
256 rv
= soft_get_operationstate(session_p
, pOperationState
,
257 pulOperationStateLen
);
260 SES_REFRELE(session_p
, lock_held
);
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
;
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
282 rv
= handle2session(hSession
, &session_p
);
286 if ((pOperationState
== NULL_PTR
) ||
287 (ulOperationStateLen
== 0)) {
288 rv
= CKR_ARGUMENTS_BAD
;
292 rv
= soft_set_operationstate(session_p
, pOperationState
,
293 ulOperationStateLen
, hEncryptionKey
, hAuthenticationKey
);
296 SES_REFRELE(session_p
, lock_held
);
301 C_Login(CK_SESSION_HANDLE hSession
, CK_USER_TYPE userType
, CK_UTF8CHAR_PTR pPin
,
305 soft_session_t
*session_p
, *sp
;
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
316 rv
= handle2session(hSession
, &session_p
);
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
);
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
);
364 soft_slot
.authenticated
= 1;
365 (void) pthread_mutex_unlock(&soft_giant_mutex
);
367 (void) pthread_mutex_unlock(&soft_giant_mutex
);
368 SES_REFRELE(session_p
, lock_held
);
373 * Load all the private token objects from keystore.
375 rv
= soft_get_token_objects_from_keystore(PRI_TOKENOBJS
);
377 SES_REFRELE(session_p
, lock_held
);
381 /* Acquire the global session list lock */
382 (void) pthread_mutex_lock(&soft_sessionlist_mutex
);
384 sp
= soft_session_list
;
387 (void) pthread_mutex_lock(&sp
->session_mutex
);
389 if (sp
->flags
& CKF_RW_SESSION
) {
390 sp
->state
= CKS_RW_USER_FUNCTIONS
;
392 sp
->state
= CKS_RO_USER_FUNCTIONS
;
394 (void) pthread_mutex_unlock(&sp
->session_mutex
);
398 (void) pthread_mutex_unlock(&soft_sessionlist_mutex
);
400 SES_REFRELE(session_p
, lock_held
);
406 C_Logout(CK_SESSION_HANDLE hSession
)
409 soft_session_t
*session_p
, *sp
;
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
420 rv
= handle2session(hSession
, &session_p
);
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
);
434 soft_slot
.userpin_change_needed
= 0;
435 (void) pthread_mutex_unlock(&soft_giant_mutex
);
436 SES_REFRELE(session_p
, lock_held
);
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
;
451 (void) pthread_mutex_lock(&sp
->session_mutex
);
453 if (sp
->flags
& CKF_RW_SESSION
) {
454 sp
->state
= CKS_RW_PUBLIC_SESSION
;
456 sp
->state
= CKS_RO_PUBLIC_SESSION
;
458 (void) pthread_mutex_unlock(&sp
->session_mutex
);
462 (void) pthread_mutex_unlock(&soft_sessionlist_mutex
);
464 SES_REFRELE(session_p
, lock_held
);