1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/softoken/pkcs11u.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1979 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * Internal PKCS #11 functions. Should only be called by pkcs11.c 1.9 + */ 1.10 +#include "pkcs11.h" 1.11 +#include "pkcs11i.h" 1.12 +#include "lowkeyi.h" 1.13 +#include "secasn1.h" 1.14 +#include "blapi.h" 1.15 +#include "secerr.h" 1.16 +#include "prnetdb.h" /* for PR_ntohl */ 1.17 +#include "sftkdb.h" 1.18 +#include "softoken.h" 1.19 + 1.20 +/* 1.21 + * ******************** Attribute Utilities ******************************* 1.22 + */ 1.23 + 1.24 +/* 1.25 + * create a new attribute with type, value, and length. Space is allocated 1.26 + * to hold value. 1.27 + */ 1.28 +static SFTKAttribute * 1.29 +sftk_NewAttribute(SFTKObject *object, 1.30 + CK_ATTRIBUTE_TYPE type, const void *value, CK_ULONG len) 1.31 +{ 1.32 + SFTKAttribute *attribute; 1.33 + 1.34 + SFTKSessionObject *so = sftk_narrowToSessionObject(object); 1.35 + int index; 1.36 + 1.37 + if (so == NULL) { 1.38 + /* allocate new attribute in a buffer */ 1.39 + PORT_Assert(0); 1.40 + return NULL; 1.41 + } 1.42 + /* 1.43 + * We attempt to keep down contention on Malloc and Arena locks by 1.44 + * limiting the number of these calls on high traversed paths. This 1.45 + * is done for attributes by 'allocating' them from a pool already 1.46 + * allocated by the parent object. 1.47 + */ 1.48 + PZ_Lock(so->attributeLock); 1.49 + index = so->nextAttr++; 1.50 + PZ_Unlock(so->attributeLock); 1.51 + PORT_Assert(index < MAX_OBJS_ATTRS); 1.52 + if (index >= MAX_OBJS_ATTRS) return NULL; 1.53 + 1.54 + attribute = &so->attrList[index]; 1.55 + attribute->attrib.type = type; 1.56 + attribute->freeAttr = PR_FALSE; 1.57 + attribute->freeData = PR_FALSE; 1.58 + if (value) { 1.59 + if (len <= ATTR_SPACE) { 1.60 + attribute->attrib.pValue = attribute->space; 1.61 + } else { 1.62 + attribute->attrib.pValue = PORT_Alloc(len); 1.63 + attribute->freeData = PR_TRUE; 1.64 + } 1.65 + if (attribute->attrib.pValue == NULL) { 1.66 + return NULL; 1.67 + } 1.68 + PORT_Memcpy(attribute->attrib.pValue,value,len); 1.69 + attribute->attrib.ulValueLen = len; 1.70 + } else { 1.71 + attribute->attrib.pValue = NULL; 1.72 + attribute->attrib.ulValueLen = 0; 1.73 + } 1.74 + attribute->attrib.type = type; 1.75 + attribute->handle = type; 1.76 + attribute->next = attribute->prev = NULL; 1.77 + return attribute; 1.78 +} 1.79 + 1.80 +/* 1.81 + * Free up all the memory associated with an attribute. Reference count 1.82 + * must be zero to call this. 1.83 + */ 1.84 +static void 1.85 +sftk_DestroyAttribute(SFTKAttribute *attribute) 1.86 +{ 1.87 + if (attribute->freeData) { 1.88 + if (attribute->attrib.pValue) { 1.89 + /* clear out the data in the attribute value... it may have been 1.90 + * sensitive data */ 1.91 + PORT_Memset(attribute->attrib.pValue, 0, 1.92 + attribute->attrib.ulValueLen); 1.93 + } 1.94 + PORT_Free(attribute->attrib.pValue); 1.95 + } 1.96 + PORT_Free(attribute); 1.97 +} 1.98 + 1.99 +/* 1.100 + * release a reference to an attribute structure 1.101 + */ 1.102 +void 1.103 +sftk_FreeAttribute(SFTKAttribute *attribute) 1.104 +{ 1.105 + if (attribute->freeAttr) { 1.106 + sftk_DestroyAttribute(attribute); 1.107 + return; 1.108 + } 1.109 +} 1.110 + 1.111 +static SFTKAttribute * 1.112 +sftk_FindTokenAttribute(SFTKTokenObject *object,CK_ATTRIBUTE_TYPE type) 1.113 +{ 1.114 + SFTKAttribute *myattribute = NULL; 1.115 + SFTKDBHandle *dbHandle = NULL; 1.116 + CK_RV crv = CKR_HOST_MEMORY; 1.117 + 1.118 + myattribute = (SFTKAttribute*)PORT_Alloc(sizeof(SFTKAttribute)); 1.119 + if (myattribute == NULL) { 1.120 + goto loser; 1.121 + } 1.122 + 1.123 + dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle); 1.124 + 1.125 + myattribute->handle = type; 1.126 + myattribute->attrib.type = type; 1.127 + myattribute->attrib.pValue = myattribute->space; 1.128 + myattribute->attrib.ulValueLen = ATTR_SPACE; 1.129 + myattribute->next = myattribute->prev = NULL; 1.130 + myattribute->freeAttr = PR_TRUE; 1.131 + myattribute->freeData = PR_FALSE; 1.132 + 1.133 + crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, 1.134 + &myattribute->attrib, 1); 1.135 + 1.136 + /* attribute is bigger than our attribute space buffer, malloc it */ 1.137 + if (crv == CKR_BUFFER_TOO_SMALL) { 1.138 + myattribute->attrib.pValue = NULL; 1.139 + crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, 1.140 + &myattribute->attrib, 1); 1.141 + if (crv != CKR_OK) { 1.142 + goto loser; 1.143 + } 1.144 + myattribute->attrib.pValue = PORT_Alloc(myattribute->attrib.ulValueLen); 1.145 + if (myattribute->attrib.pValue == NULL) { 1.146 + crv = CKR_HOST_MEMORY; 1.147 + goto loser; 1.148 + } 1.149 + myattribute->freeData = PR_TRUE; 1.150 + crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, 1.151 + &myattribute->attrib, 1); 1.152 + } 1.153 +loser: 1.154 + if (dbHandle) { 1.155 + sftk_freeDB(dbHandle); 1.156 + } 1.157 + if (crv != CKR_OK) { 1.158 + if (myattribute) { 1.159 + myattribute->attrib.ulValueLen = 0; 1.160 + sftk_FreeAttribute(myattribute); 1.161 + myattribute = NULL; 1.162 + } 1.163 + } 1.164 + return myattribute; 1.165 +} 1.166 + 1.167 +/* 1.168 + * look up and attribute structure from a type and Object structure. 1.169 + * The returned attribute is referenced and needs to be freed when 1.170 + * it is no longer needed. 1.171 + */ 1.172 +SFTKAttribute * 1.173 +sftk_FindAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.174 +{ 1.175 + SFTKAttribute *attribute; 1.176 + SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); 1.177 + 1.178 + if (sessObject == NULL) { 1.179 + return sftk_FindTokenAttribute(sftk_narrowToTokenObject(object),type); 1.180 + } 1.181 + 1.182 + PZ_Lock(sessObject->attributeLock); 1.183 + sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize); 1.184 + PZ_Unlock(sessObject->attributeLock); 1.185 + 1.186 + return(attribute); 1.187 +} 1.188 + 1.189 +/* 1.190 + * Take a buffer and it's length and return it's true size in bits; 1.191 + */ 1.192 +unsigned int 1.193 +sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen) 1.194 +{ 1.195 + unsigned int size = bufLen * 8; 1.196 + unsigned int i; 1.197 + 1.198 + /* Get the real length in bytes */ 1.199 + for (i=0; i < bufLen; i++) { 1.200 + unsigned char c = *buf++; 1.201 + if (c != 0) { 1.202 + unsigned char m; 1.203 + for (m=0x80; m > 0 ; m = m >> 1) { 1.204 + if ((c & m) != 0) { 1.205 + break; 1.206 + } 1.207 + size--; 1.208 + } 1.209 + break; 1.210 + } 1.211 + size-=8; 1.212 + } 1.213 + return size; 1.214 +} 1.215 + 1.216 +/* 1.217 + * Constrain a big num attribute. to size and padding 1.218 + * minLength means length of the object must be greater than equal to minLength 1.219 + * maxLength means length of the object must be less than equal to maxLength 1.220 + * minMultiple means that object length mod minMultiple must equal 0. 1.221 + * all input sizes are in bits. 1.222 + * if any constraint is '0' that constraint is not checked. 1.223 + */ 1.224 +CK_RV 1.225 +sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, 1.226 + int minLength, int maxLength, int minMultiple) 1.227 +{ 1.228 + SFTKAttribute *attribute; 1.229 + int size; 1.230 + unsigned char *ptr; 1.231 + 1.232 + attribute = sftk_FindAttribute(object, type); 1.233 + if (!attribute) { 1.234 + return CKR_TEMPLATE_INCOMPLETE; 1.235 + } 1.236 + ptr = (unsigned char *) attribute->attrib.pValue; 1.237 + if (ptr == NULL) { 1.238 + sftk_FreeAttribute(attribute); 1.239 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.240 + } 1.241 + size = sftk_GetLengthInBits(ptr, attribute->attrib.ulValueLen); 1.242 + sftk_FreeAttribute(attribute); 1.243 + 1.244 + if ((minLength != 0) && (size < minLength)) { 1.245 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.246 + } 1.247 + if ((maxLength != 0) && (size > maxLength)) { 1.248 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.249 + } 1.250 + if ((minMultiple != 0) && ((size % minMultiple) != 0)) { 1.251 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.252 + } 1.253 + return CKR_OK; 1.254 +} 1.255 + 1.256 +PRBool 1.257 +sftk_hasAttributeToken(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type) 1.258 +{ 1.259 + CK_ATTRIBUTE template; 1.260 + CK_RV crv; 1.261 + SFTKDBHandle *dbHandle; 1.262 + 1.263 + dbHandle = sftk_getDBForTokenObject(object->obj.slot, object->obj.handle); 1.264 + template.type = type; 1.265 + template.pValue = NULL; 1.266 + template.ulValueLen = 0; 1.267 + 1.268 + crv = sftkdb_GetAttributeValue(dbHandle, object->obj.handle, &template, 1); 1.269 + sftk_freeDB(dbHandle); 1.270 + 1.271 + /* attribute is bigger than our attribute space buffer, malloc it */ 1.272 + return (crv == CKR_OK) ? PR_TRUE : PR_FALSE; 1.273 +} 1.274 + 1.275 +/* 1.276 + * return true if object has attribute 1.277 + */ 1.278 +PRBool 1.279 +sftk_hasAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.280 +{ 1.281 + SFTKAttribute *attribute; 1.282 + SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); 1.283 + 1.284 + if (sessObject == NULL) { 1.285 + return sftk_hasAttributeToken(sftk_narrowToTokenObject(object), type); 1.286 + } 1.287 + 1.288 + PZ_Lock(sessObject->attributeLock); 1.289 + sftkqueue_find(attribute,type,sessObject->head, sessObject->hashSize); 1.290 + PZ_Unlock(sessObject->attributeLock); 1.291 + 1.292 + return (PRBool)(attribute != NULL); 1.293 +} 1.294 + 1.295 +/* 1.296 + * add an attribute to an object 1.297 + */ 1.298 +static void 1.299 +sftk_AddAttribute(SFTKObject *object,SFTKAttribute *attribute) 1.300 +{ 1.301 + SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); 1.302 + 1.303 + if (sessObject == NULL) return; 1.304 + PZ_Lock(sessObject->attributeLock); 1.305 + sftkqueue_add(attribute,attribute->handle, 1.306 + sessObject->head, sessObject->hashSize); 1.307 + PZ_Unlock(sessObject->attributeLock); 1.308 +} 1.309 + 1.310 +/* 1.311 + * copy an unsigned attribute into a SECItem. Secitem is allocated in 1.312 + * the specified arena. 1.313 + */ 1.314 +CK_RV 1.315 +sftk_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object, 1.316 + CK_ATTRIBUTE_TYPE type) 1.317 +{ 1.318 + SFTKAttribute *attribute; 1.319 + 1.320 + item->data = NULL; 1.321 + 1.322 + attribute = sftk_FindAttribute(object, type); 1.323 + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; 1.324 + 1.325 + (void)SECITEM_AllocItem(arena, item, attribute->attrib.ulValueLen); 1.326 + if (item->data == NULL) { 1.327 + sftk_FreeAttribute(attribute); 1.328 + return CKR_HOST_MEMORY; 1.329 + } 1.330 + PORT_Memcpy(item->data, attribute->attrib.pValue, item->len); 1.331 + sftk_FreeAttribute(attribute); 1.332 + return CKR_OK; 1.333 +} 1.334 + 1.335 +/* 1.336 + * fetch multiple attributes into SECItems. Secitem data is allocated in 1.337 + * the specified arena. 1.338 + */ 1.339 +CK_RV 1.340 +sftk_MultipleAttribute2SecItem(PLArenaPool *arena, SFTKObject *object, 1.341 + SFTKItemTemplate *itemTemplate, int itemTemplateCount) 1.342 +{ 1.343 + 1.344 + CK_RV crv = CKR_OK; 1.345 + CK_ATTRIBUTE templateSpace[SFTK_MAX_ITEM_TEMPLATE]; 1.346 + CK_ATTRIBUTE *template; 1.347 + SFTKTokenObject *tokObject; 1.348 + SFTKDBHandle *dbHandle = NULL; 1.349 + int i; 1.350 + 1.351 + tokObject = sftk_narrowToTokenObject(object); 1.352 + 1.353 + /* session objects, just loop through the list */ 1.354 + if (tokObject == NULL) { 1.355 + for (i=0; i < itemTemplateCount; i++) { 1.356 + crv = sftk_Attribute2SecItem(arena,itemTemplate[i].item, object, 1.357 + itemTemplate[i].type); 1.358 + if (crv != CKR_OK) { 1.359 + return crv; 1.360 + } 1.361 + } 1.362 + return CKR_OK; 1.363 + } 1.364 + 1.365 + /* don't do any work if none is required */ 1.366 + if (itemTemplateCount == 0) { 1.367 + return CKR_OK; 1.368 + } 1.369 + 1.370 + /* don't allocate the template unless we need it */ 1.371 + if (itemTemplateCount > SFTK_MAX_ITEM_TEMPLATE) { 1.372 + template = PORT_NewArray(CK_ATTRIBUTE, itemTemplateCount); 1.373 + } else { 1.374 + template = templateSpace; 1.375 + } 1.376 + 1.377 + if (template == NULL) { 1.378 + crv = CKR_HOST_MEMORY; 1.379 + goto loser; 1.380 + } 1.381 + 1.382 + dbHandle = sftk_getDBForTokenObject(object->slot, object->handle); 1.383 + if (dbHandle == NULL) { 1.384 + crv = CKR_OBJECT_HANDLE_INVALID; 1.385 + goto loser; 1.386 + } 1.387 + 1.388 + /* set up the PKCS #11 template */ 1.389 + for (i=0; i < itemTemplateCount; i++) { 1.390 + template[i].type = itemTemplate[i].type; 1.391 + template[i].pValue = NULL; 1.392 + template[i].ulValueLen = 0; 1.393 + } 1.394 + 1.395 + /* fetch the attribute lengths */ 1.396 + crv = sftkdb_GetAttributeValue(dbHandle, object->handle, 1.397 + template, itemTemplateCount); 1.398 + if (crv != CKR_OK) { 1.399 + goto loser; 1.400 + } 1.401 + 1.402 + /* allocate space for the attributes */ 1.403 + for (i=0; i < itemTemplateCount ; i++) { 1.404 + template[i].pValue = PORT_ArenaAlloc(arena, template[i].ulValueLen); 1.405 + if (template[i].pValue == NULL) { 1.406 + crv = CKR_HOST_MEMORY; 1.407 + goto loser; 1.408 + } 1.409 + } 1.410 + 1.411 + /* fetch the attributes */ 1.412 + crv = sftkdb_GetAttributeValue(dbHandle, object->handle, 1.413 + template, itemTemplateCount); 1.414 + if (crv != CKR_OK) { 1.415 + goto loser; 1.416 + } 1.417 + 1.418 + /* Fill in the items */ 1.419 + for (i=0; i < itemTemplateCount; i++) { 1.420 + itemTemplate[i].item->data = template[i].pValue; 1.421 + itemTemplate[i].item->len = template[i].ulValueLen; 1.422 + } 1.423 + 1.424 +loser: 1.425 + if (template != templateSpace) { 1.426 + PORT_Free(template); 1.427 + } 1.428 + if (dbHandle) { 1.429 + sftk_freeDB(dbHandle); 1.430 + } 1.431 + 1.432 + return crv; 1.433 +} 1.434 + 1.435 + 1.436 +/* 1.437 + * delete an attribute from an object 1.438 + */ 1.439 +static void 1.440 +sftk_DeleteAttribute(SFTKObject *object, SFTKAttribute *attribute) 1.441 +{ 1.442 + SFTKSessionObject *sessObject = sftk_narrowToSessionObject(object); 1.443 + 1.444 + if (sessObject == NULL) { 1.445 + return ; 1.446 + } 1.447 + PZ_Lock(sessObject->attributeLock); 1.448 + if (sftkqueue_is_queued(attribute,attribute->handle, 1.449 + sessObject->head, sessObject->hashSize)) { 1.450 + sftkqueue_delete(attribute,attribute->handle, 1.451 + sessObject->head, sessObject->hashSize); 1.452 + } 1.453 + PZ_Unlock(sessObject->attributeLock); 1.454 +} 1.455 + 1.456 +/* 1.457 + * this is only valid for CK_BBOOL type attributes. Return the state 1.458 + * of that attribute. 1.459 + */ 1.460 +PRBool 1.461 +sftk_isTrue(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.462 +{ 1.463 + SFTKAttribute *attribute; 1.464 + PRBool tok = PR_FALSE; 1.465 + 1.466 + attribute=sftk_FindAttribute(object,type); 1.467 + if (attribute == NULL) { return PR_FALSE; } 1.468 + tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue); 1.469 + sftk_FreeAttribute(attribute); 1.470 + 1.471 + return tok; 1.472 +} 1.473 + 1.474 +/* 1.475 + * force an attribute to null. 1.476 + * this is for sensitive keys which are stored in the database, we don't 1.477 + * want to keep this info around in memory in the clear. 1.478 + */ 1.479 +void 1.480 +sftk_nullAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.481 +{ 1.482 + SFTKAttribute *attribute; 1.483 + 1.484 + attribute=sftk_FindAttribute(object,type); 1.485 + if (attribute == NULL) return; 1.486 + 1.487 + if (attribute->attrib.pValue != NULL) { 1.488 + PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); 1.489 + if (attribute->freeData) { 1.490 + PORT_Free(attribute->attrib.pValue); 1.491 + } 1.492 + attribute->freeData = PR_FALSE; 1.493 + attribute->attrib.pValue = NULL; 1.494 + attribute->attrib.ulValueLen = 0; 1.495 + } 1.496 + sftk_FreeAttribute(attribute); 1.497 +} 1.498 + 1.499 + 1.500 +static CK_RV 1.501 +sftk_forceTokenAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 1.502 + const void *value, unsigned int len) 1.503 +{ 1.504 + CK_ATTRIBUTE attribute; 1.505 + SFTKDBHandle *dbHandle = NULL; 1.506 + SFTKTokenObject *to = sftk_narrowToTokenObject(object); 1.507 + CK_RV crv; 1.508 + 1.509 + PORT_Assert(to); 1.510 + if (to == NULL) { 1.511 + return CKR_DEVICE_ERROR; 1.512 + } 1.513 + 1.514 + dbHandle = sftk_getDBForTokenObject(object->slot, object->handle); 1.515 + 1.516 + attribute.type = type; 1.517 + attribute.pValue = (void *)value; 1.518 + attribute.ulValueLen = len; 1.519 + 1.520 + crv = sftkdb_SetAttributeValue(dbHandle, object, &attribute, 1); 1.521 + sftk_freeDB(dbHandle); 1.522 + return crv; 1.523 +} 1.524 + 1.525 +/* 1.526 + * force an attribute to a specifc value. 1.527 + */ 1.528 +CK_RV 1.529 +sftk_forceAttribute(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 1.530 + const void *value, unsigned int len) 1.531 +{ 1.532 + SFTKAttribute *attribute; 1.533 + void *att_val = NULL; 1.534 + PRBool freeData = PR_FALSE; 1.535 + 1.536 + PORT_Assert(object); 1.537 + PORT_Assert(object->refCount); 1.538 + PORT_Assert(object->slot); 1.539 + if (!object || 1.540 + !object->refCount || 1.541 + !object->slot) { 1.542 + return CKR_DEVICE_ERROR; 1.543 + } 1.544 + if (sftk_isToken(object->handle)) { 1.545 + return sftk_forceTokenAttribute(object,type,value,len); 1.546 + } 1.547 + attribute=sftk_FindAttribute(object,type); 1.548 + if (attribute == NULL) return sftk_AddAttributeType(object,type,value,len); 1.549 + 1.550 + 1.551 + if (value) { 1.552 + if (len <= ATTR_SPACE) { 1.553 + att_val = attribute->space; 1.554 + } else { 1.555 + att_val = PORT_Alloc(len); 1.556 + freeData = PR_TRUE; 1.557 + } 1.558 + if (att_val == NULL) { 1.559 + return CKR_HOST_MEMORY; 1.560 + } 1.561 + if (attribute->attrib.pValue == att_val) { 1.562 + PORT_Memset(attribute->attrib.pValue,0, 1.563 + attribute->attrib.ulValueLen); 1.564 + } 1.565 + PORT_Memcpy(att_val,value,len); 1.566 + } 1.567 + if (attribute->attrib.pValue != NULL) { 1.568 + if (attribute->attrib.pValue != att_val) { 1.569 + PORT_Memset(attribute->attrib.pValue,0, 1.570 + attribute->attrib.ulValueLen); 1.571 + } 1.572 + if (attribute->freeData) { 1.573 + PORT_Free(attribute->attrib.pValue); 1.574 + } 1.575 + attribute->freeData = PR_FALSE; 1.576 + attribute->attrib.pValue = NULL; 1.577 + attribute->attrib.ulValueLen = 0; 1.578 + } 1.579 + if (att_val) { 1.580 + attribute->attrib.pValue = att_val; 1.581 + attribute->attrib.ulValueLen = len; 1.582 + attribute->freeData = freeData; 1.583 + } 1.584 + sftk_FreeAttribute(attribute); 1.585 + return CKR_OK; 1.586 +} 1.587 + 1.588 +/* 1.589 + * return a null terminated string from attribute 'type'. This string 1.590 + * is allocated and needs to be freed with PORT_Free() When complete. 1.591 + */ 1.592 +char * 1.593 +sftk_getString(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.594 +{ 1.595 + SFTKAttribute *attribute; 1.596 + char *label = NULL; 1.597 + 1.598 + attribute=sftk_FindAttribute(object,type); 1.599 + if (attribute == NULL) return NULL; 1.600 + 1.601 + if (attribute->attrib.pValue != NULL) { 1.602 + label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1); 1.603 + if (label == NULL) { 1.604 + sftk_FreeAttribute(attribute); 1.605 + return NULL; 1.606 + } 1.607 + 1.608 + PORT_Memcpy(label,attribute->attrib.pValue, 1.609 + attribute->attrib.ulValueLen); 1.610 + label[attribute->attrib.ulValueLen] = 0; 1.611 + } 1.612 + sftk_FreeAttribute(attribute); 1.613 + return label; 1.614 +} 1.615 + 1.616 +/* 1.617 + * decode when a particular attribute may be modified 1.618 + * SFTK_NEVER: This attribute must be set at object creation time and 1.619 + * can never be modified. 1.620 + * SFTK_ONCOPY: This attribute may be modified only when you copy the 1.621 + * object. 1.622 + * SFTK_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from 1.623 + * CK_FALSE to CK_TRUE. 1.624 + * SFTK_ALWAYS: This attribute can always be modified. 1.625 + * Some attributes vary their modification type based on the class of the 1.626 + * object. 1.627 + */ 1.628 +SFTKModifyType 1.629 +sftk_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) 1.630 +{ 1.631 + /* if we don't know about it, user user defined, always allow modify */ 1.632 + SFTKModifyType mtype = SFTK_ALWAYS; 1.633 + 1.634 + switch(type) { 1.635 + /* NEVER */ 1.636 + case CKA_CLASS: 1.637 + case CKA_CERTIFICATE_TYPE: 1.638 + case CKA_KEY_TYPE: 1.639 + case CKA_MODULUS: 1.640 + case CKA_MODULUS_BITS: 1.641 + case CKA_PUBLIC_EXPONENT: 1.642 + case CKA_PRIVATE_EXPONENT: 1.643 + case CKA_PRIME: 1.644 + case CKA_SUBPRIME: 1.645 + case CKA_BASE: 1.646 + case CKA_PRIME_1: 1.647 + case CKA_PRIME_2: 1.648 + case CKA_EXPONENT_1: 1.649 + case CKA_EXPONENT_2: 1.650 + case CKA_COEFFICIENT: 1.651 + case CKA_VALUE_LEN: 1.652 + case CKA_ALWAYS_SENSITIVE: 1.653 + case CKA_NEVER_EXTRACTABLE: 1.654 + case CKA_NETSCAPE_DB: 1.655 + mtype = SFTK_NEVER; 1.656 + break; 1.657 + 1.658 + /* ONCOPY */ 1.659 + case CKA_TOKEN: 1.660 + case CKA_PRIVATE: 1.661 + case CKA_MODIFIABLE: 1.662 + mtype = SFTK_ONCOPY; 1.663 + break; 1.664 + 1.665 + /* SENSITIVE */ 1.666 + case CKA_SENSITIVE: 1.667 + case CKA_EXTRACTABLE: 1.668 + mtype = SFTK_SENSITIVE; 1.669 + break; 1.670 + 1.671 + /* ALWAYS */ 1.672 + case CKA_LABEL: 1.673 + case CKA_APPLICATION: 1.674 + case CKA_ID: 1.675 + case CKA_SERIAL_NUMBER: 1.676 + case CKA_START_DATE: 1.677 + case CKA_END_DATE: 1.678 + case CKA_DERIVE: 1.679 + case CKA_ENCRYPT: 1.680 + case CKA_DECRYPT: 1.681 + case CKA_SIGN: 1.682 + case CKA_VERIFY: 1.683 + case CKA_SIGN_RECOVER: 1.684 + case CKA_VERIFY_RECOVER: 1.685 + case CKA_WRAP: 1.686 + case CKA_UNWRAP: 1.687 + mtype = SFTK_ALWAYS; 1.688 + break; 1.689 + 1.690 + /* DEPENDS ON CLASS */ 1.691 + case CKA_VALUE: 1.692 + mtype = (inClass == CKO_DATA) ? SFTK_ALWAYS : SFTK_NEVER; 1.693 + break; 1.694 + 1.695 + case CKA_SUBJECT: 1.696 + mtype = (inClass == CKO_CERTIFICATE) ? SFTK_NEVER : SFTK_ALWAYS; 1.697 + break; 1.698 + default: 1.699 + break; 1.700 + } 1.701 + return mtype; 1.702 +} 1.703 + 1.704 +/* decode if a particular attribute is sensitive (cannot be read 1.705 + * back to the user of if the object is set to SENSITIVE) */ 1.706 +PRBool 1.707 +sftk_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass) 1.708 +{ 1.709 + switch(type) { 1.710 + /* ALWAYS */ 1.711 + case CKA_PRIVATE_EXPONENT: 1.712 + case CKA_PRIME_1: 1.713 + case CKA_PRIME_2: 1.714 + case CKA_EXPONENT_1: 1.715 + case CKA_EXPONENT_2: 1.716 + case CKA_COEFFICIENT: 1.717 + return PR_TRUE; 1.718 + 1.719 + /* DEPENDS ON CLASS */ 1.720 + case CKA_VALUE: 1.721 + /* PRIVATE and SECRET KEYS have SENSITIVE values */ 1.722 + return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY)); 1.723 + 1.724 + default: 1.725 + break; 1.726 + } 1.727 + return PR_FALSE; 1.728 +} 1.729 + 1.730 +/* 1.731 + * copy an attribute into a SECItem. Secitem is allocated in the specified 1.732 + * arena. 1.733 + */ 1.734 +CK_RV 1.735 +sftk_Attribute2SecItem(PLArenaPool *arena,SECItem *item,SFTKObject *object, 1.736 + CK_ATTRIBUTE_TYPE type) 1.737 +{ 1.738 + int len; 1.739 + SFTKAttribute *attribute; 1.740 + 1.741 + attribute = sftk_FindAttribute(object, type); 1.742 + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; 1.743 + len = attribute->attrib.ulValueLen; 1.744 + 1.745 + if (arena) { 1.746 + item->data = (unsigned char *) PORT_ArenaAlloc(arena,len); 1.747 + } else { 1.748 + item->data = (unsigned char *) PORT_Alloc(len); 1.749 + } 1.750 + if (item->data == NULL) { 1.751 + sftk_FreeAttribute(attribute); 1.752 + return CKR_HOST_MEMORY; 1.753 + } 1.754 + item->len = len; 1.755 + PORT_Memcpy(item->data,attribute->attrib.pValue, len); 1.756 + sftk_FreeAttribute(attribute); 1.757 + return CKR_OK; 1.758 +} 1.759 + 1.760 +CK_RV 1.761 +sftk_GetULongAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type, 1.762 + CK_ULONG *longData) 1.763 +{ 1.764 + SFTKAttribute *attribute; 1.765 + 1.766 + attribute = sftk_FindAttribute(object, type); 1.767 + if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; 1.768 + 1.769 + if (attribute->attrib.ulValueLen != sizeof(CK_ULONG)) { 1.770 + return CKR_ATTRIBUTE_VALUE_INVALID; 1.771 + } 1.772 + 1.773 + *longData = *(CK_ULONG *)attribute->attrib.pValue; 1.774 + sftk_FreeAttribute(attribute); 1.775 + return CKR_OK; 1.776 +} 1.777 + 1.778 +void 1.779 +sftk_DeleteAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type) 1.780 +{ 1.781 + SFTKAttribute *attribute; 1.782 + attribute = sftk_FindAttribute(object, type); 1.783 + if (attribute == NULL) return ; 1.784 + sftk_DeleteAttribute(object,attribute); 1.785 + sftk_FreeAttribute(attribute); 1.786 +} 1.787 + 1.788 +CK_RV 1.789 +sftk_AddAttributeType(SFTKObject *object,CK_ATTRIBUTE_TYPE type, 1.790 + const void *valPtr, CK_ULONG length) 1.791 +{ 1.792 + SFTKAttribute *attribute; 1.793 + attribute = sftk_NewAttribute(object,type,valPtr,length); 1.794 + if (attribute == NULL) { return CKR_HOST_MEMORY; } 1.795 + sftk_AddAttribute(object,attribute); 1.796 + return CKR_OK; 1.797 +} 1.798 + 1.799 +/* 1.800 + * ******************** Object Utilities ******************************* 1.801 + */ 1.802 + 1.803 +/* must be called holding sftk_tokenKeyLock(slot) */ 1.804 +static SECItem * 1.805 +sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle) 1.806 +{ 1.807 + return (SECItem *)PL_HashTableLookup(slot->tokObjHashTable, (void *)handle); 1.808 +} 1.809 + 1.810 +/* 1.811 + * use the refLock. This operations should be very rare, so the added 1.812 + * contention on the ref lock should be lower than the overhead of adding 1.813 + * a new lock. We use separate functions for this just in case I'm wrong. 1.814 + */ 1.815 +static void 1.816 +sftk_tokenKeyLock(SFTKSlot *slot) { 1.817 + SKIP_AFTER_FORK(PZ_Lock(slot->objectLock)); 1.818 +} 1.819 + 1.820 +static void 1.821 +sftk_tokenKeyUnlock(SFTKSlot *slot) { 1.822 + SKIP_AFTER_FORK(PZ_Unlock(slot->objectLock)); 1.823 +} 1.824 + 1.825 +static PRIntn 1.826 +sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg) 1.827 +{ 1.828 + SECItem *item = (SECItem *)entry->value; 1.829 + 1.830 + SECITEM_FreeItem(item, PR_TRUE); 1.831 + return HT_ENUMERATE_NEXT; 1.832 +} 1.833 + 1.834 +CK_RV 1.835 +SFTK_ClearTokenKeyHashTable(SFTKSlot *slot) 1.836 +{ 1.837 + sftk_tokenKeyLock(slot); 1.838 + PORT_Assert(!slot->present); 1.839 + PL_HashTableEnumerateEntries(slot->tokObjHashTable, sftk_freeHashItem, NULL); 1.840 + sftk_tokenKeyUnlock(slot); 1.841 + return CKR_OK; 1.842 +} 1.843 + 1.844 + 1.845 +/* allocation hooks that allow us to recycle old object structures */ 1.846 +static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 }; 1.847 +static SFTKObjectFreeList tokenObjectList = { NULL, NULL, 0 }; 1.848 + 1.849 +SFTKObject * 1.850 +sftk_GetObjectFromList(PRBool *hasLocks, PRBool optimizeSpace, 1.851 + SFTKObjectFreeList *list, unsigned int hashSize, PRBool isSessionObject) 1.852 +{ 1.853 + SFTKObject *object; 1.854 + int size = 0; 1.855 + 1.856 + if (!optimizeSpace) { 1.857 + PZ_Lock(list->lock); 1.858 + object = list->head; 1.859 + if (object) { 1.860 + list->head = object->next; 1.861 + list->count--; 1.862 + } 1.863 + PZ_Unlock(list->lock); 1.864 + if (object) { 1.865 + object->next = object->prev = NULL; 1.866 + *hasLocks = PR_TRUE; 1.867 + return object; 1.868 + } 1.869 + } 1.870 + size = isSessionObject ? sizeof(SFTKSessionObject) 1.871 + + hashSize *sizeof(SFTKAttribute *) : sizeof(SFTKTokenObject); 1.872 + 1.873 + object = (SFTKObject*)PORT_ZAlloc(size); 1.874 + if (isSessionObject && object) { 1.875 + ((SFTKSessionObject *)object)->hashSize = hashSize; 1.876 + } 1.877 + *hasLocks = PR_FALSE; 1.878 + return object; 1.879 +} 1.880 + 1.881 +static void 1.882 +sftk_PutObjectToList(SFTKObject *object, SFTKObjectFreeList *list, 1.883 + PRBool isSessionObject) { 1.884 + 1.885 + /* the code below is equivalent to : 1.886 + * optimizeSpace = isSessionObject ? object->optimizeSpace : PR_FALSE; 1.887 + * just faster. 1.888 + */ 1.889 + PRBool optimizeSpace = isSessionObject && 1.890 + ((SFTKSessionObject *)object)->optimizeSpace; 1.891 + if (object->refLock && !optimizeSpace 1.892 + && (list->count < MAX_OBJECT_LIST_SIZE)) { 1.893 + PZ_Lock(list->lock); 1.894 + object->next = list->head; 1.895 + list->head = object; 1.896 + list->count++; 1.897 + PZ_Unlock(list->lock); 1.898 + return; 1.899 + } 1.900 + if (isSessionObject) { 1.901 + SFTKSessionObject *so = (SFTKSessionObject *)object; 1.902 + PZ_DestroyLock(so->attributeLock); 1.903 + so->attributeLock = NULL; 1.904 + } 1.905 + if (object->refLock) { 1.906 + PZ_DestroyLock(object->refLock); 1.907 + object->refLock = NULL; 1.908 + } 1.909 + PORT_Free(object); 1.910 +} 1.911 + 1.912 +static SFTKObject * 1.913 +sftk_freeObjectData(SFTKObject *object) { 1.914 + SFTKObject *next = object->next; 1.915 + 1.916 + PORT_Free(object); 1.917 + return next; 1.918 +} 1.919 + 1.920 +static void 1.921 +sftk_InitFreeList(SFTKObjectFreeList *list) 1.922 +{ 1.923 + list->lock = PZ_NewLock(nssILockObject); 1.924 +} 1.925 + 1.926 +void sftk_InitFreeLists(void) 1.927 +{ 1.928 + sftk_InitFreeList(&sessionObjectList); 1.929 + sftk_InitFreeList(&tokenObjectList); 1.930 +} 1.931 + 1.932 +static void 1.933 +sftk_CleanupFreeList(SFTKObjectFreeList *list, PRBool isSessionList) 1.934 +{ 1.935 + SFTKObject *object; 1.936 + 1.937 + if (!list->lock) { 1.938 + return; 1.939 + } 1.940 + SKIP_AFTER_FORK(PZ_Lock(list->lock)); 1.941 + for (object= list->head; object != NULL; 1.942 + object = sftk_freeObjectData(object)) { 1.943 + PZ_DestroyLock(object->refLock); 1.944 + if (isSessionList) { 1.945 + PZ_DestroyLock(((SFTKSessionObject *)object)->attributeLock); 1.946 + } 1.947 + } 1.948 + list->count = 0; 1.949 + list->head = NULL; 1.950 + SKIP_AFTER_FORK(PZ_Unlock(list->lock)); 1.951 + SKIP_AFTER_FORK(PZ_DestroyLock(list->lock)); 1.952 + list->lock = NULL; 1.953 +} 1.954 + 1.955 +void 1.956 +sftk_CleanupFreeLists(void) 1.957 +{ 1.958 + sftk_CleanupFreeList(&sessionObjectList, PR_TRUE); 1.959 + sftk_CleanupFreeList(&tokenObjectList, PR_FALSE); 1.960 +} 1.961 + 1.962 + 1.963 +/* 1.964 + * Create a new object 1.965 + */ 1.966 +SFTKObject * 1.967 +sftk_NewObject(SFTKSlot *slot) 1.968 +{ 1.969 + SFTKObject *object; 1.970 + SFTKSessionObject *sessObject; 1.971 + PRBool hasLocks = PR_FALSE; 1.972 + unsigned int i; 1.973 + unsigned int hashSize = 0; 1.974 + 1.975 + hashSize = (slot->optimizeSpace) ? SPACE_ATTRIBUTE_HASH_SIZE : 1.976 + TIME_ATTRIBUTE_HASH_SIZE; 1.977 + 1.978 + object = sftk_GetObjectFromList(&hasLocks, slot->optimizeSpace, 1.979 + &sessionObjectList, hashSize, PR_TRUE); 1.980 + if (object == NULL) { 1.981 + return NULL; 1.982 + } 1.983 + sessObject = (SFTKSessionObject *)object; 1.984 + sessObject->nextAttr = 0; 1.985 + 1.986 + for (i=0; i < MAX_OBJS_ATTRS; i++) { 1.987 + sessObject->attrList[i].attrib.pValue = NULL; 1.988 + sessObject->attrList[i].freeData = PR_FALSE; 1.989 + } 1.990 + sessObject->optimizeSpace = slot->optimizeSpace; 1.991 + 1.992 + object->handle = 0; 1.993 + object->next = object->prev = NULL; 1.994 + object->slot = slot; 1.995 + 1.996 + object->refCount = 1; 1.997 + sessObject->sessionList.next = NULL; 1.998 + sessObject->sessionList.prev = NULL; 1.999 + sessObject->sessionList.parent = object; 1.1000 + sessObject->session = NULL; 1.1001 + sessObject->wasDerived = PR_FALSE; 1.1002 + if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock); 1.1003 + if (object->refLock == NULL) { 1.1004 + PORT_Free(object); 1.1005 + return NULL; 1.1006 + } 1.1007 + if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute); 1.1008 + if (sessObject->attributeLock == NULL) { 1.1009 + PZ_DestroyLock(object->refLock); 1.1010 + PORT_Free(object); 1.1011 + return NULL; 1.1012 + } 1.1013 + for (i=0; i < sessObject->hashSize; i++) { 1.1014 + sessObject->head[i] = NULL; 1.1015 + } 1.1016 + object->objectInfo = NULL; 1.1017 + object->infoFree = NULL; 1.1018 + return object; 1.1019 +} 1.1020 + 1.1021 +static CK_RV 1.1022 +sftk_DestroySessionObjectData(SFTKSessionObject *so) 1.1023 +{ 1.1024 + int i; 1.1025 + 1.1026 + for (i=0; i < MAX_OBJS_ATTRS; i++) { 1.1027 + unsigned char *value = so->attrList[i].attrib.pValue; 1.1028 + if (value) { 1.1029 + PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen); 1.1030 + if (so->attrList[i].freeData) { 1.1031 + PORT_Free(value); 1.1032 + } 1.1033 + so->attrList[i].attrib.pValue = NULL; 1.1034 + so->attrList[i].freeData = PR_FALSE; 1.1035 + } 1.1036 + } 1.1037 +/* PZ_DestroyLock(so->attributeLock);*/ 1.1038 + return CKR_OK; 1.1039 +} 1.1040 + 1.1041 +/* 1.1042 + * free all the data associated with an object. Object reference count must 1.1043 + * be 'zero'. 1.1044 + */ 1.1045 +static CK_RV 1.1046 +sftk_DestroyObject(SFTKObject *object) 1.1047 +{ 1.1048 + CK_RV crv = CKR_OK; 1.1049 + SFTKSessionObject *so = sftk_narrowToSessionObject(object); 1.1050 + SFTKTokenObject *to = sftk_narrowToTokenObject(object); 1.1051 + 1.1052 + PORT_Assert(object->refCount == 0); 1.1053 + 1.1054 + /* delete the database value */ 1.1055 + if (to) { 1.1056 + if (to->dbKey.data) { 1.1057 + PORT_Free(to->dbKey.data); 1.1058 + to->dbKey.data = NULL; 1.1059 + } 1.1060 + } 1.1061 + if (so) { 1.1062 + sftk_DestroySessionObjectData(so); 1.1063 + } 1.1064 + if (object->objectInfo) { 1.1065 + (*object->infoFree)(object->objectInfo); 1.1066 + object->objectInfo = NULL; 1.1067 + object->infoFree = NULL; 1.1068 + } 1.1069 + if (so) { 1.1070 + sftk_PutObjectToList(object,&sessionObjectList,PR_TRUE); 1.1071 + } else { 1.1072 + sftk_PutObjectToList(object,&tokenObjectList,PR_FALSE); 1.1073 + } 1.1074 + return crv; 1.1075 +} 1.1076 + 1.1077 +void 1.1078 +sftk_ReferenceObject(SFTKObject *object) 1.1079 +{ 1.1080 + PZ_Lock(object->refLock); 1.1081 + object->refCount++; 1.1082 + PZ_Unlock(object->refLock); 1.1083 +} 1.1084 + 1.1085 +static SFTKObject * 1.1086 +sftk_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, SFTKSlot *slot) 1.1087 +{ 1.1088 + SFTKObject *object; 1.1089 + PRUint32 index = sftk_hash(handle, slot->sessObjHashSize); 1.1090 + 1.1091 + if (sftk_isToken(handle)) { 1.1092 + return sftk_NewTokenObject(slot, NULL, handle); 1.1093 + } 1.1094 + 1.1095 + PZ_Lock(slot->objectLock); 1.1096 + sftkqueue_find2(object, handle, index, slot->sessObjHashTable); 1.1097 + if (object) { 1.1098 + sftk_ReferenceObject(object); 1.1099 + } 1.1100 + PZ_Unlock(slot->objectLock); 1.1101 + 1.1102 + return(object); 1.1103 +} 1.1104 +/* 1.1105 + * look up and object structure from a handle. OBJECT_Handles only make 1.1106 + * sense in terms of a given session. make a reference to that object 1.1107 + * structure returned. 1.1108 + */ 1.1109 +SFTKObject * 1.1110 +sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle, SFTKSession *session) 1.1111 +{ 1.1112 + SFTKSlot *slot = sftk_SlotFromSession(session); 1.1113 + 1.1114 + return sftk_ObjectFromHandleOnSlot(handle,slot); 1.1115 +} 1.1116 + 1.1117 + 1.1118 +/* 1.1119 + * release a reference to an object handle 1.1120 + */ 1.1121 +SFTKFreeStatus 1.1122 +sftk_FreeObject(SFTKObject *object) 1.1123 +{ 1.1124 + PRBool destroy = PR_FALSE; 1.1125 + CK_RV crv; 1.1126 + 1.1127 + PZ_Lock(object->refLock); 1.1128 + if (object->refCount == 1) destroy = PR_TRUE; 1.1129 + object->refCount--; 1.1130 + PZ_Unlock(object->refLock); 1.1131 + 1.1132 + if (destroy) { 1.1133 + crv = sftk_DestroyObject(object); 1.1134 + if (crv != CKR_OK) { 1.1135 + return SFTK_DestroyFailure; 1.1136 + } 1.1137 + return SFTK_Destroyed; 1.1138 + } 1.1139 + return SFTK_Busy; 1.1140 +} 1.1141 + 1.1142 +/* 1.1143 + * add an object to a slot and session queue. These two functions 1.1144 + * adopt the object. 1.1145 + */ 1.1146 +void 1.1147 +sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object) 1.1148 +{ 1.1149 + PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); 1.1150 + sftkqueue_init_element(object); 1.1151 + PZ_Lock(slot->objectLock); 1.1152 + sftkqueue_add2(object, object->handle, index, slot->sessObjHashTable); 1.1153 + PZ_Unlock(slot->objectLock); 1.1154 +} 1.1155 + 1.1156 +void 1.1157 +sftk_AddObject(SFTKSession *session, SFTKObject *object) 1.1158 +{ 1.1159 + SFTKSlot *slot = sftk_SlotFromSession(session); 1.1160 + SFTKSessionObject *so = sftk_narrowToSessionObject(object); 1.1161 + 1.1162 + if (so) { 1.1163 + PZ_Lock(session->objectLock); 1.1164 + sftkqueue_add(&so->sessionList,0,session->objects,0); 1.1165 + so->session = session; 1.1166 + PZ_Unlock(session->objectLock); 1.1167 + } 1.1168 + sftk_AddSlotObject(slot,object); 1.1169 + sftk_ReferenceObject(object); 1.1170 +} 1.1171 + 1.1172 +/* 1.1173 + * delete an object from a slot and session queue 1.1174 + */ 1.1175 +CK_RV 1.1176 +sftk_DeleteObject(SFTKSession *session, SFTKObject *object) 1.1177 +{ 1.1178 + SFTKSlot *slot = sftk_SlotFromSession(session); 1.1179 + SFTKSessionObject *so = sftk_narrowToSessionObject(object); 1.1180 + SFTKTokenObject *to = sftk_narrowToTokenObject(object); 1.1181 + CK_RV crv = CKR_OK; 1.1182 + PRUint32 index = sftk_hash(object->handle, slot->sessObjHashSize); 1.1183 + 1.1184 + /* Handle Token case */ 1.1185 + if (so && so->session) { 1.1186 + SFTKSession *session = so->session; 1.1187 + PZ_Lock(session->objectLock); 1.1188 + sftkqueue_delete(&so->sessionList,0,session->objects,0); 1.1189 + PZ_Unlock(session->objectLock); 1.1190 + PZ_Lock(slot->objectLock); 1.1191 + sftkqueue_delete2(object, object->handle, index, slot->sessObjHashTable); 1.1192 + PZ_Unlock(slot->objectLock); 1.1193 + sftkqueue_clear_deleted_element(object); 1.1194 + sftk_FreeObject(object); /* free the reference owned by the queue */ 1.1195 + } else { 1.1196 + SFTKDBHandle *handle = sftk_getDBForTokenObject(slot, object->handle); 1.1197 + 1.1198 + PORT_Assert(to); 1.1199 + crv = sftkdb_DestroyObject(handle, object->handle); 1.1200 + sftk_freeDB(handle); 1.1201 + } 1.1202 + return crv; 1.1203 +} 1.1204 + 1.1205 +/* 1.1206 + * Token objects don't explicitly store their attributes, so we need to know 1.1207 + * what attributes make up a particular token object before we can copy it. 1.1208 + * below are the tables by object type. 1.1209 + */ 1.1210 +static const CK_ATTRIBUTE_TYPE commonAttrs[] = { 1.1211 + CKA_CLASS, CKA_TOKEN, CKA_PRIVATE, CKA_LABEL, CKA_MODIFIABLE 1.1212 +}; 1.1213 +static const CK_ULONG commonAttrsCount = 1.1214 + sizeof(commonAttrs)/sizeof(commonAttrs[0]); 1.1215 + 1.1216 +static const CK_ATTRIBUTE_TYPE commonKeyAttrs[] = { 1.1217 + CKA_ID, CKA_START_DATE, CKA_END_DATE, CKA_DERIVE, CKA_LOCAL, CKA_KEY_TYPE 1.1218 +}; 1.1219 +static const CK_ULONG commonKeyAttrsCount = 1.1220 + sizeof(commonKeyAttrs)/sizeof(commonKeyAttrs[0]); 1.1221 + 1.1222 +static const CK_ATTRIBUTE_TYPE secretKeyAttrs[] = { 1.1223 + CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_ENCRYPT, CKA_DECRYPT, CKA_SIGN, 1.1224 + CKA_VERIFY, CKA_WRAP, CKA_UNWRAP, CKA_VALUE 1.1225 +}; 1.1226 +static const CK_ULONG secretKeyAttrsCount = 1.1227 + sizeof(secretKeyAttrs)/sizeof(secretKeyAttrs[0]); 1.1228 + 1.1229 +static const CK_ATTRIBUTE_TYPE commonPubKeyAttrs[] = { 1.1230 + CKA_ENCRYPT, CKA_VERIFY, CKA_VERIFY_RECOVER, CKA_WRAP, CKA_SUBJECT 1.1231 +}; 1.1232 +static const CK_ULONG commonPubKeyAttrsCount = 1.1233 + sizeof(commonPubKeyAttrs)/sizeof(commonPubKeyAttrs[0]); 1.1234 + 1.1235 +static const CK_ATTRIBUTE_TYPE rsaPubKeyAttrs[] = { 1.1236 + CKA_MODULUS, CKA_PUBLIC_EXPONENT 1.1237 +}; 1.1238 +static const CK_ULONG rsaPubKeyAttrsCount = 1.1239 + sizeof(rsaPubKeyAttrs)/sizeof(rsaPubKeyAttrs[0]); 1.1240 + 1.1241 +static const CK_ATTRIBUTE_TYPE dsaPubKeyAttrs[] = { 1.1242 + CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE 1.1243 +}; 1.1244 +static const CK_ULONG dsaPubKeyAttrsCount = 1.1245 + sizeof(dsaPubKeyAttrs)/sizeof(dsaPubKeyAttrs[0]); 1.1246 + 1.1247 +static const CK_ATTRIBUTE_TYPE dhPubKeyAttrs[] = { 1.1248 + CKA_PRIME, CKA_BASE, CKA_VALUE 1.1249 +}; 1.1250 +static const CK_ULONG dhPubKeyAttrsCount = 1.1251 + sizeof(dhPubKeyAttrs)/sizeof(dhPubKeyAttrs[0]); 1.1252 +#ifndef NSS_DISABLE_ECC 1.1253 +static const CK_ATTRIBUTE_TYPE ecPubKeyAttrs[] = { 1.1254 + CKA_EC_PARAMS, CKA_EC_POINT 1.1255 +}; 1.1256 +static const CK_ULONG ecPubKeyAttrsCount = 1.1257 + sizeof(ecPubKeyAttrs)/sizeof(ecPubKeyAttrs[0]); 1.1258 +#endif 1.1259 + 1.1260 +static const CK_ATTRIBUTE_TYPE commonPrivKeyAttrs[] = { 1.1261 + CKA_DECRYPT, CKA_SIGN, CKA_SIGN_RECOVER, CKA_UNWRAP, CKA_SUBJECT, 1.1262 + CKA_SENSITIVE, CKA_EXTRACTABLE, CKA_NETSCAPE_DB 1.1263 +}; 1.1264 +static const CK_ULONG commonPrivKeyAttrsCount = 1.1265 + sizeof(commonPrivKeyAttrs)/sizeof(commonPrivKeyAttrs[0]); 1.1266 + 1.1267 +static const CK_ATTRIBUTE_TYPE rsaPrivKeyAttrs[] = { 1.1268 + CKA_MODULUS, CKA_PUBLIC_EXPONENT, CKA_PRIVATE_EXPONENT, 1.1269 + CKA_PRIME_1, CKA_PRIME_2, CKA_EXPONENT_1, CKA_EXPONENT_2, CKA_COEFFICIENT 1.1270 +}; 1.1271 +static const CK_ULONG rsaPrivKeyAttrsCount = 1.1272 + sizeof(rsaPrivKeyAttrs)/sizeof(rsaPrivKeyAttrs[0]); 1.1273 + 1.1274 +static const CK_ATTRIBUTE_TYPE dsaPrivKeyAttrs[] = { 1.1275 + CKA_SUBPRIME, CKA_PRIME, CKA_BASE, CKA_VALUE 1.1276 +}; 1.1277 +static const CK_ULONG dsaPrivKeyAttrsCount = 1.1278 + sizeof(dsaPrivKeyAttrs)/sizeof(dsaPrivKeyAttrs[0]); 1.1279 + 1.1280 +static const CK_ATTRIBUTE_TYPE dhPrivKeyAttrs[] = { 1.1281 + CKA_PRIME, CKA_BASE, CKA_VALUE 1.1282 +}; 1.1283 +static const CK_ULONG dhPrivKeyAttrsCount = 1.1284 + sizeof(dhPrivKeyAttrs)/sizeof(dhPrivKeyAttrs[0]); 1.1285 +#ifndef NSS_DISABLE_ECC 1.1286 +static const CK_ATTRIBUTE_TYPE ecPrivKeyAttrs[] = { 1.1287 + CKA_EC_PARAMS, CKA_VALUE 1.1288 +}; 1.1289 +static const CK_ULONG ecPrivKeyAttrsCount = 1.1290 + sizeof(ecPrivKeyAttrs)/sizeof(ecPrivKeyAttrs[0]); 1.1291 +#endif 1.1292 + 1.1293 +static const CK_ATTRIBUTE_TYPE certAttrs[] = { 1.1294 + CKA_CERTIFICATE_TYPE, CKA_VALUE, CKA_SUBJECT, CKA_ISSUER, CKA_SERIAL_NUMBER 1.1295 +}; 1.1296 +static const CK_ULONG certAttrsCount = 1.1297 + sizeof(certAttrs)/sizeof(certAttrs[0]); 1.1298 + 1.1299 +static const CK_ATTRIBUTE_TYPE trustAttrs[] = { 1.1300 + CKA_ISSUER, CKA_SERIAL_NUMBER, CKA_CERT_SHA1_HASH, CKA_CERT_MD5_HASH, 1.1301 + CKA_TRUST_SERVER_AUTH, CKA_TRUST_CLIENT_AUTH, CKA_TRUST_EMAIL_PROTECTION, 1.1302 + CKA_TRUST_CODE_SIGNING, CKA_TRUST_STEP_UP_APPROVED 1.1303 +}; 1.1304 +static const CK_ULONG trustAttrsCount = 1.1305 + sizeof(trustAttrs)/sizeof(trustAttrs[0]); 1.1306 + 1.1307 +static const CK_ATTRIBUTE_TYPE smimeAttrs[] = { 1.1308 + CKA_SUBJECT, CKA_NETSCAPE_EMAIL, CKA_NETSCAPE_SMIME_TIMESTAMP, CKA_VALUE 1.1309 +}; 1.1310 +static const CK_ULONG smimeAttrsCount = 1.1311 + sizeof(smimeAttrs)/sizeof(smimeAttrs[0]); 1.1312 + 1.1313 +static const CK_ATTRIBUTE_TYPE crlAttrs[] = { 1.1314 + CKA_SUBJECT, CKA_VALUE, CKA_NETSCAPE_URL, CKA_NETSCAPE_KRL 1.1315 +}; 1.1316 +static const CK_ULONG crlAttrsCount = 1.1317 + sizeof(crlAttrs)/sizeof(crlAttrs[0]); 1.1318 + 1.1319 +/* copy an object based on it's table */ 1.1320 +CK_RV 1.1321 +stfk_CopyTokenAttributes(SFTKObject *destObject,SFTKTokenObject *src_to, 1.1322 + const CK_ATTRIBUTE_TYPE *attrArray, CK_ULONG attrCount) 1.1323 +{ 1.1324 + SFTKAttribute *attribute; 1.1325 + SFTKAttribute *newAttribute; 1.1326 + CK_RV crv = CKR_OK; 1.1327 + unsigned int i; 1.1328 + 1.1329 + for (i=0; i < attrCount; i++) { 1.1330 + if (!sftk_hasAttribute(destObject,attrArray[i])) { 1.1331 + attribute =sftk_FindAttribute(&src_to->obj, attrArray[i]); 1.1332 + if (!attribute) { 1.1333 + continue; /* return CKR_ATTRIBUTE_VALUE_INVALID; */ 1.1334 + } 1.1335 + /* we need to copy the attribute since each attribute 1.1336 + * only has one set of link list pointers */ 1.1337 + newAttribute = sftk_NewAttribute( destObject, 1.1338 + sftk_attr_expand(&attribute->attrib)); 1.1339 + sftk_FreeAttribute(attribute); /* free the old attribute */ 1.1340 + if (!newAttribute) { 1.1341 + return CKR_HOST_MEMORY; 1.1342 + } 1.1343 + sftk_AddAttribute(destObject,newAttribute); 1.1344 + } 1.1345 + } 1.1346 + return crv; 1.1347 +} 1.1348 + 1.1349 +CK_RV 1.1350 +stfk_CopyTokenPrivateKey(SFTKObject *destObject,SFTKTokenObject *src_to) 1.1351 +{ 1.1352 + CK_RV crv; 1.1353 + CK_KEY_TYPE key_type; 1.1354 + SFTKAttribute *attribute; 1.1355 + 1.1356 + /* copy the common attributes for all keys first */ 1.1357 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, 1.1358 + commonKeyAttrsCount); 1.1359 + if (crv != CKR_OK) { 1.1360 + goto fail; 1.1361 + } 1.1362 + /* copy the common attributes for all private keys next */ 1.1363 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonPrivKeyAttrs, 1.1364 + commonPrivKeyAttrsCount); 1.1365 + if (crv != CKR_OK) { 1.1366 + goto fail; 1.1367 + } 1.1368 + attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); 1.1369 + PORT_Assert(attribute); /* if it wasn't here, ww should have failed 1.1370 + * copying the common attributes */ 1.1371 + if (!attribute) { 1.1372 + /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but 1.1373 + * the fact is, the only reason we couldn't get the attribute would 1.1374 + * be a memory error or database error (an error in the 'device'). 1.1375 + * if we have a database error code, we could return it here */ 1.1376 + crv = CKR_DEVICE_ERROR; 1.1377 + goto fail; 1.1378 + } 1.1379 + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1.1380 + sftk_FreeAttribute(attribute); 1.1381 + 1.1382 + /* finally copy the attributes for various private key types */ 1.1383 + switch (key_type) { 1.1384 + case CKK_RSA: 1.1385 + crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPrivKeyAttrs, 1.1386 + rsaPrivKeyAttrsCount); 1.1387 + break; 1.1388 + case CKK_DSA: 1.1389 + crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPrivKeyAttrs, 1.1390 + dsaPrivKeyAttrsCount); 1.1391 + break; 1.1392 + case CKK_DH: 1.1393 + crv = stfk_CopyTokenAttributes(destObject, src_to, dhPrivKeyAttrs, 1.1394 + dhPrivKeyAttrsCount); 1.1395 + break; 1.1396 +#ifndef NSS_DISABLE_ECC 1.1397 + case CKK_EC: 1.1398 + crv = stfk_CopyTokenAttributes(destObject, src_to, ecPrivKeyAttrs, 1.1399 + ecPrivKeyAttrsCount); 1.1400 + break; 1.1401 +#endif 1.1402 + default: 1.1403 + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types 1.1404 + * of token keys into our database. */ 1.1405 + } 1.1406 +fail: 1.1407 + return crv; 1.1408 +} 1.1409 + 1.1410 +CK_RV 1.1411 +stfk_CopyTokenPublicKey(SFTKObject *destObject,SFTKTokenObject *src_to) 1.1412 +{ 1.1413 + CK_RV crv; 1.1414 + CK_KEY_TYPE key_type; 1.1415 + SFTKAttribute *attribute; 1.1416 + 1.1417 + /* copy the common attributes for all keys first */ 1.1418 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, 1.1419 + commonKeyAttrsCount); 1.1420 + if (crv != CKR_OK) { 1.1421 + goto fail; 1.1422 + } 1.1423 + 1.1424 + /* copy the common attributes for all public keys next */ 1.1425 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonPubKeyAttrs, 1.1426 + commonPubKeyAttrsCount); 1.1427 + if (crv != CKR_OK) { 1.1428 + goto fail; 1.1429 + } 1.1430 + attribute =sftk_FindAttribute(&src_to->obj, CKA_KEY_TYPE); 1.1431 + PORT_Assert(attribute); /* if it wasn't here, ww should have failed 1.1432 + * copying the common attributes */ 1.1433 + if (!attribute) { 1.1434 + /* OK, so CKR_ATTRIBUTE_VALUE_INVALID is the immediate error, but 1.1435 + * the fact is, the only reason we couldn't get the attribute would 1.1436 + * be a memory error or database error (an error in the 'device'). 1.1437 + * if we have a database error code, we could return it here */ 1.1438 + crv = CKR_DEVICE_ERROR; 1.1439 + goto fail; 1.1440 + } 1.1441 + key_type = *(CK_KEY_TYPE *)attribute->attrib.pValue; 1.1442 + sftk_FreeAttribute(attribute); 1.1443 + 1.1444 + /* finally copy the attributes for various public key types */ 1.1445 + switch (key_type) { 1.1446 + case CKK_RSA: 1.1447 + crv = stfk_CopyTokenAttributes(destObject, src_to, rsaPubKeyAttrs, 1.1448 + rsaPubKeyAttrsCount); 1.1449 + break; 1.1450 + case CKK_DSA: 1.1451 + crv = stfk_CopyTokenAttributes(destObject, src_to, dsaPubKeyAttrs, 1.1452 + dsaPubKeyAttrsCount); 1.1453 + break; 1.1454 + case CKK_DH: 1.1455 + crv = stfk_CopyTokenAttributes(destObject, src_to, dhPubKeyAttrs, 1.1456 + dhPubKeyAttrsCount); 1.1457 + break; 1.1458 +#ifndef NSS_DISABLE_ECC 1.1459 + case CKK_EC: 1.1460 + crv = stfk_CopyTokenAttributes(destObject, src_to, ecPubKeyAttrs, 1.1461 + ecPubKeyAttrsCount); 1.1462 + break; 1.1463 +#endif 1.1464 + default: 1.1465 + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types 1.1466 + * of token keys into our database. */ 1.1467 + } 1.1468 +fail: 1.1469 + return crv; 1.1470 +} 1.1471 +CK_RV 1.1472 +stfk_CopyTokenSecretKey(SFTKObject *destObject,SFTKTokenObject *src_to) 1.1473 +{ 1.1474 + CK_RV crv; 1.1475 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonKeyAttrs, 1.1476 + commonKeyAttrsCount); 1.1477 + if (crv != CKR_OK) { 1.1478 + goto fail; 1.1479 + } 1.1480 + crv = stfk_CopyTokenAttributes(destObject, src_to, secretKeyAttrs, 1.1481 + secretKeyAttrsCount); 1.1482 +fail: 1.1483 + return crv; 1.1484 +} 1.1485 + 1.1486 +/* 1.1487 + * Copy a token object. We need to explicitly copy the relevant 1.1488 + * attributes since token objects don't store those attributes in 1.1489 + * the token itself. 1.1490 + */ 1.1491 +CK_RV 1.1492 +sftk_CopyTokenObject(SFTKObject *destObject,SFTKObject *srcObject) 1.1493 +{ 1.1494 + SFTKTokenObject *src_to = sftk_narrowToTokenObject(srcObject); 1.1495 + CK_RV crv; 1.1496 + 1.1497 + PORT_Assert(src_to); 1.1498 + if (src_to == NULL) { 1.1499 + return CKR_DEVICE_ERROR; /* internal state inconsistant */ 1.1500 + } 1.1501 + 1.1502 + crv = stfk_CopyTokenAttributes(destObject, src_to, commonAttrs, 1.1503 + commonAttrsCount); 1.1504 + if (crv != CKR_OK) { 1.1505 + goto fail; 1.1506 + } 1.1507 + switch (src_to->obj.objclass) { 1.1508 + case CKO_CERTIFICATE: 1.1509 + crv = stfk_CopyTokenAttributes(destObject, src_to, certAttrs, 1.1510 + certAttrsCount); 1.1511 + break; 1.1512 + case CKO_NETSCAPE_TRUST: 1.1513 + crv = stfk_CopyTokenAttributes(destObject, src_to, trustAttrs, 1.1514 + trustAttrsCount); 1.1515 + break; 1.1516 + case CKO_NETSCAPE_SMIME: 1.1517 + crv = stfk_CopyTokenAttributes(destObject, src_to, smimeAttrs, 1.1518 + smimeAttrsCount); 1.1519 + break; 1.1520 + case CKO_NETSCAPE_CRL: 1.1521 + crv = stfk_CopyTokenAttributes(destObject, src_to, crlAttrs, 1.1522 + crlAttrsCount); 1.1523 + break; 1.1524 + case CKO_PRIVATE_KEY: 1.1525 + crv = stfk_CopyTokenPrivateKey(destObject,src_to); 1.1526 + break; 1.1527 + case CKO_PUBLIC_KEY: 1.1528 + crv = stfk_CopyTokenPublicKey(destObject,src_to); 1.1529 + break; 1.1530 + case CKO_SECRET_KEY: 1.1531 + crv = stfk_CopyTokenSecretKey(destObject,src_to); 1.1532 + break; 1.1533 + default: 1.1534 + crv = CKR_DEVICE_ERROR; /* shouldn't happen unless we store more types 1.1535 + * of token keys into our database. */ 1.1536 + } 1.1537 +fail: 1.1538 + return crv; 1.1539 +} 1.1540 + 1.1541 +/* 1.1542 + * copy the attributes from one object to another. Don't overwrite existing 1.1543 + * attributes. NOTE: This is a pretty expensive operation since it 1.1544 + * grabs the attribute locks for the src object for a *long* time. 1.1545 + */ 1.1546 +CK_RV 1.1547 +sftk_CopyObject(SFTKObject *destObject,SFTKObject *srcObject) 1.1548 +{ 1.1549 + SFTKAttribute *attribute; 1.1550 + SFTKSessionObject *src_so = sftk_narrowToSessionObject(srcObject); 1.1551 + unsigned int i; 1.1552 + 1.1553 + if (src_so == NULL) { 1.1554 + return sftk_CopyTokenObject(destObject,srcObject); 1.1555 + } 1.1556 + 1.1557 + PZ_Lock(src_so->attributeLock); 1.1558 + for(i=0; i < src_so->hashSize; i++) { 1.1559 + attribute = src_so->head[i]; 1.1560 + do { 1.1561 + if (attribute) { 1.1562 + if (!sftk_hasAttribute(destObject,attribute->handle)) { 1.1563 + /* we need to copy the attribute since each attribute 1.1564 + * only has one set of link list pointers */ 1.1565 + SFTKAttribute *newAttribute = sftk_NewAttribute( 1.1566 + destObject,sftk_attr_expand(&attribute->attrib)); 1.1567 + if (newAttribute == NULL) { 1.1568 + PZ_Unlock(src_so->attributeLock); 1.1569 + return CKR_HOST_MEMORY; 1.1570 + } 1.1571 + sftk_AddAttribute(destObject,newAttribute); 1.1572 + } 1.1573 + attribute=attribute->next; 1.1574 + } 1.1575 + } while (attribute != NULL); 1.1576 + } 1.1577 + PZ_Unlock(src_so->attributeLock); 1.1578 + 1.1579 + return CKR_OK; 1.1580 +} 1.1581 + 1.1582 +/* 1.1583 + * ******************** Search Utilities ******************************* 1.1584 + */ 1.1585 + 1.1586 +/* add an object to a search list */ 1.1587 +CK_RV 1.1588 +AddToList(SFTKObjectListElement **list,SFTKObject *object) 1.1589 +{ 1.1590 + SFTKObjectListElement *newElem = 1.1591 + (SFTKObjectListElement *)PORT_Alloc(sizeof(SFTKObjectListElement)); 1.1592 + 1.1593 + if (newElem == NULL) return CKR_HOST_MEMORY; 1.1594 + 1.1595 + newElem->next = *list; 1.1596 + newElem->object = object; 1.1597 + sftk_ReferenceObject(object); 1.1598 + 1.1599 + *list = newElem; 1.1600 + return CKR_OK; 1.1601 +} 1.1602 + 1.1603 + 1.1604 +/* return true if the object matches the template */ 1.1605 +PRBool 1.1606 +sftk_objectMatch(SFTKObject *object,CK_ATTRIBUTE_PTR theTemplate,int count) 1.1607 +{ 1.1608 + int i; 1.1609 + 1.1610 + for (i=0; i < count; i++) { 1.1611 + SFTKAttribute *attribute = sftk_FindAttribute(object,theTemplate[i].type); 1.1612 + if (attribute == NULL) { 1.1613 + return PR_FALSE; 1.1614 + } 1.1615 + if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) { 1.1616 + if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue, 1.1617 + theTemplate[i].ulValueLen) == 0) { 1.1618 + sftk_FreeAttribute(attribute); 1.1619 + continue; 1.1620 + } 1.1621 + } 1.1622 + sftk_FreeAttribute(attribute); 1.1623 + return PR_FALSE; 1.1624 + } 1.1625 + return PR_TRUE; 1.1626 +} 1.1627 + 1.1628 +/* search through all the objects in the queue and return the template matches 1.1629 + * in the object list. 1.1630 + */ 1.1631 +CK_RV 1.1632 +sftk_searchObjectList(SFTKSearchResults *search,SFTKObject **head, 1.1633 + unsigned int size, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, 1.1634 + int count, PRBool isLoggedIn) 1.1635 +{ 1.1636 + unsigned int i; 1.1637 + SFTKObject *object; 1.1638 + CK_RV crv = CKR_OK; 1.1639 + 1.1640 + for(i=0; i < size; i++) { 1.1641 + /* We need to hold the lock to copy a consistant version of 1.1642 + * the linked list. */ 1.1643 + PZ_Lock(lock); 1.1644 + for (object = head[i]; object != NULL; object= object->next) { 1.1645 + if (sftk_objectMatch(object,theTemplate,count)) { 1.1646 + /* don't return objects that aren't yet visible */ 1.1647 + if ((!isLoggedIn) && sftk_isTrue(object,CKA_PRIVATE)) continue; 1.1648 + sftk_addHandle(search,object->handle); 1.1649 + } 1.1650 + } 1.1651 + PZ_Unlock(lock); 1.1652 + } 1.1653 + return crv; 1.1654 +} 1.1655 + 1.1656 +/* 1.1657 + * free a single list element. Return the Next object in the list. 1.1658 + */ 1.1659 +SFTKObjectListElement * 1.1660 +sftk_FreeObjectListElement(SFTKObjectListElement *objectList) 1.1661 +{ 1.1662 + SFTKObjectListElement *ol = objectList->next; 1.1663 + 1.1664 + sftk_FreeObject(objectList->object); 1.1665 + PORT_Free(objectList); 1.1666 + return ol; 1.1667 +} 1.1668 + 1.1669 +/* free an entire object list */ 1.1670 +void 1.1671 +sftk_FreeObjectList(SFTKObjectListElement *objectList) 1.1672 +{ 1.1673 + SFTKObjectListElement *ol; 1.1674 + 1.1675 + for (ol= objectList; ol != NULL; ol = sftk_FreeObjectListElement(ol)) {} 1.1676 +} 1.1677 + 1.1678 +/* 1.1679 + * free a search structure 1.1680 + */ 1.1681 +void 1.1682 +sftk_FreeSearch(SFTKSearchResults *search) 1.1683 +{ 1.1684 + if (search->handles) { 1.1685 + PORT_Free(search->handles); 1.1686 + } 1.1687 + PORT_Free(search); 1.1688 +} 1.1689 + 1.1690 +/* 1.1691 + * ******************** Session Utilities ******************************* 1.1692 + */ 1.1693 + 1.1694 +/* update the sessions state based in it's flags and wether or not it's 1.1695 + * logged in */ 1.1696 +void 1.1697 +sftk_update_state(SFTKSlot *slot,SFTKSession *session) 1.1698 +{ 1.1699 + if (slot->isLoggedIn) { 1.1700 + if (slot->ssoLoggedIn) { 1.1701 + session->info.state = CKS_RW_SO_FUNCTIONS; 1.1702 + } else if (session->info.flags & CKF_RW_SESSION) { 1.1703 + session->info.state = CKS_RW_USER_FUNCTIONS; 1.1704 + } else { 1.1705 + session->info.state = CKS_RO_USER_FUNCTIONS; 1.1706 + } 1.1707 + } else { 1.1708 + if (session->info.flags & CKF_RW_SESSION) { 1.1709 + session->info.state = CKS_RW_PUBLIC_SESSION; 1.1710 + } else { 1.1711 + session->info.state = CKS_RO_PUBLIC_SESSION; 1.1712 + } 1.1713 + } 1.1714 +} 1.1715 + 1.1716 +/* update the state of all the sessions on a slot */ 1.1717 +void 1.1718 +sftk_update_all_states(SFTKSlot *slot) 1.1719 +{ 1.1720 + unsigned int i; 1.1721 + SFTKSession *session; 1.1722 + 1.1723 + for (i=0; i < slot->sessHashSize; i++) { 1.1724 + PZLock *lock = SFTK_SESSION_LOCK(slot,i); 1.1725 + PZ_Lock(lock); 1.1726 + for (session = slot->head[i]; session; session = session->next) { 1.1727 + sftk_update_state(slot,session); 1.1728 + } 1.1729 + PZ_Unlock(lock); 1.1730 + } 1.1731 +} 1.1732 + 1.1733 +/* 1.1734 + * context are cipher and digest contexts that are associated with a session 1.1735 + */ 1.1736 +void 1.1737 +sftk_FreeContext(SFTKSessionContext *context) 1.1738 +{ 1.1739 + if (context->cipherInfo) { 1.1740 + (*context->destroy)(context->cipherInfo,PR_TRUE); 1.1741 + } 1.1742 + if (context->hashInfo) { 1.1743 + (*context->hashdestroy)(context->hashInfo,PR_TRUE); 1.1744 + } 1.1745 + if (context->key) { 1.1746 + sftk_FreeObject(context->key); 1.1747 + context->key = NULL; 1.1748 + } 1.1749 + PORT_Free(context); 1.1750 +} 1.1751 + 1.1752 +/* 1.1753 + * create a new nession. NOTE: The session handle is not set, and the 1.1754 + * session is not added to the slot's session queue. 1.1755 + */ 1.1756 +SFTKSession * 1.1757 +sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication, 1.1758 + CK_FLAGS flags) 1.1759 +{ 1.1760 + SFTKSession *session; 1.1761 + SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE); 1.1762 + 1.1763 + if (slot == NULL) return NULL; 1.1764 + 1.1765 + session = (SFTKSession*)PORT_Alloc(sizeof(SFTKSession)); 1.1766 + if (session == NULL) return NULL; 1.1767 + 1.1768 + session->next = session->prev = NULL; 1.1769 + session->refCount = 1; 1.1770 + session->enc_context = NULL; 1.1771 + session->hash_context = NULL; 1.1772 + session->sign_context = NULL; 1.1773 + session->search = NULL; 1.1774 + session->objectIDCount = 1; 1.1775 + session->objectLock = PZ_NewLock(nssILockObject); 1.1776 + if (session->objectLock == NULL) { 1.1777 + PORT_Free(session); 1.1778 + return NULL; 1.1779 + } 1.1780 + session->objects[0] = NULL; 1.1781 + 1.1782 + session->slot = slot; 1.1783 + session->notify = notify; 1.1784 + session->appData = pApplication; 1.1785 + session->info.flags = flags; 1.1786 + session->info.slotID = slotID; 1.1787 + session->info.ulDeviceError = 0; 1.1788 + sftk_update_state(slot,session); 1.1789 + return session; 1.1790 +} 1.1791 + 1.1792 + 1.1793 +/* free all the data associated with a session. */ 1.1794 +static void 1.1795 +sftk_DestroySession(SFTKSession *session) 1.1796 +{ 1.1797 + SFTKObjectList *op,*next; 1.1798 + PORT_Assert(session->refCount == 0); 1.1799 + 1.1800 + /* clean out the attributes */ 1.1801 + /* since no one is referencing us, it's safe to walk the chain 1.1802 + * without a lock */ 1.1803 + for (op = session->objects[0]; op != NULL; op = next) { 1.1804 + next = op->next; 1.1805 + /* paranoia */ 1.1806 + op->next = op->prev = NULL; 1.1807 + sftk_DeleteObject(session,op->parent); 1.1808 + } 1.1809 + PZ_DestroyLock(session->objectLock); 1.1810 + if (session->enc_context) { 1.1811 + sftk_FreeContext(session->enc_context); 1.1812 + } 1.1813 + if (session->hash_context) { 1.1814 + sftk_FreeContext(session->hash_context); 1.1815 + } 1.1816 + if (session->sign_context) { 1.1817 + sftk_FreeContext(session->sign_context); 1.1818 + } 1.1819 + if (session->search) { 1.1820 + sftk_FreeSearch(session->search); 1.1821 + } 1.1822 + PORT_Free(session); 1.1823 +} 1.1824 + 1.1825 + 1.1826 +/* 1.1827 + * look up a session structure from a session handle 1.1828 + * generate a reference to it. 1.1829 + */ 1.1830 +SFTKSession * 1.1831 +sftk_SessionFromHandle(CK_SESSION_HANDLE handle) 1.1832 +{ 1.1833 + SFTKSlot *slot = sftk_SlotFromSessionHandle(handle); 1.1834 + SFTKSession *session; 1.1835 + PZLock *lock; 1.1836 + 1.1837 + if (!slot) return NULL; 1.1838 + lock = SFTK_SESSION_LOCK(slot,handle); 1.1839 + 1.1840 + PZ_Lock(lock); 1.1841 + sftkqueue_find(session,handle,slot->head,slot->sessHashSize); 1.1842 + if (session) session->refCount++; 1.1843 + PZ_Unlock(lock); 1.1844 + 1.1845 + return (session); 1.1846 +} 1.1847 + 1.1848 +/* 1.1849 + * release a reference to a session handle 1.1850 + */ 1.1851 +void 1.1852 +sftk_FreeSession(SFTKSession *session) 1.1853 +{ 1.1854 + PRBool destroy = PR_FALSE; 1.1855 + SFTKSlot *slot = sftk_SlotFromSession(session); 1.1856 + PZLock *lock = SFTK_SESSION_LOCK(slot,session->handle); 1.1857 + 1.1858 + PZ_Lock(lock); 1.1859 + if (session->refCount == 1) destroy = PR_TRUE; 1.1860 + session->refCount--; 1.1861 + PZ_Unlock(lock); 1.1862 + 1.1863 + if (destroy) sftk_DestroySession(session); 1.1864 +} 1.1865 + 1.1866 +void 1.1867 +sftk_addHandle(SFTKSearchResults *search, CK_OBJECT_HANDLE handle) 1.1868 +{ 1.1869 + if (search->handles == NULL) { 1.1870 + return; 1.1871 + } 1.1872 + if (search->size >= search->array_size) { 1.1873 + search->array_size += NSC_SEARCH_BLOCK_SIZE; 1.1874 + search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles, 1.1875 + sizeof(CK_OBJECT_HANDLE)* search->array_size); 1.1876 + if (search->handles == NULL) { 1.1877 + return; 1.1878 + } 1.1879 + } 1.1880 + search->handles[search->size] = handle; 1.1881 + search->size++; 1.1882 +} 1.1883 + 1.1884 +static CK_RV 1.1885 +handleToClass(SFTKSlot *slot, CK_OBJECT_HANDLE handle, 1.1886 + CK_OBJECT_CLASS *objClass) 1.1887 +{ 1.1888 + SFTKDBHandle *dbHandle = sftk_getDBForTokenObject(slot, handle); 1.1889 + CK_ATTRIBUTE objClassTemplate; 1.1890 + CK_RV crv; 1.1891 + 1.1892 + *objClass = CKO_DATA; 1.1893 + objClassTemplate.type = CKA_CLASS; 1.1894 + objClassTemplate.pValue = objClass; 1.1895 + objClassTemplate.ulValueLen = sizeof(*objClass); 1.1896 + crv = sftkdb_GetAttributeValue(dbHandle, handle, &objClassTemplate, 1); 1.1897 + sftk_freeDB(dbHandle); 1.1898 + return crv; 1.1899 +} 1.1900 + 1.1901 +SFTKObject * 1.1902 +sftk_NewTokenObject(SFTKSlot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) 1.1903 +{ 1.1904 + SFTKObject *object = NULL; 1.1905 + SFTKTokenObject *tokObject = NULL; 1.1906 + PRBool hasLocks = PR_FALSE; 1.1907 + CK_RV crv; 1.1908 + 1.1909 + object = sftk_GetObjectFromList(&hasLocks, PR_FALSE, &tokenObjectList, 0, 1.1910 + PR_FALSE); 1.1911 + if (object == NULL) { 1.1912 + return NULL; 1.1913 + } 1.1914 + tokObject = (SFTKTokenObject *) object; 1.1915 + 1.1916 + object->handle = handle; 1.1917 + /* every object must have a class, if we can't get it, the object 1.1918 + * doesn't exist */ 1.1919 + crv = handleToClass(slot, handle, &object->objclass); 1.1920 + if (crv != CKR_OK) { 1.1921 + goto loser; 1.1922 + } 1.1923 + object->slot = slot; 1.1924 + object->objectInfo = NULL; 1.1925 + object->infoFree = NULL; 1.1926 + if (!hasLocks) { 1.1927 + object->refLock = PZ_NewLock(nssILockRefLock); 1.1928 + } 1.1929 + if (object->refLock == NULL) { 1.1930 + goto loser; 1.1931 + } 1.1932 + object->refCount = 1; 1.1933 + 1.1934 + return object; 1.1935 +loser: 1.1936 + if (object) { 1.1937 + (void) sftk_DestroyObject(object); 1.1938 + } 1.1939 + return NULL; 1.1940 + 1.1941 +} 1.1942 + 1.1943 +SFTKTokenObject * 1.1944 +sftk_convertSessionToToken(SFTKObject *obj) 1.1945 +{ 1.1946 + SECItem *key; 1.1947 + SFTKSessionObject *so = (SFTKSessionObject *)obj; 1.1948 + SFTKTokenObject *to = sftk_narrowToTokenObject(obj); 1.1949 + SECStatus rv; 1.1950 + 1.1951 + sftk_DestroySessionObjectData(so); 1.1952 + PZ_DestroyLock(so->attributeLock); 1.1953 + if (to == NULL) { 1.1954 + return NULL; 1.1955 + } 1.1956 + sftk_tokenKeyLock(so->obj.slot); 1.1957 + key = sftk_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle); 1.1958 + if (key == NULL) { 1.1959 + sftk_tokenKeyUnlock(so->obj.slot); 1.1960 + return NULL; 1.1961 + } 1.1962 + rv = SECITEM_CopyItem(NULL,&to->dbKey,key); 1.1963 + sftk_tokenKeyUnlock(so->obj.slot); 1.1964 + if (rv == SECFailure) { 1.1965 + return NULL; 1.1966 + } 1.1967 + 1.1968 + return to; 1.1969 +} 1.1970 + 1.1971 +SFTKSessionObject * 1.1972 +sftk_narrowToSessionObject(SFTKObject *obj) 1.1973 +{ 1.1974 + return !sftk_isToken(obj->handle) ? (SFTKSessionObject *)obj : NULL; 1.1975 +} 1.1976 + 1.1977 +SFTKTokenObject * 1.1978 +sftk_narrowToTokenObject(SFTKObject *obj) 1.1979 +{ 1.1980 + return sftk_isToken(obj->handle) ? (SFTKTokenObject *)obj : NULL; 1.1981 +} 1.1982 +