security/nss/lib/softoken/pkcs11u.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * Internal PKCS #11 functions. Should only be called by pkcs11.c
     6  */
     7 #include "pkcs11.h"
     8 #include "pkcs11i.h"
     9 #include "lowkeyi.h"
    10 #include "secasn1.h"
    11 #include "blapi.h"
    12 #include "secerr.h"
    13 #include "prnetdb.h" /* for PR_ntohl */
    14 #include "sftkdb.h"
    15 #include "softoken.h"
    17 /*
    18  * ******************** Attribute Utilities *******************************
    19  */
    21 /*
    22  * create a new attribute with type, value, and length. Space is allocated
    23  * to hold value.
    24  */
    25 static SFTKAttribute *
    26 sftk_NewAttribute(SFTKObject *object,
    27 	CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len)
    28 {
    29     SFTKAttribute *attribute;
    31     SFTKSessionObject *so = sftk_narrowToSessionObject(object);
    32     int index;
    34     if (so == NULL)  {
    35 	/* allocate new attribute in a buffer */
    36 	PORT_Assert(0);
    37 	return NULL;
    38     }
    39     /* 
    40      * We attempt to keep down contention on Malloc and Arena locks by
    41      * limiting the number of these calls on high traversed paths. This
    42      * is done for attributes by 'allocating' them from a pool already
    43      * allocated by the parent object.
    44      */
    45     PZ_Lock(so->attributeLock);
    46     index = so->nextAttr++;
    47     PZ_Unlock(so->attributeLock);
    48     PORT_Assert(index < MAX_OBJS_ATTRS);
    49     if (index >= MAX_OBJS_ATTRS) return NULL;
    51     attribute = &so->attrList[index];
    52     attribute->attrib.type = type;
    53     attribute->freeAttr = PR_FALSE;
    54     attribute->freeData = PR_FALSE;
    55     if (value) {
    56         if (len <= ATTR_SPACE) {
    57 	    attribute->attrib.pValue = attribute->space;
    58 	} else {
    59 	    attribute->attrib.pValue = PORT_Alloc(len);
    60     	    attribute->freeData = PR_TRUE;
    61 	}
    62 	if (attribute->attrib.pValue == NULL) {
    63 	    return NULL;
    64 	}
    65 	PORT_Memcpy(attribute->attrib.pValue,value,len);
    66 	attribute->attrib.ulValueLen = len;
    67     } else {
    68 	attribute->attrib.pValue = NULL;
    69 	attribute->attrib.ulValueLen = 0;
    70     }
    71     attribute->attrib.type = type;
    72     attribute->handle = type;
    73     attribute->next = attribute->prev = NULL;
    74     return attribute;
    75 }
    77 /*
    78  * Free up all the memory associated with an attribute. Reference count
    79  * must be zero to call this.
    80  */
    81 static void
    82 sftk_DestroyAttribute(SFTKAttribute *attribute)
    83 {
    84     if (attribute->freeData) {
    85 	if (attribute->attrib.pValue) {
    86 	    /* clear out the data in the attribute value... it may have been
    87 	     * sensitive data */
    88 	    PORT_Memset(attribute->attrib.pValue, 0,
    89 						attribute->attrib.ulValueLen);
    90 	}
    91 	PORT_Free(attribute->attrib.pValue);
    92     }
    93     PORT_Free(attribute);
    94 }
    96 /*
    97  * release a reference to an attribute structure
    98  */
    99 void
   100 sftk_FreeAttribute(SFTKAttribute *attribute)
   101 {
   102     if (attribute->freeAttr) {
   103 	sftk_DestroyAttribute(attribute);
   104 	return;
   105     }
   106 }
   108 static SFTKAttribute *    
   109 sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type)
   110 {
   111     SFTKAttribute *myattribute = NULL;
   112     SFTKDBHandle *dbHandle = NULL;
   113     CK_RV crv = CKR_HOST_MEMORY;
   115     myattribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute));
   116     if (myattribute == NULL) {
   117 	goto loser;
   118     }
   120     dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
   122     myattribute->handle = type;
   123     myattribute->attrib.type = type;
   124     myattribute->attrib.pValue = myattribute->space;
   125     myattribute->attrib.ulValueLen = ATTR_SPACE;
   126     myattribute->next = myattribute->prev = NULL;
   127     myattribute->freeAttr = PR_TRUE;
   128     myattribute->freeData = PR_FALSE;
   130     crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
   131 		&myattribute->attrib, 1);
   133     /* attribute is bigger than our attribute space buffer, malloc it */
   134     if (crv == CKR_BUFFER_TOO_SMALL) {
   135     	myattribute->attrib.pValue = NULL;
   136     	crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
   137 		&myattribute->attrib, 1);
   138 	if (crv != CKR_OK) {
   139 	    goto loser;
   140 	}
   141 	myattribute->attrib.pValue = PORT_Alloc(myattribute->attrib.ulValueLen);
   142 	if (myattribute->attrib.pValue == NULL) {
   143 	    crv = CKR_HOST_MEMORY;
   144 	    goto loser;
   145 	}
   146 	myattribute->freeData = PR_TRUE;
   147     	crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle,
   148 		 &myattribute->attrib, 1);
   149     } 
   150 loser:
   151     if (dbHandle) {
   152 	sftk_freeDB(dbHandle);
   153     }
   154     if (crv != CKR_OK) {
   155 	if (myattribute) {
   156 	    myattribute->attrib.ulValueLen = 0;
   157 	    sftk_FreeAttribute(myattribute);
   158 	    myattribute = NULL;
   159 	}
   160     }
   161     return myattribute;
   162 } 
   164 /*
   165  * look up and attribute structure from a type and Object structure.
   166  * The returned attribute is referenced and needs to be freed when 
   167  * it is no longer needed.
   168  */
   169 SFTKAttribute *
   170 sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   171 {
   172     SFTKAttribute *attribute;
   173     SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
   175     if (sessObject == NULL) {
   176 	return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type);
   177     }
   179     PZ_Lock(sessObject->attributeLock);
   180     sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
   181     PZ_Unlock(sessObject->attributeLock);
   183     return(attribute);
   184 }
   186 /*
   187  * Take a buffer and it's length and return it's true size in bits;
   188  */
   189 unsigned int
   190 sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
   191 {
   192     unsigned int size = bufLen * 8;
   193     unsigned int i;
   195     /* Get the real length in bytes */
   196     for (i=0; i < bufLen; i++) {
   197 	unsigned char  c = *buf++;
   198 	if (c != 0) {
   199 	    unsigned char m;
   200 	    for (m=0x80; m > 0 ;  m = m >> 1) {
   201 		if ((c & m) != 0) {
   202 		    break;
   203 		} 
   204 		size--;
   205 	    }
   206 	    break;
   207 	}
   208 	size-=8;
   209     }
   210     return size;
   211 }
   213 /*
   214  * Constrain a big num attribute. to size and padding
   215  * minLength means length of the object must be greater than equal to minLength
   216  * maxLength means length of the object must be less than equal to maxLength
   217  * minMultiple means that object length mod minMultiple must equal 0.
   218  * all input sizes are in bits.
   219  * if any constraint is '0' that constraint is not checked.
   220  */
   221 CK_RV
   222 sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, 
   223 			int minLength, int maxLength, int minMultiple)
   224 {
   225     SFTKAttribute *attribute;
   226     int size;
   227     unsigned char *ptr;
   229     attribute = sftk_FindAttribute(object, type);
   230     if (!attribute) {
   231 	return CKR_TEMPLATE_INCOMPLETE;
   232     }
   233     ptr = (unsigned char *) attribute->attrib.pValue;
   234     if (ptr == NULL) {
   235 	sftk_FreeAttribute(attribute);
   236 	return CKR_ATTRIBUTE_VALUE_INVALID;
   237     }
   238     size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen);
   239     sftk_FreeAttribute(attribute);
   241     if ((minLength != 0) && (size <  minLength)) {
   242 	return CKR_ATTRIBUTE_VALUE_INVALID;
   243     }
   244     if ((maxLength != 0) && (size >  maxLength)) {
   245 	return CKR_ATTRIBUTE_VALUE_INVALID;
   246     }
   247     if ((minMultiple != 0) && ((size % minMultiple) != 0)) {
   248 	return CKR_ATTRIBUTE_VALUE_INVALID;
   249     }
   250     return CKR_OK;
   251 }
   253 PRBool
   254 sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
   255 {
   256     CK_ATTRIBUTE template;
   257     CK_RV crv;
   258     SFTKDBHandle *dbHandle;
   260     dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle);
   261     template.type = type;
   262     template.pValue = NULL;
   263     template.ulValueLen = 0;
   265     crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1);
   266     sftk_freeDB(dbHandle);
   268     /* attribute is bigger than our attribute space buffer, malloc it */
   269     return (crv == CKR_OK) ? PR_TRUE : PR_FALSE;
   270 }
   272 /*
   273  * return true if object has attribute
   274  */
   275 PRBool
   276 sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   277 {
   278     SFTKAttribute *attribute;
   279     SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
   281     if (sessObject == NULL) {
   282 	return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type);
   283     }
   285     PZ_Lock(sessObject->attributeLock);
   286     sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize);
   287     PZ_Unlock(sessObject->attributeLock);
   289     return (PRBool)(attribute != NULL);
   290 }
   292 /*
   293  * add an attribute to an object
   294  */
   295 static void
   296 sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute)
   297 {
   298     SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
   300     if (sessObject == NULL) return;
   301     PZ_Lock(sessObject->attributeLock);
   302     sftkqueue_add(attribute,attribute->handle,
   303 				sessObject->head, sessObject->hashSize);
   304     PZ_Unlock(sessObject->attributeLock);
   305 }
   307 /* 
   308  * copy an unsigned attribute into a SECItem. Secitem is allocated in
   309  * the specified arena.
   310  */
   311 CK_RV
   312 sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
   313                                       CK_ATTRIBUTE_TYPE type)
   314 {
   315     SFTKAttribute *attribute;
   317     item->data = NULL;
   319     attribute = sftk_FindAttribute(object, type);
   320     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
   322     (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen);
   323     if (item->data == NULL) {
   324 	sftk_FreeAttribute(attribute);
   325 	return CKR_HOST_MEMORY;
   326     }
   327     PORT_Memcpy(item->data, attribute->attrib.pValue, item->len);
   328     sftk_FreeAttribute(attribute);
   329     return CKR_OK;
   330 }
   332 /* 
   333  * fetch multiple attributes into  SECItems. Secitem data is allocated in
   334  * the specified arena.
   335  */
   336 CK_RV
   337 sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object,
   338 	 SFTKItemTemplate *itemTemplate, int itemTemplateCount)
   339 {
   341     CK_RV crv = CKR_OK;
   342     CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE];
   343     CK_ATTRIBUTE *template;
   344     SFTKTokenObject *tokObject;
   345     SFTKDBHandle *dbHandle = NULL;
   346     int i;
   348     tokObject = sftk_narrowToTokenObject(object);
   350     /* session objects, just loop through the list */
   351     if (tokObject == NULL) {
   352 	for (i=0; i < itemTemplateCount; i++) {
   353 	    crv = sftk_Attribute2SecItem(arena,itemTemplate[i].item, object,
   354 					 itemTemplate[i].type);
   355 	    if (crv != CKR_OK) {
   356 		return crv;
   357 	    }
   358 	}
   359 	return CKR_OK;
   360     }
   362     /* don't do any work if none is required */
   363     if (itemTemplateCount == 0) {
   364 	return CKR_OK;
   365     }
   367     /* don't allocate the template unless we need it */
   368     if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE) {
   369 	template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount);
   370     } else {
   371 	template = templateSpace;
   372     }
   374     if (template == NULL) {
   375 	crv = CKR_HOST_MEMORY;
   376 	goto loser;
   377     }
   379     dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
   380     if (dbHandle == NULL) {
   381 	crv = CKR_OBJECT_HANDLE_INVALID;
   382 	goto loser;
   383     }
   385     /* set up the PKCS #11 template */
   386     for (i=0; i < itemTemplateCount; i++) {
   387 	template[i].type = itemTemplate[i].type;
   388 	template[i].pValue = NULL;
   389 	template[i].ulValueLen = 0;
   390     }
   392     /* fetch the attribute lengths */
   393     crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
   394 				   template, itemTemplateCount);
   395     if (crv != CKR_OK) {
   396 	goto loser;
   397     }
   399     /* allocate space for the attributes */
   400     for (i=0; i < itemTemplateCount ; i++) {
   401 	template[i].pValue = PORT_ArenaAlloc(arena, template[i].ulValueLen);
   402 	if (template[i].pValue == NULL) {
   403 	    crv = CKR_HOST_MEMORY;
   404 	    goto loser;
   405 	}
   406     }
   408     /* fetch the attributes */
   409     crv = sftkdb_GetAttributeValue(dbHandle, object->handle,
   410 				   template, itemTemplateCount);
   411     if (crv != CKR_OK) {
   412 	goto loser;
   413     }
   415     /* Fill in the items */	
   416     for (i=0; i < itemTemplateCount; i++) {
   417 	itemTemplate[i].item->data = template[i].pValue;
   418 	itemTemplate[i].item->len = template[i].ulValueLen;
   419     }
   421 loser:
   422     if (template != templateSpace) {
   423 	PORT_Free(template);
   424     }
   425     if (dbHandle) {
   426 	sftk_freeDB(dbHandle);
   427     }
   429     return crv;
   430 }
   433 /*
   434  * delete an attribute from an object
   435  */
   436 static void
   437 sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute)
   438 {
   439     SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object);
   441     if (sessObject == NULL) {
   442 	return ;
   443     }
   444     PZ_Lock(sessObject->attributeLock);
   445     if (sftkqueue_is_queued(attribute,attribute->handle,
   446 				sessObject->head, sessObject->hashSize)) {
   447 	sftkqueue_delete(attribute,attribute->handle,
   448 				sessObject->head, sessObject->hashSize);
   449     }
   450     PZ_Unlock(sessObject->attributeLock);
   451 }
   453 /*
   454  * this is only valid for CK_BBOOL type attributes. Return the state
   455  * of that attribute.
   456  */
   457 PRBool
   458 sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   459 {
   460     SFTKAttribute *attribute;
   461     PRBool tok = PR_FALSE;
   463     attribute=sftk_FindAttribute(object,type);
   464     if (attribute == NULL) { return PR_FALSE; }
   465     tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);
   466     sftk_FreeAttribute(attribute);
   468     return tok;
   469 }
   471 /*
   472  * force an attribute to null.
   473  * this is for sensitive keys which are stored in the database, we don't
   474  * want to keep this info around in memory in the clear.
   475  */
   476 void
   477 sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   478 {
   479     SFTKAttribute *attribute;
   481     attribute=sftk_FindAttribute(object,type);
   482     if (attribute == NULL) return;
   484     if (attribute->attrib.pValue != NULL) {
   485 	PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);
   486 	if (attribute->freeData) {
   487 	    PORT_Free(attribute->attrib.pValue);
   488 	}
   489 	attribute->freeData = PR_FALSE;
   490 	attribute->attrib.pValue = NULL;
   491 	attribute->attrib.ulValueLen = 0;
   492     }
   493     sftk_FreeAttribute(attribute);
   494 }
   497 static CK_RV
   498 sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 
   499 				const void *value, unsigned int len)
   500 {
   501     CK_ATTRIBUTE attribute;
   502     SFTKDBHandle *dbHandle = NULL;
   503     SFTKTokenObject *to = sftk_narrowToTokenObject(object);
   504     CK_RV crv;
   506     PORT_Assert(to);
   507     if (to == NULL) {
   508 	return CKR_DEVICE_ERROR;
   509     }
   511     dbHandle = sftk_getDBForTokenObject(object->slot, object->handle);
   513     attribute.type = type;
   514     attribute.pValue = (void *)value;
   515     attribute.ulValueLen = len;
   517     crv = sftkdb_SetAttributeValue(dbHandle, object, &attribute, 1);
   518     sftk_freeDB(dbHandle);
   519     return crv;
   520 }
   522 /*
   523  * force an attribute to a specifc value.
   524  */
   525 CK_RV
   526 sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 
   527 				const void *value, unsigned int len)
   528 {
   529     SFTKAttribute *attribute;
   530     void *att_val = NULL;
   531     PRBool freeData = PR_FALSE;
   533     PORT_Assert(object);
   534     PORT_Assert(object->refCount);
   535     PORT_Assert(object->slot);
   536     if (!object ||
   537         !object->refCount ||
   538         !object->slot) {
   539         return CKR_DEVICE_ERROR;
   540     }
   541     if (sftk_isToken(object->handle)) {
   542 	return sftk_forceTokenAttribute(object,type,value,len);
   543     }
   544     attribute=sftk_FindAttribute(object,type);
   545     if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len);
   548     if (value) {
   549         if (len <= ATTR_SPACE) {
   550 	    att_val = attribute->space;
   551 	} else {
   552 	    att_val = PORT_Alloc(len);
   553 	    freeData = PR_TRUE;
   554 	}
   555 	if (att_val == NULL) {
   556 	    return CKR_HOST_MEMORY;
   557 	}
   558 	if (attribute->attrib.pValue == att_val) {
   559 	    PORT_Memset(attribute->attrib.pValue,0,
   560 					attribute->attrib.ulValueLen);
   561 	}
   562 	PORT_Memcpy(att_val,value,len);
   563     }
   564     if (attribute->attrib.pValue != NULL) {
   565 	if (attribute->attrib.pValue != att_val) {
   566 	    PORT_Memset(attribute->attrib.pValue,0,
   567 					attribute->attrib.ulValueLen);
   568 	}
   569 	if (attribute->freeData) {
   570 	    PORT_Free(attribute->attrib.pValue);
   571 	}
   572 	attribute->freeData = PR_FALSE;
   573 	attribute->attrib.pValue = NULL;
   574 	attribute->attrib.ulValueLen = 0;
   575     }
   576     if (att_val) {
   577 	attribute->attrib.pValue = att_val;
   578 	attribute->attrib.ulValueLen = len;
   579 	attribute->freeData = freeData;
   580     }
   581     sftk_FreeAttribute(attribute);
   582     return CKR_OK;
   583 }
   585 /*
   586  * return a null terminated string from attribute 'type'. This string
   587  * is allocated and needs to be freed with PORT_Free() When complete.
   588  */
   589 char *
   590 sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   591 {
   592     SFTKAttribute *attribute;
   593     char *label = NULL;
   595     attribute=sftk_FindAttribute(object,type);
   596     if (attribute == NULL) return NULL;
   598     if (attribute->attrib.pValue != NULL) {
   599 	label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);
   600 	if (label == NULL) {
   601     	    sftk_FreeAttribute(attribute);
   602 	    return NULL;
   603 	}
   605 	PORT_Memcpy(label,attribute->attrib.pValue,
   606 						attribute->attrib.ulValueLen);
   607 	label[attribute->attrib.ulValueLen] = 0;
   608     }
   609     sftk_FreeAttribute(attribute);
   610     return label;
   611 }
   613 /*
   614  * decode when a particular attribute may be modified
   615  * 	SFTK_NEVER: This attribute must be set at object creation time and
   616  *  can never be modified.
   617  *	SFTK_ONCOPY: This attribute may be modified only when you copy the
   618  *  object.
   619  *	SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from
   620  *  CK_FALSE to CK_TRUE.
   621  *	SFTK_ALWAYS: This attribute can always be modified.
   622  * Some attributes vary their modification type based on the class of the 
   623  *   object.
   624  */
   625 SFTKModifyType
   626 sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
   627 {
   628     /* if we don't know about it, user user defined, always allow modify */
   629     SFTKModifyType mtype = SFTK_ALWAYS; 
   631     switch(type) {
   632     /* NEVER */
   633     case CKA_CLASS:
   634     case CKA_CERTIFICATE_TYPE:
   635     case CKA_KEY_TYPE:
   636     case CKA_MODULUS:
   637     case CKA_MODULUS_BITS:
   638     case CKA_PUBLIC_EXPONENT:
   639     case CKA_PRIVATE_EXPONENT:
   640     case CKA_PRIME:
   641     case CKA_SUBPRIME:
   642     case CKA_BASE:
   643     case CKA_PRIME_1:
   644     case CKA_PRIME_2:
   645     case CKA_EXPONENT_1:
   646     case CKA_EXPONENT_2:
   647     case CKA_COEFFICIENT:
   648     case CKA_VALUE_LEN:
   649     case CKA_ALWAYS_SENSITIVE:
   650     case CKA_NEVER_EXTRACTABLE:
   651     case CKA_NETSCAPE_DB:
   652 	mtype = SFTK_NEVER;
   653 	break;
   655     /* ONCOPY */
   656     case CKA_TOKEN:
   657     case CKA_PRIVATE:
   658     case CKA_MODIFIABLE:
   659 	mtype = SFTK_ONCOPY;
   660 	break;
   662     /* SENSITIVE */
   663     case CKA_SENSITIVE:
   664     case CKA_EXTRACTABLE:
   665 	mtype = SFTK_SENSITIVE;
   666 	break;
   668     /* ALWAYS */
   669     case CKA_LABEL:
   670     case CKA_APPLICATION:
   671     case CKA_ID:
   672     case CKA_SERIAL_NUMBER:
   673     case CKA_START_DATE:
   674     case CKA_END_DATE:
   675     case CKA_DERIVE:
   676     case CKA_ENCRYPT:
   677     case CKA_DECRYPT:
   678     case CKA_SIGN:
   679     case CKA_VERIFY:
   680     case CKA_SIGN_RECOVER:
   681     case CKA_VERIFY_RECOVER:
   682     case CKA_WRAP:
   683     case CKA_UNWRAP:
   684 	mtype = SFTK_ALWAYS;
   685 	break;
   687     /* DEPENDS ON CLASS */
   688     case CKA_VALUE:
   689 	mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER;
   690 	break;
   692     case CKA_SUBJECT:
   693 	mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS;
   694 	break;
   695     default:
   696 	break;
   697     }
   698     return mtype;
   699 }
   701 /* decode if a particular attribute is sensitive (cannot be read
   702  * back to the user of if the object is set to SENSITIVE) */
   703 PRBool
   704 sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass)
   705 {
   706     switch(type) {
   707     /* ALWAYS */
   708     case CKA_PRIVATE_EXPONENT:
   709     case CKA_PRIME_1:
   710     case CKA_PRIME_2:
   711     case CKA_EXPONENT_1:
   712     case CKA_EXPONENT_2:
   713     case CKA_COEFFICIENT:
   714 	return PR_TRUE;
   716     /* DEPENDS ON CLASS */
   717     case CKA_VALUE:
   718 	/* PRIVATE and SECRET KEYS have SENSITIVE values */
   719 	return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY));
   721     default:
   722 	break;
   723     }
   724     return PR_FALSE;
   725 }
   727 /* 
   728  * copy an attribute into a SECItem. Secitem is allocated in the specified
   729  * arena.
   730  */
   731 CK_RV
   732 sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object,
   733 					CK_ATTRIBUTE_TYPE type)
   734 {
   735     int len;
   736     SFTKAttribute *attribute;
   738     attribute = sftk_FindAttribute(object, type);
   739     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
   740     len = attribute->attrib.ulValueLen;
   742     if (arena) {
   743     	item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);
   744     } else {
   745     	item->data = (unsigned char *) PORT_Alloc(len);
   746     }
   747     if (item->data == NULL) {
   748 	sftk_FreeAttribute(attribute);
   749 	return CKR_HOST_MEMORY;
   750     }
   751     item->len = len;
   752     PORT_Memcpy(item->data,attribute->attrib.pValue, len);
   753     sftk_FreeAttribute(attribute);
   754     return CKR_OK;
   755 }
   757 CK_RV
   758 sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
   759 							 CK_ULONG *longData)
   760 {
   761     SFTKAttribute *attribute;
   763     attribute = sftk_FindAttribute(object, type);
   764     if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;
   766     if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) {
   767 	return CKR_ATTRIBUTE_VALUE_INVALID;
   768     }
   770     *longData = *(CK_ULONG *)attribute->attrib.pValue;
   771     sftk_FreeAttribute(attribute);
   772     return CKR_OK;
   773 }
   775 void
   776 sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type)
   777 {
   778     SFTKAttribute *attribute;
   779     attribute = sftk_FindAttribute(object, type);
   780     if (attribute == NULL) return ;
   781     sftk_DeleteAttribute(object,attribute);
   782     sftk_FreeAttribute(attribute);
   783 }
   785 CK_RV
   786 sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type,
   787 				const void *valPtr, CK_ULONG length)
   788 {
   789     SFTKAttribute *attribute;
   790     attribute = sftk_NewAttribute(object,type,valPtr,length);
   791     if (attribute == NULL) { return CKR_HOST_MEMORY; }
   792     sftk_AddAttribute(object,attribute);
   793     return CKR_OK;
   794 }
   796 /*
   797  * ******************** Object Utilities *******************************
   798  */
   800 /* must be called holding sftk_tokenKeyLock(slot) */
   801 static SECItem *
   802 sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
   803 {
   804     return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle);
   805 }
   807 /*
   808  * use the refLock. This operations should be very rare, so the added
   809  * contention on the ref lock should be lower than the overhead of adding
   810  * a new lock. We use separate functions for this just in case I'm wrong.
   811  */
   812 static void
   813 sftk_tokenKeyLock(SFTKSlot *slot) {
   814     SKIP_AFTER_FORK(PZ_Lock(slot->objectLock));
   815 }
   817 static void
   818 sftk_tokenKeyUnlock(SFTKSlot *slot) {
   819     SKIP_AFTER_FORK(PZ_Unlock(slot->objectLock));
   820 }
   822 static PRIntn
   823 sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
   824 {
   825     SECItem *item = (SECItem *)entry->value;
   827     SECITEM_FreeItem(item, PR_TRUE);
   828     return HT_ENUMERATE_NEXT;
   829 }
   831 CK_RV
   832 SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
   833 {
   834     sftk_tokenKeyLock(slot);
   835     PORT_Assert(!slot->present);
   836     PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL);
   837     sftk_tokenKeyUnlock(slot);
   838     return CKR_OK;
   839 }
   842 /* allocation hooks that allow us to recycle old object structures */
   843 static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 };
   844 static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 };
   846 SFTKObject *
   847 sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace, 
   848      SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject)
   849 {
   850     SFTKObject *object;
   851     int size = 0;
   853     if (!optimizeSpace) {
   854 	PZ_Lock(list->lock);
   855 	object = list->head;
   856 	if (object) {
   857 	    list->head = object->next;
   858 	    list->count--;
   859 	}    	
   860 	PZ_Unlock(list->lock);
   861 	if (object) {
   862 	    object->next = object->prev = NULL;
   863             *hasLocks = PR_TRUE;
   864 	    return object;
   865 	}
   866     }
   867     size = isSessionObject ? sizeof(SFTKSessionObject) 
   868 		+ hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject);
   870     object  = (SFTKObject*)PORT_ZAlloc(size);
   871     if (isSessionObject && object) {
   872 	((SFTKSessionObject *)object)->hashSize = hashSize;
   873     }
   874     *hasLocks = PR_FALSE;
   875     return object;
   876 }
   878 static void
   879 sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list,
   880 						PRBool isSessionObject) {
   882     /* the code below is equivalent to :
   883      *     optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE;
   884      * just faster.
   885      */
   886     PRBool optimizeSpace = isSessionObject && 
   887 				((SFTKSessionObject *)object)->optimizeSpace; 
   888     if (object->refLock && !optimizeSpace 
   889 	               && (list->count < MAX_OBJECT_LIST_SIZE)) {
   890 	PZ_Lock(list->lock);
   891 	object->next = list->head;
   892 	list->head = object;
   893 	list->count++;
   894 	PZ_Unlock(list->lock);
   895 	return;
   896     }
   897     if (isSessionObject) {
   898 	SFTKSessionObject *so = (SFTKSessionObject *)object;
   899 	PZ_DestroyLock(so->attributeLock);
   900 	so->attributeLock = NULL;
   901     }
   902     if (object->refLock) {
   903 	PZ_DestroyLock(object->refLock);
   904 	object->refLock = NULL;
   905     }
   906     PORT_Free(object);
   907 }
   909 static SFTKObject *
   910 sftk_freeObjectData(SFTKObject *object) {
   911    SFTKObject *next = object->next;
   913    PORT_Free(object);
   914    return next;
   915 }
   917 static void
   918 sftk_InitFreeList(SFTKObjectFreeList *list)
   919 {
   920     list->lock = PZ_NewLock(nssILockObject);
   921 }
   923 void sftk_InitFreeLists(void)
   924 {
   925     sftk_InitFreeList(&sessionObjectList);
   926     sftk_InitFreeList(&tokenObjectList);
   927 }
   929 static void
   930 sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList)
   931 {
   932     SFTKObject *object;
   934     if (!list->lock) {
   935 	return;
   936     }
   937     SKIP_AFTER_FORK(PZ_Lock(list->lock));
   938     for (object= list->head; object != NULL; 
   939 					object = sftk_freeObjectData(object)) {
   940 	PZ_DestroyLock(object->refLock);
   941 	if (isSessionList) {
   942 	    PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock);
   943 	}
   944     }
   945     list->count = 0;
   946     list->head = NULL;
   947     SKIP_AFTER_FORK(PZ_Unlock(list->lock));
   948     SKIP_AFTER_FORK(PZ_DestroyLock(list->lock));
   949     list->lock = NULL;
   950 }
   952 void
   953 sftk_CleanupFreeLists(void)
   954 {
   955     sftk_CleanupFreeList(&sessionObjectList, PR_TRUE);
   956     sftk_CleanupFreeList(&tokenObjectList, PR_FALSE);
   957 }
   960 /*
   961  * Create a new object
   962  */
   963 SFTKObject *
   964 sftk_NewObject(SFTKSlot *slot)
   965 {
   966     SFTKObject *object;
   967     SFTKSessionObject *sessObject;
   968     PRBool hasLocks = PR_FALSE;
   969     unsigned int i;
   970     unsigned int hashSize = 0;
   972     hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE :
   973 				TIME_ATTRIBUTE_HASH_SIZE;
   975     object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace,
   976 				&sessionObjectList,  hashSize, PR_TRUE);
   977     if (object == NULL) {
   978 	return NULL;
   979     }
   980     sessObject = (SFTKSessionObject *)object;
   981     sessObject->nextAttr = 0;
   983     for (i=0; i < MAX_OBJS_ATTRS; i++) {
   984 	sessObject->attrList[i].attrib.pValue = NULL;
   985 	sessObject->attrList[i].freeData = PR_FALSE;
   986     }
   987     sessObject->optimizeSpace = slot->optimizeSpace;
   989     object->handle = 0;
   990     object->next = object->prev = NULL;
   991     object->slot = slot;
   993     object->refCount = 1;
   994     sessObject->sessionList.next = NULL;
   995     sessObject->sessionList.prev = NULL;
   996     sessObject->sessionList.parent = object;
   997     sessObject->session = NULL;
   998     sessObject->wasDerived = PR_FALSE;
   999     if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock);
  1000     if (object->refLock == NULL) {
  1001 	PORT_Free(object);
  1002 	return NULL;
  1004     if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute);
  1005     if (sessObject->attributeLock == NULL) {
  1006 	PZ_DestroyLock(object->refLock);
  1007 	PORT_Free(object);
  1008 	return NULL;
  1010     for (i=0; i < sessObject->hashSize; i++) {
  1011 	sessObject->head[i] = NULL;
  1013     object->objectInfo = NULL;
  1014     object->infoFree = NULL;
  1015     return object;
  1018 static CK_RV
  1019 sftk_DestroySessionObjectData(SFTKSessionObject *so)
  1021 	int i;
  1023 	for (i=0; i < MAX_OBJS_ATTRS; i++) {
  1024 	    unsigned char *value = so->attrList[i].attrib.pValue;
  1025 	    if (value) {
  1026 		PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen);
  1027 		if (so->attrList[i].freeData) {
  1028 		    PORT_Free(value);
  1030 		so->attrList[i].attrib.pValue = NULL;
  1031 		so->attrList[i].freeData = PR_FALSE;
  1034 /*	PZ_DestroyLock(so->attributeLock);*/
  1035 	return CKR_OK;
  1038 /*
  1039  * free all the data associated with an object. Object reference count must
  1040  * be 'zero'.
  1041  */
  1042 static CK_RV
  1043 sftk_DestroyObject(SFTKObject *object)
  1045     CK_RV crv = CKR_OK;
  1046     SFTKSessionObject *so = sftk_narrowToSessionObject(object);
  1047     SFTKTokenObject *to = sftk_narrowToTokenObject(object);
  1049     PORT_Assert(object->refCount == 0);
  1051     /* delete the database value */
  1052     if (to) {
  1053 	if (to->dbKey.data) {
  1054 	   PORT_Free(to->dbKey.data);
  1055 	   to->dbKey.data = NULL;
  1058     if (so) {
  1059 	sftk_DestroySessionObjectData(so);
  1061     if (object->objectInfo) {
  1062 	(*object->infoFree)(object->objectInfo);
  1063 	object->objectInfo = NULL;
  1064 	object->infoFree = NULL;
  1066     if (so) {
  1067 	sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE);
  1068     } else {
  1069 	sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE);
  1071     return crv;
  1074 void
  1075 sftk_ReferenceObject(SFTKObject *object)
  1077     PZ_Lock(object->refLock);
  1078     object->refCount++;
  1079     PZ_Unlock(object->refLock);
  1082 static SFTKObject *
  1083 sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot)
  1085     SFTKObject *object;
  1086     PRUint32 index = sftk_hash(handle, slot->sessObjHashSize);
  1088     if (sftk_isToken(handle)) {
  1089 	return sftk_NewTokenObject(slot, NULL, handle);
  1092     PZ_Lock(slot->objectLock);
  1093     sftkqueue_find2(object, handle, index, slot->sessObjHashTable);
  1094     if (object) {
  1095 	sftk_ReferenceObject(object);
  1097     PZ_Unlock(slot->objectLock);
  1099     return(object);
  1101 /*
  1102  * look up and object structure from a handle. OBJECT_Handles only make
  1103  * sense in terms of a given session.  make a reference to that object
  1104  * structure returned.
  1105  */
  1106 SFTKObject *
  1107 sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session)
  1109     SFTKSlot *slot = sftk_SlotFromSession(session);
  1111     return sftk_ObjectFromHandleOnSlot(handle,slot);
  1115 /*
  1116  * release a reference to an object handle
  1117  */
  1118 SFTKFreeStatus
  1119 sftk_FreeObject(SFTKObject *object)
  1121     PRBool destroy = PR_FALSE;
  1122     CK_RV crv;
  1124     PZ_Lock(object->refLock);
  1125     if (object->refCount == 1) destroy = PR_TRUE;
  1126     object->refCount--;
  1127     PZ_Unlock(object->refLock);
  1129     if (destroy) {
  1130 	crv = sftk_DestroyObject(object);
  1131 	if (crv != CKR_OK) {
  1132 	   return SFTK_DestroyFailure;
  1134 	return SFTK_Destroyed;
  1136     return SFTK_Busy;
  1139 /*
  1140  * add an object to a slot and session queue. These two functions
  1141  * adopt the object.
  1142  */
  1143 void
  1144 sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object)
  1146     PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
  1147     sftkqueue_init_element(object);
  1148     PZ_Lock(slot->objectLock);
  1149     sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable);
  1150     PZ_Unlock(slot->objectLock);
  1153 void
  1154 sftk_AddObject(SFTKSession *session, SFTKObject *object)
  1156     SFTKSlot *slot = sftk_SlotFromSession(session);
  1157     SFTKSessionObject *so = sftk_narrowToSessionObject(object);
  1159     if (so) {
  1160 	PZ_Lock(session->objectLock);
  1161 	sftkqueue_add(&so->sessionList,0,session->objects,0);
  1162 	so->session = session;
  1163 	PZ_Unlock(session->objectLock);
  1165     sftk_AddSlotObject(slot,object);
  1166     sftk_ReferenceObject(object);
  1169 /*
  1170  * delete an object from a slot and session queue
  1171  */
  1172 CK_RV
  1173 sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
  1175     SFTKSlot *slot = sftk_SlotFromSession(session);
  1176     SFTKSessionObject *so = sftk_narrowToSessionObject(object);
  1177     SFTKTokenObject *to = sftk_narrowToTokenObject(object);
  1178     CK_RV crv = CKR_OK;
  1179     PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize);
  1181     /* Handle Token case */
  1182     if (so && so->session) {
  1183 	SFTKSession *session = so->session;
  1184 	PZ_Lock(session->objectLock);
  1185 	sftkqueue_delete(&so->sessionList,0,session->objects,0);
  1186 	PZ_Unlock(session->objectLock);
  1187 	PZ_Lock(slot->objectLock);
  1188 	sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable);
  1189 	PZ_Unlock(slot->objectLock);
  1190 	sftkqueue_clear_deleted_element(object);
  1191 	sftk_FreeObject(object); /* free the reference owned by the queue */
  1192     } else {
  1193 	SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle);
  1195 	PORT_Assert(to);
  1196 	crv = sftkdb_DestroyObject(handle, object->handle);
  1197 	sftk_freeDB(handle);
  1199     return crv;
  1202 /*
  1203  * Token objects don't explicitly store their attributes, so we need to know
  1204  * what attributes make up a particular token object before we can copy it.
  1205  * below are the tables by object type.
  1206  */
  1207 static const CK_ATTRIBUTE_TYPE commonAttrs[] = {
  1208     CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE
  1209 };
  1210 static const CK_ULONG commonAttrsCount = 
  1211 			sizeof(commonAttrs)/sizeof(commonAttrs[0]);
  1213 static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = {
  1214     CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE
  1215 };
  1216 static const CK_ULONG commonKeyAttrsCount = 
  1217 			sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]);
  1219 static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = {
  1220     CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN,
  1221     CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE
  1222 };
  1223 static const CK_ULONG secretKeyAttrsCount = 
  1224 			sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]);
  1226 static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = {
  1227     CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT
  1228 };
  1229 static const CK_ULONG commonPubKeyAttrsCount = 
  1230 			sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]);
  1232 static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = {
  1233     CKA_MODULUS, CKA_PUBLIC_EXPONENT
  1234 };
  1235 static const CK_ULONG rsaPubKeyAttrsCount = 
  1236 			sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]);
  1238 static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = {
  1239     CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
  1240 };
  1241 static const CK_ULONG dsaPubKeyAttrsCount = 
  1242 			sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]);
  1244 static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = {
  1245     CKA_PRIME, CKA_BASE, CKA_VALUE
  1246 };
  1247 static const CK_ULONG dhPubKeyAttrsCount = 
  1248 			sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]);
  1249 #ifndef NSS_DISABLE_ECC
  1250 static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = {
  1251     CKA_EC_PARAMS, CKA_EC_POINT
  1252 };
  1253 static const CK_ULONG ecPubKeyAttrsCount = 
  1254 			sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]);
  1255 #endif
  1257 static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = {
  1258     CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT,
  1259     CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB
  1260 };
  1261 static const CK_ULONG commonPrivKeyAttrsCount = 
  1262 		sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]);
  1264 static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = {
  1265     CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, 
  1266     CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT
  1267 };
  1268 static const CK_ULONG rsaPrivKeyAttrsCount = 
  1269 			sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]);
  1271 static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = {
  1272     CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE
  1273 };
  1274 static const CK_ULONG dsaPrivKeyAttrsCount = 
  1275 			sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]);
  1277 static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = {
  1278     CKA_PRIME, CKA_BASE, CKA_VALUE
  1279 };
  1280 static const CK_ULONG dhPrivKeyAttrsCount = 
  1281 			sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]);
  1282 #ifndef NSS_DISABLE_ECC
  1283 static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = {
  1284     CKA_EC_PARAMS, CKA_VALUE
  1285 };
  1286 static const CK_ULONG ecPrivKeyAttrsCount = 
  1287 			sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]);
  1288 #endif
  1290 static const CK_ATTRIBUTE_TYPE certAttrs[] = {
  1291     CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER
  1292 };
  1293 static const CK_ULONG certAttrsCount = 
  1294 		sizeof(certAttrs)/sizeof(certAttrs[0]);
  1296 static const CK_ATTRIBUTE_TYPE trustAttrs[] = {
  1297     CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH,
  1298     CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION,
  1299     CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED
  1300 };
  1301 static const CK_ULONG trustAttrsCount = 
  1302 		sizeof(trustAttrs)/sizeof(trustAttrs[0]);
  1304 static const CK_ATTRIBUTE_TYPE smimeAttrs[] = {
  1305     CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE
  1306 };
  1307 static const CK_ULONG smimeAttrsCount = 
  1308 		sizeof(smimeAttrs)/sizeof(smimeAttrs[0]);
  1310 static const CK_ATTRIBUTE_TYPE crlAttrs[] = {
  1311     CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL
  1312 };
  1313 static const CK_ULONG crlAttrsCount = 
  1314 		sizeof(crlAttrs)/sizeof(crlAttrs[0]);
  1316 /* copy an object based on it's table */
  1317 CK_RV
  1318 stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to,
  1319 	const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount)
  1321     SFTKAttribute *attribute;
  1322     SFTKAttribute *newAttribute;
  1323     CK_RV crv = CKR_OK;
  1324     unsigned int i;
  1326     for (i=0; i < attrCount; i++) {
  1327 	if (!sftk_hasAttribute(destObject,attrArray[i])) {
  1328 	    attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]);
  1329 	    if (!attribute) {
  1330 		continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */
  1332 	    /* we need to copy the attribute since each attribute
  1333 	     * only has one set of link list pointers */
  1334 	    newAttribute = sftk_NewAttribute( destObject,
  1335 				sftk_attr_expand(&attribute->attrib));
  1336 	    sftk_FreeAttribute(attribute); /* free the old attribute */
  1337 	    if (!newAttribute) {
  1338 		return CKR_HOST_MEMORY;
  1340 	    sftk_AddAttribute(destObject,newAttribute);
  1343     return crv;
  1346 CK_RV
  1347 stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to)
  1349     CK_RV crv;
  1350     CK_KEY_TYPE key_type;
  1351     SFTKAttribute *attribute;
  1353     /* copy the common attributes for all keys first */
  1354     crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
  1355 							commonKeyAttrsCount);
  1356     if (crv != CKR_OK) {
  1357 	goto fail;
  1359     /* copy the common attributes for all private keys next */
  1360     crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs,
  1361 						commonPrivKeyAttrsCount);
  1362     if (crv != CKR_OK) {
  1363 	goto fail;
  1365     attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
  1366     PORT_Assert(attribute); /* if it wasn't here, ww should have failed
  1367 			     * copying the common attributes */
  1368     if (!attribute) {
  1369 	/* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
  1370 	 * the fact is, the only reason we couldn't get the attribute would
  1371 	 * be a memory error or database error (an error in the 'device').
  1372 	 * if we have a database error code, we could return it here */
  1373 	crv = CKR_DEVICE_ERROR;
  1374 	goto fail;
  1376     key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
  1377     sftk_FreeAttribute(attribute);
  1379     /* finally copy the attributes for various private key types */
  1380     switch (key_type) {
  1381     case CKK_RSA:
  1382 	crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs,
  1383 							rsaPrivKeyAttrsCount);
  1384 	break;
  1385     case CKK_DSA:
  1386 	crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs,
  1387 							dsaPrivKeyAttrsCount);
  1388 	break;
  1389     case CKK_DH:
  1390 	crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs,
  1391 							dhPrivKeyAttrsCount);
  1392 	break;
  1393 #ifndef NSS_DISABLE_ECC
  1394     case CKK_EC:
  1395 	crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs,
  1396 							ecPrivKeyAttrsCount);
  1397 	break;
  1398 #endif
  1399      default:
  1400 	crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
  1401 				* of token keys into our database. */
  1403 fail:
  1404     return crv;
  1407 CK_RV
  1408 stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to)
  1410     CK_RV crv;
  1411     CK_KEY_TYPE key_type;
  1412     SFTKAttribute *attribute;
  1414     /* copy the common attributes for all keys first */
  1415     crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
  1416 							commonKeyAttrsCount);
  1417     if (crv != CKR_OK) {
  1418 	goto fail;
  1421     /* copy the common attributes for all public keys next */
  1422     crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs,
  1423 							commonPubKeyAttrsCount);
  1424     if (crv != CKR_OK) {
  1425 	goto fail;
  1427     attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE);
  1428     PORT_Assert(attribute); /* if it wasn't here, ww should have failed
  1429 			     * copying the common attributes */
  1430     if (!attribute) {
  1431 	/* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but
  1432 	 * the fact is, the only reason we couldn't get the attribute would
  1433 	 * be a memory error or database error (an error in the 'device').
  1434 	 * if we have a database error code, we could return it here */
  1435 	crv = CKR_DEVICE_ERROR;
  1436 	goto fail;
  1438     key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue;
  1439     sftk_FreeAttribute(attribute);
  1441     /* finally copy the attributes for various public key types */
  1442     switch (key_type) {
  1443     case CKK_RSA:
  1444 	crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs,
  1445 							rsaPubKeyAttrsCount);
  1446 	break;
  1447     case CKK_DSA:
  1448 	crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs,
  1449 							dsaPubKeyAttrsCount);
  1450 	break;
  1451     case CKK_DH:
  1452 	crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs,
  1453 							dhPubKeyAttrsCount);
  1454 	break;
  1455 #ifndef NSS_DISABLE_ECC
  1456     case CKK_EC:
  1457 	crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs,
  1458 							ecPubKeyAttrsCount);
  1459 	break;
  1460 #endif
  1461      default:
  1462 	crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
  1463 				* of token keys into our database. */
  1465 fail:
  1466     return crv;
  1468 CK_RV
  1469 stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to)
  1471     CK_RV crv;
  1472     crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs,
  1473 							commonKeyAttrsCount);
  1474     if (crv != CKR_OK) {
  1475 	goto fail;
  1477     crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs,
  1478 							secretKeyAttrsCount);
  1479 fail:
  1480     return crv;
  1483 /*
  1484  * Copy a token object. We need to explicitly copy the relevant
  1485  * attributes since token objects don't store those attributes in
  1486  * the token itself.
  1487  */
  1488 CK_RV
  1489 sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject)
  1491     SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject);
  1492     CK_RV crv;
  1494     PORT_Assert(src_to);
  1495     if (src_to == NULL) {
  1496 	return CKR_DEVICE_ERROR; /* internal state inconsistant */
  1499     crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs,
  1500 							commonAttrsCount);
  1501     if (crv != CKR_OK) {
  1502 	goto fail;
  1504     switch (src_to->obj.objclass) {
  1505     case CKO_CERTIFICATE:
  1506 	crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs,
  1507 							certAttrsCount);
  1508  	break;
  1509     case CKO_NETSCAPE_TRUST:
  1510 	crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs,
  1511 							trustAttrsCount);
  1512 	break;
  1513     case CKO_NETSCAPE_SMIME:
  1514 	crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs,
  1515 							smimeAttrsCount);
  1516 	break;
  1517     case CKO_NETSCAPE_CRL:
  1518 	crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs,
  1519 							crlAttrsCount);
  1520 	break;
  1521     case CKO_PRIVATE_KEY:
  1522 	crv = stfk_CopyTokenPrivateKey(destObject,src_to);
  1523 	break;
  1524     case CKO_PUBLIC_KEY:
  1525 	crv = stfk_CopyTokenPublicKey(destObject,src_to);
  1526 	break;
  1527     case CKO_SECRET_KEY:
  1528 	crv = stfk_CopyTokenSecretKey(destObject,src_to);
  1529 	break;
  1530     default:
  1531 	crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types
  1532 				* of token keys into our database. */
  1534 fail:
  1535     return crv;
  1538 /*
  1539  * copy the attributes from one object to another. Don't overwrite existing
  1540  * attributes. NOTE: This is a pretty expensive operation since it
  1541  * grabs the attribute locks for the src object for a *long* time.
  1542  */
  1543 CK_RV
  1544 sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject)
  1546     SFTKAttribute *attribute;
  1547     SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject);
  1548     unsigned int i;
  1550     if (src_so == NULL) {
  1551 	return sftk_CopyTokenObject(destObject,srcObject); 
  1554     PZ_Lock(src_so->attributeLock);
  1555     for(i=0; i < src_so->hashSize; i++) {
  1556 	attribute = src_so->head[i];
  1557 	do {
  1558 	    if (attribute) {
  1559 		if (!sftk_hasAttribute(destObject,attribute->handle)) {
  1560 		    /* we need to copy the attribute since each attribute
  1561 		     * only has one set of link list pointers */
  1562 		    SFTKAttribute *newAttribute = sftk_NewAttribute(
  1563 			  destObject,sftk_attr_expand(&attribute->attrib));
  1564 		    if (newAttribute == NULL) {
  1565 			PZ_Unlock(src_so->attributeLock);
  1566 			return CKR_HOST_MEMORY;
  1568 		    sftk_AddAttribute(destObject,newAttribute);
  1570 		attribute=attribute->next;
  1572 	} while (attribute != NULL);
  1574     PZ_Unlock(src_so->attributeLock);
  1576     return CKR_OK;
  1579 /*
  1580  * ******************** Search Utilities *******************************
  1581  */
  1583 /* add an object to a search list */
  1584 CK_RV
  1585 AddToList(SFTKObjectListElement **list,SFTKObject *object)
  1587      SFTKObjectListElement *newElem = 
  1588 	(SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement));
  1590      if (newElem == NULL) return CKR_HOST_MEMORY;
  1592      newElem->next = *list;
  1593      newElem->object = object;
  1594      sftk_ReferenceObject(object);
  1596     *list = newElem;
  1597     return CKR_OK;
  1601 /* return true if the object matches the template */
  1602 PRBool
  1603 sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count)
  1605     int i;
  1607     for (i=0; i < count; i++) {
  1608 	SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type);
  1609 	if (attribute == NULL) {
  1610 	    return PR_FALSE;
  1612 	if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {
  1613 	    if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,
  1614 					theTemplate[i].ulValueLen) == 0) {
  1615         	sftk_FreeAttribute(attribute);
  1616 		continue;
  1619         sftk_FreeAttribute(attribute);
  1620 	return PR_FALSE;
  1622     return PR_TRUE;
  1625 /* search through all the objects in the queue and return the template matches
  1626  * in the object list.
  1627  */
  1628 CK_RV
  1629 sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head, 
  1630 	unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, 
  1631 						int count, PRBool isLoggedIn)
  1633     unsigned int i;
  1634     SFTKObject *object;
  1635     CK_RV crv = CKR_OK;
  1637     for(i=0; i < size; i++) {
  1638         /* We need to hold the lock to copy a consistant version of
  1639          * the linked list. */
  1640         PZ_Lock(lock);
  1641 	for (object = head[i]; object != NULL; object= object->next) {
  1642 	    if (sftk_objectMatch(object,theTemplate,count)) {
  1643 		/* don't return objects that aren't yet visible */
  1644 		if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue;
  1645 		sftk_addHandle(search,object->handle);
  1648         PZ_Unlock(lock);
  1650     return crv;
  1653 /*
  1654  * free a single list element. Return the Next object in the list.
  1655  */
  1656 SFTKObjectListElement *
  1657 sftk_FreeObjectListElement(SFTKObjectListElement *objectList)
  1659     SFTKObjectListElement *ol = objectList->next;
  1661     sftk_FreeObject(objectList->object);
  1662     PORT_Free(objectList);
  1663     return ol;
  1666 /* free an entire object list */
  1667 void
  1668 sftk_FreeObjectList(SFTKObjectListElement *objectList)
  1670     SFTKObjectListElement *ol;
  1672     for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {}
  1675 /*
  1676  * free a search structure
  1677  */
  1678 void
  1679 sftk_FreeSearch(SFTKSearchResults *search)
  1681     if (search->handles) {
  1682 	PORT_Free(search->handles);
  1684     PORT_Free(search);
  1687 /*
  1688  * ******************** Session Utilities *******************************
  1689  */
  1691 /* update the sessions state based in it's flags and wether or not it's
  1692  * logged in */
  1693 void
  1694 sftk_update_state(SFTKSlot *slot,SFTKSession *session)
  1696     if (slot->isLoggedIn) {
  1697 	if (slot->ssoLoggedIn) {
  1698     	    session->info.state = CKS_RW_SO_FUNCTIONS;
  1699 	} else if (session->info.flags & CKF_RW_SESSION) {
  1700     	    session->info.state = CKS_RW_USER_FUNCTIONS;
  1701 	} else {
  1702     	    session->info.state = CKS_RO_USER_FUNCTIONS;
  1704     } else {
  1705 	if (session->info.flags & CKF_RW_SESSION) {
  1706     	    session->info.state = CKS_RW_PUBLIC_SESSION;
  1707 	} else {
  1708     	    session->info.state = CKS_RO_PUBLIC_SESSION;
  1713 /* update the state of all the sessions on a slot */
  1714 void
  1715 sftk_update_all_states(SFTKSlot *slot)
  1717     unsigned int i;
  1718     SFTKSession *session;
  1720     for (i=0; i < slot->sessHashSize; i++) {
  1721 	PZLock *lock = SFTK_SESSION_LOCK(slot,i);
  1722 	PZ_Lock(lock);
  1723 	for (session = slot->head[i]; session; session = session->next) {
  1724 	    sftk_update_state(slot,session);
  1726 	PZ_Unlock(lock);
  1730 /*
  1731  * context are cipher and digest contexts that are associated with a session
  1732  */
  1733 void
  1734 sftk_FreeContext(SFTKSessionContext *context)
  1736     if (context->cipherInfo) {
  1737 	(*context->destroy)(context->cipherInfo,PR_TRUE);
  1739     if (context->hashInfo) {
  1740 	(*context->hashdestroy)(context->hashInfo,PR_TRUE);
  1742     if (context->key) {
  1743 	sftk_FreeObject(context->key);
  1744 	context->key = NULL;
  1746     PORT_Free(context);
  1749 /*
  1750  * create a new nession. NOTE: The session handle is not set, and the
  1751  * session is not added to the slot's session queue.
  1752  */
  1753 SFTKSession *
  1754 sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
  1755 							     CK_FLAGS flags)
  1757     SFTKSession *session;
  1758     SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
  1760     if (slot == NULL) return NULL;
  1762     session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession));
  1763     if (session == NULL) return NULL;
  1765     session->next = session->prev = NULL;
  1766     session->refCount = 1;
  1767     session->enc_context = NULL;
  1768     session->hash_context = NULL;
  1769     session->sign_context = NULL;
  1770     session->search = NULL;
  1771     session->objectIDCount = 1;
  1772     session->objectLock = PZ_NewLock(nssILockObject);
  1773     if (session->objectLock == NULL) {
  1774 	PORT_Free(session);
  1775 	return NULL;
  1777     session->objects[0] = NULL;
  1779     session->slot = slot;
  1780     session->notify = notify;
  1781     session->appData = pApplication;
  1782     session->info.flags = flags;
  1783     session->info.slotID = slotID;
  1784     session->info.ulDeviceError = 0;
  1785     sftk_update_state(slot,session);
  1786     return session;
  1790 /* free all the data associated with a session. */
  1791 static void
  1792 sftk_DestroySession(SFTKSession *session)
  1794     SFTKObjectList *op,*next;
  1795     PORT_Assert(session->refCount == 0);
  1797     /* clean out the attributes */
  1798     /* since no one is referencing us, it's safe to walk the chain
  1799      * without a lock */
  1800     for (op = session->objects[0]; op != NULL; op = next) {
  1801         next = op->next;
  1802         /* paranoia */
  1803 	op->next = op->prev = NULL;
  1804 	sftk_DeleteObject(session,op->parent);
  1806     PZ_DestroyLock(session->objectLock);
  1807     if (session->enc_context) {
  1808 	sftk_FreeContext(session->enc_context);
  1810     if (session->hash_context) {
  1811 	sftk_FreeContext(session->hash_context);
  1813     if (session->sign_context) {
  1814 	sftk_FreeContext(session->sign_context);
  1816     if (session->search) {
  1817 	sftk_FreeSearch(session->search);
  1819     PORT_Free(session);
  1823 /*
  1824  * look up a session structure from a session handle
  1825  * generate a reference to it.
  1826  */
  1827 SFTKSession *
  1828 sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
  1830     SFTKSlot	*slot = sftk_SlotFromSessionHandle(handle);
  1831     SFTKSession *session;
  1832     PZLock	*lock;
  1834     if (!slot) return NULL;
  1835     lock = SFTK_SESSION_LOCK(slot,handle);
  1837     PZ_Lock(lock);
  1838     sftkqueue_find(session,handle,slot->head,slot->sessHashSize);
  1839     if (session) session->refCount++;
  1840     PZ_Unlock(lock);
  1842     return (session);
  1845 /*
  1846  * release a reference to a session handle
  1847  */
  1848 void
  1849 sftk_FreeSession(SFTKSession *session)
  1851     PRBool destroy = PR_FALSE;
  1852     SFTKSlot *slot = sftk_SlotFromSession(session);
  1853     PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle);
  1855     PZ_Lock(lock);
  1856     if (session->refCount == 1) destroy = PR_TRUE;
  1857     session->refCount--;
  1858     PZ_Unlock(lock);
  1860     if (destroy) sftk_DestroySession(session);
  1863 void
  1864 sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle)
  1866     if (search->handles == NULL) {
  1867 	return;
  1869     if (search->size >= search->array_size) {
  1870 	search->array_size += NSC_SEARCH_BLOCK_SIZE;
  1871 	search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
  1872 				 sizeof(CK_OBJECT_HANDLE)* search->array_size);
  1873 	if (search->handles == NULL) {
  1874 	   return;
  1877     search->handles[search->size] = handle;
  1878     search->size++;
  1881 static  CK_RV
  1882 handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle, 
  1883 	      CK_OBJECT_CLASS *objClass)
  1885     SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle);
  1886     CK_ATTRIBUTE objClassTemplate;
  1887     CK_RV crv;
  1889     *objClass = CKO_DATA;
  1890     objClassTemplate.type = CKA_CLASS;
  1891     objClassTemplate.pValue = objClass;
  1892     objClassTemplate.ulValueLen = sizeof(*objClass);
  1893     crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1);
  1894     sftk_freeDB(dbHandle);
  1895     return crv;
  1898 SFTKObject *
  1899 sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle)
  1901     SFTKObject *object = NULL;
  1902     SFTKTokenObject *tokObject = NULL;
  1903     PRBool hasLocks = PR_FALSE;
  1904     CK_RV crv;
  1906     object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList,  0,
  1907 							PR_FALSE);
  1908     if (object == NULL) {
  1909 	return NULL;
  1911     tokObject = (SFTKTokenObject *) object;
  1913     object->handle = handle;
  1914     /* every object must have a class, if we can't get it, the object
  1915      * doesn't exist */
  1916     crv = handleToClass(slot, handle, &object->objclass);
  1917     if (crv != CKR_OK) {
  1918 	goto loser;
  1920     object->slot = slot;
  1921     object->objectInfo = NULL;
  1922     object->infoFree = NULL;
  1923     if (!hasLocks) {
  1924 	object->refLock = PZ_NewLock(nssILockRefLock);
  1926     if (object->refLock == NULL) {
  1927 	goto loser;
  1929     object->refCount = 1;
  1931     return object;
  1932 loser:
  1933     if (object) {
  1934 	(void) sftk_DestroyObject(object);
  1936     return NULL;
  1940 SFTKTokenObject *
  1941 sftk_convertSessionToToken(SFTKObject *obj)
  1943     SECItem *key;
  1944     SFTKSessionObject *so = (SFTKSessionObject *)obj;
  1945     SFTKTokenObject *to = sftk_narrowToTokenObject(obj);
  1946     SECStatus rv;
  1948     sftk_DestroySessionObjectData(so);
  1949     PZ_DestroyLock(so->attributeLock);
  1950     if (to == NULL) {
  1951 	return NULL;
  1953     sftk_tokenKeyLock(so->obj.slot);
  1954     key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle);
  1955     if (key == NULL) {
  1956     	sftk_tokenKeyUnlock(so->obj.slot);
  1957 	return NULL;
  1959     rv = SECITEM_CopyItem(NULL,&to->dbKey,key);
  1960     sftk_tokenKeyUnlock(so->obj.slot);
  1961     if (rv == SECFailure) {
  1962 	return NULL;
  1965     return to;
  1968 SFTKSessionObject *
  1969 sftk_narrowToSessionObject(SFTKObject *obj)
  1971     return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL;
  1974 SFTKTokenObject *
  1975 sftk_narrowToTokenObject(SFTKObject *obj)
  1977     return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL;

mercurial