static CK_RV nss_dbm_db_unwrap_object ( NSSArena *arena, DBT *object, CK_ATTRIBUTE_PTR *ppTemplate, CK_ULONG *pulAttributeCount ) { CK_ULONG *pulData; char *pcData; CK_ULONG n, i; CK_ATTRIBUTE_PTR pTemplate; pulData = (CK_ULONG *)object->data; pcData = (char *)object->data; n = ntohl(pulData[0]); *pulAttributeCount = n; pTemplate = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, n); if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) { return CKR_HOST_MEMORY; } for( i = 0; i < n; i++ ) { CK_ULONG len; CK_ULONG offset; void *p; pTemplate[i].type = ntohl(pulData[1 + i*3]); len = ntohl(pulData[2 + i*3]); offset = ntohl(pulData[3 + i*3]); p = nss_ZAlloc(arena, len); if( (void *)NULL == p ) { return CKR_HOST_MEMORY; } nss_dbm_db_swap_copy(pTemplate[i].type, p, &pcData[offset], len); pTemplate[i].ulValueLen = len; pTemplate[i].pValue = p; } *ppTemplate = pTemplate; return CKR_OK; }
/* Sigh. The methods to find objects declared above cause problems with * the low-level object cache in the softoken -- the objects are found in * toto, then one wave of GetAttributes is done, then another. Having a * large number of objects causes the cache to be thrashed, as the objects * are gone before there's any chance to ask for their attributes. * So, for now, bringing back traversal methods for certs. This way all of * the cert's attributes can be grabbed immediately after finding it, * increasing the likelihood that the cache takes care of it. */ NSS_IMPLEMENT PRStatus nssToken_TraverseCertificates ( NSSToken *token, nssSession *sessionOpt, nssTokenSearchType searchType, PRStatus (* callback)(nssCryptokiObject *instance, void *arg), void *arg ) { CK_RV ckrv; CK_ULONG count; CK_OBJECT_HANDLE *objectHandles; CK_ATTRIBUTE_PTR attr; CK_ATTRIBUTE cert_template[2]; CK_ULONG ctsize; NSSArena *arena; PRStatus status; PRUint32 arraySize, numHandles; nssCryptokiObject **objects; void *epv = nssToken_GetCryptokiEPV(token); nssSession *session = (sessionOpt) ? sessionOpt : token->defaultSession; /* Don't ask the module to use an invalid session handle. */ if (!session || session->handle == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_NO_TOKEN); return PR_FAILURE; } /* template for all certs */ NSS_CK_TEMPLATE_START(cert_template, attr, ctsize); if (searchType == nssTokenSearchType_SessionOnly) { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_false); } else if (searchType == nssTokenSearchType_TokenOnly || searchType == nssTokenSearchType_TokenForced) { NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_TOKEN, &g_ck_true); } NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CLASS, &g_ck_class_cert); NSS_CK_TEMPLATE_FINISH(cert_template, attr, ctsize); /* the arena is only for the array of object handles */ arena = nssArena_Create(); if (!arena) { return PR_FAILURE; } arraySize = OBJECT_STACK_SIZE; numHandles = 0; objectHandles = nss_ZNEWARRAY(arena, CK_OBJECT_HANDLE, arraySize); if (!objectHandles) { goto loser; } nssSession_EnterMonitor(session); /* ==== session lock === */ /* Initialize the find with the template */ ckrv = CKAPI(epv)->C_FindObjectsInit(session->handle, cert_template, ctsize); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); goto loser; } while (PR_TRUE) { /* Issue the find for up to arraySize - numHandles objects */ ckrv = CKAPI(epv)->C_FindObjects(session->handle, objectHandles + numHandles, arraySize - numHandles, &count); if (ckrv != CKR_OK) { nssSession_ExitMonitor(session); goto loser; } /* bump the number of found objects */ numHandles += count; if (numHandles < arraySize) { break; } /* the array is filled, double it and continue */ arraySize *= 2; objectHandles = nss_ZREALLOCARRAY(objectHandles, CK_OBJECT_HANDLE, arraySize); if (!objectHandles) { nssSession_ExitMonitor(session); goto loser; } } ckrv = CKAPI(epv)->C_FindObjectsFinal(session->handle); nssSession_ExitMonitor(session); /* ==== end session lock === */ if (ckrv != CKR_OK) { goto loser; } if (numHandles > 0) { objects = create_objects_from_handles(token, session, objectHandles, numHandles); if (objects) { nssCryptokiObject **op; for (op = objects; *op; op++) { status = (*callback)(*op, arg); } nss_ZFreeIf(objects); } } nssArena_Destroy(arena); return PR_SUCCESS; loser: nssArena_Destroy(arena); return PR_FAILURE; }
/* * nssCKMDSessionObject_Create * */ NSS_IMPLEMENT NSSCKMDObject * nssCKMDSessionObject_Create ( NSSCKFWToken *fwToken, NSSArena *arena, CK_ATTRIBUTE_PTR attributes, CK_ULONG ulCount, CK_RV *pError ) { NSSCKMDObject *mdObject = (NSSCKMDObject *)NULL; nssCKMDSessionObject *mdso = (nssCKMDSessionObject *)NULL; CK_ULONG i; nssCKFWHash *hash; *pError = CKR_OK; mdso = nss_ZNEW(arena, nssCKMDSessionObject); if (!mdso) { goto loser; } mdso->arena = arena; mdso->n = ulCount; mdso->attributes = nss_ZNEWARRAY(arena, NSSItem, ulCount); if (!mdso->attributes) { goto loser; } mdso->types = nss_ZNEWARRAY(arena, CK_ATTRIBUTE_TYPE, ulCount); if (!mdso->types) { goto loser; } for( i = 0; i < ulCount; i++ ) { mdso->types[i] = attributes[i].type; mdso->attributes[i].size = attributes[i].ulValueLen; mdso->attributes[i].data = nss_ZAlloc(arena, attributes[i].ulValueLen); if (!mdso->attributes[i].data) { goto loser; } (void)nsslibc_memcpy(mdso->attributes[i].data, attributes[i].pValue, attributes[i].ulValueLen); } mdObject = nss_ZNEW(arena, NSSCKMDObject); if (!mdObject) { goto loser; } mdObject->etc = (void *)mdso; mdObject->Finalize = nss_ckmdSessionObject_Finalize; mdObject->Destroy = nss_ckmdSessionObject_Destroy; mdObject->IsTokenObject = nss_ckmdSessionObject_IsTokenObject; mdObject->GetAttributeCount = nss_ckmdSessionObject_GetAttributeCount; mdObject->GetAttributeTypes = nss_ckmdSessionObject_GetAttributeTypes; mdObject->GetAttributeSize = nss_ckmdSessionObject_GetAttributeSize; mdObject->GetAttribute = nss_ckmdSessionObject_GetAttribute; mdObject->SetAttribute = nss_ckmdSessionObject_SetAttribute; mdObject->GetObjectSize = nss_ckmdSessionObject_GetObjectSize; hash = nssCKFWToken_GetSessionObjectHash(fwToken); if (!hash) { *pError = CKR_GENERAL_ERROR; goto loser; } mdso->hash = hash; *pError = nssCKFWHash_Add(hash, mdObject, mdObject); if( CKR_OK != *pError ) { goto loser; } #ifdef DEBUG if(( *pError = nss_ckmdSessionObject_add_pointer(mdObject)) != CKR_OK ) { goto loser; } #endif /* DEBUG */ return mdObject; loser: if (mdso) { if (mdso->attributes) { for( i = 0; i < ulCount; i++ ) { nss_ZFreeIf(mdso->attributes[i].data); } nss_ZFreeIf(mdso->attributes); } nss_ZFreeIf(mdso->types); nss_ZFreeIf(mdso); } nss_ZFreeIf(mdObject); if (*pError == CKR_OK) { *pError = CKR_HOST_MEMORY; } return (NSSCKMDObject *)NULL; }