summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2000-06-13 21:37:28 +0000
committerrelyea%netscape.com <devnull@localhost>2000-06-13 21:37:28 +0000
commiteaa056d41046b41fee0c3b8d6fa93714a6e5474a (patch)
treec26321ca40d30c3d906bafb42aa56dc637ec81fe
parent930f5c5e6a7609ec639cc700ba7d5c33036ed07c (diff)
downloadnss-hg-eaa056d41046b41fee0c3b8d6fa93714a6e5474a.tar.gz
reuse old key structures on a given token rather than building it up and
tearing it down every time.
-rw-r--r--security/nss/lib/pk11wrap/pk11func.h2
-rw-r--r--security/nss/lib/pk11wrap/pk11skey.c82
-rw-r--r--security/nss/lib/pk11wrap/pk11slot.c28
-rw-r--r--security/nss/lib/pk11wrap/secmodti.h5
4 files changed, 106 insertions, 11 deletions
diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h
index 21003d1ce..99310d48d 100644
--- a/security/nss/lib/pk11wrap/pk11func.h
+++ b/security/nss/lib/pk11wrap/pk11func.h
@@ -89,6 +89,8 @@ SECStatus PK11_Logout(PK11SlotInfo *slot);
void PK11_LogoutAll(void);
void PK11_EnterSlotMonitor(PK11SlotInfo *);
void PK11_ExitSlotMonitor(PK11SlotInfo *);
+void PK11_CleanKeyList(PK11SlotInfo *slot);
+
/************************************************************
diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c
index 52f2ce30d..e48c88a6d 100644
--- a/security/nss/lib/pk11wrap/pk11skey.c
+++ b/security/nss/lib/pk11wrap/pk11skey.c
@@ -154,6 +154,54 @@ pk11_ExitKeyMonitor(PK11SymKey *symKey) {
PK11_ExitSlotMonitor(symKey->slot);
}
+
+static PK11SymKey *pk11SymKeyHead = NULL;
+static PK11SymKey *
+pk11_getKeyFromList(PK11SlotInfo *slot) {
+ PK11SymKey *symKey;
+
+
+ PK11_USE_THREADS(PR_Lock(slot->freeListLock);)
+ if (slot->freeSymKeysHead) {
+ symKey = slot->freeSymKeysHead;
+ slot->freeSymKeysHead = symKey->next;
+ slot->keyCount--;
+ }
+ PK11_USE_THREADS(PR_Unlock(slot->freeListLock);)
+ if (symKey) {
+ symKey->next = NULL;
+ return symKey;
+ }
+
+ symKey = (PK11SymKey *)PORT_ZAlloc(sizeof(PK11SymKey));
+ if (symKey == NULL) {
+ return NULL;
+ }
+ symKey->refLock = PR_NewLock();
+ if (symKey->refLock == NULL) {
+ PORT_Free(symKey);
+ return NULL;
+ }
+ symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);
+ symKey->next = NULL;
+ return symKey;
+}
+
+void
+PK11_CleanKeyList(PK11SlotInfo *slot)
+{
+ PK11SymKey *symKey = NULL;
+
+ while (slot->freeSymKeysHead) {
+ symKey = slot->freeSymKeysHead;
+ slot->freeSymKeysHead = symKey->next;
+ pk11_CloseSession(symKey->slot, symKey->session,symKey->sessionOwner);
+ PK11_USE_THREADS(PR_DestroyLock(symKey->refLock);)
+ PORT_Free(symKey);
+ };
+ return;
+}
+
/*
* create a symetric key:
* Slot is the slot to create the key in.
@@ -163,15 +211,13 @@ PK11SymKey *
PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx)
{
- PK11SymKey *symKey = (PK11SymKey *)PORT_Alloc(sizeof(PK11SymKey));
+ PK11SymKey *symKey = pk11_getKeyFromList(slot);
+
+
if (symKey == NULL) {
return NULL;
}
- symKey->refLock = PR_NewLock();
- if (symKey->refLock == NULL) {
- PORT_Free(symKey);
- return NULL;
- }
+
symKey->type = type;
symKey->data.data = NULL;
symKey->data.len = 0;
@@ -183,7 +229,6 @@ PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx)
symKey->size = 0;
symKey->refCount = 1;
symKey->origin = PK11_OriginNULL;
- symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);
symKey->origin = PK11_OriginNULL;
PK11_ReferenceSlot(slot);
return symKey;
@@ -196,6 +241,8 @@ void
PK11_FreeSymKey(PK11SymKey *symKey)
{
PRBool destroy = PR_FALSE;
+ PK11SlotInfo *slot;
+ PRBool freeit = PR_TRUE;
PK11_USE_THREADS(PR_Lock(symKey->refLock);)
if (symKey->refCount-- == 1) {
@@ -209,14 +256,27 @@ PK11_FreeSymKey(PK11SymKey *symKey)
C_DestroyObject(symKey->session, symKey->objectID);
pk11_ExitKeyMonitor(symKey);
}
- pk11_CloseSession(symKey->slot, symKey->session,symKey->sessionOwner);
if (symKey->data.data) {
PORT_Memset(symKey->data.data, 0, symKey->data.len);
PORT_Free(symKey->data.data);
}
- PK11_USE_THREADS(PR_DestroyLock(symKey->refLock);)
- PK11_FreeSlot(symKey->slot);
- PORT_Free(symKey);
+ slot = symKey->slot;
+ PK11_USE_THREADS(PR_Lock(slot->freeListLock);)
+ if (slot->keyCount < slot->maxKeyCount) {
+ symKey->next = slot->freeSymKeysHead;
+ slot->freeSymKeysHead = symKey;
+ slot->keyCount++;
+ symKey->slot = NULL;
+ freeit = PR_FALSE;
+ }
+ PK11_USE_THREADS(PR_Unlock(slot->freeListLock);)
+ if (freeit) {
+ pk11_CloseSession(symKey->slot, symKey->session,
+ symKey->sessionOwner);
+ PK11_USE_THREADS(PR_DestroyLock(symKey->refLock);)
+ PORT_Free(symKey);
+ }
+ PK11_FreeSlot(slot);
}
}
diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c
index 82d7466d4..6c7cb4296 100644
--- a/security/nss/lib/pk11wrap/pk11slot.c
+++ b/security/nss/lib/pk11wrap/pk11slot.c
@@ -385,10 +385,21 @@ PK11_NewSlotInfo(void)
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;
@@ -449,6 +460,9 @@ PK11_DestroySlot(PK11SlotInfo *slot)
/* 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);
@@ -462,6 +476,10 @@ PK11_DestroySlot(PK11SlotInfo *slot)
PR_DestroyLock(slot->sessionLock);
slot->sessionLock = NULL;
}
+ if (slot->freeListLock) {
+ PR_DestroyLock(slot->freeListLock);
+ slot->freeListLock = NULL;
+ }
#endif
/* ok, well not quit finally... now we free the memory */
@@ -1587,6 +1605,16 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts)
slot->hasRSAInfo = PR_FALSE;
slot->RSAInfoFlags = 0;
+ /* initialize the maxKeyCount value */
+ if (tokenInfo.ulMaxSessionCount == 0) {
+ slot->maxKeyCount = 300; /* should be #define or a config param */
+ } else if (tokenInfo.ulMaxSessionCount < 20) {
+ /* don't have enough sessions to keep that many keys around */
+ slot->maxKeyCount = 0;
+ } else {
+ slot->maxKeyCount = tokenInfo.ulMaxSessionCount/2;
+ }
+
/* Make sure our session handle is valid */
if (slot->session == CK_INVALID_SESSION) {
/* we know we don't have a valid session, go get one */
diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h
index c7028641c..d97059a9b 100644
--- a/security/nss/lib/pk11wrap/secmodti.h
+++ b/security/nss/lib/pk11wrap/secmodti.h
@@ -83,6 +83,10 @@ struct PK11SlotInfoStr {
* still in use */
int refCount;
PRLock *refLock;
+ PRLock *freeListLock;
+ PK11SymKey *freeSymKeysHead;
+ int keyCount;
+ int maxKeyCount;
/* Password control functions for this slot. many of these are only
* active if the appropriate flag is on in defaultFlags */
int askpw; /* what our password options are */
@@ -133,6 +137,7 @@ struct PK11SymKeyStr {
CK_OBJECT_HANDLE objectID; /* object id of this key in the slot */
PK11SlotInfo *slot; /* Slot this key is loaded into */
void *cx; /* window context in case we need to loggin */
+ PK11SymKey *next;
PRBool owner;
SECItem data; /* raw key data if available */
CK_SESSION_HANDLE session;