pkcs11u.c

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

C
1,271
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * Internal PKCS #11 functions. Should only be called by pkcs11.c */#include "pkcs11.h"#include "pkcs11i.h"#include "key.h"#include "certdb.h"/* declare the internal pkcs11 slot structures: *  There are threee: *	slot 0 is the generic crypto service token. *	slot 1 is the Database service token. *	slot 2 is the FIPS token (both generic and database). */static PK11Slot pk11_slot[3];/* * ******************** Attribute Utilities ******************************* *//* * create a new attribute with type, value, and length. Space is allocated * to hold value. */static PK11Attribute *pk11_NewAttribute(PK11Object *object,	CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, CK_ULONG len){    PK11Attribute *attribute;#ifdef NO_ARENA    int index;    /*      * NO_ARENA attempts to keep down contention on Malloc and Arena locks     * by limiting the number of these calls on high traversed paths. this     * is done for attributes by 'allocating' them from a pool already allocated     * by the parent object.     */    PK11_USE_THREADS(PR_Lock(object->attributeLock);)    index = object->nextAttr++;    PK11_USE_THREADS(PR_Unlock(object->attributeLock);)    PORT_Assert(index < MAX_OBJS_ATTRS);    if (index >= MAX_OBJS_ATTRS) return NULL;    attribute = &object->attrList[index];    attribute->attrib.type = type;    if (value) {        if (len <= ATTR_SPACE) {	    attribute->attrib.pValue = attribute->space;	} else {	    attribute->attrib.pValue = PORT_Alloc(len);	}	if (attribute->attrib.pValue == NULL) {	    return NULL;	}	PORT_Memcpy(attribute->attrib.pValue,value,len);	attribute->attrib.ulValueLen = len;    } else {	attribute->attrib.pValue = NULL;	attribute->attrib.ulValueLen = 0;    }#else#ifdef REF_COUNT_ATTRIBUTE    attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute));#else    attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute));#endif /* REF_COUNT_ATTRIBUTE */    if (attribute == NULL) return NULL;    if (value) {#ifdef REF_COUNT_ATTRIBUTE	attribute->attrib.pValue = PORT_Alloc(len);#else	attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len);#endif /* REF_COUNT_ATTRIBUTE */	if (attribute->attrib.pValue == NULL) {#ifdef REF_COUNT_ATTRIBUTE	    PORT_Free(attribute);#endif /* REF_COUNT_ATTRIBUTE */	    return NULL;	}	PORT_Memcpy(attribute->attrib.pValue,value,len);	attribute->attrib.ulValueLen = len;    } else {	attribute->attrib.pValue = NULL;	attribute->attrib.ulValueLen = 0;    }#endif /* NO_ARENA */    attribute->attrib.type = type;    attribute->handle = type;    attribute->next = attribute->prev = NULL;#ifdef REF_COUNT_ATTRIBUTE    attribute->refCount = 1;#ifdef PKCS11_USE_THREADS    attribute->refLock = PR_NewLock();    if (attribute->refLock == NULL) {	if (attribute->attrib.pValue) PORT_Free(attribute->attrib.pValue);	PORT_Free(attribute);	return NULL;    }#else    attribute->refLock = NULL;#endif#endif /* REF_COUNT_ATTRIBUTE */    return attribute;}/* * Free up all the memory associated with an attribute. Reference count * must be zero to call this. */static voidpk11_DestroyAttribute(PK11Attribute *attribute){#ifdef REF_COUNT_ATTRIBUTE    PORT_Assert(attribute->refCount == 0);    PK11_USE_THREADS(PR_DestroyLock(attribute->refLock);)    if (attribute->attrib.pValue) {	 /* clear out the data in the attribute value... it may have been	  * sensitive data */	 PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);	 PORT_Free(attribute->attrib.pValue);    }    PORT_Free(attribute);#endif}        /* * look up and attribute structure from a type and Object structure. * The returned attribute is referenced and needs to be freed when  * it is no longer needed. */PK11Attribute *pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    PK11_USE_THREADS(PR_Lock(object->attributeLock);)    pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);#ifdef REF_COUNT_ATTRIBUTE    if (attribute) {	/* atomic increment would be nice here */	PK11_USE_THREADS(PR_Lock(attribute->refLock);)	attribute->refCount++;	PK11_USE_THREADS(PR_Unlock(attribute->refLock);)    }#endif    PK11_USE_THREADS(PR_Unlock(object->attributeLock);)    return(attribute);}/* * release a reference to an attribute structure */voidpk11_FreeAttribute(PK11Attribute *attribute){#ifdef REF_COUNT_ATTRIBUTE    PRBool destroy = PR_FALSE;    PK11_USE_THREADS(PR_Lock(attribute->refLock);)    if (attribute->refCount == 1) destroy = PR_TRUE;    attribute->refCount--;    PK11_USE_THREADS(PR_Unlock(attribute->refLock);)    if (destroy) pk11_DestroyAttribute(attribute);#endif}/* * return true if object has attribute */PRBoolpk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    PK11_USE_THREADS(PR_Lock(object->attributeLock);)    pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE);    PK11_USE_THREADS(PR_Unlock(object->attributeLock);)    return (PRBool)(attribute != NULL);}/* * add an attribute to an object */staticvoid pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute){    PK11_USE_THREADS(PR_Lock(object->attributeLock);)    pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE);    PK11_USE_THREADS(PR_Unlock(object->attributeLock);)}/*  * copy an unsigned attribute into a 'signed' SECItem. Secitem is allocated in * the specified arena. */CK_RVpk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object,                                      CK_ATTRIBUTE_TYPE type){    int len;    PK11Attribute *attribute;    unsigned char *start;    int real_len;    attribute = pk11_FindAttribute(object, type);    if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE;    real_len = len = attribute->attrib.ulValueLen;    if ((*((unsigned char *)attribute->attrib.pValue) & 0x80) != 0) {	real_len++;    }    if (arena) {	start = item->data = (unsigned char *) PORT_ArenaAlloc(arena,real_len);    } else {	start = item->data = (unsigned char *) PORT_Alloc(real_len);    }    if (item->data == NULL) {	pk11_FreeAttribute(attribute);	return CKR_HOST_MEMORY;    }    item->len = real_len;    if (real_len != len) {	*start = 0;	start++;    }    PORT_Memcpy(start, attribute->attrib.pValue, len);    pk11_FreeAttribute(attribute);    return CKR_OK;}/* * delete an attribute from an object */static voidpk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute){    PK11_USE_THREADS(PR_Lock(object->attributeLock);)    if (pk11queue_is_queued(attribute,attribute->handle,					object->head,ATTRIBUTE_HASH_SIZE)) {	pk11queue_delete(attribute,attribute->handle,					object->head,ATTRIBUTE_HASH_SIZE);    }    PK11_USE_THREADS(PR_Unlock(object->attributeLock);)    pk11_FreeAttribute(attribute);}/* * this is only valid for CK_BBOOL type attributes. Return the state * of that attribute. */PRBoolpk11_isTrue(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    PRBool tok = PR_FALSE;    attribute=pk11_FindAttribute(object,type);    if (attribute == NULL) { return PR_FALSE; }    tok = (PRBool)(*(CK_BBOOL *)attribute->attrib.pValue);    pk11_FreeAttribute(attribute);    return tok;}/* * force an attribute to null. * this is for sensitive keys which are stored in the database, we don't * want to keep this info around in memory in the clear. */voidpk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    attribute=pk11_FindAttribute(object,type);    if (attribute == NULL) return;    if (attribute->attrib.pValue != NULL) {	PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen);#ifdef REF_COUNT_ATTRIBUTE	PORT_Free(attribute->attrib.pValue);#endif /* REF_COUNT_ATTRIBUTE */#ifdef NO_ARENA	if (attribute->attrib.pValue != attribute->space) {	    PORT_Free(attribute->attrib.pValue);	}#endif /* NO_ARENA */	attribute->attrib.pValue = NULL;	attribute->attrib.ulValueLen = 0;    }    pk11_FreeAttribute(attribute);}/* * force an attribute to a spaecif value. */CK_RVpk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value,						unsigned int len){    PK11Attribute *attribute;    void *att_val = NULL;    attribute=pk11_FindAttribute(object,type);    if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len);    if (value) {#ifdef NO_ARENA        if (len <= ATTR_SPACE) {	    att_val = attribute->space;	} else {	    att_val = PORT_Alloc(len);	}#else#ifdef REF_COUNT_ATTRIBUTE	att_val = PORT_Alloc(len);#else	att_val = PORT_ArenaAlloc(object->arena,len);#endif /* REF_COUNT_ATTRIBUTE */#endif /* NO_ARENA */	if (att_val == NULL) {	    return CKR_HOST_MEMORY;	}	if (attribute->attrib.pValue == att_val) {	    PORT_Memset(attribute->attrib.pValue,0,					attribute->attrib.ulValueLen);	}	PORT_Memcpy(att_val,value,len);    }    if (attribute->attrib.pValue != NULL) {	if (attribute->attrib.pValue != att_val) {	    PORT_Memset(attribute->attrib.pValue,0,					attribute->attrib.ulValueLen);	}#ifdef REF_COUNT_ATTRIBUTE	PORT_Free(attribute->attrib.pValue);#endif /* REF_COUNT_ATTRIBUTE */#ifdef NO_ARENA	if (attribute->attrib.pValue != attribute->space) {	    PORT_Free(attribute->attrib.pValue);	}#endif /* NO_ARENA */	attribute->attrib.pValue = NULL;	attribute->attrib.ulValueLen = 0;    }    if (att_val) {	attribute->attrib.pValue = att_val;	attribute->attrib.ulValueLen = len;    }    return CKR_OK;}/* * return a null terminated string from attribute 'type'. This string * is allocated and needs to be freed with PORT_Free() When complete. */char *pk11_getString(PK11Object *object,CK_ATTRIBUTE_TYPE type){    PK11Attribute *attribute;    char *label = NULL;    attribute=pk11_FindAttribute(object,type);    if (attribute == NULL) return NULL;    if (attribute->attrib.pValue != NULL) {	label = (char *) PORT_Alloc(attribute->attrib.ulValueLen+1);	if (label == NULL) {    	    pk11_FreeAttribute(attribute);	    return NULL;	}	PORT_Memcpy(label,attribute->attrib.pValue,						attribute->attrib.ulValueLen);	label[attribute->attrib.ulValueLen] = 0;    }    pk11_FreeAttribute(attribute);    return label;}/*

⌨️ 快捷键说明

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