pkcs11u.c

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

C
1,271
字号
 * decode when a particular attribute may be modified * 	PK11_NEVER: This attribute must be set at object creation time and *  can never be modified. *	PK11_ONCOPY: This attribute may be modified only when you copy the *  object. *	PK11_SENSITIVE: The CKA_SENSITIVE attribute can only be changed from *  CK_FALSE to CK_TRUE. *	PK11_ALWAYS: This attribute can always be modified. * Some attributes vary their modification type based on the class of the  *   object. */PK11ModifyTypepk11_modifyType(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass){    /* if we don't know about it, user user defined, always allow modify */    PK11ModifyType mtype = PK11_ALWAYS;     switch(type) {    /* NEVER */    case CKA_CLASS:    case CKA_CERTIFICATE_TYPE:    case CKA_KEY_TYPE:    case CKA_MODULUS:    case CKA_MODULUS_BITS:    case CKA_PUBLIC_EXPONENT:    case CKA_PRIVATE_EXPONENT:    case CKA_PRIME:    case CKA_SUBPRIME:    case CKA_BASE:    case CKA_PRIME_1:    case CKA_PRIME_2:    case CKA_EXPONENT_1:    case CKA_EXPONENT_2:    case CKA_COEFFICIENT:    case CKA_VALUE_LEN:    case CKA_ALWAYS_SENSITIVE:    case CKA_NEVER_EXTRACTABLE:    case CKA_NETSCAPE_DB:	mtype = PK11_NEVER;	break;    /* ONCOPY */    case CKA_TOKEN:    case CKA_PRIVATE:    case CKA_MODIFIABLE:	mtype = PK11_ONCOPY;	break;    /* SENSITIVE */    case CKA_SENSITIVE:    case CKA_EXTRACTABLE:	mtype = PK11_SENSITIVE;	break;    /* ALWAYS */    case CKA_LABEL:    case CKA_APPLICATION:    case CKA_ID:    case CKA_SERIAL_NUMBER:    case CKA_START_DATE:    case CKA_END_DATE:    case CKA_DERIVE:    case CKA_ENCRYPT:    case CKA_DECRYPT:    case CKA_SIGN:    case CKA_VERIFY:    case CKA_SIGN_RECOVER:    case CKA_VERIFY_RECOVER:    case CKA_WRAP:    case CKA_UNWRAP:	mtype = PK11_ALWAYS;	break;    /* DEPENDS ON CLASS */    case CKA_VALUE:	mtype = (inClass == CKO_DATA) ? PK11_ALWAYS : PK11_NEVER;	break;    case CKA_SUBJECT:	mtype = (inClass == CKO_CERTIFICATE) ? PK11_NEVER : PK11_ALWAYS;	break;    default:	break;    }    return mtype;}/* decode if a particular attribute is sensitive (cannot be read * back to the user of if the object is set to SENSITIVE) */PRBoolpk11_isSensitive(CK_ATTRIBUTE_TYPE type, CK_OBJECT_CLASS inClass){    switch(type) {    /* ALWAYS */    case CKA_PRIVATE_EXPONENT:    case CKA_PRIME_1:    case CKA_PRIME_2:    case CKA_EXPONENT_1:    case CKA_EXPONENT_2:    case CKA_COEFFICIENT:	return PR_TRUE;    /* DEPENDS ON CLASS */    case CKA_VALUE:	/* PRIVATE and SECRET KEYS have SENSITIVE values */	return (PRBool)((inClass == CKO_PRIVATE_KEY) || (inClass == CKO_SECRET_KEY));    default:	break;    }    return PR_FALSE;}/*  * copy an attribute into a SECItem. Secitem is allocated in the specified * arena. */CK_RVpk11_Attribute2SecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,					CK_ATTRIBUTE_TYPE type){    int len;    PK11Attribute *attribute;    attribute = pk11_FindAttribute(object, type);    if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;    len = attribute->attrib.ulValueLen;    if (arena) {    	item->data = (unsigned char *) PORT_ArenaAlloc(arena,len);    } else {    	item->data = (unsigned char *) PORT_Alloc(len);    }    if (item->data == NULL) {	pk11_FreeAttribute(attribute);	return CKR_HOST_MEMORY;    }    item->len = len;    PORT_Memcpy(item->data,attribute->attrib.pValue, len);    pk11_FreeAttribute(attribute);    return CKR_OK;}voidpk11_DeleteAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    attribute = pk11_FindAttribute(object, type);    if (attribute == NULL) return ;    pk11_DeleteAttribute(object,attribute);    pk11_FreeAttribute(attribute);}CK_RVpk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr,							CK_ULONG length){    PK11Attribute *attribute;    attribute = pk11_NewAttribute(object,type,valPtr,length);    if (attribute == NULL) { return CKR_HOST_MEMORY; }    pk11_AddAttribute(object,attribute);    return CKR_OK;}/* * ******************** Object Utilities ******************************* *//* allocation hooks that allow us to recycle old object structures */#ifdef MAX_OBJECT_LIST_SIZEstatic PK11Object * objectFreeList = NULL;static PRLock *objectLock = NULL;static int object_count = 0;#endifPK11Object *pk11_GetObjectFromList(PRBool *hasLocks) {    PK11Object *object;#if MAX_OBJECT_LIST_SIZE    if (objectLock == NULL) {	objectLock = PR_NewLock();    }    PK11_USE_THREADS(PR_Lock(objectLock));    object = objectFreeList;    if (object) {	objectFreeList = object->next;	object_count--;    }    	    PK11_USE_THREADS(PR_Unlock(objectLock));    if (object) {	object->next = object->prev = NULL;        *hasLocks = PR_TRUE;	return object;    }#endif    object  = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object));    *hasLocks = PR_FALSE;    return object;}static voidpk11_PutObjectToList(PK11Object *object) {#ifdef MAX_OBJECT_LIST_SIZE    if (object_count < MAX_OBJECT_LIST_SIZE) {	PK11_USE_THREADS(PR_Lock(objectLock));	object->next = objectFreeList;	objectFreeList = object;	object_count++;	PK11_USE_THREADS(PR_Unlock(objectLock));	return;     }#endif    PK11_USE_THREADS(PR_DestroyLock(object->attributeLock);)    PK11_USE_THREADS(PR_DestroyLock(object->refLock);)    object->attributeLock = object->refLock = NULL;    PORT_Free(object);}/* * Create a new object */PK11Object *pk11_NewObject(PK11Slot *slot){    PK11Object *object;    PLArenaPool *arena;    PRBool hasLocks = PR_FALSE;    int i;#ifdef NO_ARENA    object = pk11_GetObjectFromList(&hasLocks);    if (object == NULL) {	return NULL;    }    object->nextAttr = 0;#else    arena = PORT_NewArena(2048);    if (arena == NULL) return NULL;    object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object));    if (object == NULL) {	PORT_FreeArena(arena,PR_FALSE);	return NULL;    }    object->arena = arena;    for (i=0; i < MAX_OBJS_ATTRS; i++) {	object->attrList[i].attrib.pValue = NULL;    }#endif    object->handle = 0;    object->next = object->prev = NULL;    object->sessionList.next = NULL;    object->sessionList.prev = NULL;    object->sessionList.parent = object;    object->inDB = PR_FALSE;    object->label = NULL;    object->refCount = 1;    object->session = NULL;    object->slot = slot;    object->objclass = 0xffff;    object->wasDerived = PR_FALSE;#ifdef PKCS11_USE_THREADS    if (!hasLocks) object->refLock = PR_NewLock();    if (object->refLock == NULL) {#ifdef NO_ARENA	PORT_Free(object);#else	PORT_FreeArena(arena,PR_FALSE);#endif	return NULL;    }    if (!hasLocks) object->attributeLock = PR_NewLock();    if (object->attributeLock == NULL) {	PK11_USE_THREADS(PR_DestroyLock(object->refLock);)#ifdef NO_ARENA	PORT_Free(object);#else	PORT_FreeArena(arena,PR_FALSE);#endif	return NULL;    }#else    object->attributeLock = NULL;    object->refLock = NULL;#endif    for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {	object->head[i] = NULL;    }    object->objectInfo = NULL;    object->infoFree = NULL;    return object;}/* * free all the data associated with an object. Object reference count must * be 'zero'. */static CK_RVpk11_DestroyObject(PK11Object *object){#if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA)    int i;#endif    SECItem pubKey;    CK_RV crv = CKR_OK;    SECStatus rv;    PLArenaPool *arena = NULL;    PORT_Assert(object->refCount == 0);    /* delete the database value */    if (object->inDB) {	if (pk11_isToken(object->handle)) {	/* remove the objects from the real data base */	    switch (object->handle & PK11_TOKEN_TYPE_MASK) {	      case PK11_TOKEN_TYPE_PRIV:		/* KEYID is the public KEY for DSA and DH, and the MODULUS for		 *  RSA */		crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);		if (crv != CKR_OK) break;		rv = SECKEY_DeleteKey(SECKEY_GetDefaultKeyDB(), &pubKey);		if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;		break;	      case PK11_TOKEN_TYPE_CERT:		rv = SEC_DeletePermCertificate((CERTCertificate *)object->objectInfo);		if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;		break;	    }	}    }     if (object->label) PORT_Free(object->label);    object->inDB = PR_FALSE;    object->label = NULL;#ifdef NO_ARENA    for (i=0; i < MAX_OBJS_ATTRS; i++) {	unsigned char *value = object->attrList[i].attrib.pValue;	if (value) {	    PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen);	    if (value != object->attrList[i].space) {		PORT_Free(value);	    }	    object->attrList[i].attrib.pValue = NULL;	}    }#endif#ifdef REF_COUNT_ATTRIBUTE    /* clean out the attributes */    /* since no one is referencing us, it's safe to walk the chain     * without a lock */    for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) {	PK11Attribute *ap,*next;	for (ap = object->head[i]; ap != NULL; ap = next) {	    next = ap->next;	    /* paranoia */	    ap->next = ap->prev = NULL;	    pk11_FreeAttribute(ap);	}	object->head[i] = NULL;    }#endif    if (object->objectInfo) {	(*object->infoFree)(object->objectInfo);    }#ifdef NO_ARENA    pk11_PutObjectToList(object);#else    PK11_USE_THREADS(PR_DestroyLock(object->attributeLock);)    PK11_USE_THREADS(PR_DestroyLock(object->refLock);)    arena = object->arena;    PORT_FreeArena(arena,PR_FALSE);#endif    return crv;}voidpk11_ReferenceObject(PK11Object *object){    PK11_USE_THREADS(PR_Lock(object->refLock);)    object->refCount++;    PK11_USE_THREADS(PR_Unlock(object->refLock);)}static PK11Object *pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot){    PK11Object **head;    PRLock *lock;    PK11Object *object;    head = slot->tokObjects;    lock = slot->objectLock;    PK11_USE_THREADS(PR_Lock(lock);)    pk11queue_find(object,handle,head,TOKEN_OBJECT_HASH_SIZE);    if (object) {	pk11_ReferenceObject(object);    }    PK11_USE_THREADS(PR_Unlock(lock);)    return(object);}/* * look up and object structure from a handle. OBJECT_Handles only make * sense in terms of a given session.  make a reference to that object * structure returned. */PK11Object *pk11_ObjectFromHandle(CK_OBJECT_HANDLE handle, PK11Session *session){    PK11Slot *slot = pk11_SlotFromSession(session);    return pk11_ObjectFromHandleOnSlot(handle,slot);}

⌨️ 快捷键说明

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