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 + -
显示快捷键?