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]
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
30 #include <security/cryptoki.h>
31 #include "softGlobal.h"
32 #include "softObject.h"
33 #include "softSession.h"
34 #include "softKeystore.h"
35 #include "softKeystoreUtil.h"
38 * Add an object to the session's object list.
40 * This function will acquire the lock on the session, and release
41 * that lock after adding the object to the session's object list.
44 soft_add_object_to_session(soft_object_t
*objp
, soft_session_t
*sp
)
47 /* Acquire the session lock. */
48 (void) pthread_mutex_lock(&sp
->session_mutex
);
50 /* Insert the new object in front of session's object list. */
51 if (sp
->object_list
== NULL
) {
52 sp
->object_list
= objp
;
56 sp
->object_list
->prev
= objp
;
57 objp
->next
= sp
->object_list
;
59 sp
->object_list
= objp
;
62 /* Release the session lock. */
63 (void) pthread_mutex_unlock(&sp
->session_mutex
);
68 * Clean up and release the storage allocated to the object.
70 * The function is called either with the object lock being held
71 * (by caller soft_delete_object()), or there is no object lock
72 * yet (by soft_build_XXX_object() during creating an object).
75 soft_cleanup_object(soft_object_t
*objp
)
78 * Free the storage allocated to big integer attributes.
80 soft_cleanup_object_bigint_attrs(objp
);
83 * Free the storage allocated to the extra attribute list.
85 soft_cleanup_extra_attr(objp
);
88 * Free the storage allocated to certificate attributes.
90 soft_cleanup_cert_object(objp
);
95 * Create a new object. Copy the attributes that can be modified
96 * (in the boolean attribute mask field and extra attribute list)
97 * from the old object to the new object.
99 * The caller of this function holds the lock on the old object.
102 soft_copy_object(soft_object_t
*old_object
, soft_object_t
**new_object
,
103 CK_ULONG object_func
, soft_session_t
*sp
)
107 soft_object_t
*new_objp
= NULL
;
108 CK_ATTRIBUTE_INFO_PTR attrp
;
110 /* Allocate new object. */
111 new_objp
= calloc(1, sizeof (soft_object_t
));
112 if (new_objp
== NULL
)
113 return (CKR_HOST_MEMORY
);
115 new_objp
->class = old_object
->class;
116 new_objp
->bool_attr_mask
= old_object
->bool_attr_mask
;
117 new_objp
->cert_type
= old_object
->cert_type
;
118 new_objp
->object_type
= old_object
->object_type
;
120 attrp
= old_object
->extra_attrlistp
;
123 * Copy the attribute_info struct from the old
124 * object to a new attribute_info struct, and add
125 * that new struct to the extra attribute list
128 rv
= soft_copy_extra_attr(attrp
, new_objp
);
130 soft_cleanup_extra_attr(new_objp
);
137 *new_object
= new_objp
;
139 if (object_func
== SOFT_SET_ATTR_VALUE
) {
140 /* done with copying all information that can be modified */
145 * Copy the rest of the object.
146 * Certain fields that are not appropriate for coping will be
149 new_objp
->key_type
= old_object
->key_type
;
150 new_objp
->magic_marker
= old_object
->magic_marker
;
151 new_objp
->mechanism
= old_object
->mechanism
;
153 switch (object_func
) {
154 case SOFT_COPY_OBJ_ORIG_SH
:
155 new_objp
->session_handle
= old_object
->session_handle
;
157 case SOFT_COPY_OBJECT
:
159 * Save the session handle of the C_CopyObject function
160 * in the new copy of the session object.
162 new_objp
->session_handle
= (CK_SESSION_HANDLE
)sp
;
166 (void) pthread_cond_init(&(new_objp
->obj_free_cond
), NULL
);
167 (void) pthread_mutex_init(&(new_objp
->object_mutex
), NULL
);
168 /* copy key related information */
169 switch (new_objp
->class) {
171 rv
= soft_copy_public_key_attr(OBJ_PUB(old_object
),
172 &(OBJ_PUB(new_objp
)), new_objp
->key_type
);
174 case CKO_PRIVATE_KEY
:
175 rv
= soft_copy_private_key_attr(OBJ_PRI(old_object
),
176 &(OBJ_PRI(new_objp
)), new_objp
->key_type
);
179 rv
= soft_copy_secret_key_attr(OBJ_SEC(old_object
),
180 &(OBJ_SEC(new_objp
)));
182 case CKO_DOMAIN_PARAMETERS
:
183 rv
= soft_copy_domain_attr(OBJ_DOM(old_object
),
184 &(OBJ_DOM(new_objp
)), new_objp
->key_type
);
186 case CKO_CERTIFICATE
:
187 rv
= soft_copy_certificate(OBJ_CERT(old_object
),
188 &(OBJ_CERT(new_objp
)), new_objp
->cert_type
);
191 /* should never be this case */
196 * don't need to cleanup the memory from failure of copying
197 * any key related stuff. Each individual function for
198 * copying key attr will free the memory if it fails
200 soft_cleanup_extra_attr(new_objp
);
208 * Copy the attributes (in the boolean attribute mask field and
209 * extra attribute list) from the new object back to the original
210 * object. Also, clean up and release all the storage in the extra
211 * attribute list of the original object.
213 * The caller of this function holds the lock on the old object.
216 soft_merge_object(soft_object_t
*old_object
, soft_object_t
*new_object
)
218 old_object
->bool_attr_mask
= new_object
->bool_attr_mask
;
219 soft_cleanup_extra_attr(old_object
);
220 old_object
->extra_attrlistp
= new_object
->extra_attrlistp
;
225 * Create a new object struct, and add it to the session's object list.
228 soft_add_object(CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
229 CK_ULONG
*objecthandle_p
, soft_session_t
*sp
)
233 soft_object_t
*new_objp
= NULL
;
235 new_objp
= calloc(1, sizeof (soft_object_t
));
236 if (new_objp
== NULL
) {
237 return (CKR_HOST_MEMORY
);
240 new_objp
->extra_attrlistp
= NULL
;
243 * Validate attribute template and fill in the attributes
244 * in the soft_object_t.
246 rv
= soft_build_object(pTemplate
, ulCount
, new_objp
);
251 rv
= soft_pin_expired_check(new_objp
);
256 rv
= soft_object_write_access_check(sp
, new_objp
);
261 /* Initialize the rest of stuffs in soft_object_t. */
262 (void) pthread_cond_init(&new_objp
->obj_free_cond
, NULL
);
263 (void) pthread_mutex_init(&new_objp
->object_mutex
, NULL
);
264 new_objp
->magic_marker
= SOFTTOKEN_OBJECT_MAGIC
;
265 new_objp
->obj_refcnt
= 0;
266 new_objp
->obj_delete_sync
= 0;
268 /* Write the new token object to the keystore */
269 if (IS_TOKEN_OBJECT(new_objp
)) {
270 if (!soft_keystore_status(KEYSTORE_INITIALIZED
)) {
271 rv
= CKR_DEVICE_REMOVED
;
274 new_objp
->version
= 1;
275 rv
= soft_put_object_to_keystore(new_objp
);
277 (void) pthread_cond_destroy(&new_objp
->obj_free_cond
);
278 (void) pthread_mutex_destroy(&new_objp
->object_mutex
);
281 new_objp
->session_handle
= (CK_SESSION_HANDLE
)NULL
;
282 soft_add_token_object_to_slot(new_objp
);
284 * Type casting the address of an object struct to
287 *objecthandle_p
= (CK_ULONG
)new_objp
;
292 new_objp
->session_handle
= (CK_SESSION_HANDLE
)sp
;
294 /* Add the new object to the session's object list. */
295 soft_add_object_to_session(new_objp
, sp
);
297 /* Type casting the address of an object struct to an object handle. */
298 *objecthandle_p
= (CK_ULONG
)new_objp
;
304 * When any error occurs after soft_build_object(), we will need to
305 * clean up the memory allocated by the soft_build_object().
307 soft_cleanup_object(new_objp
);
312 * The storage allocated inside of this object should have
313 * been cleaned up by the soft_build_object() if it failed.
314 * Therefore, we can safely free the object.
325 * Remove an object from the session's object list.
327 * The caller of this function holds the session lock.
330 soft_remove_object_from_session(soft_object_t
*objp
, soft_session_t
*sp
)
332 soft_object_t
*tmp_objp
;
333 boolean_t found
= B_FALSE
;
336 * Remove the object from the session's object list.
339 (sp
->magic_marker
!= SOFTTOKEN_SESSION_MAGIC
)) {
340 return (CKR_SESSION_HANDLE_INVALID
);
343 if ((sp
->object_list
== NULL
) || (objp
== NULL
) ||
344 (objp
->magic_marker
!= SOFTTOKEN_OBJECT_MAGIC
)) {
345 return (CKR_OBJECT_HANDLE_INVALID
);
348 tmp_objp
= sp
->object_list
;
350 if (tmp_objp
== objp
) {
354 tmp_objp
= tmp_objp
->next
;
357 return (CKR_OBJECT_HANDLE_INVALID
);
359 if (sp
->object_list
== objp
) {
360 /* Object is the first one in the list. */
362 sp
->object_list
= objp
->next
;
363 objp
->next
->prev
= NULL
;
365 /* Object is the only one in the list. */
366 sp
->object_list
= NULL
;
369 /* Object is not the first one in the list. */
371 /* Object is in the middle of the list. */
372 objp
->prev
->next
= objp
->next
;
373 objp
->next
->prev
= objp
->prev
;
375 /* Object is the last one in the list. */
376 objp
->prev
->next
= NULL
;
383 * This function adds the to-be-freed session object to a linked list.
384 * When the number of objects queued in the linked list reaches the
385 * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
386 * object (FIFO) in the list.
389 object_delay_free(soft_object_t
*objp
)
393 (void) pthread_mutex_lock(&obj_delay_freed
.obj_to_be_free_mutex
);
395 /* Add the newly deleted object at the end of the list */
397 if (obj_delay_freed
.first
== NULL
) {
398 obj_delay_freed
.last
= objp
;
399 obj_delay_freed
.first
= objp
;
401 obj_delay_freed
.last
->next
= objp
;
402 obj_delay_freed
.last
= objp
;
405 if (++obj_delay_freed
.count
>= MAX_OBJ_TO_BE_FREED
) {
407 * Free the first object in the list only if
408 * the total count reaches maximum threshold.
410 obj_delay_freed
.count
--;
411 tmp
= obj_delay_freed
.first
->next
;
412 free(obj_delay_freed
.first
);
413 obj_delay_freed
.first
= tmp
;
415 (void) pthread_mutex_unlock(&obj_delay_freed
.obj_to_be_free_mutex
);
419 soft_delete_object_cleanup(soft_object_t
*objp
, boolean_t force
)
421 /* Acquire the lock on the object. */
422 (void) pthread_mutex_lock(&objp
->object_mutex
);
425 * Make sure another thread hasn't freed the object.
427 if (objp
->magic_marker
!= SOFTTOKEN_OBJECT_MAGIC
) {
428 (void) pthread_mutex_unlock(&objp
->object_mutex
);
433 * The deletion of an object must be blocked when the object
434 * reference count is not zero. This means if any object related
435 * operation starts prior to the delete object operation gets in,
436 * the object deleting thread must wait for the non-deleting
437 * operation to be completed before it can proceed the delete
440 * Unless we are being forced to shut everything down, this only
441 * happens if the libraries _fini() is running not of someone
442 * explicitly called C_Finalize().
445 objp
->obj_refcnt
= 0;
447 while (objp
->obj_refcnt
!= 0) {
449 * We set the OBJECT_REFCNT_WAITING flag before we put
450 * this deleting thread in a wait state, so other non-deleting
451 * operation thread will signal to wake it up only when
452 * the object reference count becomes zero and this flag
455 objp
->obj_delete_sync
|= OBJECT_REFCNT_WAITING
;
456 (void) pthread_cond_wait(&objp
->obj_free_cond
,
457 &objp
->object_mutex
);
460 objp
->obj_delete_sync
&= ~OBJECT_REFCNT_WAITING
;
462 /* Mark object as no longer valid. */
463 objp
->magic_marker
= 0;
465 (void) pthread_cond_destroy(&objp
->obj_free_cond
);
468 * Cleanup the contents of this object such as free all the
469 * storage allocated for this object.
471 soft_cleanup_object(objp
);
473 /* Reset OBJECT_IS_DELETING flag. */
474 objp
->obj_delete_sync
&= ~OBJECT_IS_DELETING
;
476 (void) pthread_mutex_unlock(&objp
->object_mutex
);
477 /* Destroy the object lock */
478 (void) pthread_mutex_destroy(&objp
->object_mutex
);
480 /* Free the object itself */
481 if (IS_TOKEN_OBJECT(objp
))
485 * Delay freeing the session object as S1WS/NSS uses session
486 * objects for its SSL Handshake.
488 (void) object_delay_free(objp
);
493 * - Remove the object from the session's object list.
494 * Holding the lock on the session which the object was created at
495 * is needed to do this.
496 * - Release the storage allocated to the object.
498 * The boolean argument lock_held is used to indicate that whether
499 * the caller holds the session lock or not.
500 * - When called by soft_delete_all_objects_in_session() -- the
503 * When the caller does not hold the session lock, this function
504 * will acquire that lock in order to proceed, and also release
505 * that lock before returning to caller.
508 soft_delete_object(soft_session_t
*sp
, soft_object_t
*objp
,
509 boolean_t force
, boolean_t lock_held
)
513 * Check to see if the caller holds the lock on the session.
514 * If not, we need to acquire that lock in order to proceed.
517 /* Acquire the session lock. */
518 (void) pthread_mutex_lock(&sp
->session_mutex
);
521 /* Remove the object from the session's object list first. */
522 if (soft_remove_object_from_session(objp
, sp
) != CKR_OK
) {
524 (void) pthread_mutex_unlock(&sp
->session_mutex
);
531 * If the session lock is obtained by this function,
532 * then release that lock after removing the object
533 * from session's object list.
534 * We want the releasing of the object storage to
535 * be done without holding the session lock.
537 (void) pthread_mutex_unlock(&sp
->session_mutex
);
540 soft_delete_object_cleanup(objp
, force
);
545 * Delete all the objects in a session. The caller holds the lock
549 soft_delete_all_objects_in_session(soft_session_t
*sp
, boolean_t force
)
551 soft_object_t
*objp
= sp
->object_list
;
552 soft_object_t
*objp1
;
554 /* Delete all the objects in the session. */
559 * Delete an object by calling soft_delete_object()
560 * with a TRUE boolean argument indicating that
561 * the caller holds the lock on the session.
563 soft_delete_object(sp
, objp
, force
, B_TRUE
);
570 add_to_search_result(soft_object_t
*obj
, find_context_t
*fcontext
,
571 CK_ULONG
*num_result_alloc
)
574 * allocate space for storing results if the currently
575 * allocated space is not enough
577 if (*num_result_alloc
<= fcontext
->num_results
) {
578 fcontext
->objs_found
= reallocarray(fcontext
->objs_found
,
579 *num_result_alloc
+ BUFSIZ
, sizeof (soft_object_t
*));
580 if (fcontext
->objs_found
== NULL
) {
581 return (CKR_HOST_MEMORY
);
583 *num_result_alloc
+= BUFSIZ
;
586 (fcontext
->objs_found
)[(fcontext
->num_results
)++] = obj
;
591 search_for_objects(CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
592 find_context_t
*fcontext
)
594 soft_session_t
*session_p
;
596 CK_OBJECT_CLASS pclasses
[6]; /* classes attrs possibly exist */
597 CK_ULONG num_pclasses
; /* number of possible classes */
598 CK_ULONG num_result_alloc
= 0; /* spaces allocated for results */
600 /* whether CKA_TOKEN flag specified or not */
601 boolean_t token_specified
= B_FALSE
;
602 /* value of CKA_TOKEN flag, if specified */
603 boolean_t token_flag_val
= B_FALSE
;
607 /* there are some search requirement */
608 soft_process_find_attr(pclasses
, &num_pclasses
,
612 for (i
= 0; i
< ulCount
; i
++) {
613 if (pTemplate
[i
].type
== CKA_PRIVATE
) {
614 (void) pthread_mutex_lock(&soft_giant_mutex
);
615 if (soft_slot
.userpin_change_needed
) {
616 (void) pthread_mutex_unlock(&soft_giant_mutex
);
617 return (CKR_PIN_EXPIRED
);
619 (void) pthread_mutex_unlock(&soft_giant_mutex
);
624 * look through template and see if it explicitly specifies
625 * whether we need to look for token objects or not
627 for (i
= 0; i
< ulCount
; i
++) {
628 if (pTemplate
[i
].type
== CKA_TOKEN
) {
629 token_specified
= B_TRUE
;
630 token_flag_val
= *((CK_BBOOL
*)pTemplate
[i
].pValue
);
636 * Need go through token objects if it explicitly say so, or
637 * it is not mentioned in the template. And this will ONLY be
638 * done when the keystore exists. Otherwise, we will skip re-loading
641 * If a session has not logged into the token, only public
642 * objects, if any, will be searched. If a session is logged
643 * into the token, all public and private objects in the keystore
646 if (((token_flag_val
) || (!token_specified
)) &&
647 soft_keystore_status(KEYSTORE_INITIALIZED
)) {
648 /* acquire token session lock */
649 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
650 rv
= refresh_token_objects();
652 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
655 obj
= soft_slot
.token_object_list
;
657 (void) pthread_mutex_lock(&obj
->object_mutex
);
658 if (((token_specified
) && (ulCount
> 1)) ||
659 ((!token_specified
) && (ulCount
> 0))) {
660 if (soft_find_match_attrs(obj
, pclasses
,
661 num_pclasses
, pTemplate
, ulCount
)) {
662 rv
= add_to_search_result(
663 obj
, fcontext
, &num_result_alloc
);
666 /* no search criteria, just record the object */
667 rv
= add_to_search_result(obj
, fcontext
,
670 (void) pthread_mutex_unlock(&obj
->object_mutex
);
672 (void) pthread_mutex_unlock
673 (&soft_slot
.slot_mutex
);
678 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
681 if (token_flag_val
) {
682 /* no need to look through session objects */
686 /* Acquire the global session list lock */
687 (void) pthread_mutex_lock(&soft_sessionlist_mutex
);
690 * Go through all objects in each session.
691 * Acquire individual session lock for the session
694 session_p
= soft_session_list
;
696 (void) pthread_mutex_lock(&session_p
->session_mutex
);
698 obj
= session_p
->object_list
;
700 (void) pthread_mutex_lock(&obj
->object_mutex
);
702 if (soft_find_match_attrs(obj
, pclasses
,
703 num_pclasses
, pTemplate
, ulCount
)) {
704 rv
= add_to_search_result(
705 obj
, fcontext
, &num_result_alloc
);
708 /* no search criteria, just record the object */
709 rv
= add_to_search_result(obj
, fcontext
,
712 (void) pthread_mutex_unlock(&obj
->object_mutex
);
714 (void) pthread_mutex_unlock(
715 &session_p
->session_mutex
);
720 (void) pthread_mutex_unlock(&session_p
->session_mutex
);
721 session_p
= session_p
->next
;
725 /* Release the global session list lock */
726 (void) pthread_mutex_unlock(&soft_sessionlist_mutex
);
731 * Initialize the context for C_FindObjects() calls
734 soft_find_objects_init(soft_session_t
*sp
, CK_ATTRIBUTE_PTR pTemplate
,
739 CK_OBJECT_CLASS
class; /* for soft_validate_attr(). Value unused */
740 find_context_t
*fcontext
;
743 rv
= soft_validate_attr(pTemplate
, ulCount
, &class);
744 /* Make sure all attributes in template are valid */
751 /* prepare the find context */
752 fcontext
= calloc(1, sizeof (find_context_t
));
753 if (fcontext
== NULL
) {
754 return (CKR_HOST_MEMORY
);
757 rv
= search_for_objects(pTemplate
, ulCount
, fcontext
);
763 /* store the find_context in the session */
764 sp
->find_objects
.context
= (CK_VOID_PTR
)fcontext
;
770 soft_find_objects_final(soft_session_t
*sp
)
772 find_context_t
*fcontext
;
774 fcontext
= sp
->find_objects
.context
;
775 sp
->find_objects
.context
= NULL
;
776 sp
->find_objects
.flags
= 0;
777 if (fcontext
->objs_found
!= NULL
) {
778 free(fcontext
->objs_found
);
785 soft_find_objects(soft_session_t
*sp
, CK_OBJECT_HANDLE
*obj_found
,
786 CK_ULONG max_obj_requested
, CK_ULONG
*found_obj_count
)
788 find_context_t
*fcontext
;
789 CK_ULONG num_obj_found
= 0;
793 fcontext
= sp
->find_objects
.context
;
795 for (i
= fcontext
->next_result_index
;
796 ((num_obj_found
< max_obj_requested
) &&
797 (i
< fcontext
->num_results
));
799 obj
= fcontext
->objs_found
[i
];
801 (void) pthread_mutex_lock(&obj
->object_mutex
);
802 /* a sanity check to make sure the obj is still valid */
803 if (obj
->magic_marker
== SOFTTOKEN_OBJECT_MAGIC
) {
804 obj_found
[num_obj_found
] =
805 (CK_OBJECT_HANDLE
)obj
;
808 (void) pthread_mutex_unlock(&obj
->object_mutex
);
811 fcontext
->next_result_index
= i
;
812 *found_obj_count
= num_obj_found
;
816 * Below are the token object related functions
819 soft_add_token_object_to_slot(soft_object_t
*objp
)
822 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
824 /* Insert the new object in front of slot's token object list. */
825 if (soft_slot
.token_object_list
== NULL
) {
826 soft_slot
.token_object_list
= objp
;
830 soft_slot
.token_object_list
->prev
= objp
;
831 objp
->next
= soft_slot
.token_object_list
;
833 soft_slot
.token_object_list
= objp
;
836 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
841 soft_remove_token_object_from_slot(soft_object_t
*objp
, boolean_t lock_held
)
845 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
848 * Remove the object from the slot's token object list.
850 if (soft_slot
.token_object_list
== objp
) {
851 /* Object is the first one in the list. */
853 soft_slot
.token_object_list
= objp
->next
;
854 objp
->next
->prev
= NULL
;
856 /* Object is the only one in the list. */
857 soft_slot
.token_object_list
= NULL
;
860 /* Object is not the first one in the list. */
862 /* Object is in the middle of the list. */
863 objp
->prev
->next
= objp
->next
;
864 objp
->next
->prev
= objp
->prev
;
866 /* Object is the last one in the list. */
867 objp
->prev
->next
= NULL
;
872 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
876 soft_delete_token_object(soft_object_t
*objp
, boolean_t persistent
,
881 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
883 /* Delete the object from the keystore. */
884 (void) soft_keystore_del_obj(&objp
->ks_handle
, B_FALSE
);
886 /* Remove the object from the slot's token object list. */
887 soft_remove_token_object_from_slot(objp
, B_TRUE
);
889 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
891 soft_delete_object_cleanup(objp
, B_FALSE
);
895 soft_delete_all_in_core_token_objects(token_obj_type_t type
)
899 soft_object_t
*objp1
;
901 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
902 objp
= soft_slot
.token_object_list
;
908 if (objp
->object_type
== TOKEN_PRIVATE
) {
909 soft_delete_token_object(objp
, B_FALSE
, B_TRUE
);
918 if (objp
->object_type
== TOKEN_PUBLIC
) {
919 soft_delete_token_object(objp
, B_FALSE
, B_TRUE
);
928 soft_delete_token_object(objp
, B_FALSE
, B_TRUE
);
934 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
939 * Mark all the token objects in the global list to be valid.
942 soft_validate_token_objects(boolean_t validate
)
947 (void) pthread_mutex_lock(&soft_slot
.slot_mutex
);
949 objp
= soft_slot
.token_object_list
;
953 objp
->magic_marker
= SOFTTOKEN_OBJECT_MAGIC
;
955 objp
->magic_marker
= 0;
960 (void) pthread_mutex_unlock(&soft_slot
.slot_mutex
);
965 * Verify user's write access rule to the token object.
968 soft_object_write_access_check(soft_session_t
*sp
, soft_object_t
*objp
)
972 * This function is called by C_CreateObject, C_CopyObject,
973 * C_DestroyObject, C_SetAttributeValue, C_GenerateKey,
974 * C_GenerateKeyPairs, C_DeriveKey. All of them will write
975 * the token object to the keystore.
977 (void) pthread_mutex_lock(&soft_giant_mutex
);
978 if (!soft_slot
.authenticated
) {
979 (void) pthread_mutex_unlock(&soft_giant_mutex
);
980 /* User is not logged in */
981 if (sp
->flags
& CKF_RW_SESSION
) {
983 * For R/W Public Session:
984 * we allow write access to public session or token
985 * object, but not for private token/session object.
987 if ((objp
->object_type
== TOKEN_PRIVATE
) ||
988 (objp
->object_type
== SESSION_PRIVATE
)) {
989 return (CKR_USER_NOT_LOGGED_IN
);
993 * For R/O Public Session:
994 * we allow write access to public session object.
996 if (objp
->object_type
!= SESSION_PUBLIC
)
997 return (CKR_SESSION_READ_ONLY
);
1000 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1001 /* User is logged in */
1002 if (!(sp
->flags
& CKF_RW_SESSION
)) {
1004 * For R/O User Function Session:
1005 * we allow write access to public or private
1006 * session object, but not for public or private
1009 if ((objp
->object_type
== TOKEN_PUBLIC
) ||
1010 (objp
->object_type
== TOKEN_PRIVATE
)) {
1011 return (CKR_SESSION_READ_ONLY
);
1020 * Verify if user is required to setpin when accessing the
1021 * private token/session object.
1024 soft_pin_expired_check(soft_object_t
*objp
)
1028 * This function is called by C_CreateObject, C_CopyObject,
1029 * C_DestroyObject, C_GenerateKey,
1030 * C_GenerateKeyPairs, C_DeriveKey.
1031 * All of them will return CKR_PIN_EXPIRED if the
1032 * "userpin_change_needed" is set.
1034 * The following functions will not be necessary to call
1035 * this routine even though CKR_PIN_EXPIRED is one of the
1036 * valid error code they might return. These functions are:
1037 * C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit,
1038 * C_SignRecoverInit, C_VerifyInit, C_VerifyRecoverInit.
1039 * This is because they will not get the object handle
1040 * before the above functions are called.
1043 (void) pthread_mutex_lock(&soft_giant_mutex
);
1044 if (soft_slot
.userpin_change_needed
) {
1046 * Access private token/session object but user's
1047 * PIN is expired or never set.
1049 if ((objp
->object_type
== TOKEN_PRIVATE
) ||
1050 (objp
->object_type
== SESSION_PRIVATE
)) {
1051 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1052 return (CKR_PIN_EXPIRED
);
1056 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1061 * Copy the selected fields from new token object to old
1065 soft_copy_to_old_object(soft_object_t
*new, soft_object_t
*old
)
1069 CK_ATTRIBUTE_INFO_PTR attrp
;
1071 old
->class = new->class;
1072 old
->bool_attr_mask
= new->bool_attr_mask
;
1073 soft_cleanup_extra_attr(old
);
1074 attrp
= new->extra_attrlistp
;
1076 rv
= soft_copy_extra_attr(attrp
, old
);
1078 soft_cleanup_extra_attr(old
);
1081 attrp
= attrp
->next
;
1084 /* Done with copying all information that can be modified */
1089 * Update an existing object with new data from keystore.
1092 soft_update_object(ks_obj_t
*ks_obj
, soft_object_t
*old_obj
)
1095 soft_object_t
*new_object
;
1098 new_object
= calloc(1, sizeof (soft_object_t
));
1099 if (new_object
== NULL
)
1100 return (CKR_HOST_MEMORY
);
1102 rv
= soft_keystore_unpack_obj(new_object
, ks_obj
);
1104 soft_cleanup_object(new_object
);
1108 rv
= soft_copy_to_old_object(new_object
, old_obj
);
1110 soft_cleanup_object(new_object
);
1117 soft_keystore_load_latest_object(soft_object_t
*old_obj
)
1121 ks_obj_t
*ks_obj
= NULL
;
1125 * Get the current version number from the keystore for
1126 * the specified token object.
1128 if (soft_keystore_get_object_version(&old_obj
->ks_handle
, &version
,
1130 return (CKR_FUNCTION_FAILED
);
1133 * If the keystore version is newer than the in-core version,
1134 * re-read the token object from the keystore.
1136 if (old_obj
->version
!= version
) {
1137 rv
= soft_keystore_get_single_obj(&old_obj
->ks_handle
,
1141 old_obj
->version
= version
;
1144 * Update an existing object with new data from keystore.
1146 rv
= soft_update_object(ks_obj
, old_obj
);
1155 * Insert an object into a list of soft_object_t objects. It is assumed
1156 * that the object to be inserted doesn't previously belong to any list
1159 insert_into_list(soft_object_t
**list
, soft_object_t
**end_of_list
,
1160 soft_object_t
*objp
)
1162 if (*list
== NULL
) {
1166 *end_of_list
= objp
;
1168 (*list
)->prev
= objp
;
1176 * Move an object from an existing list into a new list of
1177 * soft_object_t objects.
1180 move_into_list(soft_object_t
**existing_list
, soft_object_t
**new_list
,
1181 soft_object_t
**end_of_list
, soft_object_t
*objp
)
1184 /* first, remove object from existing list */
1185 if (objp
== *existing_list
) {
1186 /* first item in list */
1188 *existing_list
= objp
->next
;
1189 objp
->next
->prev
= NULL
;
1191 *existing_list
= NULL
;
1195 objp
->prev
->next
= objp
->next
;
1196 objp
->next
->prev
= objp
->prev
;
1198 objp
->prev
->next
= NULL
;
1202 /* then, add into new list */
1203 insert_into_list(new_list
, end_of_list
, objp
);
1207 * Insert "new_list" into "existing_list", new list will always be inserted
1208 * into the front of existing list
1211 insert_list_into_list(soft_object_t
**existing_list
,
1212 soft_object_t
*new_list
, soft_object_t
*end_new_list
)
1215 if (new_list
== NULL
) {
1219 if (*existing_list
== NULL
) {
1220 *existing_list
= new_list
;
1222 (*existing_list
)->prev
= end_new_list
;
1223 end_new_list
->next
= *existing_list
;
1224 *existing_list
= new_list
;
1229 delete_all_objs_in_list(soft_object_t
*list
)
1231 soft_object_t
*objp
, *objp_next
;
1239 objp_next
= objp
->next
;
1240 soft_delete_object_cleanup(objp
, B_FALSE
);
1246 * Makes sure that the list of in-core token objects are up to date
1247 * with respect to the on disk keystore. Other process/applications
1248 * might have modified the keystore since the objects are last loaded
1250 * If there's any error from refreshing the token object list (eg: unable
1251 * to read, unable to unpack and object...etc), the in-core list
1252 * will be restored back to the state before the refresh. An error
1253 * will be returned to indicate the failure.
1255 * It is assumed that the caller holds the lock for the token slot
1258 refresh_token_objects()
1260 uint_t on_disk_ks_version
;
1261 ks_obj_t
*on_disk_list
= NULL
, *tmp_on_disk
, *next_on_disk
;
1262 soft_object_t
*in_core_obj
, *tmp_incore_obj
, *new_objp
= NULL
;
1265 /* deleted in-core objects */
1266 soft_object_t
*del_objs_list
= NULL
;
1267 soft_object_t
*end_del_objs_list
= NULL
;
1269 /* modified in-core objects */
1270 soft_object_t
*mod_objs_list
= NULL
;
1271 soft_object_t
*end_mod_objs_list
= NULL
;
1274 * copy of modified in-core objects, in case we need
1277 soft_object_t
*copy_of_mod_objs_list
= NULL
;
1278 soft_object_t
*end_copy_of_mod_objs_list
= NULL
;
1280 /* objects to be added to the in-core list */
1281 soft_object_t
*added_objs_list
= NULL
;
1282 soft_object_t
*end_added_objs_list
= NULL
;
1284 if (soft_keystore_get_version(&on_disk_ks_version
, B_FALSE
) != 0) {
1285 return (CKR_FUNCTION_FAILED
);
1288 (void) pthread_mutex_lock(&soft_giant_mutex
);
1289 if (on_disk_ks_version
== soft_slot
.ks_version
) {
1291 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1295 if (soft_slot
.authenticated
) {
1296 /* get both public and private objects */
1297 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1298 rv
= soft_keystore_get_objs(ALL_TOKENOBJS
, &on_disk_list
,
1301 /* get both public objects only */
1302 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1303 rv
= soft_keystore_get_objs(PUB_TOKENOBJS
, &on_disk_list
,
1311 * The in-core tokens list will be updated as follows:
1313 * Go through each item in the in-core tokens list.
1314 * Try to match the in-core object with one of the
1315 * objects from the on-disk list. If a match is made,
1316 * check the version number, and update in-core object
1319 * If there's no match between in-core object with on-disk
1320 * object, that means the object is deleted since
1321 * last loaded. Will remove object from in-core list.
1323 * When doing the matching of on-disk object list above,
1324 * Delete every matched on-disk object from the on-disk list
1325 * regardless the in-core object need to be deleted or not
1327 * At the end of matching the in-core tokens list, if
1328 * any object is still left on the on-disk object list,
1329 * those are all new objects added since last load,
1330 * include all of them to the in-core list
1332 * Since we need to be able to revert the in-core list
1333 * back to original state if there's any error with the refresh,
1334 * we need to do the following.
1335 * When an in-core object is "deleted", it is not immediately
1336 * deleted. It is moved to the list of "deleted_objects".
1337 * When an in-core object is "modified", a copy of the
1338 * unmodified object is made. After the object is modified,
1339 * it is temporarily moved to the "mod_objects" list
1340 * from the in-core list.
1341 * When the refresh is completed without any error,
1342 * the actual deleted objects and unmodified objects is deleted.
1344 in_core_obj
= soft_slot
.token_object_list
;
1345 while (in_core_obj
) {
1346 /* try to match object with on_disk_list */
1347 ks_obj_t
*ondisk_obj
, *prev_ondisk_obj
;
1348 boolean_t found
= B_FALSE
;
1349 soft_object_t
*obj_copy
;
1351 ondisk_obj
= on_disk_list
;
1352 prev_ondisk_obj
= NULL
;
1354 /* larval object that has not been written to disk */
1355 if (in_core_obj
->ks_handle
.name
[0] == '\0') {
1356 in_core_obj
= in_core_obj
->next
;
1360 while ((!found
) && (ondisk_obj
!= NULL
)) {
1362 if (strcmp((char *)((ondisk_obj
->ks_handle
).name
),
1363 (char *)((in_core_obj
->ks_handle
).name
)) == 0) {
1368 /* update in-core obj if necessary */
1369 if (ondisk_obj
->obj_version
!=
1370 in_core_obj
->version
) {
1371 /* make a copy of before updating */
1372 rv
= soft_copy_object(in_core_obj
,
1373 &obj_copy
, SOFT_COPY_OBJ_ORIG_SH
,
1379 ©_of_mod_objs_list
,
1380 &end_copy_of_mod_objs_list
,
1383 rv
= soft_update_object(ondisk_obj
,
1389 &(soft_slot
.token_object_list
),
1390 &mod_objs_list
, &end_mod_objs_list
,
1394 /* remove processed obj from on disk list */
1395 if (ondisk_obj
== on_disk_list
) {
1397 on_disk_list
= ondisk_obj
->next
;
1399 prev_ondisk_obj
->next
=
1402 free(ondisk_obj
->buf
);
1405 prev_ondisk_obj
= ondisk_obj
;
1406 ondisk_obj
= ondisk_obj
->next
;
1411 tmp_incore_obj
= in_core_obj
->next
;
1412 move_into_list(&(soft_slot
.token_object_list
),
1413 &del_objs_list
, &end_del_objs_list
, in_core_obj
);
1414 in_core_obj
= tmp_incore_obj
;
1416 in_core_obj
= in_core_obj
->next
;
1421 * At this point, if there's still anything on the on_disk_list, they
1422 * are all newly added objects since in-core list last loaded.
1423 * include all of them into the in-core list
1425 next_on_disk
= on_disk_list
;
1426 while (next_on_disk
) {
1427 new_objp
= calloc(1, sizeof (soft_object_t
));
1428 if (new_objp
== NULL
) {
1429 rv
= CKR_HOST_MEMORY
;
1433 /* Convert the keystore format to memory format */
1434 rv
= soft_keystore_unpack_obj(new_objp
, next_on_disk
);
1436 soft_cleanup_object(new_objp
);
1441 insert_into_list(&added_objs_list
, &end_added_objs_list
,
1444 /* free the on_disk object */
1445 tmp_on_disk
= next_on_disk
;
1446 next_on_disk
= tmp_on_disk
->next
;
1447 free(tmp_on_disk
->buf
);
1452 (void) pthread_mutex_lock(&soft_giant_mutex
);
1453 soft_slot
.ks_version
= on_disk_ks_version
;
1454 (void) pthread_mutex_unlock(&soft_giant_mutex
);
1456 /* add the new objects into in-core list */
1457 insert_list_into_list(&(soft_slot
.token_object_list
),
1458 added_objs_list
, end_added_objs_list
);
1460 /* add modified objects back into the in-core list */
1461 insert_list_into_list(&(soft_slot
.token_object_list
),
1462 mod_objs_list
, end_mod_objs_list
);
1464 /* actually remove deleted objs, and copy of modified objs */
1465 delete_all_objs_in_list(copy_of_mod_objs_list
);
1466 delete_all_objs_in_list(del_objs_list
);
1472 next_on_disk
= on_disk_list
;
1473 while (next_on_disk
) {
1474 tmp_on_disk
= next_on_disk
;
1475 next_on_disk
= tmp_on_disk
->next
;
1476 free(tmp_on_disk
->buf
);
1481 * restore the in-core list back to the original state by adding
1482 * copy of original objects and deleted objects back to list
1484 insert_list_into_list(&(soft_slot
.token_object_list
),
1485 del_objs_list
, end_del_objs_list
);
1486 insert_list_into_list(&(soft_slot
.token_object_list
),
1487 copy_of_mod_objs_list
, end_copy_of_mod_objs_list
);
1490 * remove the modified objects, and newly objects list
1492 delete_all_objs_in_list(mod_objs_list
);
1493 delete_all_objs_in_list(added_objs_list
);
1498 dup_bigint_attr(biginteger_t
*bi
, CK_BYTE
*buf
, CK_ULONG buflen
)
1500 bi
->big_value_len
= buflen
;
1501 if ((bi
->big_value
= malloc(buflen
)) == NULL
) {
1502 return (CKR_HOST_MEMORY
);
1504 (void) memcpy(bi
->big_value
, buf
, buflen
);