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]
21 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <security/cryptoki.h>
27 #include "kmsGlobal.h"
28 #include "kmsSession.h"
30 #include "kmsKeystoreUtil.h"
33 C_OpenSession(CK_SLOT_ID slotID
, CK_FLAGS flags
, CK_VOID_PTR pApplication
,
34 CK_NOTIFY Notify
, CK_SESSION_HANDLE_PTR phSession
)
40 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
42 if (!(flags
& CKF_SERIAL_SESSION
))
43 return (CKR_SESSION_PARALLEL_NOT_SUPPORTED
);
45 if (phSession
== NULL
)
46 return (CKR_ARGUMENTS_BAD
);
48 if (slotID
!= KMS_TOKEN_SLOTID
) {
49 return (CKR_SLOT_ID_INVALID
);
53 * Acquire the slot lock to protect sl_state and sl_sess_list.
54 * These two fields need to be protected atomically, even though
55 * "sl_sess_list" is updated in kms_add_session().
57 pslot
= get_slotinfo();
58 (void) pthread_mutex_lock(&pslot
->sl_mutex
);
60 /* If SO is logged in the slot, only the RW session is allowed. */
61 if ((pslot
->sl_state
== CKU_SO
) && !(flags
& CKF_RW_SESSION
)) {
62 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);
63 return (CKR_SESSION_READ_WRITE_SO_EXISTS
);
66 /* Create a new session */
67 rv
= kms_add_session(slotID
, flags
, pApplication
, Notify
,
70 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);
75 C_CloseSession(CK_SESSION_HANDLE hSession
)
79 kms_session_t
*session_p
;
80 boolean_t ses_lock_held
= B_FALSE
;
83 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
86 * Obtain the session pointer. Also, increment the session
89 rv
= handle2session(hSession
, &session_p
);
93 (void) pthread_mutex_lock(&session_p
->session_mutex
);
94 ses_lock_held
= B_TRUE
;
97 * Set SESSION_IS_CLOSING flag so any access to this
98 * session will be rejected.
100 if (session_p
->ses_close_sync
& SESSION_IS_CLOSING
) {
101 REFRELE(session_p
, ses_lock_held
);
102 return (CKR_SESSION_CLOSED
);
104 session_p
->ses_close_sync
|= SESSION_IS_CLOSING
;
107 * Decrement the session reference count.
108 * We hold the session lock, and REFRELE()
109 * will release the session lock for us.
111 REFRELE(session_p
, ses_lock_held
);
114 * Delete a session by calling kms_delete_session() with
115 * a session pointer and two boolean arguments. The 3rd argument
116 * boolean value FALSE indicates that the caller does not
117 * hold the slot lock. The 4th argument boolean value B_FALSE
118 * indicates that we want to delete all the objects completely.
120 * kms_delete_session() will reset SESSION_IS_CLOSING
121 * flag after it is done.
123 kms_delete_session(session_p
, B_FALSE
, B_FALSE
);
129 C_CloseAllSessions(CK_SLOT_ID slotID
)
131 if (!kms_initialized
)
132 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
134 /* Delete all the sessions and release the allocated resources */
135 kms_delete_all_sessions(B_FALSE
);
141 * Utility routine to get CK_STATE value for a session.
142 * The caller should not be holding the session lock.
145 get_ses_state(kms_session_t
*session_p
)
150 pslot
= get_slotinfo();
151 (void) pthread_mutex_lock(&pslot
->sl_mutex
);
153 if (pslot
->sl_state
== CKU_PUBLIC
) {
154 state
= (session_p
->ses_RO
) ?
155 CKS_RO_PUBLIC_SESSION
: CKS_RW_PUBLIC_SESSION
;
156 } else if (pslot
->sl_state
== CKU_USER
) {
157 state
= (session_p
->ses_RO
) ?
158 CKS_RO_USER_FUNCTIONS
: CKS_RW_USER_FUNCTIONS
;
159 } else if (pslot
->sl_state
== CKU_SO
) {
160 state
= CKS_RW_SO_FUNCTIONS
;
163 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);
169 C_GetSessionInfo(CK_SESSION_HANDLE hSession
, CK_SESSION_INFO_PTR pInfo
)
171 kms_session_t
*session_p
;
173 boolean_t ses_lock_held
= B_FALSE
;
175 if (!kms_initialized
)
176 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
179 return (CKR_ARGUMENTS_BAD
);
182 * Obtain the session pointer. Also, increment the session
185 rv
= handle2session(hSession
, &session_p
);
189 /* Provide information for the specified session */
190 pInfo
->slotID
= session_p
->ses_slotid
;
191 pInfo
->flags
= session_p
->flags
;
192 pInfo
->ulDeviceError
= 0;
193 pInfo
->state
= get_ses_state(session_p
);
196 * Decrement the session reference count.
198 REFRELE(session_p
, ses_lock_held
);
205 C_GetOperationState(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pOperationState
,
206 CK_ULONG_PTR pulOperationStateLen
)
208 if (!kms_initialized
)
209 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
211 return (CKR_FUNCTION_NOT_SUPPORTED
);
216 C_SetOperationState(CK_SESSION_HANDLE hSession
, CK_BYTE_PTR pOperationState
,
217 CK_ULONG ulOperationStateLen
, CK_OBJECT_HANDLE hEncryptionKey
,
218 CK_OBJECT_HANDLE hAuthenticationKey
)
220 if (!kms_initialized
)
221 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
223 return (CKR_FUNCTION_NOT_SUPPORTED
);
227 C_Login(CK_SESSION_HANDLE hSession
, CK_USER_TYPE userType
,
228 CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
)
231 kms_session_t
*session_p
;
233 boolean_t ses_lock_held
= B_FALSE
;
235 if (!kms_initialized
)
236 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
238 if ((userType
!= CKU_SO
) && (userType
!= CKU_USER
)) {
239 return (CKR_USER_TYPE_INVALID
);
243 * Obtain the session pointer. Also, increment the session
246 rv
= handle2session(hSession
, &session_p
);
250 /* Acquire the slot lock */
251 pslot
= get_slotinfo();
252 (void) pthread_mutex_lock(&pslot
->sl_mutex
);
254 /* Check if the slot is logged in already */
255 if ((pslot
->sl_state
== CKU_USER
) || (pslot
->sl_state
== CKU_SO
)) {
256 rv
= CKR_USER_ALREADY_LOGGED_IN
;
260 /* To login as SO, every session in this slot needs to be R/W */
261 if (userType
== CKU_SO
) {
266 sp
= pslot
->sl_sess_list
;
269 * Need not to lock individual sessions before
270 * accessing their "ses_RO" and "next" fields,
271 * because they are always accessed under the
272 * slot's mutex protection.
282 rv
= CKR_SESSION_READ_ONLY_EXISTS
;
288 * Login to KMS by attempting to load the profile using
289 * the given password.
291 rv
= KMS_LoadProfile(
292 &session_p
->kmsProfile
,
293 &session_p
->configInfo
,
298 /* Set the slot's session state. */
299 pslot
->sl_state
= userType
;
304 REFRELE(session_p
, ses_lock_held
);
305 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);
310 C_Logout(CK_SESSION_HANDLE hSession
)
313 kms_session_t
*session_p
;
315 boolean_t ses_lock_held
= B_FALSE
;
317 if (!kms_initialized
)
318 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
321 * Obtain the session pointer. Also, increment the session
324 rv
= handle2session(hSession
, &session_p
);
328 /* Acquire the slot lock. */
329 pslot
= get_slotinfo();
330 (void) pthread_mutex_lock(&pslot
->sl_mutex
);
332 /* Check if the user or SO was logged in */
333 if (pslot
->sl_state
== CKU_PUBLIC
) {
334 rv
= CKR_USER_NOT_LOGGED_IN
;
338 KMS_UnloadProfile(&session_p
->kmsProfile
);
341 * If this slot was logged in as USER previously, we need to clean up
342 * all private object wrappers in library for this slot.
344 kms_cleanup_pri_objects_in_slot(pslot
, session_p
);
347 /* Reset the slot's session state. */
348 pslot
->sl_state
= CKU_PUBLIC
;
352 REFRELE(session_p
, ses_lock_held
);
353 (void) pthread_mutex_unlock(&pslot
->sl_mutex
);