metaObjectManager.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <fcntl.h>
#include "metaGlobal.h"
#define WRAP_KEY_TEMPLATE_SIZE 7
/*
* Information necessary to create keys for C_WrapKey/C_UnwrapKey
*/
typedef struct _wrap_info {
} wrap_info_t;
extern meta_session_t *meta_sessionlist_head;
static wrap_info_t common_wrap_info[] = {
};
static unsigned int num_common_wrap_info =
sizeof (common_wrap_info) / sizeof (wrap_info_t);
static wrap_info_t special_wrap_info[] = {
};
static unsigned int num_special_wrap_info =
sizeof (special_wrap_info) / sizeof (wrap_info_t);
static wrap_info_t rsa_wrap_info[] = {
};
static unsigned int num_rsa_wrap_info =
sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
static meta_object_t *tokenobject_list_head;
/*
* Public and private exponent, and Module value for
*
*/
0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
static CK_RV
/*
* meta_objectManager_initialize
*
* Called from meta_Initialize. Initializes all the variables used
* by the object manager.
*/
{
return (CKR_FUNCTION_FAILED);
}
(void) pthread_rwlock_destroy(&meta_objectclose_lock);
return (CKR_FUNCTION_FAILED);
}
return (CKR_OK);
}
void
{
/*
* If there are still any token object in the list, need to
* deactivate all of them.
*/
(void) meta_token_object_deactivate(ALL_TOKEN);
(void) pthread_rwlock_destroy(&meta_objectclose_lock);
(void) pthread_rwlock_destroy(&tokenobject_list_lock);
}
/*
* meta_handle2object
*
* Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
* successful, a reader-lock on the object will be held to indicate
* that it's in use. Call OBJRELEASE() when finished.
*
*/
{
/* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
if (tmp_object == NULL) {
return (CKR_OBJECT_HANDLE_INVALID);
}
/* Lock to ensure the magic-check + read-lock is atomic. */
(void) pthread_rwlock_rdlock(&meta_objectclose_lock);
(void) pthread_rwlock_unlock(&meta_objectclose_lock);
return (CKR_OBJECT_HANDLE_INVALID);
}
(void) pthread_rwlock_unlock(&meta_objectclose_lock);
*object = tmp_object;
return (CKR_OK);
}
/*
* meta_object_alloc
*
* Creates a new metaobject, but does not yet add it to the object list.
* Once the caller has finished initializing the object (by setting
* object attributes), meta_object_add should be called. This two-step
* process prevents others from seeing the object until fully intitialized.
*
*/
{
/* Allocate memory for the object. */
if (new_object == NULL)
return (CKR_HOST_MEMORY);
return (CKR_HOST_MEMORY);
}
return (CKR_HOST_MEMORY);
}
/* Initialize the object fields. */
*object = new_object;
return (CKR_OK);
}
/*
* meta_object_get_attr
*
* Get attribute values to fill in attribute values
* being kept in the metaslot object. The following 4 attributes
* in the meta_object_t structure will be filled in:
* isToken, isPrivate, isSensitive, isExtractable
*
* It's basically an easy way to do a C_GetAttributeValue.
* So, the hSession argument is assumed
* to be valid, and the pointer to meta_object_t is also assumed
* to be valid.
*/
{
attrs, 3);
return (rv);
}
/*
* CKA_SENSITIVE and CKA_EXTRACTABLE only applies to private
* and secret keys.
*/
return (rv);
}
} else {
}
return (CKR_OK);
}
/*
* meta_object_activate
*
* Add a new metaobject to the list of objects. See also meta_object_create,
* which would be called to create an object before it is added.
*/
void
{
/*
* For session objects, we keep the list in the session that created
* this object, because this object will be destroyed when that session
* is closed.
*
* For token objects, the list is global (ie, not associated with any
* particular session).
*/
if (new_object->isToken) {
} else {
}
/* Add object to the list of objects. */
(void) pthread_rwlock_wrlock(list_lock);
(void) pthread_rwlock_unlock(list_lock);
}
/*
* meta_object_deactivate
*
* Removes the object from the list of valid meta objects. Note
* that this function does not clean up any allocated
* resources (memory, object clones, etc). Cleaning up of
* allocated resources is done by calling the meta_object_deallocate()
*
*/
{
if (!have_object_lock) {
}
if (object->isClosingObject) {
/* Lost a delete race. */
return (CKR_OBJECT_HANDLE_INVALID);
}
} else {
}
/*
* Remove object from the object list. Once removed, it will not
* be possible for another thread to begin using the object.
*/
(void) pthread_rwlock_wrlock(&meta_objectclose_lock);
if (!have_list_lock) {
(void) pthread_rwlock_wrlock(list_lock);
}
/*
* Can't use the regular REMOVE_FROM_LIST() function because
* that will miss the "error cleanup" situation where object is not yet
* in the list (object->next == NULL && object->prev == NULL)
*/
/* Object is the first one in the list */
} else {
/* Object is the only one in the list */
}
} else {
/* Object is the last one in the list */
}
}
if (!have_list_lock) {
(void) pthread_rwlock_unlock(list_lock);
}
(void) pthread_rwlock_unlock(&meta_objectclose_lock);
/*
* Wait for anyone already using object to finish, by obtaining
* a writer-lock (need to release our reader-lock first). Once we
* get the write lock, we can just release it and finish cleaning
* up the object.
*/
return (CKR_OK);
}
/*
* meta_object_dealloc
*
* Performs final object cleanup, releasing any allocated memory and
* destroying any clones on other slots. Caller is assumed to have
* called meta_object_deactivate() before this function.
*
* Caller is assumed to have only reference to object, but should have
* released any lock.
*
* If "nukeSourceObj" argument is true, we will actually delete the
* object from the underlying slot.
*/
{
CK_ULONG i;
/* First, delete all the clones of this object on other slots. */
continue;
}
}
}
}
/* Now erase and delete any attributes in the metaobject. */
if (object->clone_template) {
for (i = 0; i < object->clone_template_size; i++) {
}
}
/* Cleanup remaining object fields. */
return (save_rv);
}
/*
* meta_slot_object_alloc
*/
if (new_object == NULL)
return (CKR_HOST_MEMORY);
*object = new_object;
return (CKR_OK);
}
/*
* meta_slot_object_activate
*/
void
{
if (isToken) {
extern slot_data_t *slots;
} else {
/* Add to session's list of session objects. */
}
}
/*
* meta_slot_object_deactivate
*
* Remove the specified slot object from the appropriate object list.
*/
void
{
extern slot_data_t *slots;
} else {
}
(void) pthread_rwlock_wrlock(list_lock);
(void) pthread_rwlock_unlock(list_lock);
}
/*
* meta_slot_object_dealloc
*/
void
{
/* Not much cleanup for slot objects, unlike meta objects... */
}
/*
* meta_object_copyin
*
* created by the token are not immediately read into our copy of the
* attributes. We defer this work until we actually need to know.
*/
{
/* Make sure no one else is looking at attributes. */
/* Did we just lose a copyin race with another thread */
goto finish;
}
goto finish;
}
/*
* first, get the master template of all the attributes
* for this object
*/
goto finish;
}
/*
* Get value for each attribute items.
*
* Some attributes are required by the given object type.
* Some are optional. Get all the values first, and then
* make sure we have value for all required values,
*/
goto finish;
}
for (i = 0; i < object->num_attributes; i++) {
}
/* first, call C_GetAttributeValue() to get size for each attribute */
/*
* If the return value is not CKR_OK, allow it to be
* CKR_ATTRIBUTE_TYPE_INVALID for now.
* Some attributes defined in PKCS#11 version 2.11
* might not be defined in earlier versions. We will
* TRY to work with those providers if the attribute
* is optional.
*/
goto finish;
}
/*
* allocate space.
* Since we don't know how many attributes have
* values at this time, just assume all of them
* have values so we save one loop to count the number
* of attributes that have value.
*/
if (attrs_with_val == NULL) {
goto finish;
}
num_attrs_with_val = 0;
for (i = 0; i < num_attrs; i++) {
/* if it isn't an optional attr, len should be > 0 */
goto finish;
}
} else {
attrs[i].ulValueLen;
goto finish;
}
}
}
goto finish;
}
/* store these values into the meta object */
for (i = 0; i < num_attrs_with_val; i++) {
goto finish;
}
}
if (session)
if (attrs) {
for (i = 0; i < num_attrs; i++) {
}
}
}
if (attrs_with_val) {
for (i = 0; i < num_attrs; i++) {
}
}
}
return (rv);
}
/*
* Create an object to be used for wrapping and unwrapping.
* The same template will be used for all wrapping/unwrapping keys all
* the time
*/
static CK_RV
{
int i;
i = 0;
i++;
i++;
if (objclass == CKO_SECRET_KEY) {
i++;
i++;
i++;
} else {
/* Modulus is the same for rsa public and private key */
i++;
if (objclass == CKO_PUBLIC_KEY) {
/* RSA public key */
i++;
i++;
} else {
/* RSA private key */
i++;
i++;
}
}
return (rv);
}
/*
* Create a clone of a non-sensitive and extractable object.
* If the template required for creating the clone doesn't exist,
* it will be retrieved from the master clone.
*/
static CK_RV
{
return (rv);
}
}
return (rv);
}
}
/* Create the clone... */
return (rv);
}
return (CKR_OK);
}
/*
* Goes through the list of wraping mechanisms, and returns the first
* one that is supported by both the source and the destination slot.
* If none of the mechanisms are supported by both slot, return the
* first mechanism that's supported by the source slot
*/
static CK_RV
int *first_src_mech)
{
int i;
for (i = 0; i < num_info; i++) {
return (rv);
}
return (rv);
}
/* both source and destination supports the mech */
if ((src_supports) && (dst_supports)) {
*first_both_mech = i;
return (CKR_OK);
}
*first_src_mech = i;
}
}
return (CKR_OK);
}
/*
* Determine the wrapping/unwrapping mechanism to be used
*
* If possible, select a mechanism that's supported by both source
* and destination slot. If none of the mechanisms are supported
* by both slot, then, select the first one supported by
* the source slot.
*/
static CK_RV
{
unsigned int num_wrap_info;
int i;
/*
* only SKIPJACK keys can be used for wrapping
* KEA private keys
*/
for (i = 0; i < num_special_wrap_info; i++) {
if ((special_wrap_info[i]).mech_type
!= CKM_SKIPJACK_WRAP) {
continue;
}
goto finish;
}
goto finish;
}
if (src_supports) {
/*
* both src and dst supports the mech or
* only the src supports the mech
*/
&(special_wrap_info[i]),
sizeof (wrap_info_t));
goto finish;
}
}
/*
* if we are here, that means neither the source slot
* nor the destination slots suppports CKM_SKIPJACK_WRAP
*/
goto finish;
}
(key_type == CKK_JUNIPER)) {
/* special key types */
} else {
/* use the regular wrapping mechanisms */
}
first_both_mech = -1;
first_src_mech = -1;
goto finish;
}
if (first_both_mech != -1) {
sizeof (wrap_info_t));
goto finish;
}
/*
* If we are here, we did not find a mechanism that's supported
* by both source and destination slot.
*
* If it is a secret key, can also try to wrap it with
* a RSA public key
*/
if (obj_class == CKO_SECRET_KEY) {
first_both_mech = -1;
rsa_first_src_mech = -1;
goto finish;
}
if (first_both_mech > -1) {
sizeof (wrap_info_t));
goto finish;
}
}
/*
* if we are here, that means none of the mechanisms are supported
* by both the source and the destination
*/
if (first_src_mech > -1) {
/* source slot support one of the secret key mechs */
sizeof (wrap_info_t));
} else if (rsa_first_src_mech > -1) {
/* source slot support one of the RSA mechs */
sizeof (wrap_info_t));
} else {
/* neither source nor destination support any wrap mechs */
}
return (rv);
}
/*
* This is called if the object to be cloned is a sensitive object
*/
static CK_RV
{
CK_ULONG wrappedKeyLen = 0;
return (rv);
}
/*
* get the object class and key type for unwrap template
* This information will also be used for determining
* which wrap mechanism and which key to use for
* doing the wrapping
*/
unwrap_template, 2);
goto finish;
}
goto finish;
}
/*
* open the random device and read number of bytes required for
* creating a secret key for wrapping and unwrapping
*/
/*
* one time operation only. It doesn't need to be stored.
*/
int fd;
break;
}
if (fd == -1) {
goto finish;
}
goto finish;
}
goto finish;
}
}
}
/* create the wrapping key */
goto finish;
}
/* get the size of the wrapped key */
goto finish;
}
if (wrappedKey == NULL) {
goto finish;
}
/* do the actual key wrapping */
goto finish;
}
/* explicitly force the unwrapped object to be not sensitive */
sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
if (!wrap_info.dst_supports) {
/*
* if we know for sure that the destination slot doesn't
* support the wrapping mechanism, no point in trying.
* go directly to unwrap in source slot, and create key
* in destination
*/
goto unwrap_in_source;
}
/* create the unwrapping key in destination slot */
/* for RSA key, the unwrapping key need to be private key */
}
goto finish;
}
/*
* There seemed to be a problem with unwrapping in the
* destination slot.
* Try to do the unwrap in the src slot so it becomes
* a non-sensitive object, then, get all the attributes
* and create the object in the destination slot
*/
/* unwrap with same key used for wrapping */
} else {
/*
* If the object is wrapping with RSA public key, need
* need to create RSA private key for unwrapping
*/
goto finish;
}
}
goto finish;
}
goto finish;
}
goto finish;
}
goto finish;
}
= tmp_slot_obj;
B_FALSE);
tmp_slot_obj = NULL;
goto finish;
}
}
if (unwrappingKey) {
}
if (wrappingKey) {
}
if (tmp_slot_obj) {
(void) meta_slot_object_dealloc(tmp_slot_obj);
}
if (tmp_meta_obj) {
}
if (tmp_meta_session) {
(void) meta_session_dealloc(tmp_meta_session);
}
if (wrappedKey) {
}
if (src_slot_session) {
}
return (rv);
}
/*
* meta_object_get_clone
*
* Creates a "clone" of a metaobject on the specified slot. A clone is a
* copy of the object.
*
* Clones are cached, so that they can be reused with subsquent operations.
*/
{
/* Does a clone already exist? */
return (CKR_OK);
}
/*
* if the object is a sensitive token object, and auto
* key migrate is not allowed, will not create the clone
* in another slot
*/
return (CKR_FUNCTION_FAILED);
}
/* object attributes can't be extracted and attributes are not known */
return (CKR_FUNCTION_FAILED);
}
/*
* has an attempt already been made to create this object in
* slot? If yes, and there's no clone, as indicated above,
* that means this object can't be created in this slot.
*/
return (CKR_FUNCTION_FAILED);
}
/* Maybe someone just created one? */
goto finish;
}
goto finish;
if (object->isSensitive) {
} else {
}
goto finish;
}
if (newclone)
return (rv);
}
/*
* meta_setup_clone_template
*
* Create a clone template for the specified object.
*/
static CK_RV
{
size_t i, c = 0;
if (clone_template == NULL) {
goto finish;
}
/* Don't allow attributes to change while we look at them. */
for (i = 0; i < num_attributes; i++) {
if (!attributes[i].isCloneAttr) {
continue;
}
if ((!(attributes[i].hasValueForClone)) &&
(attributes[i].canBeEmptyValue)) {
continue;
}
clone_template[c].ulValueLen =
/* Allocate space to store the attribute value. */
goto finish;
}
clone_template[c].ulValueLen);
c++;
}
object->clone_template_size = c;
return (rv);
}
/*
* meta_object_find_by_handle
*
* Search for an existing metaobject, using the object handle of a clone
* on a particular slot.
*
* Returns a matching metaobject, or NULL if no match was found.
*/
{
if (!token_only) {
(void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
/* lock the objects list while we look at it */
(void) pthread_rwlock_rdlock(
&(session->object_list_lock));
(void) pthread_rwlock_rdlock(
&(tmp_obj->object_lock));
if (slot_object != NULL) {
}
}
(void) pthread_rwlock_unlock(
&(tmp_obj->object_lock));
break;
}
}
(void) pthread_rwlock_unlock(
&(session->object_list_lock));
break;
}
}
(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
}
/* found the object, no need to look further */
return (object);
}
/*
* Look at list of token objects
*/
(void) pthread_rwlock_rdlock(&tokenobject_list_lock);
if (slot_object != NULL) {
}
break;
}
}
(void) pthread_rwlock_unlock(&tokenobject_list_lock);
return (object);
}
{
/* get a write lock on the token object list */
(void) pthread_rwlock_wrlock(&tokenobject_list_lock);
/* go through each object and delete the one with matching type */
if ((token_type == ALL_TOKEN) ||
goto finish;
}
goto finish;
}
}
object = tmp_object;
}
(void) pthread_rwlock_unlock(&tokenobject_list_lock);
return (save_rv);
}
/*
* This function adds the to-be-freed meta 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.
*/
}
}