pkcs11u.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,271 行 · 第 1/3 页

C
1,271
字号
/* * release a reference to an object handle */PK11FreeStatuspk11_FreeObject(PK11Object *object){    PRBool destroy = PR_FALSE;    CK_RV crv;    PK11_USE_THREADS(PR_Lock(object->refLock);)    if (object->refCount == 1) destroy = PR_TRUE;    object->refCount--;    PK11_USE_THREADS(PR_Unlock(object->refLock);)    if (destroy) {	crv = pk11_DestroyObject(object);	if (crv != CKR_OK) {	   return PK11_DestroyFailure;	} 	return PK11_Destroyed;    }    return PK11_Busy;} /* * add an object to a slot and session queue. These two functions * adopt the object. */voidpk11_AddSlotObject(PK11Slot *slot, PK11Object *object){    PK11_USE_THREADS(PR_Lock(slot->objectLock);)    pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE);    PK11_USE_THREADS(PR_Unlock(slot->objectLock);)}voidpk11_AddObject(PK11Session *session, PK11Object *object){    PK11Slot *slot = pk11_SlotFromSession(session);    if (!pk11_isToken(object->handle)) {	PK11_USE_THREADS(PR_Lock(session->objectLock);)	pk11queue_add(&object->sessionList,0,session->objects,0);	object->session = session;	PK11_USE_THREADS(PR_Unlock(session->objectLock);)    }    pk11_AddSlotObject(slot,object);} /* * add an object to a slot andsession queue */voidpk11_DeleteObject(PK11Session *session, PK11Object *object){    PK11Slot *slot = pk11_SlotFromSession(session);    if (object->session) {	PK11Session *session = object->session;	PK11_USE_THREADS(PR_Lock(session->objectLock);)	pk11queue_delete(&object->sessionList,0,session->objects,0);	PK11_USE_THREADS(PR_Unlock(session->objectLock);)    }    PK11_USE_THREADS(PR_Lock(slot->objectLock);)    pk11queue_delete(object,object->handle,slot->tokObjects,						TOKEN_OBJECT_HASH_SIZE);    PK11_USE_THREADS(PR_Unlock(slot->objectLock);)    pk11_FreeObject(object);}/* * copy the attributes from one object to another. Don't overwrite existing * attributes. NOTE: This is a pretty expensive operation since it * grabs the attribute locks for the src object for a *long* time. */CK_RVpk11_CopyObject(PK11Object *destObject,PK11Object *srcObject){    PK11Attribute *attribute;    int i;    PK11_USE_THREADS(PR_Lock(srcObject->attributeLock);)    for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) {	attribute = srcObject->head[i];	do {	    if (attribute) {		if (!pk11_hasAttribute(destObject,attribute->handle)) {		    /* we need to copy the attribute since each attribute		     * only has one set of link list pointers */		    PK11Attribute *newAttribute = pk11_NewAttribute(			  destObject,pk11_attr_expand(&attribute->attrib));		    if (newAttribute == NULL) {			PK11_USE_THREADS(PR_Unlock(srcObject->attributeLock);)			return CKR_HOST_MEMORY;		    }		    pk11_AddAttribute(destObject,newAttribute);		}		attribute=attribute->next;	    }	} while (attribute != NULL);    }    PK11_USE_THREADS(PR_Unlock(srcObject->attributeLock);)    return CKR_OK;}/* * ******************** Search Utilities ******************************* *//* add an object to a search list */CK_RVAddToList(PK11ObjectListElement **list,PK11Object *object){     PK11ObjectListElement *newElem = 	(PK11ObjectListElement *)PORT_Alloc(sizeof(PK11ObjectListElement));     if (newElem == NULL) return CKR_HOST_MEMORY;     newElem->next = *list;     newElem->object = object;     pk11_ReferenceObject(object);    *list = newElem;    return CKR_OK;}/* return true if the object matches the template */PRBoolpk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count){    int i;    for (i=0; i < count; i++) {	PK11Attribute *attribute = pk11_FindAttribute(object,theTemplate[i].type);	if (attribute == NULL) {	    return PR_FALSE;	}	if (attribute->attrib.ulValueLen == theTemplate[i].ulValueLen) {	    if (PORT_Memcmp(attribute->attrib.pValue,theTemplate[i].pValue,					theTemplate[i].ulValueLen) == 0) {        	pk11_FreeAttribute(attribute);		continue;	    }	}        pk11_FreeAttribute(attribute);	return PR_FALSE;    }    return PR_TRUE;}/* search through all the objects in the queue and return the template matches * in the object list. */CK_RVpk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head,        PRLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn){    int i;    PK11Object *object;    CK_RV crv = CKR_OK;    for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) {        /* We need to hold the lock to copy a consistant version of         * the linked list. */        PK11_USE_THREADS(PR_Lock(lock);)	for (object = head[i]; object != NULL; object= object->next) {	    if (pk11_objectMatch(object,theTemplate,count)) {		/* don't return objects that aren't yet visible */		if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue;	        crv = AddToList(objectList,object);		if (crv != CKR_OK) {		    break;		}	    }	}        PK11_USE_THREADS(PR_Unlock(lock);)    }    return crv;}/* * free a single list element. Return the Next object in the list. */PK11ObjectListElement *pk11_FreeObjectListElement(PK11ObjectListElement *objectList){    PK11ObjectListElement *ol = objectList->next;    pk11_FreeObject(objectList->object);    PORT_Free(objectList);    return ol;}/* free an entire object list */voidpk11_FreeObjectList(PK11ObjectListElement *objectList){    PK11ObjectListElement *ol;    for (ol= objectList; ol != NULL; ol = pk11_FreeObjectListElement(ol)) {}}/* * free a search structure */voidpk11_FreeSearch(PK11SearchResults *search){    if (search->handles) {	PORT_Free(search->handles);    }    PORT_Free(search);}/* * ******************** Session Utilities ******************************* *//* update the sessions state based in it's flags and wether or not it's * logged in */voidpk11_update_state(PK11Slot *slot,PK11Session *session){    if (slot->isLoggedIn) {	if (slot->ssoLoggedIn) {    	    session->info.state = CKS_RW_SO_FUNCTIONS;	} else if (session->info.flags & CKF_RW_SESSION) {    	    session->info.state = CKS_RW_USER_FUNCTIONS;	} else {    	    session->info.state = CKS_RO_USER_FUNCTIONS;	}    } else {	if (session->info.flags & CKF_RW_SESSION) {    	    session->info.state = CKS_RW_PUBLIC_SESSION;	} else {    	    session->info.state = CKS_RO_PUBLIC_SESSION;	}    }}/* update the state of all the sessions on a slot */voidpk11_update_all_states(PK11Slot *slot){    int i;    PK11Session *session;    for (i=0; i < SESSION_HASH_SIZE; i++) {	PK11_USE_THREADS(PR_Lock(slot->sessionLock);)	for (session = slot->head[i]; session; session = session->next) {	    pk11_update_state(slot,session);	}	PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)    }}/* * context are cipher and digest contexts that are associated with a session */voidpk11_FreeContext(PK11SessionContext *context){    if (context->cipherInfo) {	(*context->destroy)(context->cipherInfo,PR_TRUE);    }    if (context->hashInfo) {	(*context->hashdestroy)(context->hashInfo,PR_TRUE);    }    PORT_Free(context);}/* look up a slot structure from the ID (used to be a macro when we only * had two slots) */PK11Slot *pk11_SlotFromID(CK_SLOT_ID slotID){    switch (slotID) {    case NETSCAPE_SLOT_ID:	return &pk11_slot[0];    case PRIVATE_KEY_SLOT_ID:	return &pk11_slot[1];    case FIPS_SLOT_ID:	return &pk11_slot[2];    default:	break; /* fall through to NULL */    }    return NULL;}PK11Slot *pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle){    if (handle & PK11_PRIVATE_KEY_FLAG) {	return &pk11_slot[1];    }    if (handle & PK11_FIPS_FLAG) {	return &pk11_slot[2];    }    return &pk11_slot[0];}/* * create a new nession. NOTE: The session handle is not set, and the * session is not added to the slot's session queue. */PK11Session *pk11_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,							     CK_FLAGS flags){    PK11Session *session;    PK11Slot *slot = pk11_SlotFromID(slotID);    if (slot == NULL) return NULL;    session = (PK11Session*)PORT_Alloc(sizeof(PK11Session));    if (session == NULL) return NULL;    session->next = session->prev = NULL;    session->refCount = 1;    session->enc_context = NULL;    session->hash_context = NULL;    session->sign_context = NULL;    session->search = NULL;    session->objectIDCount = 1;#ifdef PKCS11_USE_THREADS    session->refLock = PR_NewLock();    if (session->refLock == NULL) {	PORT_Free(session);	return NULL;    }    session->objectLock = PR_NewLock();    if (session->objectLock == NULL) {	PK11_USE_THREADS(PR_DestroyLock(session->refLock);)	PORT_Free(session);	return NULL;    }#else    session->refLock = NULL;    session->objectLock = NULL;#endif    session->objects[0] = NULL;    session->slot = slot;    session->notify = notify;    session->appData = pApplication;    session->info.flags = flags;    session->info.slotID = slotID;    pk11_update_state(slot,session);    return session;}/* free all the data associated with a session. */static voidpk11_DestroySession(PK11Session *session){    PK11ObjectList *op,*next;    PORT_Assert(session->refCount == 0);    /* clean out the attributes */    /* since no one is referencing us, it's safe to walk the chain     * without a lock */    for (op = session->objects[0]; op != NULL; op = next) {        next = op->next;        /* paranoia */	op->next = op->prev = NULL;	pk11_DeleteObject(session,op->parent);    }    PK11_USE_THREADS(PR_DestroyLock(session->objectLock);)    PK11_USE_THREADS(PR_DestroyLock(session->refLock);)    if (session->enc_context) {	pk11_FreeContext(session->enc_context);    }    if (session->hash_context) {	pk11_FreeContext(session->hash_context);    }    if (session->sign_context) {	pk11_FreeContext(session->sign_context);    }    if (session->search) {	pk11_FreeSearch(session->search);    }    PORT_Free(session);}/* * look up a session structure from a session handle * generate a reference to it. */PK11Session *pk11_SessionFromHandle(CK_SESSION_HANDLE handle){    PK11Slot	*slot = pk11_SlotFromSessionHandle(handle);    PK11Session *session;    PK11_USE_THREADS(PR_Lock(slot->sessionLock);)    pk11queue_find(session,handle,slot->head,SESSION_HASH_SIZE);    if (session) session->refCount++;    PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)    return (session);}/* * release a reference to a session handle */voidpk11_FreeSession(PK11Session *session){    PRBool destroy = PR_FALSE;    PK11_USE_THREADS(PK11Slot *slot = pk11_SlotFromSession(session);)    PK11_USE_THREADS(PR_Lock(slot->sessionLock);)    if (session->refCount == 1) destroy = PR_TRUE;    session->refCount--;    PK11_USE_THREADS(PR_Unlock(slot->sessionLock);)    if (destroy) pk11_DestroySession(session);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?