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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
28 #include <security/cryptoki.h>
29 #include "softGlobal.h"
30 #include "softObject.h"
31 #include "softSession.h"
32 #include "softKeystore.h"
33 #include "softKeystoreUtil.h"
37 C_CreateObject(CK_SESSION_HANDLE hSession
,
38 CK_ATTRIBUTE_PTR pTemplate
,
40 CK_OBJECT_HANDLE_PTR phObject
)
44 soft_session_t
*session_p
;
45 boolean_t lock_held
= B_FALSE
;
47 if (!softtoken_initialized
)
48 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
51 * Obtain the session pointer. Also, increment the session
54 rv
= handle2session(hSession
, &session_p
);
58 if ((pTemplate
== NULL
) || (ulCount
== 0) ||
60 rv
= CKR_ARGUMENTS_BAD
;
64 /* Create a new object. */
65 rv
= soft_add_object(pTemplate
, ulCount
, phObject
, session_p
);
69 * Decrement the session reference count.
70 * We do not hold the session lock.
72 SES_REFRELE(session_p
, lock_held
);
77 C_CopyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
78 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
79 CK_OBJECT_HANDLE_PTR phNewObject
)
83 soft_session_t
*session_p
;
84 boolean_t lock_held
= B_FALSE
;
85 soft_object_t
*old_object
, *new_object
= NULL
;
88 if (!softtoken_initialized
)
89 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
92 * Obtain the session pointer. Also, increment the session
95 rv
= handle2session(hSession
, &session_p
);
100 if (((ulCount
> 0) && (pTemplate
== NULL
)) ||
101 (phNewObject
== NULL
)) {
102 rv
= CKR_ARGUMENTS_BAD
;
106 /* Obtain the object pointer. */
107 HANDLE2OBJECT(hObject
, old_object
, rv
);
113 * Copy the old object to a new object.
114 * The 3rd argument with SOFT_COPY_OBJ value indicates that
115 * everything in the object will be duplicated for C_CopyObject.
116 * The 4th argument has the session pointer that will be
117 * saved in the new copy of the session object.
119 (void) pthread_mutex_lock(&old_object
->object_mutex
);
120 rv
= soft_copy_object(old_object
, &new_object
, SOFT_COPY_OBJECT
,
123 if ((rv
!= CKR_OK
) || (new_object
== NULL
)) {
124 /* Most likely we ran out of space. */
125 (void) pthread_mutex_unlock(&old_object
->object_mutex
);
129 /* No need to hold the lock on the old object. */
130 (void) pthread_mutex_unlock(&old_object
->object_mutex
);
132 /* Modifiy the objects if requested */
133 for (i
= 0; i
< ulCount
; i
++) {
134 /* Set the requested attribute into the new object. */
135 rv
= soft_set_attribute(new_object
, &pTemplate
[i
], B_TRUE
);
141 rv
= soft_pin_expired_check(new_object
);
147 * Does the new object violate the creation rule or access rule?
149 rv
= soft_object_write_access_check(session_p
, new_object
);
155 * If the new object is a token object, it will be added
156 * to token object list and write to disk.
158 if (IS_TOKEN_OBJECT(new_object
)) {
159 new_object
->version
= 1;
161 * Write to the keystore file.
163 rv
= soft_put_object_to_keystore(new_object
);
168 new_object
->session_handle
= (CK_SESSION_HANDLE
)NULL
;
170 * Add the newly created token object to the global
171 * token object list in the slot struct.
173 soft_add_token_object_to_slot(new_object
);
174 OBJ_REFRELE(old_object
);
175 SES_REFRELE(session_p
, lock_held
);
176 *phNewObject
= (CK_ULONG
)new_object
;
181 /* Insert new object into this session's object list */
182 soft_add_object_to_session(new_object
, session_p
);
185 * Decrement the session reference count.
186 * We do not hold the session lock.
188 OBJ_REFRELE(old_object
);
189 SES_REFRELE(session_p
, lock_held
);
191 /* set handle of the new object */
192 *phNewObject
= (CK_ULONG
)new_object
;
197 soft_cleanup_object(new_object
);
201 OBJ_REFRELE(old_object
);
203 SES_REFRELE(session_p
, lock_held
);
208 C_DestroyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
)
212 soft_object_t
*object_p
;
213 soft_session_t
*session_p
= (soft_session_t
*)(hSession
);
214 boolean_t lock_held
= B_FALSE
;
215 CK_SESSION_HANDLE creating_session
;
218 if (!softtoken_initialized
)
219 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
222 * The reason that we don't call handle2session is because
223 * the argument hSession may not be the creating_session of
224 * the object to be destroyed, and we want to avoid the lock
225 * contention. The handle2session will be called later for
226 * the creating_session.
228 if ((session_p
== NULL
) ||
229 (session_p
->magic_marker
!= SOFTTOKEN_SESSION_MAGIC
)) {
230 return (CKR_SESSION_HANDLE_INVALID
);
233 /* Obtain the object pointer. */
234 HANDLE2OBJECT_DESTROY(hObject
, object_p
, rv
);
239 /* Obtain the session handle which object belongs to. */
240 creating_session
= object_p
->session_handle
;
242 if (creating_session
== NULL
) {
244 * This is a token object to be deleted.
245 * For token object, there is no creating session concept,
246 * therefore, creating_session is always NULL.
248 rv
= soft_pin_expired_check(object_p
);
253 /* Obtain the session pointer just for validity check. */
254 rv
= handle2session(hSession
, &session_p
);
259 rv
= soft_object_write_access_check(session_p
, object_p
);
261 SES_REFRELE(session_p
, lock_held
);
266 * Set OBJECT_IS_DELETING flag so any access to this
267 * object will be rejected.
269 (void) pthread_mutex_lock(&object_p
->object_mutex
);
270 if (object_p
->obj_delete_sync
& OBJECT_IS_DELETING
) {
271 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
272 SES_REFRELE(session_p
, lock_held
);
273 return (CKR_OBJECT_HANDLE_INVALID
);
275 object_p
->obj_delete_sync
|= OBJECT_IS_DELETING
;
276 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
277 SES_REFRELE(session_p
, lock_held
);
280 * Delete a token object by calling soft_delete_token_object()
281 * with the second argument B_TRUE indicating to delete the
282 * object from keystore and the third argument B_FALSE
283 * indicating that the caller does not hold the slot mutex.
285 soft_delete_token_object(object_p
, B_TRUE
, B_FALSE
);
290 * Obtain the session pointer. Also, increment the session
293 rv
= handle2session(creating_session
, &session_p
);
299 * Set OBJECT_IS_DELETING flag so any access to this
300 * object will be rejected.
302 (void) pthread_mutex_lock(&object_p
->object_mutex
);
303 if (object_p
->obj_delete_sync
& OBJECT_IS_DELETING
) {
304 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
305 SES_REFRELE(session_p
, lock_held
);
306 return (CKR_OBJECT_HANDLE_INVALID
);
308 object_p
->obj_delete_sync
|= OBJECT_IS_DELETING
;
309 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
312 * Delete an object by calling soft_delete_object()
313 * with a FALSE boolean argument indicating that
314 * the caller does not hold the session lock.
316 soft_delete_object(session_p
, object_p
, B_FALSE
, B_FALSE
);
319 * Decrement the session reference count.
320 * We do not hold the session lock.
322 SES_REFRELE(session_p
, lock_held
);
329 C_GetAttributeValue(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
330 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
)
333 CK_RV rv
= CKR_OK
, rv1
= CKR_OK
;
334 soft_object_t
*object_p
;
335 soft_session_t
*session_p
;
336 boolean_t lock_held
= B_FALSE
;
339 if (!softtoken_initialized
)
340 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
343 * Obtain the session pointer. Also, increment the session
346 rv
= handle2session(hSession
, &session_p
);
350 if ((pTemplate
== NULL
) || (ulCount
== 0)) {
352 * Decrement the session reference count.
353 * We do not hold the session lock.
355 SES_REFRELE(session_p
, lock_held
);
356 return (CKR_ARGUMENTS_BAD
);
359 /* Obtain the object pointer. */
360 HANDLE2OBJECT(hObject
, object_p
, rv
);
363 * Decrement the session reference count.
364 * We do not hold the session lock.
366 SES_REFRELE(session_p
, lock_held
);
370 if (IS_TOKEN_OBJECT(object_p
)) {
372 rv
= soft_keystore_load_latest_object(object_p
);
374 OBJ_REFRELE(object_p
);
375 SES_REFRELE(session_p
, lock_held
);
380 /* Acquire the lock on the object. */
381 (void) pthread_mutex_lock(&object_p
->object_mutex
);
383 for (i
= 0; i
< ulCount
; i
++) {
385 * Get the value of each attribute in the template.
386 * (We must process EVERY attribute in the template.)
388 rv
= soft_get_attribute(object_p
, &pTemplate
[i
]);
390 /* At least we catch some type of error. */
394 /* Release the object lock */
395 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
398 * Decrement the session reference count.
399 * We do not hold the session lock.
401 OBJ_REFRELE(object_p
);
402 SES_REFRELE(session_p
, lock_held
);
410 C_SetAttributeValue(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
411 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
)
414 soft_object_t
*object_p
;
415 soft_object_t
*new_object
= NULL
;
416 soft_session_t
*session_p
;
417 boolean_t lock_held
= B_FALSE
;
420 if (!softtoken_initialized
)
421 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
424 * Obtain the session pointer. Also, increment the session
427 rv
= handle2session(hSession
, &session_p
);
431 if ((pTemplate
== NULL
) || (ulCount
== 0)) {
433 * Decrement the session reference count.
434 * We do not hold the session lock.
436 SES_REFRELE(session_p
, lock_held
);
437 return (CKR_ARGUMENTS_BAD
);
440 /* Obtain the object pointer. */
441 HANDLE2OBJECT(hObject
, object_p
, rv
);
444 * Decrement the session reference count.
445 * We do not hold the session lock.
447 SES_REFRELE(session_p
, lock_held
);
451 if (object_p
->bool_attr_mask
& NOT_MODIFIABLE_BOOL_ON
) {
452 rv
= CKR_ATTRIBUTE_READ_ONLY
;
457 * Start working on the object, so we need to set the write lock so that
458 * no one can write to it but still can read it.
460 if (IS_TOKEN_OBJECT(object_p
)) {
461 rv
= soft_keystore_load_latest_object(object_p
);
468 * Copy the old object to a new object. We work on the copied
469 * version because in case of error we still keep the old one
471 * The 3rd argument with SOFT_SET_ATTR_VALUE value indicates that
472 * not everything will be duplicated for C_SetAttributeValue.
473 * Information not duplicated are those attributes that are not
476 (void) pthread_mutex_lock(&object_p
->object_mutex
);
477 rv
= soft_copy_object(object_p
, &new_object
, SOFT_SET_ATTR_VALUE
, NULL
);
479 if ((rv
!= CKR_OK
) || (new_object
== NULL
)) {
480 /* Most likely we ran out of space. */
481 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
483 * Decrement the session reference count.
484 * We do not hold the session lock.
490 * No need to hold the lock on the old object, because we
491 * will be working on the new scratch object.
493 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
495 rv
= soft_object_write_access_check(session_p
, new_object
);
500 for (i
= 0; i
< ulCount
; i
++) {
501 /* Set the requested attribute into the new object. */
502 rv
= soft_set_attribute(new_object
, &pTemplate
[i
], B_FALSE
);
510 * We've successfully set all the requested attributes.
511 * Merge the new object with the old object, then destory
512 * the new one. The reason to do the merging is because we
513 * have to keep the original object handle (address of object).
515 (void) pthread_mutex_lock(&object_p
->object_mutex
);
517 soft_merge_object(object_p
, new_object
);
520 * The object has been modified, so we write it back to keystore.
522 if (IS_TOKEN_OBJECT(object_p
)) {
524 rv
= soft_modify_object_to_keystore(object_p
);
527 (void) pthread_mutex_unlock(&object_p
->object_mutex
);
531 * Decrement the session reference count.
532 * We do not hold the session lock.
534 OBJ_REFRELE(object_p
);
535 SES_REFRELE(session_p
, lock_held
);
539 soft_cleanup_object(new_object
);
543 OBJ_REFRELE(object_p
);
544 SES_REFRELE(session_p
, lock_held
);
551 C_GetObjectSize(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
552 CK_ULONG_PTR pulSize
)
554 if (!softtoken_initialized
)
555 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
557 return (CKR_FUNCTION_NOT_SUPPORTED
);
561 C_FindObjectsInit(CK_SESSION_HANDLE sh
, CK_ATTRIBUTE_PTR pTemplate
,
566 soft_session_t
*session_p
;
567 boolean_t lock_held
= B_TRUE
;
569 if (!softtoken_initialized
)
570 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
573 * Obtain the session pointer. Also, increment the session
576 rv
= handle2session(sh
, &session_p
);
580 /* Check the arguments */
581 if ((ulCount
> 0) && (pTemplate
== NULL
)) {
582 /* decrement the session count, we do not hold the lock */
584 SES_REFRELE(session_p
, lock_held
);
585 return (CKR_ARGUMENTS_BAD
);
588 /* Acquire the session lock */
589 (void) pthread_mutex_lock(&session_p
->session_mutex
);
591 /* Check to see if find operation is already active */
592 if (session_p
->find_objects
.flags
& CRYPTO_OPERATION_ACTIVE
) {
593 /* decrement the session count, and unlock the mutex */
594 SES_REFRELE(session_p
, lock_held
);
595 return (CKR_OPERATION_ACTIVE
);
598 * This active flag will remain ON until application calls
599 * C_FindObjectsFinal.
601 session_p
->find_objects
.flags
= CRYPTO_OPERATION_ACTIVE
;
604 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
606 rv
= soft_find_objects_init(session_p
, pTemplate
, ulCount
);
609 (void) pthread_mutex_lock(&session_p
->session_mutex
);
610 session_p
->find_objects
.flags
= 0;
611 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
614 /* decrement the session count, and unlock the mutex */
616 SES_REFRELE(session_p
, lock_held
);
621 C_FindObjects(CK_SESSION_HANDLE sh
,
622 CK_OBJECT_HANDLE_PTR phObject
,
623 CK_ULONG ulMaxObjectCount
,
624 CK_ULONG_PTR pulObjectCount
)
626 soft_session_t
*session_p
;
628 boolean_t lock_held
= B_TRUE
;
630 if (!softtoken_initialized
)
631 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
634 * Obtain the session pointer. Also, increment the session
637 rv
= handle2session(sh
, &session_p
);
641 /* check for invalid arguments */
642 if (((phObject
== NULL
) && (ulMaxObjectCount
!= 0)) ||
643 (pulObjectCount
== NULL
)) {
644 /* decrement the session count, we do not hold the lock */
646 SES_REFRELE(session_p
, lock_held
);
647 return (CKR_ARGUMENTS_BAD
);
650 if (ulMaxObjectCount
== 0) {
651 /* don't need to do anything, just return */
653 /* decrement the session count, we do not hold the lock */
655 SES_REFRELE(session_p
, lock_held
);
659 /* Acquire the session lock */
660 (void) pthread_mutex_lock(&session_p
->session_mutex
);
662 /* Check to see if find operation is active */
663 if (!(session_p
->find_objects
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
664 SES_REFRELE(session_p
, lock_held
);
665 return (CKR_OPERATION_NOT_INITIALIZED
);
668 soft_find_objects(session_p
, phObject
, ulMaxObjectCount
,
671 /* decrement the session count, and release the lock */
672 SES_REFRELE(session_p
, lock_held
);
677 C_FindObjectsFinal(CK_SESSION_HANDLE sh
)
679 soft_session_t
*session_p
;
681 boolean_t lock_held
= B_TRUE
;
683 if (!softtoken_initialized
)
684 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
687 * Obtain the session pointer. Also, increment the session
690 rv
= handle2session(sh
, &session_p
);
694 /* Acquire the session lock */
695 (void) pthread_mutex_lock(&session_p
->session_mutex
);
697 /* Check to see if find operation is active */
698 if (!(session_p
->find_objects
.flags
& CRYPTO_OPERATION_ACTIVE
)) {
699 SES_REFRELE(session_p
, lock_held
);
700 return (CKR_OPERATION_NOT_INITIALIZED
);
703 soft_find_objects_final(session_p
);
705 /* decrement the session count, and release the lock */
706 SES_REFRELE(session_p
, lock_held
);