pk11slot.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,388 行 · 第 1/5 页
C
2,388 行
/* * 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. *//* * Deal with PKCS #11 Slots. */#include "seccomon.h"#include "secmod.h"#include "prlock.h"#include "secmodi.h"#include "pkcs11t.h"#include "pk11func.h"#include "cert.h"#include "key.h"#include "secitem.h"#include "secder.h"#include "secasn1.h"#include "secoid.h"#include "prtime.h"#include "prlong.h"#include "secerr.h"#define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */#include "ckt.h"/************************************************************* * local static and global data *************************************************************//* * This array helps parsing between names, mechanisms, and flags. * to make the config files understand more entries, add them * to this table. (NOTE: we need function to export this table and it's size) */PK11DefaultArrayEntry PK11_DefaultArray[] = { { "RSA", SECMOD_RSA_FLAG, CKM_RSA_PKCS }, { "DSA", SECMOD_DSA_FLAG, CKM_DSA }, { "DH", SECMOD_DH_FLAG, CKM_DH_PKCS_DERIVE }, { "RC2", SECMOD_RC2_FLAG, CKM_RC2_CBC }, { "RC4", SECMOD_RC4_FLAG, CKM_RC4 }, { "DES", SECMOD_DES_FLAG, CKM_DES_CBC }, { "RC5", SECMOD_RC5_FLAG, CKM_RC5_CBC }, { "SHA-1", SECMOD_SHA1_FLAG, CKM_SHA_1 }, { "MD5", SECMOD_MD5_FLAG, CKM_MD5 }, { "MD2", SECMOD_MD2_FLAG, CKM_MD2 }, { "SSL", SECMOD_SSL_FLAG, CKM_SSL3_PRE_MASTER_KEY_GEN }, { "TLS", SECMOD_TLS_FLAG, CKM_TLS_MASTER_KEY_DERIVE }, { "SKIPJACK", SECMOD_FORTEZZA_FLAG, CKM_SKIPJACK_CBC64 }, { "Publicly-readable certs", SECMOD_FRIENDLY_FLAG, CKM_INVALID_MECHANISM }, { "Random Num Generator", SECMOD_RANDOM_FLAG, CKM_FAKE_RANDOM },};int num_pk11_default_mechanisms = sizeof(PK11_DefaultArray) / sizeof(PK11_DefaultArray[0]);/* * These slotlists are lists of modules which provide default support for * a given algorithm or mechanism. */static PK11SlotList pk11_desSlotList, pk11_rc4SlotList, pk11_rc2SlotList, pk11_rc5SlotList, pk11_sha1SlotList, pk11_md5SlotList, pk11_md2SlotList, pk11_rsaSlotList, pk11_dsaSlotList, pk11_dhSlotList, pk11_ideaSlotList, pk11_sslSlotList, pk11_tlsSlotList, pk11_randomSlotList;/* * Tables used for Extended mechanism mapping (currently not used) */typedef struct { CK_MECHANISM_TYPE keyGen; CK_KEY_TYPE keyType; CK_MECHANISM_TYPE type; int blockSize; int iv;} pk11MechanismData; static pk11MechanismData pk11_default = { CKM_GENERIC_SECRET_KEY_GEN, CKK_GENERIC_SECRET, CKM_FAKE_RANDOM, 8, 8 };static pk11MechanismData *pk11_MechanismTable = NULL;static int pk11_MechTableSize = 0;static int pk11_MechEntrySize = 0;/* * list of mechanisms we're willing to wrap secret keys with. * This list is ordered by preference. */CK_MECHANISM_TYPE wrapMechanismList[] = { CKM_DES3_ECB, CKM_CAST5_ECB, CKM_DES_ECB, CKM_KEY_WRAP_LYNKS, CKM_IDEA_ECB, CKM_CAST3_ECB, CKM_CAST_ECB, CKM_RC5_ECB, CKM_RC2_ECB, CKM_CDMF_ECB, CKM_SKIPJACK_WRAP,};int wrapMechanismCount = sizeof(wrapMechanismList)/sizeof(wrapMechanismList[0]);/* * This structure keeps track of status that spans all the Slots. * NOTE: This is a global data structure. It semantics expect thread crosstalk * be very careful when you see it used. * It's major purpose in life is to allow the user to log in one PER * Tranaction, even if a transaction spans threads. The problem is the user * may have to enter a password one just to be able to look at the * personalities/certificates (s)he can use. Then if Auth every is one, they * may have to enter the password again to use the card. See PK11_StartTransac * and PK11_EndTransaction. */static struct PK11GlobalStruct { int transaction; PRBool inTransaction; char *(*getPass)(PK11SlotInfo *,PRBool,void *); PRBool (*verifyPass)(PK11SlotInfo *,void *); PRBool (*isLoggedIn)(PK11SlotInfo *,void *);} PK11_Global = { 1, PR_FALSE, NULL, NULL, NULL }; /************************************************************ * Generic Slot List and Slot List element manipulations ************************************************************//* * allocate a new list */PK11SlotList *PK11_NewSlotList(void){ PK11SlotList *list; list = (PK11SlotList *)PORT_Alloc(sizeof(PK11SlotList)); if (list == NULL) return NULL; list->head = NULL; list->tail = NULL;#ifdef PKCS11_USE_THREADS list->lock = PR_NewLock(); if (list->lock == NULL) { PORT_Free(list); return NULL; }#else list->lock = NULL;#endif return list;}/* * free a list element when all the references go away. */static voidpk11_FreeListElement(PK11SlotList *list, PK11SlotListElement *le){ PRBool freeit = PR_FALSE; PK11_USE_THREADS(PR_Lock((PRLock *)(list->lock));) if (le->refCount-- == 1) { freeit = PR_TRUE; } PK11_USE_THREADS(PR_Unlock((PRLock *)(list->lock));) if (freeit) { PK11_FreeSlot(le->slot); PORT_Free(le); }}/* * if we are freeing the list, we must be the only ones with a pointer * to the list. */voidPK11_FreeSlotList(PK11SlotList *list){ PK11SlotListElement *le, *next ; if (list == NULL) return; for (le = list->head ; le; le = next) { next = le->next; pk11_FreeListElement(list,le); } PK11_USE_THREADS(PR_DestroyLock((PRLock *)(list->lock));) PORT_Free(list);}/* * add a slot to a list */SECStatusPK11_AddSlotToList(PK11SlotList *list,PK11SlotInfo *slot){ PK11SlotListElement *le; le = (PK11SlotListElement *) PORT_Alloc(sizeof(PK11SlotListElement)); if (le == NULL) return SECFailure; le->slot = PK11_ReferenceSlot(slot); le->prev = NULL; le->refCount = 1; PK11_USE_THREADS(PR_Lock((PRLock *)(list->lock));) if (list->head) list->head->prev = le; else list->tail = le; le->next = list->head; list->head = le; PK11_USE_THREADS(PR_Unlock((PRLock *)(list->lock));) return SECSuccess;}/* * remove a slot entry from the list */SECStatusPK11_DeleteSlotFromList(PK11SlotList *list,PK11SlotListElement *le){ PK11_USE_THREADS(PR_Lock((PRLock *)(list->lock));) if (le->prev) le->prev->next = le->next; else list->head = le->next; if (le->next) le->next->prev = le->prev; else list->tail = le->prev; le->next = le->prev = NULL; PK11_USE_THREADS(PR_Unlock((PRLock *)(list->lock));) pk11_FreeListElement(list,le); return SECSuccess;}/* * Move a list to the end of the target list. NOTE: There is no locking * here... This assumes BOTH lists are private copy lists. */SECStatusPK11_MoveListToList(PK11SlotList *target,PK11SlotList *src){ if (src->head == NULL) return SECSuccess; if (target->tail == NULL) { target->head = src->head; } else { target->tail->next = src->head; } src->head->prev = target->tail; target->tail = src->tail; src->head = src->tail = NULL; return SECSuccess;}/* * get an element from the list with a reference. You must own the list. */PK11SlotListElement *PK11_GetFirstRef(PK11SlotList *list){ PK11SlotListElement *le; le = list->head; if (le != NULL) (le)->refCount++; return le;}/* * get the next element from the list with a reference. You must own the list. */PK11SlotListElement *PK11_GetNextRef(PK11SlotList *list, PK11SlotListElement *le, PRBool restart){ PK11SlotListElement *new_le; new_le = le->next; if (new_le) new_le->refCount++; pk11_FreeListElement(list,le); return new_le;}/* * get an element safely from the list. This just makes sure that if * this element is not deleted while we deal with it. */PK11SlotListElement *PK11_GetFirstSafe(PK11SlotList *list){ PK11SlotListElement *le; PK11_USE_THREADS(PR_Lock((PRLock *)(list->lock));) le = list->head; if (le != NULL) (le)->refCount++; PK11_USE_THREADS(PR_Unlock((PRLock *)(list->lock));) return le;}/* * NOTE: if this element gets deleted, we can no longer safely traverse using * it's pointers. We can either terminate the loop, or restart from the * beginning. This is controlled by the restart option. */PK11SlotListElement *PK11_GetNextSafe(PK11SlotList *list, PK11SlotListElement *le, PRBool restart){ PK11SlotListElement *new_le; PK11_USE_THREADS(PR_Lock((PRLock *)(list->lock));) new_le = le->next; if (le->next == NULL) { /* if the prev and next fields are NULL then either this element * has been removed and we need to walk the list again (if restart * is true) or this was the only element on the list */ if ((le->prev == NULL) && restart && (list->head != le)) { new_le = list->head; } } if (new_le) new_le->refCount++; PK11_USE_THREADS(PR_Unlock((PRLock *)(list->lock));) pk11_FreeListElement(list,le); return new_le;}/* * Find the element that holds this slot */PK11SlotListElement *PK11_FindSlotElement(PK11SlotList *list,PK11SlotInfo *slot){ PK11SlotListElement *le; for (le = PK11_GetFirstSafe(list); le; le = PK11_GetNextSafe(list,le,PR_TRUE)) { if (le->slot == slot) return le; } return NULL;}/************************************************************ * Generic Slot Utilities ************************************************************//* * Create a new slot structure */PK11SlotInfo *PK11_NewSlotInfo(void){ PK11SlotInfo *slot; slot = (PK11SlotInfo *)PORT_Alloc(sizeof(PK11SlotInfo)); if (slot == NULL) return slot;#ifdef PKCS11_USE_THREADS slot->refLock = PR_NewLock(); if (slot->refLock == NULL) { PORT_Free(slot); return slot; } slot->sessionLock = PR_NewLock(); if (slot->sessionLock == NULL) { PR_DestroyLock(slot->refLock); PORT_Free(slot); return slot; } slot->freeListLock = PR_NewLock(); if (slot->freeListLock == NULL) { PR_DestroyLock(slot->sessionLock); PR_DestroyLock(slot->refLock); PORT_Free(slot); return slot; }#else slot->sessionLock = NULL; slot->refLock = NULL; slot->freeListLock = NULL;#endif slot->freeSymKeysHead = NULL; slot->keyCount = 0; slot->maxKeyCount = 0; slot->functionList = NULL; slot->needTest = PR_TRUE; slot->isPerm = PR_FALSE; slot->isHW = PR_FALSE; slot->isInternal = PR_FALSE; slot->isThreadSafe = PR_FALSE; slot->disabled = PR_FALSE; slot->series = 0; slot->wrapKey = 0; slot->wrapMechanism = CKM_INVALID_MECHANISM; slot->refKeys[0] = CK_INVALID_KEY; slot->reason = PK11_DIS_NONE; slot->readOnly = PR_TRUE; slot->needLogin = PR_FALSE; slot->hasRandom = PR_FALSE; slot->defRWSession = PR_FALSE; slot->flags = 0; slot->session = CK_INVALID_SESSION; slot->slotID = 0; slot->defaultFlags = 0; slot->refCount = 1; slot->askpw = 0; slot->timeout = 0; slot->mechanismList = NULL; slot->mechanismCount = 0; slot->cert_array = NULL; slot->cert_count = 0; slot->slot_name[0] = 0; slot->token_name[0] = 0; PORT_Memset(slot->serial,' ',sizeof(slot->serial)); slot->module = NULL; slot->authTransact = 0; slot->authTime = LL_ZERO; slot->minPassword = 0; slot->maxPassword = 0; slot->hasRootCerts = PR_FALSE; return slot;} /* create a new reference to a slot so it doesn't go away */PK11SlotInfo *PK11_ReferenceSlot(PK11SlotInfo *slot){ PK11_USE_THREADS(PR_Lock(slot->refLock);) slot->refCount++; PK11_USE_THREADS(PR_Unlock(slot->refLock);) return slot;}/* Destroy all info on a slot we have built up */voidPK11_DestroySlot(PK11SlotInfo *slot){ /* first free up all the sessions on this slot */ if (slot->functionList) { PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); } /* now free up all the certificates we grabbed on this slot */ PK11_FreeSlotCerts(slot); /* free up the cached keys and sessions */ PK11_CleanKeyList(slot); /* finally Tell our parent module that we've gone away so it can unload */ if (slot->module) { SECMOD_SlotDestroyModule(slot->module,PR_TRUE); }#ifdef PKCS11_USE_THREADS if (slot->refLock) { PR_DestroyLock(slot->refLock); slot->refLock = NULL; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?