/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <security/cryptoki.h>
#include <cryptoutil.h>
#include "kernelGlobal.h"
#include "kernelObject.h"
#include "kernelSession.h"
#include "kernelSlot.h"
/*
* Add an object to the session's object list.
*
* This function will acquire the lock on the session, and release
* that lock after adding the object to the session's object list.
*/
void
{
/* Acquire the session lock. */
/* Insert the new object in front of session's object list. */
} else {
}
/* Release the session lock. */
}
/*
* Clean up and release the storage allocated to the object.
*
* The function is called either with the object lock being held
* (by caller kernel_delete_object()), or there is no object lock
* yet (by kernel_build_XXX_object() during creating an object).
*/
void
{
/*
* Free the storage allocated to a secret key object.
*/
OBJ_SEC_VALUE_LEN(objp) = 0;
}
} else {
}
/*
* Free the storage allocated to the extra attribute list.
*/
}
/*
* Create a new object. Copy the attributes that can be modified
* (in the boolean attribute mask field and extra attribute list)
* from the old object to the new object.
*
* The caller of this function holds the lock on the old object.
*/
{
/* Allocate new object. */
return (CKR_HOST_MEMORY);
while (attrp) {
/*
* Copy the attribute_info struct from the old
* object to a new attribute_info struct, and add
* that new struct to the extra attribute list
* of the new object.
*/
return (rv);
}
}
*new_object = new_objp;
if (!copy_everything) {
/* done with copying all information that can be modified */
return (CKR_OK);
}
/*
* Copy the rest of the object.
* Certain fields that are not appropriate for coping will be
* initialized.
*/
/* copy key related information */
case CKO_PUBLIC_KEY:
break;
case CKO_PRIVATE_KEY:
break;
case CKO_SECRET_KEY:
break;
default:
/* should never be this case */
break;
}
/*
* don't need to cleanup the memory from failure of copying
* any key related stuff. Each individual function for
* copying key attr will free the memory if it fails
*/
}
return (rv);
}
/*
* Copy the attributes (in the boolean attribute mask field and
* extra attribute list) from the new object back to the original
* object. Also, clean up and release all the storage in the extra
* attribute list of the original object.
*
* The caller of this function holds the lock on the old object.
*/
void
{
}
/*
* Create a new object struct. If it is a session object, add the object to
* the session's object list. If it is a token object, add it to the slot's
* token object list. The caller does not hold the slot lock.
*/
{
int r;
goto fail_cleanup;
}
/*
* If the HW provider supports object creation, create the object
* in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl.
* Otherwise, create the object in the library.
*/
goto fail_cleanup;
}
/* Cannot create a token object with a READ-ONLY session */
goto fail_cleanup;
}
&objc)) < 0) {
break;
}
if (r < 0) {
} else {
}
goto fail_cleanup;
}
/* Get the CKA_PRIVATE value of this object. */
&is_pri_obj);
goto fail_cleanup;
}
/* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */
if (is_pri_obj)
else
if (is_token_obj)
else
} else {
/*
* Create the object in the library.
* Validate attribute template and fill in the attributes
* in the kernel_object_t.
*/
goto fail_cleanup;
}
}
/* Initialize the rest of stuffs in kernel_object_t. */
if (is_token_obj) {
/* Add the new object to the slot's token object list. */
} else {
/* Add the new object to the session's object list. */
}
/* Type casting the address of an object struct to an object handle. */
return (CKR_OK);
if (new_objp) {
/*
* If the object is created in the HW provider, the storage
* allocated for the ioctl call is always cleaned up after
* the call. If the object is created in the library,
* the storage allocated inside of this object should
* have been cleaned up in the kernel_build_object()
* after an error occurred. Therefore, we can safely
* free the object.
*/
}
return (rv);
}
/*
* Remove an object from the session's object list.
*
* The caller of this function holds the session lock.
*/
{
/*
* Remove the object from the session's object list.
*/
return (CKR_SESSION_HANDLE_INVALID);
}
return (CKR_OBJECT_HANDLE_INVALID);
}
while (tmp_objp) {
break;
}
}
if (!found)
return (CKR_OBJECT_HANDLE_INVALID);
/* Object is the first one in the list. */
} else {
/* Object is the only one in the list. */
}
} else {
/* Object is not the first one in the list. */
/* Object is in the middle of the list. */
} else {
/* Object is the last one in the list. */
}
}
return (CKR_OK);
}
static void
{
/* Acquire the lock on the object. */
/*
* Make sure another thread hasn't freed the object.
*/
return;
}
/*
* The deletion of an object must be blocked when the object
* reference count is not zero. This means if any object related
* operation starts prior to the delete object operation gets in,
* the object deleting thread must wait for the non-deleting
* operation to be completed before it can proceed the delete
* operation.
*
* Unless we are being forced to shut everything down, this only
* happens if the library's _fini() is running not if someone
* explicitly called C_Finalize().
*/
if (wrapper_only) {
objp->obj_refcnt = 0;
}
while (objp->obj_refcnt != 0) {
/*
* We set the OBJECT_REFCNT_WAITING flag before we put
* this deleting thread in a wait state, so other non-deleting
* operation thread will signal to wake it up only when
* the object reference count becomes zero and this flag
* is set.
*/
&objp->object_mutex);
}
/* Mark object as no longer valid. */
objp->magic_marker = 0;
}
/*
* Delete a session object:
* - Remove the object from the session's object list.
* - Release the storage allocated to the object.
*
* The boolean argument ses_lock_held is used to indicate that whether
* the caller holds the session lock or not.
* - When called by kernel_delete_all_objects_in_session() or
* kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE.
*
* The boolean argument wrapper_only is used to indicate that whether
* the caller only wants to clean up the object wrapper from the library and
* needs not to make an ioctl call.
* - This argument only applies to the object created in the provider level.
* - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE.
* - When called by C_DestroyObject(), wrapper_only is FALSE.
* - When called by kernel_delete_all_objects_in_session(), the value of
* wrapper_only depends on its caller.
*/
{
/*
* Check to see if the caller holds the lock on the session.
* If not, we need to acquire that lock in order to proceed.
*/
if (!ses_lock_held) {
/* Acquire the session lock. */
}
/* Remove the object from the session's object list first. */
if (!ses_lock_held) {
/*
* If the session lock is obtained by this function,
* then release that lock after removing the object
* from session's object list.
* We want the releasing of the object storage to
* be done without holding the session lock.
*/
}
return (rv);
/* Destroy the object. */
if (objp->is_lib_obj) {
/*
* If this object is created in the library, cleanup the
* contents of this object such as free all the storage
* allocated for this object.
*/
} else {
/*
* This object is created in the HW provider. If wrapper_only
* is FALSE, make an ioctl call to destroy it in kernel.
*/
if (!wrapper_only) {
&obj_destroy) < 0) {
break;
}
/*
* Ignore ioctl return codes for a session object.
* If the kernel can not delete a session object, it
* is likely caused by the HW provider. There's not
* much that can be done. The library will still
* cleanup the object wrapper in the library. The HW
* provider will destroy all session objects when
* the application exits.
*/
}
}
/* Reset OBJECT_IS_DELETING flag. */
/* Destroy the object lock */
/* Free the object itself */
return (CKR_OK);
}
/*
* Delete all the objects in a session. The caller holds the lock
* on the session. If the wrapper_only argument is TRUE, the caller only
* want to clean up object wrappers in the library.
*/
void
{
/* Delete all the objects in the session. */
while (objp) {
/*
* Delete an session object by calling
* kernel_delete_session_object():
* - The 3rd TRUE boolean argument indicates that the caller
* holds the session lock.
* - The 4th boolean argument indicates whether we only want
* clean up object wrappers in the library.
*/
}
}
static CK_RV
{
/*
* allocate space for storing results if the currently
* allocated space is not enough
*/
return (CKR_HOST_MEMORY);
}
*num_result_alloc += BUFSIZ;
}
return (CKR_OK);
}
static CK_RV
{
if (ulCount > 0) {
/* there are some search requirement */
}
/* Acquire the slot lock */
/*
* Go through all objects in each session.
* Acquire individual session lock for the session
* we are searching.
*/
while (session_p) {
while (obj) {
if (ulCount > 0) {
}
} else {
/* no search criteria, just record the object */
}
(void) pthread_mutex_unlock(
goto cleanup;
}
}
}
/* Release the slot lock */
return (rv);
}
/*
* Initialize the context for C_FindObjects() calls
*/
{
if (ulCount) {
/* Make sure all attributes in template are valid */
return (rv);
}
}
/* prepare the find context */
return (CKR_HOST_MEMORY);
}
return (rv);
}
/* store the find_context in the session */
return (rv);
}
void
{
}
}
void
{
CK_ULONG i;
for (i = fcontext->next_result_index;
((num_obj_found < max_obj_requested) &&
(i < fcontext->num_results));
i++) {
/* a sanity check to make sure the obj is still valid */
}
}
}
fcontext->next_result_index = i;
}
/*
* Add an token object to the token object list in slot.
*
* This function will acquire the lock on the slot, and release
* that lock after adding the object to the slot's token object list.
*/
void
{
/* Acquire the slot lock. */
/* Insert the new object in front of slot's token object list. */
} else {
}
/* Release the slot lock. */
}
/*
* Remove an token object from the slot's token object list.
* This routine is called by kernel_delete_token_object().
* The caller of this function hold the slot lock.
*/
void
{
/* Object is the first one in the list */
} else {
/* Object is the only one in the list. */
}
} else {
/* Object is not the first one in the list. */
/* Object is in the middle of the list. */
} else {
/* Object is the last one in the list. */
}
}
}
/*
* Delete a token object:
* - Remove the object from the slot's token object list.
* - Release the storage allocated to the object.
*
* The boolean argument slot_lock_held is used to indicate that whether
* the caller holds the slot lock or not. When the caller does not hold
* the slot lock, this function will acquire that lock in order to proceed,
* and also release that lock before returning to caller.
*
* The boolean argument wrapper_only is used to indicate that whether
* the caller only wants to the object wrapper from library.
*/
{
int r;
/*
* Check to see if the caller holds the lock on the slot.
* If not, we need to acquire that lock in order to proceed.
*/
if (!slot_lock_held) {
}
/* Remove the object from the slot's token object list first. */
/* Release the slot lock if the call doesn't hold the lock. */
if (!slot_lock_held) {
}
if (!wrapper_only) {
&obj_destroy)) < 0) {
break;
}
if (r < 0) {
} else {
}
/*
* Could not destroy an object from kernel. Write a warning
* in syslog, but we still clean up the object wrapper in
* the library.
*/
"destroy an object in kernel.");
}
}
/* Destroy the object lock */
/* Free the object itself */
return (CKR_OK);
}
/*
* Clean up private object wrappers in this slot. The caller holds the slot
* lock.
*/
void
{
/*
* Delete every private token object from the slot' token object list
*/
while (objp) {
/*
* The first TRUE boolean argument indicates that the caller
* hold the slot lock. The second TRUE boolean argument
* indicates that the caller just wants to clean up the object
* wrapper from the library only.
*/
}
}
/*
* Walk through all the sessions in this slot and delete every
* private object.
*/
while (session_p) {
/* Delete all the objects in the session. */
while (objp) {
/*
* The FALSE boolean argument indicates that the
* caller does not hold the session lock. The TRUE
* boolean argument indicates that the caller just
* want to clean upt the object wrapper from the
* library only.
*/
}
}
}
}
/*
* Get the object size in bytes for the objects created in the library.
*/
{
obj_size = sizeof (kernel_object_t);
case CKO_PUBLIC_KEY:
} else {
}
break;
case CKO_PRIVATE_KEY:
}
}
}
}
}
}
} else {
}
break;
case CKO_SECRET_KEY:
break;
default:
}
}
return (rv);
}
/*
* This function adds the to-be-freed session object to a linked list.
* When the number of objects queued in the linked list reaches the
* maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
* object (FIFO) in the list.
*/
void
{
/* Add the newly deleted object at the end of the list */
} else {
}
/*
* Free the first object in the list only if
* the total count reaches maximum threshold.
*/
}
}