Index: mozilla/security/nss/lib/softoken/pkcs11u.c |
=================================================================== |
--- mozilla/security/nss/lib/softoken/pkcs11u.c (revision 191424) |
+++ mozilla/security/nss/lib/softoken/pkcs11u.c (working copy) |
@@ -1,1979 +0,0 @@ |
-/* This Source Code Form is subject to the terms of the Mozilla Public |
- * License, v. 2.0. If a copy of the MPL was not distributed with this |
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
-/* |
- * Internal PKCS #11 functions. Should only be called by pkcs11.c |
- */ |
-#include "pkcs11.h" |
-#include "pkcs11i.h" |
-#include "lowkeyi.h" |
-#include "secasn1.h" |
-#include "blapi.h" |
-#include "secerr.h" |
-#include "prnetdb.h" /* for PR_ntohl */ |
-#include "sftkdb.h" |
-#include "softoken.h" |
- |
-/* |
- * ******************** Attribute Utilities ******************************* |
- */ |
- |
-/* |
- * create a new attribute with type, value, and length. Space is allocated |
- * to hold value. |
- */ |
-static SFTKAttribute * |
-sftk_NewAttribute(SFTKObject *object, |
- CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len) |
-{ |
- SFTKAttribute *attribute; |
- |
- SFTKSessionObject *so = sftk_narrowToSessionObject(object); |
- int index; |
- |
- if (so == NULL) { |
- /* allocate new attribute in a buffer */ |
- PORT_Assert(0); |
- return NULL; |
- } |
- /* |
- * We attempt to keep down contention on Malloc and Arena locks by |
- * limiting the number of these calls on high traversed paths. This |
- * is done for attributes by 'allocating' them from a pool already |
- * allocated by the parent object. |
- */ |
- PZ_Lock(so->attributeLock); |
- index = so->nextAttr++; |
- PZ_Unlock(so->attributeLock); |
- PORT_Assert(index < MAX_OBJS_ATTRS); |
- if (index >= MAX_OBJS_ATTRS) return NULL; |
- |
- attribute = &so->attrList[index]; |
- attribute->attrib.type = type; |
- attribute->freeAttr = PR_FALSE; |
- attribute->freeData = PR_FALSE; |
- if (value) { |
- if (len <= ATTR_SPACE) { |
- attribute->attrib.pValue = attribute->space; |
- } else { |
- attribute->attrib.pValue = PORT_Alloc(len); |
- attribute->freeData = PR_TRUE; |
- } |
- if (attribute->attrib.pValue == NULL) { |
- return NULL; |
- } |
- PORT_Memcpy(attribute->attrib.pValue,value,len); |
- attribute->attrib.ulValueLen = len; |
- } else { |
- attribute->attrib.pValue = NULL; |
- attribute->attrib.ulValueLen = 0; |
- } |
- attribute->attrib.type = type; |
- attribute->handle = type; |
- attribute->next = attribute->prev = NULL; |
- return attribute; |
-} |
- |
-/* |
- * Free up all the memory associated with an attribute. Reference count |
- * must be zero to call this. |
- */ |
-static void |
-sftk_DestroyAttribute(SFTKAttribute *attribute) |
-{ |
- if (attribute->freeData) { |
- if (attribute->attrib.pValue) { |
- /* clear out the data in the attribute value... it may have been |
- * sensitive data */ |
- PORT_Memset(attribute->attrib.pValue, 0, |
- attribute->attrib.ulValueLen); |
- } |
- PORT_Free(attribute->attrib.pValue); |
- } |
- PORT_Free(attribute); |
-} |
- |
-/* |
- * release a reference to an attribute structure |
- */ |
-void |
-sftk_FreeAttribute(SFTKAttribute *attribute) |
-{ |
- if (attribute->freeAttr) { |
- sftk_DestroyAttribute(attribute); |
- return; |
- } |
-} |
- |
-static SFTKAttribute * |
-sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *myattribute = NULL; |
- SFTKDBHandle *dbHandle = NULL; |
- CK_RV crv = CKR_HOST_MEMORY; |
- |
- myattribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute)); |
- if (myattribute == NULL) { |
- goto loser; |
- } |
- |
- dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle); |
- |
- myattribute->handle = type; |
- myattribute->attrib.type = type; |
- myattribute->attrib.pValue = myattribute->space; |
- myattribute->attrib.ulValueLen = ATTR_SPACE; |
- myattribute->next = myattribute->prev = NULL; |
- myattribute->freeAttr = PR_TRUE; |
- myattribute->freeData = PR_FALSE; |
- |
- crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, |
- &myattribute->attrib, 1); |
- |
- /* attribute is bigger than our attribute space buffer, malloc it */ |
- if (crv == CKR_BUFFER_TOO_SMALL) { |
- myattribute->attrib.pValue = NULL; |
- crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, |
- &myattribute->attrib, 1); |
- if (crv != CKR_OK) { |
- goto loser; |
- } |
- myattribute->attrib.pValue = PORT_Alloc(myattribute->attrib.ulValueLen); |
- if (myattribute->attrib.pValue == NULL) { |
- crv = CKR_HOST_MEMORY; |
- goto loser; |
- } |
- myattribute->freeData = PR_TRUE; |
- crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, |
- &myattribute->attrib, 1); |
- } |
-loser: |
- if (dbHandle) { |
- sftk_freeDB(dbHandle); |
- } |
- if (crv != CKR_OK) { |
- if (myattribute) { |
- myattribute->attrib.ulValueLen = 0; |
- sftk_FreeAttribute(myattribute); |
- myattribute = NULL; |
- } |
- } |
- return myattribute; |
-} |
- |
-/* |
- * look up and attribute structure from a type and Object structure. |
- * The returned attribute is referenced and needs to be freed when |
- * it is no longer needed. |
- */ |
-SFTKAttribute * |
-sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); |
- |
- if (sessObject == NULL) { |
- return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type); |
- } |
- |
- PZ_Lock(sessObject->attributeLock); |
- sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize); |
- PZ_Unlock(sessObject->attributeLock); |
- |
- return(attribute); |
-} |
- |
-/* |
- * Take a buffer and it's length and return it's true size in bits; |
- */ |
-unsigned int |
-sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen) |
-{ |
- unsigned int size = bufLen * 8; |
- unsigned int i; |
- |
- /* Get the real length in bytes */ |
- for (i=0; i < bufLen; i++) { |
- unsigned char c = *buf++; |
- if (c != 0) { |
- unsigned char m; |
- for (m=0x80; m > 0 ; m = m >> 1) { |
- if ((c & m) != 0) { |
- break; |
- } |
- size--; |
- } |
- break; |
- } |
- size-=8; |
- } |
- return size; |
-} |
- |
-/* |
- * Constrain a big num attribute. to size and padding |
- * minLength means length of the object must be greater than equal to minLength |
- * maxLength means length of the object must be less than equal to maxLength |
- * minMultiple means that object length mod minMultiple must equal 0. |
- * all input sizes are in bits. |
- * if any constraint is '0' that constraint is not checked. |
- */ |
-CK_RV |
-sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, |
- int minLength, int maxLength, int minMultiple) |
-{ |
- SFTKAttribute *attribute; |
- int size; |
- unsigned char *ptr; |
- |
- attribute = sftk_FindAttribute(object, type); |
- if (!attribute) { |
- return CKR_TEMPLATE_INCOMPLETE; |
- } |
- ptr = (unsigned char *) attribute->attrib.pValue; |
- if (ptr == NULL) { |
- sftk_FreeAttribute(attribute); |
- return CKR_ATTRIBUTE_VALUE_INVALID; |
- } |
- size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen); |
- sftk_FreeAttribute(attribute); |
- |
- if ((minLength != 0) && (size < minLength)) { |
- return CKR_ATTRIBUTE_VALUE_INVALID; |
- } |
- if ((maxLength != 0) && (size > maxLength)) { |
- return CKR_ATTRIBUTE_VALUE_INVALID; |
- } |
- if ((minMultiple != 0) && ((size % minMultiple) != 0)) { |
- return CKR_ATTRIBUTE_VALUE_INVALID; |
- } |
- return CKR_OK; |
-} |
- |
-PRBool |
-sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) |
-{ |
- CK_ATTRIBUTE template; |
- CK_RV crv; |
- SFTKDBHandle *dbHandle; |
- |
- dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle); |
- template.type = type; |
- template.pValue = NULL; |
- template.ulValueLen = 0; |
- |
- crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1); |
- sftk_freeDB(dbHandle); |
- |
- /* attribute is bigger than our attribute space buffer, malloc it */ |
- return (crv == CKR_OK) ? PR_TRUE : PR_FALSE; |
-} |
- |
-/* |
- * return true if object has attribute |
- */ |
-PRBool |
-sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); |
- |
- if (sessObject == NULL) { |
- return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type); |
- } |
- |
- PZ_Lock(sessObject->attributeLock); |
- sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize); |
- PZ_Unlock(sessObject->attributeLock); |
- |
- return (PRBool)(attribute != NULL); |
-} |
- |
-/* |
- * add an attribute to an object |
- */ |
-static void |
-sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute) |
-{ |
- SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); |
- |
- if (sessObject == NULL) return; |
- PZ_Lock(sessObject->attributeLock); |
- sftkqueue_add(attribute,attribute->handle, |
- sessObject->head, sessObject->hashSize); |
- PZ_Unlock(sessObject->attributeLock); |
-} |
- |
-/* |
- * copy an unsigned attribute into a SECItem. Secitem is allocated in |
- * the specified arena. |
- */ |
-CK_RV |
-sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object, |
- CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- |
- item->data = NULL; |
- |
- attribute = sftk_FindAttribute(object, type); |
- if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; |
- |
- (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen); |
- if (item->data == NULL) { |
- sftk_FreeAttribute(attribute); |
- return CKR_HOST_MEMORY; |
- } |
- PORT_Memcpy(item->data, attribute->attrib.pValue, item->len); |
- sftk_FreeAttribute(attribute); |
- return CKR_OK; |
-} |
- |
-/* |
- * fetch multiple attributes into SECItems. Secitem data is allocated in |
- * the specified arena. |
- */ |
-CK_RV |
-sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object, |
- SFTKItemTemplate *itemTemplate, int itemTemplateCount) |
-{ |
- |
- CK_RV crv = CKR_OK; |
- CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE]; |
- CK_ATTRIBUTE *template; |
- SFTKTokenObject *tokObject; |
- SFTKDBHandle *dbHandle = NULL; |
- int i; |
- |
- tokObject = sftk_narrowToTokenObject(object); |
- |
- /* session objects, just loop through the list */ |
- if (tokObject == NULL) { |
- for (i=0; i < itemTemplateCount; i++) { |
- crv = sftk_Attribute2SecItem(arena,itemTemplate[i].item, object, |
- itemTemplate[i].type); |
- if (crv != CKR_OK) { |
- return crv; |
- } |
- } |
- return CKR_OK; |
- } |
- |
- /* don't do any work if none is required */ |
- if (itemTemplateCount == 0) { |
- return CKR_OK; |
- } |
- |
- /* don't allocate the template unless we need it */ |
- if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE) { |
- template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount); |
- } else { |
- template = templateSpace; |
- } |
- |
- if (template == NULL) { |
- crv = CKR_HOST_MEMORY; |
- goto loser; |
- } |
- |
- dbHandle = sftk_getDBForTokenObject(object->slot, object->handle); |
- if (dbHandle == NULL) { |
- crv = CKR_OBJECT_HANDLE_INVALID; |
- goto loser; |
- } |
- |
- /* set up the PKCS #11 template */ |
- for (i=0; i < itemTemplateCount; i++) { |
- template[i].type = itemTemplate[i].type; |
- template[i].pValue = NULL; |
- template[i].ulValueLen = 0; |
- } |
- |
- /* fetch the attribute lengths */ |
- crv = sftkdb_GetAttributeValue(dbHandle, object->handle, |
- template, itemTemplateCount); |
- if (crv != CKR_OK) { |
- goto loser; |
- } |
- |
- /* allocate space for the attributes */ |
- for (i=0; i < itemTemplateCount ; i++) { |
- template[i].pValue = PORT_ArenaAlloc(arena, template[i].ulValueLen); |
- if (template[i].pValue == NULL) { |
- crv = CKR_HOST_MEMORY; |
- goto loser; |
- } |
- } |
- |
- /* fetch the attributes */ |
- crv = sftkdb_GetAttributeValue(dbHandle, object->handle, |
- template, itemTemplateCount); |
- if (crv != CKR_OK) { |
- goto loser; |
- } |
- |
- /* Fill in the items */ |
- for (i=0; i < itemTemplateCount; i++) { |
- itemTemplate[i].item->data = template[i].pValue; |
- itemTemplate[i].item->len = template[i].ulValueLen; |
- } |
- |
-loser: |
- if (template != templateSpace) { |
- PORT_Free(template); |
- } |
- if (dbHandle) { |
- sftk_freeDB(dbHandle); |
- } |
- |
- return crv; |
-} |
- |
- |
-/* |
- * delete an attribute from an object |
- */ |
-static void |
-sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute) |
-{ |
- SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); |
- |
- if (sessObject == NULL) { |
- return ; |
- } |
- PZ_Lock(sessObject->attributeLock); |
- if (sftkqueue_is_queued(attribute,attribute->handle, |
- sessObject->head, sessObject->hashSize)) { |
- sftkqueue_delete(attribute,attribute->handle, |
- sessObject->head, sessObject->hashSize); |
- } |
- PZ_Unlock(sessObject->attributeLock); |
-} |
- |
-/* |
- * this is only valid for CK_BBOOL type attributes. Return the state |
- * of that attribute. |
- */ |
-PRBool |
-sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- PRBool tok = PR_FALSE; |
- |
- attribute=sftk_FindAttribute(object,type); |
- if (attribute == NULL) { return PR_FALSE; } |
- tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue); |
- sftk_FreeAttribute(attribute); |
- |
- return tok; |
-} |
- |
-/* |
- * force an attribute to null. |
- * this is for sensitive keys which are stored in the database, we don't |
- * want to keep this info around in memory in the clear. |
- */ |
-void |
-sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- |
- attribute=sftk_FindAttribute(object,type); |
- if (attribute == NULL) return; |
- |
- if (attribute->attrib.pValue != NULL) { |
- PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); |
- if (attribute->freeData) { |
- PORT_Free(attribute->attrib.pValue); |
- } |
- attribute->freeData = PR_FALSE; |
- attribute->attrib.pValue = NULL; |
- attribute->attrib.ulValueLen = 0; |
- } |
- sftk_FreeAttribute(attribute); |
-} |
- |
- |
-static CK_RV |
-sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, |
- const void *value, unsigned int len) |
-{ |
- CK_ATTRIBUTE attribute; |
- SFTKDBHandle *dbHandle = NULL; |
- SFTKTokenObject *to = sftk_narrowToTokenObject(object); |
- CK_RV crv; |
- |
- PORT_Assert(to); |
- if (to == NULL) { |
- return CKR_DEVICE_ERROR; |
- } |
- |
- dbHandle = sftk_getDBForTokenObject(object->slot, object->handle); |
- |
- attribute.type = type; |
- attribute.pValue = (void *)value; |
- attribute.ulValueLen = len; |
- |
- crv = sftkdb_SetAttributeValue(dbHandle, object, &attribute, 1); |
- sftk_freeDB(dbHandle); |
- return crv; |
-} |
- |
-/* |
- * force an attribute to a specifc value. |
- */ |
-CK_RV |
-sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, |
- const void *value, unsigned int len) |
-{ |
- SFTKAttribute *attribute; |
- void *att_val = NULL; |
- PRBool freeData = PR_FALSE; |
- |
- PORT_Assert(object); |
- PORT_Assert(object->refCount); |
- PORT_Assert(object->slot); |
- if (!object || |
- !object->refCount || |
- !object->slot) { |
- return CKR_DEVICE_ERROR; |
- } |
- if (sftk_isToken(object->handle)) { |
- return sftk_forceTokenAttribute(object,type,value,len); |
- } |
- attribute=sftk_FindAttribute(object,type); |
- if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len); |
- |
- |
- if (value) { |
- if (len <= ATTR_SPACE) { |
- att_val = attribute->space; |
- } else { |
- att_val = PORT_Alloc(len); |
- freeData = PR_TRUE; |
- } |
- if (att_val == NULL) { |
- return CKR_HOST_MEMORY; |
- } |
- if (attribute->attrib.pValue == att_val) { |
- PORT_Memset(attribute->attrib.pValue,0, |
- attribute->attrib.ulValueLen); |
- } |
- PORT_Memcpy(att_val,value,len); |
- } |
- if (attribute->attrib.pValue != NULL) { |
- if (attribute->attrib.pValue != att_val) { |
- PORT_Memset(attribute->attrib.pValue,0, |
- attribute->attrib.ulValueLen); |
- } |
- if (attribute->freeData) { |
- PORT_Free(attribute->attrib.pValue); |
- } |
- attribute->freeData = PR_FALSE; |
- attribute->attrib.pValue = NULL; |
- attribute->attrib.ulValueLen = 0; |
- } |
- if (att_val) { |
- attribute->attrib.pValue = att_val; |
- attribute->attrib.ulValueLen = len; |
- attribute->freeData = freeData; |
- } |
- sftk_FreeAttribute(attribute); |
- return CKR_OK; |
-} |
- |
-/* |
- * return a null terminated string from attribute 'type'. This string |
- * is allocated and needs to be freed with PORT_Free() When complete. |
- */ |
-char * |
-sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- char *label = NULL; |
- |
- attribute=sftk_FindAttribute(object,type); |
- if (attribute == NULL) return NULL; |
- |
- if (attribute->attrib.pValue != NULL) { |
- label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1); |
- if (label == NULL) { |
- sftk_FreeAttribute(attribute); |
- return NULL; |
- } |
- |
- PORT_Memcpy(label,attribute->attrib.pValue, |
- attribute->attrib.ulValueLen); |
- label[attribute->attrib.ulValueLen] = 0; |
- } |
- sftk_FreeAttribute(attribute); |
- return label; |
-} |
- |
-/* |
- * decode when a particular attribute may be modified |
- * SFTK_NEVER: This attribute must be set at object creation time and |
- * can never be modified. |
- * SFTK_ONCOPY: This attribute may be modified only when you copy the |
- * object. |
- * SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from |
- * CK_FALSE to CK_TRUE. |
- * SFTK_ALWAYS: This attribute can always be modified. |
- * Some attributes vary their modification type based on the class of the |
- * object. |
- */ |
-SFTKModifyType |
-sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) |
-{ |
- /* if we don't know about it, user user defined, always allow modify */ |
- SFTKModifyType mtype = SFTK_ALWAYS; |
- |
- switch(type) { |
- /* NEVER */ |
- case CKA_CLASS: |
- case CKA_CERTIFICATE_TYPE: |
- case CKA_KEY_TYPE: |
- case CKA_MODULUS: |
- case CKA_MODULUS_BITS: |
- case CKA_PUBLIC_EXPONENT: |
- case CKA_PRIVATE_EXPONENT: |
- case CKA_PRIME: |
- case CKA_SUBPRIME: |
- case CKA_BASE: |
- case CKA_PRIME_1: |
- case CKA_PRIME_2: |
- case CKA_EXPONENT_1: |
- case CKA_EXPONENT_2: |
- case CKA_COEFFICIENT: |
- case CKA_VALUE_LEN: |
- case CKA_ALWAYS_SENSITIVE: |
- case CKA_NEVER_EXTRACTABLE: |
- case CKA_NETSCAPE_DB: |
- mtype = SFTK_NEVER; |
- break; |
- |
- /* ONCOPY */ |
- case CKA_TOKEN: |
- case CKA_PRIVATE: |
- case CKA_MODIFIABLE: |
- mtype = SFTK_ONCOPY; |
- break; |
- |
- /* SENSITIVE */ |
- case CKA_SENSITIVE: |
- case CKA_EXTRACTABLE: |
- mtype = SFTK_SENSITIVE; |
- break; |
- |
- /* ALWAYS */ |
- case CKA_LABEL: |
- case CKA_APPLICATION: |
- case CKA_ID: |
- case CKA_SERIAL_NUMBER: |
- case CKA_START_DATE: |
- case CKA_END_DATE: |
- case CKA_DERIVE: |
- case CKA_ENCRYPT: |
- case CKA_DECRYPT: |
- case CKA_SIGN: |
- case CKA_VERIFY: |
- case CKA_SIGN_RECOVER: |
- case CKA_VERIFY_RECOVER: |
- case CKA_WRAP: |
- case CKA_UNWRAP: |
- mtype = SFTK_ALWAYS; |
- break; |
- |
- /* DEPENDS ON CLASS */ |
- case CKA_VALUE: |
- mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER; |
- break; |
- |
- case CKA_SUBJECT: |
- mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS; |
- break; |
- default: |
- break; |
- } |
- return mtype; |
-} |
- |
-/* decode if a particular attribute is sensitive (cannot be read |
- * back to the user of if the object is set to SENSITIVE) */ |
-PRBool |
-sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) |
-{ |
- switch(type) { |
- /* ALWAYS */ |
- case CKA_PRIVATE_EXPONENT: |
- case CKA_PRIME_1: |
- case CKA_PRIME_2: |
- case CKA_EXPONENT_1: |
- case CKA_EXPONENT_2: |
- case CKA_COEFFICIENT: |
- return PR_TRUE; |
- |
- /* DEPENDS ON CLASS */ |
- case CKA_VALUE: |
- /* PRIVATE and SECRET KEYS have SENSITIVE values */ |
- return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY)); |
- |
- default: |
- break; |
- } |
- return PR_FALSE; |
-} |
- |
-/* |
- * copy an attribute into a SECItem. Secitem is allocated in the specified |
- * arena. |
- */ |
-CK_RV |
-sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object, |
- CK_ATTRIBUTE_TYPE type) |
-{ |
- int len; |
- SFTKAttribute *attribute; |
- |
- attribute = sftk_FindAttribute(object, type); |
- if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; |
- len = attribute->attrib.ulValueLen; |
- |
- if (arena) { |
- item->data = (unsigned char *) PORT_ArenaAlloc(arena,len); |
- } else { |
- item->data = (unsigned char *) PORT_Alloc(len); |
- } |
- if (item->data == NULL) { |
- sftk_FreeAttribute(attribute); |
- return CKR_HOST_MEMORY; |
- } |
- item->len = len; |
- PORT_Memcpy(item->data,attribute->attrib.pValue, len); |
- sftk_FreeAttribute(attribute); |
- return CKR_OK; |
-} |
- |
-CK_RV |
-sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, |
- CK_ULONG *longData) |
-{ |
- SFTKAttribute *attribute; |
- |
- attribute = sftk_FindAttribute(object, type); |
- if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; |
- |
- if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) { |
- return CKR_ATTRIBUTE_VALUE_INVALID; |
- } |
- |
- *longData = *(CK_ULONG *)attribute->attrib.pValue; |
- sftk_FreeAttribute(attribute); |
- return CKR_OK; |
-} |
- |
-void |
-sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type) |
-{ |
- SFTKAttribute *attribute; |
- attribute = sftk_FindAttribute(object, type); |
- if (attribute == NULL) return ; |
- sftk_DeleteAttribute(object,attribute); |
- sftk_FreeAttribute(attribute); |
-} |
- |
-CK_RV |
-sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type, |
- const void *valPtr, CK_ULONG length) |
-{ |
- SFTKAttribute *attribute; |
- attribute = sftk_NewAttribute(object,type,valPtr,length); |
- if (attribute == NULL) { return CKR_HOST_MEMORY; } |
- sftk_AddAttribute(object,attribute); |
- return CKR_OK; |
-} |
- |
-/* |
- * ******************** Object Utilities ******************************* |
- */ |
- |
-/* must be called holding sftk_tokenKeyLock(slot) */ |
-static SECItem * |
-sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) |
-{ |
- return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle); |
-} |
- |
-/* |
- * use the refLock. This operations should be very rare, so the added |
- * contention on the ref lock should be lower than the overhead of adding |
- * a new lock. We use separate functions for this just in case I'm wrong. |
- */ |
-static void |
-sftk_tokenKeyLock(SFTKSlot *slot) { |
- SKIP_AFTER_FORK(PZ_Lock(slot->objectLock)); |
-} |
- |
-static void |
-sftk_tokenKeyUnlock(SFTKSlot *slot) { |
- SKIP_AFTER_FORK(PZ_Unlock(slot->objectLock)); |
-} |
- |
-static PRIntn |
-sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg) |
-{ |
- SECItem *item = (SECItem *)entry->value; |
- |
- SECITEM_FreeItem(item, PR_TRUE); |
- return HT_ENUMERATE_NEXT; |
-} |
- |
-CK_RV |
-SFTK_ClearTokenKeyHashTable(SFTKSlot *slot) |
-{ |
- sftk_tokenKeyLock(slot); |
- PORT_Assert(!slot->present); |
- PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL); |
- sftk_tokenKeyUnlock(slot); |
- return CKR_OK; |
-} |
- |
- |
-/* allocation hooks that allow us to recycle old object structures */ |
-static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 }; |
-static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 }; |
- |
-SFTKObject * |
-sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace, |
- SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject) |
-{ |
- SFTKObject *object; |
- int size = 0; |
- |
- if (!optimizeSpace) { |
- PZ_Lock(list->lock); |
- object = list->head; |
- if (object) { |
- list->head = object->next; |
- list->count--; |
- } |
- PZ_Unlock(list->lock); |
- if (object) { |
- object->next = object->prev = NULL; |
- *hasLocks = PR_TRUE; |
- return object; |
- } |
- } |
- size = isSessionObject ? sizeof(SFTKSessionObject) |
- + hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject); |
- |
- object = (SFTKObject*)PORT_ZAlloc(size); |
- if (isSessionObject && object) { |
- ((SFTKSessionObject *)object)->hashSize = hashSize; |
- } |
- *hasLocks = PR_FALSE; |
- return object; |
-} |
- |
-static void |
-sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list, |
- PRBool isSessionObject) { |
- |
- /* the code below is equivalent to : |
- * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE; |
- * just faster. |
- */ |
- PRBool optimizeSpace = isSessionObject && |
- ((SFTKSessionObject *)object)->optimizeSpace; |
- if (object->refLock && !optimizeSpace |
- && (list->count < MAX_OBJECT_LIST_SIZE)) { |
- PZ_Lock(list->lock); |
- object->next = list->head; |
- list->head = object; |
- list->count++; |
- PZ_Unlock(list->lock); |
- return; |
- } |
- if (isSessionObject) { |
- SFTKSessionObject *so = (SFTKSessionObject *)object; |
- PZ_DestroyLock(so->attributeLock); |
- so->attributeLock = NULL; |
- } |
- if (object->refLock) { |
- PZ_DestroyLock(object->refLock); |
- object->refLock = NULL; |
- } |
- PORT_Free(object); |
-} |
- |
-static SFTKObject * |
-sftk_freeObjectData(SFTKObject *object) { |
- SFTKObject *next = object->next; |
- |
- PORT_Free(object); |
- return next; |
-} |
- |
-static void |
-sftk_InitFreeList(SFTKObjectFreeList *list) |
-{ |
- list->lock = PZ_NewLock(nssILockObject); |
-} |
- |
-void sftk_InitFreeLists(void) |
-{ |
- sftk_InitFreeList(&sessionObjectList); |
- sftk_InitFreeList(&tokenObjectList); |
-} |
- |
-static void |
-sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList) |
-{ |
- SFTKObject *object; |
- |
- if (!list->lock) { |
- return; |
- } |
- SKIP_AFTER_FORK(PZ_Lock(list->lock)); |
- for (object= list->head; object != NULL; |
- object = sftk_freeObjectData(object)) { |
- PZ_DestroyLock(object->refLock); |
- if (isSessionList) { |
- PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock); |
- } |
- } |
- list->count = 0; |
- list->head = NULL; |
- SKIP_AFTER_FORK(PZ_Unlock(list->lock)); |
- SKIP_AFTER_FORK(PZ_DestroyLock(list->lock)); |
- list->lock = NULL; |
-} |
- |
-void |
-sftk_CleanupFreeLists(void) |
-{ |
- sftk_CleanupFreeList(&sessionObjectList, PR_TRUE); |
- sftk_CleanupFreeList(&tokenObjectList, PR_FALSE); |
-} |
- |
- |
-/* |
- * Create a new object |
- */ |
-SFTKObject * |
-sftk_NewObject(SFTKSlot *slot) |
-{ |
- SFTKObject *object; |
- SFTKSessionObject *sessObject; |
- PRBool hasLocks = PR_FALSE; |
- unsigned int i; |
- unsigned int hashSize = 0; |
- |
- hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE : |
- TIME_ATTRIBUTE_HASH_SIZE; |
- |
- object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace, |
- &sessionObjectList, hashSize, PR_TRUE); |
- if (object == NULL) { |
- return NULL; |
- } |
- sessObject = (SFTKSessionObject *)object; |
- sessObject->nextAttr = 0; |
- |
- for (i=0; i < MAX_OBJS_ATTRS; i++) { |
- sessObject->attrList[i].attrib.pValue = NULL; |
- sessObject->attrList[i].freeData = PR_FALSE; |
- } |
- sessObject->optimizeSpace = slot->optimizeSpace; |
- |
- object->handle = 0; |
- object->next = object->prev = NULL; |
- object->slot = slot; |
- |
- object->refCount = 1; |
- sessObject->sessionList.next = NULL; |
- sessObject->sessionList.prev = NULL; |
- sessObject->sessionList.parent = object; |
- sessObject->session = NULL; |
- sessObject->wasDerived = PR_FALSE; |
- if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock); |
- if (object->refLock == NULL) { |
- PORT_Free(object); |
- return NULL; |
- } |
- if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute); |
- if (sessObject->attributeLock == NULL) { |
- PZ_DestroyLock(object->refLock); |
- PORT_Free(object); |
- return NULL; |
- } |
- for (i=0; i < sessObject->hashSize; i++) { |
- sessObject->head[i] = NULL; |
- } |
- object->objectInfo = NULL; |
- object->infoFree = NULL; |
- return object; |
-} |
- |
-static CK_RV |
-sftk_DestroySessionObjectData(SFTKSessionObject *so) |
-{ |
- int i; |
- |
- for (i=0; i < MAX_OBJS_ATTRS; i++) { |
- unsigned char *value = so->attrList[i].attrib.pValue; |
- if (value) { |
- PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen); |
- if (so->attrList[i].freeData) { |
- PORT_Free(value); |
- } |
- so->attrList[i].attrib.pValue = NULL; |
- so->attrList[i].freeData = PR_FALSE; |
- } |
- } |
-/* PZ_DestroyLock(so->attributeLock);*/ |
- return CKR_OK; |
-} |
- |
-/* |
- * free all the data associated with an object. Object reference count must |
- * be 'zero'. |
- */ |
-static CK_RV |
-sftk_DestroyObject(SFTKObject *object) |
-{ |
- CK_RV crv = CKR_OK; |
- SFTKSessionObject *so = sftk_narrowToSessionObject(object); |
- SFTKTokenObject *to = sftk_narrowToTokenObject(object); |
- |
- PORT_Assert(object->refCount == 0); |
- |
- /* delete the database value */ |
- if (to) { |
- if (to->dbKey.data) { |
- PORT_Free(to->dbKey.data); |
- to->dbKey.data = NULL; |
- } |
- } |
- if (so) { |
- sftk_DestroySessionObjectData(so); |
- } |
- if (object->objectInfo) { |
- (*object->infoFree)(object->objectInfo); |
- object->objectInfo = NULL; |
- object->infoFree = NULL; |
- } |
- if (so) { |
- sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE); |
- } else { |
- sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE); |
- } |
- return crv; |
-} |
- |
-void |
-sftk_ReferenceObject(SFTKObject *object) |
-{ |
- PZ_Lock(object->refLock); |
- object->refCount++; |
- PZ_Unlock(object->refLock); |
-} |
- |
-static SFTKObject * |
-sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot) |
-{ |
- SFTKObject *object; |
- PRUint32 index = sftk_hash(handle, slot->sessObjHashSize); |
- |
- if (sftk_isToken(handle)) { |
- return sftk_NewTokenObject(slot, NULL, handle); |
- } |
- |
- PZ_Lock(slot->objectLock); |
- sftkqueue_find2(object, handle, index, slot->sessObjHashTable); |
- if (object) { |
- sftk_ReferenceObject(object); |
- } |
- PZ_Unlock(slot->objectLock); |
- |
- return(object); |
-} |
-/* |
- * look up and object structure from a handle. OBJECT_Handles only make |
- * sense in terms of a given session. make a reference to that object |
- * structure returned. |
- */ |
-SFTKObject * |
-sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session) |
-{ |
- SFTKSlot *slot = sftk_SlotFromSession(session); |
- |
- return sftk_ObjectFromHandleOnSlot(handle,slot); |
-} |
- |
- |
-/* |
- * release a reference to an object handle |
- */ |
-SFTKFreeStatus |
-sftk_FreeObject(SFTKObject *object) |
-{ |
- PRBool destroy = PR_FALSE; |
- CK_RV crv; |
- |
- PZ_Lock(object->refLock); |
- if (object->refCount == 1) destroy = PR_TRUE; |
- object->refCount--; |
- PZ_Unlock(object->refLock); |
- |
- if (destroy) { |
- crv = sftk_DestroyObject(object); |
- if (crv != CKR_OK) { |
- return SFTK_DestroyFailure; |
- } |
- return SFTK_Destroyed; |
- } |
- return SFTK_Busy; |
-} |
- |
-/* |
- * add an object to a slot and session queue. These two functions |
- * adopt the object. |
- */ |
-void |
-sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object) |
-{ |
- PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); |
- sftkqueue_init_element(object); |
- PZ_Lock(slot->objectLock); |
- sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable); |
- PZ_Unlock(slot->objectLock); |
-} |
- |
-void |
-sftk_AddObject(SFTKSession *session, SFTKObject *object) |
-{ |
- SFTKSlot *slot = sftk_SlotFromSession(session); |
- SFTKSessionObject *so = sftk_narrowToSessionObject(object); |
- |
- if (so) { |
- PZ_Lock(session->objectLock); |
- sftkqueue_add(&so->sessionList,0,session->objects,0); |
- so->session = session; |
- PZ_Unlock(session->objectLock); |
- } |
- sftk_AddSlotObject(slot,object); |
- sftk_ReferenceObject(object); |
-} |
- |
-/* |
- * delete an object from a slot and session queue |
- */ |
-CK_RV |
-sftk_DeleteObject(SFTKSession *session, SFTKObject *object) |
-{ |
- SFTKSlot *slot = sftk_SlotFromSession(session); |
- SFTKSessionObject *so = sftk_narrowToSessionObject(object); |
- SFTKTokenObject *to = sftk_narrowToTokenObject(object); |
- CK_RV crv = CKR_OK; |
- PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); |
- |
- /* Handle Token case */ |
- if (so && so->session) { |
- SFTKSession *session = so->session; |
- PZ_Lock(session->objectLock); |
- sftkqueue_delete(&so->sessionList,0,session->objects,0); |
- PZ_Unlock(session->objectLock); |
- PZ_Lock(slot->objectLock); |
- sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable); |
- PZ_Unlock(slot->objectLock); |
- sftkqueue_clear_deleted_element(object); |
- sftk_FreeObject(object); /* free the reference owned by the queue */ |
- } else { |
- SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle); |
- |
- PORT_Assert(to); |
- crv = sftkdb_DestroyObject(handle, object->handle); |
- sftk_freeDB(handle); |
- } |
- return crv; |
-} |
- |
-/* |
- * Token objects don't explicitly store their attributes, so we need to know |
- * what attributes make up a particular token object before we can copy it. |
- * below are the tables by object type. |
- */ |
-static const CK_ATTRIBUTE_TYPE commonAttrs[] = { |
- CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE |
-}; |
-static const CK_ULONG commonAttrsCount = |
- sizeof(commonAttrs)/sizeof(commonAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = { |
- CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE |
-}; |
-static const CK_ULONG commonKeyAttrsCount = |
- sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = { |
- CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, |
- CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE |
-}; |
-static const CK_ULONG secretKeyAttrsCount = |
- sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = { |
- CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT |
-}; |
-static const CK_ULONG commonPubKeyAttrsCount = |
- sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = { |
- CKA_MODULUS, CKA_PUBLIC_EXPONENT |
-}; |
-static const CK_ULONG rsaPubKeyAttrsCount = |
- sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = { |
- CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE |
-}; |
-static const CK_ULONG dsaPubKeyAttrsCount = |
- sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = { |
- CKA_PRIME, CKA_BASE, CKA_VALUE |
-}; |
-static const CK_ULONG dhPubKeyAttrsCount = |
- sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]); |
-#ifdef NSS_ENABLE_ECC |
-static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = { |
- CKA_EC_PARAMS, CKA_EC_POINT |
-}; |
-static const CK_ULONG ecPubKeyAttrsCount = |
- sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]); |
-#endif |
- |
-static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = { |
- CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT, |
- CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB |
-}; |
-static const CK_ULONG commonPrivKeyAttrsCount = |
- sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = { |
- CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, |
- CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT |
-}; |
-static const CK_ULONG rsaPrivKeyAttrsCount = |
- sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = { |
- CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE |
-}; |
-static const CK_ULONG dsaPrivKeyAttrsCount = |
- sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = { |
- CKA_PRIME, CKA_BASE, CKA_VALUE |
-}; |
-static const CK_ULONG dhPrivKeyAttrsCount = |
- sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]); |
-#ifdef NSS_ENABLE_ECC |
-static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = { |
- CKA_EC_PARAMS, CKA_VALUE |
-}; |
-static const CK_ULONG ecPrivKeyAttrsCount = |
- sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]); |
-#endif |
- |
-static const CK_ATTRIBUTE_TYPE certAttrs[] = { |
- CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER |
-}; |
-static const CK_ULONG certAttrsCount = |
- sizeof(certAttrs)/sizeof(certAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE trustAttrs[] = { |
- CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, |
- CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION, |
- CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED |
-}; |
-static const CK_ULONG trustAttrsCount = |
- sizeof(trustAttrs)/sizeof(trustAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE smimeAttrs[] = { |
- CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE |
-}; |
-static const CK_ULONG smimeAttrsCount = |
- sizeof(smimeAttrs)/sizeof(smimeAttrs[0]); |
- |
-static const CK_ATTRIBUTE_TYPE crlAttrs[] = { |
- CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL |
-}; |
-static const CK_ULONG crlAttrsCount = |
- sizeof(crlAttrs)/sizeof(crlAttrs[0]); |
- |
-/* copy an object based on it's table */ |
-CK_RV |
-stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to, |
- const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount) |
-{ |
- SFTKAttribute *attribute; |
- SFTKAttribute *newAttribute; |
- CK_RV crv = CKR_OK; |
- unsigned int i; |
- |
- for (i=0; i < attrCount; i++) { |
- if (!sftk_hasAttribute(destObject,attrArray[i])) { |
- attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]); |
- if (!attribute) { |
- continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */ |
- } |
- /* we need to copy the attribute since each attribute |
- * only has one set of link list pointers */ |
- newAttribute = sftk_NewAttribute( destObject, |
- sftk_attr_expand(&attribute->attrib)); |
- sftk_FreeAttribute(attribute); /* free the old attribute */ |
- if (!newAttribute) { |
- return CKR_HOST_MEMORY; |
- } |
- sftk_AddAttribute(destObject,newAttribute); |
- } |
- } |
- return crv; |
-} |
- |
-CK_RV |
-stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to) |
-{ |
- CK_RV crv; |
- CK_KEY_TYPE key_type; |
- SFTKAttribute *attribute; |
- |
- /* copy the common attributes for all keys first */ |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, |
- commonKeyAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- /* copy the common attributes for all private keys next */ |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs, |
- commonPrivKeyAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); |
- PORT_Assert(attribute); /* if it wasn't here, ww should have failed |
- * copying the common attributes */ |
- if (!attribute) { |
- /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but |
- * the fact is, the only reason we couldn't get the attribute would |
- * be a memory error or database error (an error in the 'device'). |
- * if we have a database error code, we could return it here */ |
- crv = CKR_DEVICE_ERROR; |
- goto fail; |
- } |
- key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; |
- sftk_FreeAttribute(attribute); |
- |
- /* finally copy the attributes for various private key types */ |
- switch (key_type) { |
- case CKK_RSA: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs, |
- rsaPrivKeyAttrsCount); |
- break; |
- case CKK_DSA: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs, |
- dsaPrivKeyAttrsCount); |
- break; |
- case CKK_DH: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs, |
- dhPrivKeyAttrsCount); |
- break; |
-#ifdef NSS_ENABLE_ECC |
- case CKK_EC: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs, |
- ecPrivKeyAttrsCount); |
- break; |
-#endif |
- default: |
- crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types |
- * of token keys into our database. */ |
- } |
-fail: |
- return crv; |
-} |
- |
-CK_RV |
-stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to) |
-{ |
- CK_RV crv; |
- CK_KEY_TYPE key_type; |
- SFTKAttribute *attribute; |
- |
- /* copy the common attributes for all keys first */ |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, |
- commonKeyAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- |
- /* copy the common attributes for all public keys next */ |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs, |
- commonPubKeyAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); |
- PORT_Assert(attribute); /* if it wasn't here, ww should have failed |
- * copying the common attributes */ |
- if (!attribute) { |
- /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but |
- * the fact is, the only reason we couldn't get the attribute would |
- * be a memory error or database error (an error in the 'device'). |
- * if we have a database error code, we could return it here */ |
- crv = CKR_DEVICE_ERROR; |
- goto fail; |
- } |
- key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; |
- sftk_FreeAttribute(attribute); |
- |
- /* finally copy the attributes for various public key types */ |
- switch (key_type) { |
- case CKK_RSA: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs, |
- rsaPubKeyAttrsCount); |
- break; |
- case CKK_DSA: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs, |
- dsaPubKeyAttrsCount); |
- break; |
- case CKK_DH: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs, |
- dhPubKeyAttrsCount); |
- break; |
-#ifdef NSS_ENABLE_ECC |
- case CKK_EC: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs, |
- ecPubKeyAttrsCount); |
- break; |
-#endif |
- default: |
- crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types |
- * of token keys into our database. */ |
- } |
-fail: |
- return crv; |
-} |
-CK_RV |
-stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to) |
-{ |
- CK_RV crv; |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, |
- commonKeyAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs, |
- secretKeyAttrsCount); |
-fail: |
- return crv; |
-} |
- |
-/* |
- * Copy a token object. We need to explicitly copy the relevant |
- * attributes since token objects don't store those attributes in |
- * the token itself. |
- */ |
-CK_RV |
-sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject) |
-{ |
- SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject); |
- CK_RV crv; |
- |
- PORT_Assert(src_to); |
- if (src_to == NULL) { |
- return CKR_DEVICE_ERROR; /* internal state inconsistant */ |
- } |
- |
- crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs, |
- commonAttrsCount); |
- if (crv != CKR_OK) { |
- goto fail; |
- } |
- switch (src_to->obj.objclass) { |
- case CKO_CERTIFICATE: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs, |
- certAttrsCount); |
- break; |
- case CKO_NETSCAPE_TRUST: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs, |
- trustAttrsCount); |
- break; |
- case CKO_NETSCAPE_SMIME: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs, |
- smimeAttrsCount); |
- break; |
- case CKO_NETSCAPE_CRL: |
- crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs, |
- crlAttrsCount); |
- break; |
- case CKO_PRIVATE_KEY: |
- crv = stfk_CopyTokenPrivateKey(destObject,src_to); |
- break; |
- case CKO_PUBLIC_KEY: |
- crv = stfk_CopyTokenPublicKey(destObject,src_to); |
- break; |
- case CKO_SECRET_KEY: |
- crv = stfk_CopyTokenSecretKey(destObject,src_to); |
- break; |
- default: |
- crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types |
- * of token keys into our database. */ |
- } |
-fail: |
- return crv; |
-} |
- |
-/* |
- * copy the attributes from one object to another. Don't overwrite existing |
- * attributes. NOTE: This is a pretty expensive operation since it |
- * grabs the attribute locks for the src object for a *long* time. |
- */ |
-CK_RV |
-sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject) |
-{ |
- SFTKAttribute *attribute; |
- SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject); |
- unsigned int i; |
- |
- if (src_so == NULL) { |
- return sftk_CopyTokenObject(destObject,srcObject); |
- } |
- |
- PZ_Lock(src_so->attributeLock); |
- for(i=0; i < src_so->hashSize; i++) { |
- attribute = src_so->head[i]; |
- do { |
- if (attribute) { |
- if (!sftk_hasAttribute(destObject,attribute->handle)) { |
- /* we need to copy the attribute since each attribute |
- * only has one set of link list pointers */ |
- SFTKAttribute *newAttribute = sftk_NewAttribute( |
- destObject,sftk_attr_expand(&attribute->attrib)); |
- if (newAttribute == NULL) { |
- PZ_Unlock(src_so->attributeLock); |
- return CKR_HOST_MEMORY; |
- } |
- sftk_AddAttribute(destObject,newAttribute); |
- } |
- attribute=attribute->next; |
- } |
- } while (attribute != NULL); |
- } |
- PZ_Unlock(src_so->attributeLock); |
- |
- return CKR_OK; |
-} |
- |
-/* |
- * ******************** Search Utilities ******************************* |
- */ |
- |
-/* add an object to a search list */ |
-CK_RV |
-AddToList(SFTKObjectListElement **list,SFTKObject *object) |
-{ |
- SFTKObjectListElement *newElem = |
- (SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement)); |
- |
- if (newElem == NULL) return CKR_HOST_MEMORY; |
- |
- newElem->next = *list; |
- newElem->object = object; |
- sftk_ReferenceObject(object); |
- |
- *list = newElem; |
- return CKR_OK; |
-} |
- |
- |
-/* return true if the object matches the template */ |
-PRBool |
-sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count) |
-{ |
- int i; |
- |
- for (i=0; i < count; i++) { |
- SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type); |
- if (attribute == NULL) { |
- return PR_FALSE; |
- } |
- if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) { |
- if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue, |
- theTemplate[i].ulValueLen) == 0) { |
- sftk_FreeAttribute(attribute); |
- continue; |
- } |
- } |
- sftk_FreeAttribute(attribute); |
- return PR_FALSE; |
- } |
- return PR_TRUE; |
-} |
- |
-/* search through all the objects in the queue and return the template matches |
- * in the object list. |
- */ |
-CK_RV |
-sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head, |
- unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, |
- int count, PRBool isLoggedIn) |
-{ |
- unsigned int i; |
- SFTKObject *object; |
- CK_RV crv = CKR_OK; |
- |
- for(i=0; i < size; i++) { |
- /* We need to hold the lock to copy a consistant version of |
- * the linked list. */ |
- PZ_Lock(lock); |
- for (object = head[i]; object != NULL; object= object->next) { |
- if (sftk_objectMatch(object,theTemplate,count)) { |
- /* don't return objects that aren't yet visible */ |
- if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue; |
- sftk_addHandle(search,object->handle); |
- } |
- } |
- PZ_Unlock(lock); |
- } |
- return crv; |
-} |
- |
-/* |
- * free a single list element. Return the Next object in the list. |
- */ |
-SFTKObjectListElement * |
-sftk_FreeObjectListElement(SFTKObjectListElement *objectList) |
-{ |
- SFTKObjectListElement *ol = objectList->next; |
- |
- sftk_FreeObject(objectList->object); |
- PORT_Free(objectList); |
- return ol; |
-} |
- |
-/* free an entire object list */ |
-void |
-sftk_FreeObjectList(SFTKObjectListElement *objectList) |
-{ |
- SFTKObjectListElement *ol; |
- |
- for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {} |
-} |
- |
-/* |
- * free a search structure |
- */ |
-void |
-sftk_FreeSearch(SFTKSearchResults *search) |
-{ |
- if (search->handles) { |
- PORT_Free(search->handles); |
- } |
- PORT_Free(search); |
-} |
- |
-/* |
- * ******************** Session Utilities ******************************* |
- */ |
- |
-/* update the sessions state based in it's flags and wether or not it's |
- * logged in */ |
-void |
-sftk_update_state(SFTKSlot *slot,SFTKSession *session) |
-{ |
- if (slot->isLoggedIn) { |
- if (slot->ssoLoggedIn) { |
- session->info.state = CKS_RW_SO_FUNCTIONS; |
- } else if (session->info.flags & CKF_RW_SESSION) { |
- session->info.state = CKS_RW_USER_FUNCTIONS; |
- } else { |
- session->info.state = CKS_RO_USER_FUNCTIONS; |
- } |
- } else { |
- if (session->info.flags & CKF_RW_SESSION) { |
- session->info.state = CKS_RW_PUBLIC_SESSION; |
- } else { |
- session->info.state = CKS_RO_PUBLIC_SESSION; |
- } |
- } |
-} |
- |
-/* update the state of all the sessions on a slot */ |
-void |
-sftk_update_all_states(SFTKSlot *slot) |
-{ |
- unsigned int i; |
- SFTKSession *session; |
- |
- for (i=0; i < slot->sessHashSize; i++) { |
- PZLock *lock = SFTK_SESSION_LOCK(slot,i); |
- PZ_Lock(lock); |
- for (session = slot->head[i]; session; session = session->next) { |
- sftk_update_state(slot,session); |
- } |
- PZ_Unlock(lock); |
- } |
-} |
- |
-/* |
- * context are cipher and digest contexts that are associated with a session |
- */ |
-void |
-sftk_FreeContext(SFTKSessionContext *context) |
-{ |
- if (context->cipherInfo) { |
- (*context->destroy)(context->cipherInfo,PR_TRUE); |
- } |
- if (context->hashInfo) { |
- (*context->hashdestroy)(context->hashInfo,PR_TRUE); |
- } |
- if (context->key) { |
- sftk_FreeObject(context->key); |
- context->key = NULL; |
- } |
- PORT_Free(context); |
-} |
- |
-/* |
- * create a new nession. NOTE: The session handle is not set, and the |
- * session is not added to the slot's session queue. |
- */ |
-SFTKSession * |
-sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, |
- CK_FLAGS flags) |
-{ |
- SFTKSession *session; |
- SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); |
- |
- if (slot == NULL) return NULL; |
- |
- session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession)); |
- if (session == NULL) return NULL; |
- |
- session->next = session->prev = NULL; |
- session->refCount = 1; |
- session->enc_context = NULL; |
- session->hash_context = NULL; |
- session->sign_context = NULL; |
- session->search = NULL; |
- session->objectIDCount = 1; |
- session->objectLock = PZ_NewLock(nssILockObject); |
- if (session->objectLock == NULL) { |
- PORT_Free(session); |
- return NULL; |
- } |
- session->objects[0] = NULL; |
- |
- session->slot = slot; |
- session->notify = notify; |
- session->appData = pApplication; |
- session->info.flags = flags; |
- session->info.slotID = slotID; |
- session->info.ulDeviceError = 0; |
- sftk_update_state(slot,session); |
- return session; |
-} |
- |
- |
-/* free all the data associated with a session. */ |
-static void |
-sftk_DestroySession(SFTKSession *session) |
-{ |
- SFTKObjectList *op,*next; |
- PORT_Assert(session->refCount == 0); |
- |
- /* clean out the attributes */ |
- /* since no one is referencing us, it's safe to walk the chain |
- * without a lock */ |
- for (op = session->objects[0]; op != NULL; op = next) { |
- next = op->next; |
- /* paranoia */ |
- op->next = op->prev = NULL; |
- sftk_DeleteObject(session,op->parent); |
- } |
- PZ_DestroyLock(session->objectLock); |
- if (session->enc_context) { |
- sftk_FreeContext(session->enc_context); |
- } |
- if (session->hash_context) { |
- sftk_FreeContext(session->hash_context); |
- } |
- if (session->sign_context) { |
- sftk_FreeContext(session->sign_context); |
- } |
- if (session->search) { |
- sftk_FreeSearch(session->search); |
- } |
- PORT_Free(session); |
-} |
- |
- |
-/* |
- * look up a session structure from a session handle |
- * generate a reference to it. |
- */ |
-SFTKSession * |
-sftk_SessionFromHandle(CK_SESSION_HANDLE handle) |
-{ |
- SFTKSlot *slot = sftk_SlotFromSessionHandle(handle); |
- SFTKSession *session; |
- PZLock *lock; |
- |
- if (!slot) return NULL; |
- lock = SFTK_SESSION_LOCK(slot,handle); |
- |
- PZ_Lock(lock); |
- sftkqueue_find(session,handle,slot->head,slot->sessHashSize); |
- if (session) session->refCount++; |
- PZ_Unlock(lock); |
- |
- return (session); |
-} |
- |
-/* |
- * release a reference to a session handle |
- */ |
-void |
-sftk_FreeSession(SFTKSession *session) |
-{ |
- PRBool destroy = PR_FALSE; |
- SFTKSlot *slot = sftk_SlotFromSession(session); |
- PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle); |
- |
- PZ_Lock(lock); |
- if (session->refCount == 1) destroy = PR_TRUE; |
- session->refCount--; |
- PZ_Unlock(lock); |
- |
- if (destroy) sftk_DestroySession(session); |
-} |
- |
-void |
-sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle) |
-{ |
- if (search->handles == NULL) { |
- return; |
- } |
- if (search->size >= search->array_size) { |
- search->array_size += NSC_SEARCH_BLOCK_SIZE; |
- search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles, |
- sizeof(CK_OBJECT_HANDLE)* search->array_size); |
- if (search->handles == NULL) { |
- return; |
- } |
- } |
- search->handles[search->size] = handle; |
- search->size++; |
-} |
- |
-static CK_RV |
-handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle, |
- CK_OBJECT_CLASS *objClass) |
-{ |
- SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle); |
- CK_ATTRIBUTE objClassTemplate; |
- CK_RV crv; |
- |
- *objClass = CKO_DATA; |
- objClassTemplate.type = CKA_CLASS; |
- objClassTemplate.pValue = objClass; |
- objClassTemplate.ulValueLen = sizeof(*objClass); |
- crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1); |
- sftk_freeDB(dbHandle); |
- return crv; |
-} |
- |
-SFTKObject * |
-sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) |
-{ |
- SFTKObject *object = NULL; |
- SFTKTokenObject *tokObject = NULL; |
- PRBool hasLocks = PR_FALSE; |
- CK_RV crv; |
- |
- object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0, |
- PR_FALSE); |
- if (object == NULL) { |
- return NULL; |
- } |
- tokObject = (SFTKTokenObject *) object; |
- |
- object->handle = handle; |
- /* every object must have a class, if we can't get it, the object |
- * doesn't exist */ |
- crv = handleToClass(slot, handle, &object->objclass); |
- if (crv != CKR_OK) { |
- goto loser; |
- } |
- object->slot = slot; |
- object->objectInfo = NULL; |
- object->infoFree = NULL; |
- if (!hasLocks) { |
- object->refLock = PZ_NewLock(nssILockRefLock); |
- } |
- if (object->refLock == NULL) { |
- goto loser; |
- } |
- object->refCount = 1; |
- |
- return object; |
-loser: |
- if (object) { |
- (void) sftk_DestroyObject(object); |
- } |
- return NULL; |
- |
-} |
- |
-SFTKTokenObject * |
-sftk_convertSessionToToken(SFTKObject *obj) |
-{ |
- SECItem *key; |
- SFTKSessionObject *so = (SFTKSessionObject *)obj; |
- SFTKTokenObject *to = sftk_narrowToTokenObject(obj); |
- SECStatus rv; |
- |
- sftk_DestroySessionObjectData(so); |
- PZ_DestroyLock(so->attributeLock); |
- if (to == NULL) { |
- return NULL; |
- } |
- sftk_tokenKeyLock(so->obj.slot); |
- key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle); |
- if (key == NULL) { |
- sftk_tokenKeyUnlock(so->obj.slot); |
- return NULL; |
- } |
- rv = SECITEM_CopyItem(NULL,&to->dbKey,key); |
- sftk_tokenKeyUnlock(so->obj.slot); |
- if (rv == SECFailure) { |
- return NULL; |
- } |
- |
- return to; |
-} |
- |
-SFTKSessionObject * |
-sftk_narrowToSessionObject(SFTKObject *obj) |
-{ |
- return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL; |
-} |
- |
-SFTKTokenObject * |
-sftk_narrowToTokenObject(SFTKObject *obj) |
-{ |
- return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL; |
-} |
- |