summaryrefslogtreecommitdiff
path: root/security/nss/lib
diff options
context:
space:
mode:
authorrelyea%netscape.com <devnull@localhost>2005-09-28 17:12:17 +0000
committerrelyea%netscape.com <devnull@localhost>2005-09-28 17:12:17 +0000
commitf2f4f32c0c92b8051dd4e8e2a62a8f5b160f6207 (patch)
tree668af1b0b2f0a9e6c3f26eaf4e19b563f60c0cc8 /security/nss/lib
parent87354b359da58e57f254d57e9939a2d8e17254ca (diff)
downloadnss-hg-f2f4f32c0c92b8051dd4e8e2a62a8f5b160f6207.tar.gz
bug 305697: open additional database on the fly in softoken. part1: softoken changes.
r=julien
Diffstat (limited to 'security/nss/lib')
-rw-r--r--security/nss/lib/softoken/cdbhdl.h4
-rw-r--r--security/nss/lib/softoken/dbinit.c49
-rw-r--r--security/nss/lib/softoken/keydb.c279
-rw-r--r--security/nss/lib/softoken/keydbi.h2
-rw-r--r--security/nss/lib/softoken/lowcert.c1
-rw-r--r--security/nss/lib/softoken/manifest.mn1
-rw-r--r--security/nss/lib/softoken/pcertdb.c19
-rw-r--r--security/nss/lib/softoken/pk11db.c6
-rw-r--r--security/nss/lib/softoken/pk11pars.h13
-rw-r--r--security/nss/lib/softoken/pkcs11.c818
-rw-r--r--security/nss/lib/softoken/pkcs11i.h108
-rw-r--r--security/nss/lib/softoken/pkcs11n.h10
-rw-r--r--security/nss/lib/softoken/pkcs11u.c345
13 files changed, 1166 insertions, 489 deletions
diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h
index a53aacea3..238a48669 100644
--- a/security/nss/lib/softoken/cdbhdl.h
+++ b/security/nss/lib/softoken/cdbhdl.h
@@ -45,6 +45,7 @@
#include "nspr.h"
#include "mcom_db.h"
#include "pcertt.h"
+#include "prtypes.h"
/*
* Handle structure for open certificate databases
@@ -53,8 +54,11 @@ struct NSSLOWCERTCertDBHandleStr {
DB *permCertDB;
PZMonitor *dbMon;
PRBool dbVerify;
+ PRInt32 ref; /* reference count */
};
+#define nsslowcert_reference(x) (PR_AtomicIncrement(&(x)->ref) , (x))
+
#ifdef DBM_USING_NSPR
#define NO_RDONLY PR_RDONLY
#define NO_RDWR PR_RDWR
diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c
index 110419dac..2b7f81a73 100644
--- a/security/nss/lib/softoken/dbinit.c
+++ b/security/nss/lib/softoken/dbinit.c
@@ -43,10 +43,12 @@
#include "prinit.h"
#include "prprf.h"
#include "prmem.h"
+#include "pratom.h"
#include "pcertt.h"
#include "lowkeyi.h"
#include "pcert.h"
#include "cdbhdl.h"
+#include "keydbi.h"
#include "pkcs11i.h"
static char *
@@ -164,6 +166,7 @@ sftk_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly,
if (certdb == NULL)
goto loser;
+ certdb->ref = 1;
/* fix when we get the DB in */
rv = nsslowcert_OpenCertDB(certdb, readOnly, appName, prefix,
sftk_certdb_name_cb, (void *)name, PR_FALSE);
@@ -254,20 +257,52 @@ loser:
return crv;
}
-
-void
-sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
- NSSLOWKEYDBHandle *keyHandle)
+NSSLOWCERTCertDBHandle *
+sftk_getCertDB(SFTKSlot *slot)
{
+ NSSLOWCERTCertDBHandle *certHandle;
+
+ PZ_Lock(slot->slotLock);
+ certHandle = slot->certDB;
if (certHandle) {
- nsslowcert_ClosePermCertDB(certHandle);
- PORT_Free(certHandle);
+ PR_AtomicIncrement(&certHandle->ref);
}
+ PZ_Unlock(slot->slotLock);
+ return certHandle;
+}
+NSSLOWKEYDBHandle *
+sftk_getKeyDB(SFTKSlot *slot)
+{
+ NSSLOWKEYDBHandle *keyHandle;
+
+ PZ_Lock(slot->slotLock);
+ keyHandle = slot->keyDB;
if (keyHandle) {
- nsslowkey_CloseKeyDB(keyHandle);
+ PR_AtomicIncrement(&keyHandle->ref);
}
+ PZ_Unlock(slot->slotLock);
+ return keyHandle;
+}
+
+void
+sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle)
+{
+ PRInt32 ref = PR_AtomicDecrement(&certHandle->ref);
+ if (ref == 0) {
+ nsslowcert_ClosePermCertDB(certHandle);
+ }
+}
+
+void
+sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle)
+{
+ PRInt32 ref = PR_AtomicDecrement(&keyHandle->ref);
+ if (ref == 0) {
+ nsslowkey_CloseKeyDB(keyHandle);
+ }
}
+
static int rdbmapflags(int flags);
static rdbfunc sftk_rdbfunc = NULL;
diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c
index 8ab56ec5b..2f685a5a6 100644
--- a/security/nss/lib/softoken/keydb.c
+++ b/security/nss/lib/softoken/keydb.c
@@ -161,20 +161,21 @@ free_dbt(DBT *dbt)
return;
}
-static int keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags);
-static int keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags);
-static int keydb_Sync(DB *db, unsigned int flags);
-static int keydb_Del(DB *db, DBT *key, unsigned int flags);
-static int keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags);
-static void keydb_Close(DB *db);
-
-static PZLock *kdbLock = NULL;
+static int keydb_Get(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
+ unsigned int flags);
+static int keydb_Put(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
+ unsigned int flags);
+static int keydb_Sync(NSSLOWKEYDBHandle *db, unsigned int flags);
+static int keydb_Del(NSSLOWKEYDBHandle *db, DBT *key, unsigned int flags);
+static int keydb_Seq(NSSLOWKEYDBHandle *db, DBT *key, DBT *data,
+ unsigned int flags);
+static void keydb_Close(NSSLOWKEYDBHandle *db);
static void
keydb_InitLocks(NSSLOWKEYDBHandle *handle)
{
- if (kdbLock == NULL) {
- nss_InitLock(&kdbLock, nssILockKeyDB);
+ if (handle->lock == NULL) {
+ nss_InitLock(&handle->lock, nssILockKeyDB);
}
return;
@@ -183,9 +184,9 @@ keydb_InitLocks(NSSLOWKEYDBHandle *handle)
static void
keydb_DestroyLocks(NSSLOWKEYDBHandle *handle)
{
- if (kdbLock != NULL) {
- PZ_DestroyLock(kdbLock);
- kdbLock = NULL;
+ if (handle->lock != NULL) {
+ PZ_DestroyLock(handle->lock);
+ handle->lock = NULL;
}
return;
@@ -348,7 +349,7 @@ get_dbkey(NSSLOWKEYDBHandle *handle, DBT *index)
int ret;
/* get it from the database */
- ret = keydb_Get(handle->db, index, &entry, 0);
+ ret = keydb_Get(handle, index, &entry, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return NULL;
@@ -374,9 +375,9 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u
/* put it in the database */
if ( update ) {
- status = keydb_Put(handle->db, index, keydata, 0);
+ status = keydb_Put(handle, index, keydata, 0);
} else {
- status = keydb_Put(handle->db, index, keydata, R_NOOVERWRITE);
+ status = keydb_Put(handle, index, keydata, R_NOOVERWRITE);
}
if ( status ) {
@@ -384,7 +385,7 @@ put_dbkey(NSSLOWKEYDBHandle *handle, DBT *index, NSSLOWKEYDBKey *dbkey, PRBool u
}
/* sync the database */
- status = keydb_Sync(handle->db, 0);
+ status = keydb_Sync(handle, 0);
if ( status ) {
goto loser;
}
@@ -414,7 +415,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
return(SECFailure);
}
- ret = keydb_Seq(handle->db, &key, &data, R_FIRST);
+ ret = keydb_Seq(handle, &key, &data, R_FIRST);
if ( ret ) {
return(SECFailure);
}
@@ -441,7 +442,7 @@ nsslowkey_TraverseKeys(NSSLOWKEYDBHandle *handle,
return(status);
}
}
- } while ( keydb_Seq(handle->db, &key, &data, R_NEXT) == 0 );
+ } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 );
return(SECSuccess);
}
@@ -521,7 +522,7 @@ GetKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
- ret = keydb_Get(handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Get(handle, &saltKey, &saltData, 0);
if ( ret ) {
return(NULL);
}
@@ -543,7 +544,7 @@ StoreKeyDBGlobalSalt(NSSLOWKEYDBHandle *handle)
saltData.size = handle->global_salt->len;
/* put global salt into the database now */
- status = keydb_Put(handle->db, &saltKey, &saltData, 0);
+ status = keydb_Put(handle, &saltKey, &saltData, 0);
if ( status ) {
return(SECFailure);
}
@@ -566,7 +567,7 @@ makeGlobalVersion(NSSLOWKEYDBHandle *handle)
versionKey.size = sizeof(VERSION_STRING)-1;
/* put version string into the database now */
- status = keydb_Put(handle->db, &versionKey, &versionData, 0);
+ status = keydb_Put(handle, &versionKey, &versionData, 0);
if ( status ) {
return(SECFailure);
}
@@ -592,7 +593,7 @@ makeGlobalSalt(NSSLOWKEYDBHandle *handle)
RNG_GenerateGlobalRandomBytes(saltbuf, sizeof(saltbuf));
/* put global salt into the database now */
- status = keydb_Put(handle->db, &saltKey, &saltData, 0);
+ status = keydb_Put(handle, &saltKey, &saltData, 0);
if ( status ) {
return(SECFailure);
}
@@ -623,7 +624,7 @@ encodePWCheckEntry(PLArenaPool *arena, SECItem *entry, SECOidTag alg,
SECItem *encCheck);
static unsigned char
-nsslowkey_version(DB *db)
+nsslowkey_version(NSSLOWKEYDBHandle *handle)
{
DBT versionKey;
DBT versionData;
@@ -631,8 +632,12 @@ nsslowkey_version(DB *db)
versionKey.data = VERSION_STRING;
versionKey.size = sizeof(VERSION_STRING)-1;
+ if (handle->db == NULL) {
+ return 255;
+ }
+
/* lookup version string in database */
- ret = keydb_Get( db, &versionKey, &versionData, 0 );
+ ret = keydb_Get( handle, &versionKey, &versionData, 0 );
/* error accessing the database */
if ( ret < 0 ) {
@@ -646,14 +651,14 @@ nsslowkey_version(DB *db)
}
static PRBool
-seckey_HasAServerKey(DB *db)
+seckey_HasAServerKey(NSSLOWKEYDBHandle *handle)
{
DBT key;
DBT data;
int ret;
PRBool found = PR_FALSE;
- ret = keydb_Seq(db, &key, &data, R_FIRST);
+ ret = keydb_Seq(handle, &key, &data, R_FIRST);
if ( ret ) {
return PR_FALSE;
}
@@ -690,10 +695,14 @@ seckey_HasAServerKey(DB *db)
}
}
- } while ( keydb_Seq(db, &key, &data, R_NEXT) == 0 );
+ } while ( keydb_Seq(handle, &key, &data, R_NEXT) == 0 );
return found;
}
+
+/* forward declare local create function */
+static NSSLOWKEYDBHandle * nsslowkey_NewHandle(DB *dbHandle);
+
/*
* currently updates key database from v2 to v3
*/
@@ -710,18 +719,29 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
unsigned char version;
SECItem *rc4key = NULL;
NSSLOWKEYDBKey *dbkey = NULL;
+ NSSLOWKEYDBHandle *update = NULL;
SECItem *oldSalt = NULL;
int ret;
SECItem checkitem;
if ( handle->updatedb == NULL ) {
- return(SECSuccess);
+ return SECSuccess;
+ }
+
+ /* create a full DB Handle for our update so we
+ * can use the correct locks for the db primatives */
+ update = nsslowkey_NewHandle(handle->updatedb);
+ if ( update == NULL) {
+ return SECSuccess;
}
+ /* update has now inherited the database handle */
+ handle->updatedb = NULL;
+
/*
* check the version record
*/
- version = nsslowkey_version(handle->updatedb);
+ version = nsslowkey_version(update);
if (version != 2) {
goto done;
}
@@ -729,7 +749,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
saltKey.data = SALT_STRING;
saltKey.size = sizeof(SALT_STRING) - 1;
- ret = keydb_Get(handle->updatedb, &saltKey, &saltData, 0);
+ ret = keydb_Get(update, &saltKey, &saltData, 0);
if ( ret ) {
/* no salt in old db, so it is corrupted */
goto done;
@@ -747,8 +767,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
checkKey.data = KEYDB_PW_CHECK_STRING;
checkKey.size = KEYDB_PW_CHECK_LEN;
- ret = keydb_Get(handle->updatedb, &checkKey,
- &checkData, 0 );
+ ret = keydb_Get(update, &checkKey, &checkData, 0 );
if (ret) {
/*
* if we have a key, but no KEYDB_PW_CHECK_STRING, then this must
@@ -756,7 +775,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
* with it. Put a fake entry in so we can identify this db when we do
* get the password for it.
*/
- if (seckey_HasAServerKey(handle->updatedb)) {
+ if (seckey_HasAServerKey(update)) {
DBT fcheckKey;
DBT fcheckData;
@@ -768,11 +787,11 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
fcheckData.data = "1";
fcheckData.size = 1;
/* put global salt into the new database now */
- ret = keydb_Put( handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Put( handle, &saltKey, &saltData, 0);
if ( ret ) {
goto done;
}
- ret = keydb_Put( handle->db, &fcheckKey, &fcheckData, 0);
+ ret = keydb_Put( handle, &fcheckKey, &fcheckData, 0);
if ( ret ) {
goto done;
}
@@ -781,7 +800,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
}
} else {
/* put global salt into the new database now */
- ret = keydb_Put( handle->db, &saltKey, &saltData, 0);
+ ret = keydb_Put( handle, &saltKey, &saltData, 0);
if ( ret ) {
goto done;
}
@@ -811,7 +830,7 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
/* now traverse the database */
- ret = keydb_Seq(handle->updatedb, &key, &data, R_FIRST);
+ ret = keydb_Seq(update, &key, &data, R_FIRST);
if ( ret ) {
goto done;
}
@@ -857,17 +876,15 @@ nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle)
sec_destroy_dbkey(dbkey);
}
- } while ( keydb_Seq(handle->updatedb, &key, &data,
- R_NEXT) == 0 );
+ } while ( keydb_Seq(update, &key, &data, R_NEXT) == 0 );
dbkey = NULL;
done:
/* sync the database */
- ret = keydb_Sync(handle->db, 0);
+ ret = keydb_Sync(handle, 0);
- keydb_Close(handle->updatedb);
- handle->updatedb = NULL;
+ nsslowkey_CloseKeyDB(update);
if ( rc4key ) {
SECITEM_FreeItem(rc4key, PR_TRUE);
@@ -913,7 +930,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
/* force a transactional read, which will verify that one and only one
* process attempts the update. */
- if (nsslowkey_version(handle->db) == NSSLOWKEY_DB_FILE_VERSION) {
+ if (nsslowkey_version(handle) == NSSLOWKEY_DB_FILE_VERSION) {
/* someone else has already updated the database for us */
db_FinishTransaction(handle->db, PR_FALSE);
db_InitComplete(handle->db);
@@ -925,20 +942,35 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
* local database we can update from.
*/
if (appName) {
+ NSSLOWKEYDBHandle *updateHandle = nsslowkey_NewHandle(updatedb);
updatedb = dbopen( dbname, NO_RDONLY, 0600, DB_HASH, 0 );
- if (updatedb) {
- handle->version = nsslowkey_version(updatedb);
- if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
- keydb_Close(updatedb);
- } else {
- db_Copy(handle->db, updatedb);
- keydb_Close(updatedb);
- db_FinishTransaction(handle->db,PR_FALSE);
- db_InitComplete(handle->db);
- return SECSuccess;
- }
+ if (!updatedb) {
+ goto noupdate;
}
+
+ /* nsslowkey_version needs a full handle because it calls
+ * the kdb_Get() function, which needs to lock.
+ */
+ updateHandle = nsslowkey_NewHandle(updatedb);
+ if (!updateHandle) {
+ updatedb->close(updatedb);
+ goto noupdate;
+ }
+
+ handle->version = nsslowkey_version(updateHandle);
+ if (handle->version != NSSLOWKEY_DB_FILE_VERSION) {
+ nsslowkey_CloseKeyDB(updateHandle);
+ goto noupdate;
+ }
+
+ /* copy the new DB from the old one */
+ db_Copy(handle->db, updatedb);
+ nsslowkey_CloseKeyDB(updateHandle);
+ db_FinishTransaction(handle->db,PR_FALSE);
+ db_InitComplete(handle->db);
+ return SECSuccess;
}
+noupdate:
/* update the version number */
rv = makeGlobalVersion(handle);
@@ -978,7 +1010,7 @@ openNewDB(const char *appName, const char *prefix, const char *dbname,
}
/* sync the database */
- ret = keydb_Sync(handle->db, 0);
+ ret = keydb_Sync(handle, 0);
if ( ret ) {
rv = SECFailure;
goto loser;
@@ -994,7 +1026,7 @@ loser:
static DB *
openOldDB(const char *appName, const char *prefix, const char *dbname,
- PRBool openflags, int *version) {
+ PRBool openflags) {
DB *db = NULL;
if (appName) {
@@ -1003,54 +1035,79 @@ openOldDB(const char *appName, const char *prefix, const char *dbname,
db = dbopen( dbname, openflags, 0600, DB_HASH, 0 );
}
- /* check for correct version number */
- if (db != NULL) {
- *version = nsslowkey_version(db);
- if (*version != NSSLOWKEY_DB_FILE_VERSION ) {
- /* bogus version number record, reset the database */
- keydb_Close( db );
- db = NULL;
+ return db;
+}
+
+/* check for correct version number */
+static PRBool
+verifyVersion(NSSLOWKEYDBHandle *handle)
+{
+ int version = nsslowkey_version(handle);
+
+ handle->version = version;
+ if (version != NSSLOWKEY_DB_FILE_VERSION ) {
+ if (handle->db) {
+ keydb_Close(handle);
+ handle->db = NULL;
}
}
- return db;
+ return handle->db != NULL;
}
-NSSLOWKEYDBHandle *
-nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
- NSSLOWKEYDBNameFunc namecb, void *cbarg)
+static NSSLOWKEYDBHandle *
+nsslowkey_NewHandle(DB *dbHandle)
{
NSSLOWKEYDBHandle *handle;
- SECStatus rv;
- int openflags;
- char *dbname = NULL;
-
handle = (NSSLOWKEYDBHandle *)PORT_ZAlloc (sizeof(NSSLOWKEYDBHandle));
if (handle == NULL) {
PORT_SetError (SEC_ERROR_NO_MEMORY);
return NULL;
}
+ handle->appname = NULL;
+ handle->dbname = NULL;
+ handle->global_salt = NULL;
+ handle->updatedb = NULL;
+ handle->db = dbHandle;
+ handle->ref = 1;
+
+ keydb_InitLocks(handle);
+ return handle;
+}
+
+NSSLOWKEYDBHandle *
+nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
+ NSSLOWKEYDBNameFunc namecb, void *cbarg)
+{
+ NSSLOWKEYDBHandle *handle = NULL;
+ SECStatus rv;
+ int openflags;
+ char *dbname = NULL;
+
+
+ handle = nsslowkey_NewHandle(NULL);
+
openflags = readOnly ? NO_RDONLY : NO_RDWR;
+
dbname = (*namecb)(cbarg, NSSLOWKEY_DB_FILE_VERSION);
if ( dbname == NULL ) {
goto loser;
}
-
handle->appname = appName ? PORT_Strdup(appName) : NULL ;
handle->dbname = (appName == NULL) ? PORT_Strdup(dbname) :
(prefix ? PORT_Strdup(prefix) : NULL);
handle->readOnly = readOnly;
- keydb_InitLocks(handle);
- handle->db = openOldDB(appName, prefix, dbname, openflags,
- &handle->version);
- if (handle->version == 255) {
- goto loser;
+ handle->db = openOldDB(appName, prefix, dbname, openflags);
+ if (handle->db) {
+ verifyVersion(handle);
+ if (handle->version == 255) {
+ goto loser;
+ }
}
-
/* if first open fails, try to create a new DB */
if ( handle->db == NULL ) {
@@ -1063,8 +1120,8 @@ nsslowkey_OpenKeyDB(PRBool readOnly, const char *appName, const char *prefix,
* The multiprocess code blocked the second one, then had it retry to
* see if it can just open the database normally */
if (rv == SECWouldBlock) {
- handle->db = openOldDB(appName,prefix,dbname,
- openflags, &handle->version);
+ handle->db = openOldDB(appName,prefix,dbname, openflags);
+ verifyVersion(handle);
if (handle->db == NULL) {
goto loser;
}
@@ -1083,14 +1140,7 @@ loser:
if ( dbname )
PORT_Free( dbname );
PORT_SetError(SEC_ERROR_BAD_DATABASE);
-
- if ( handle->db ) {
- keydb_Close(handle->db);
- }
- if ( handle->updatedb ) {
- keydb_Close(handle->updatedb);
- }
- PORT_Free(handle);
+ nsslowkey_CloseKeyDB(handle);
return NULL;
}
@@ -1102,8 +1152,11 @@ nsslowkey_CloseKeyDB(NSSLOWKEYDBHandle *handle)
{
if (handle != NULL) {
if (handle->db != NULL) {
- keydb_Close(handle->db);
+ keydb_Close(handle);
}
+ if (handle->updatedb) {
+ handle->updatedb->close(handle->updatedb);
+ }
if (handle->dbname) PORT_Free(handle->dbname);
if (handle->appname) PORT_Free(handle->appname);
if (handle->global_salt) {
@@ -1143,14 +1196,14 @@ nsslowkey_DeleteKey(NSSLOWKEYDBHandle *handle, SECItem *pubkey)
namekey.size = pubkey->len;
/* delete it from the database */
- ret = keydb_Del(handle->db, &namekey, 0);
+ ret = keydb_Del(handle, &namekey, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return(SECFailure);
}
/* sync the database */
- ret = keydb_Sync(handle->db, 0);
+ ret = keydb_Sync(handle, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
return(SECFailure);
@@ -1195,7 +1248,7 @@ nsslowkey_KeyForIDExists(NSSLOWKEYDBHandle *handle, SECItem *id)
namekey.data = (char *)id->data;
namekey.size = id->len;
- status = keydb_Get(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle, &namekey, &dummy, 0);
if ( status ) {
return PR_FALSE;
}
@@ -1253,7 +1306,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
namekey.size = sizeof(buf);
}
- status = keydb_Get(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle, &namekey, &dummy, 0);
/* some databases have the key stored as a signed value */
if (status) {
unsigned char *buf = (unsigned char *)PORT_Alloc(namekey.size+1);
@@ -1262,7 +1315,7 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer
buf[0] = 0;
namekey.data = buf;
namekey.size ++;
- status = keydb_Get(handle->db, &namekey, &dummy, 0);
+ status = keydb_Get(handle, &namekey, &dummy, 0);
PORT_Free(buf);
}
}
@@ -1290,12 +1343,12 @@ nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle)
checkkey.data = KEYDB_PW_CHECK_STRING;
checkkey.size = KEYDB_PW_CHECK_LEN;
- ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
+ ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
if ( ret ) {
/* see if this was an updated DB first */
checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
+ ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
if ( ret ) {
return(SECFailure);
}
@@ -2423,7 +2476,7 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem)
if ( dbkey == NULL ) {
checkkey.data = KEYDB_FAKE_PW_CHECK_STRING;
checkkey.size = KEYDB_FAKE_PW_CHECK_LEN;
- ret = keydb_Get(handle->db, &checkkey, &checkdata, 0 );
+ ret = keydb_Get(handle, &checkkey, &checkdata, 0 );
if (ret) {
goto loser;
}
@@ -2568,7 +2621,7 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle,
}
/* delete the old record */
- ret = keydb_Del(handle->db, &node->key, 0);
+ ret = keydb_Del(handle, &node->key, 0);
if ( ret ) {
PORT_SetError(SEC_ERROR_BAD_DATABASE);
rv = SECFailure;
@@ -2685,7 +2738,7 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
return SECFailure;
}
- keydb_Close(handle->db);
+ keydb_Close(handle);
if (handle->appname) {
handle->db=
rdbopen(handle->appname, handle->dbname, "key", NO_CREATE, NULL);
@@ -2717,17 +2770,19 @@ nsslowkey_ResetKeyDB(NSSLOWKEYDBHandle *handle)
done:
/* sync the database */
- ret = keydb_Sync(handle->db, 0);
+ ret = keydb_Sync(handle, 0);
db_InitComplete(handle->db);
return (errors == 0 ? SECSuccess : SECFailure);
}
static int
-keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags)
+keydb_Get(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
{
PRStatus prstat;
int ret;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
@@ -2740,10 +2795,12 @@ keydb_Get(DB *db, DBT *key, DBT *data, unsigned int flags)
}
static int
-keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags)
+keydb_Put(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
{
PRStatus prstat;
int ret = 0;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
@@ -2756,10 +2813,12 @@ keydb_Put(DB *db, DBT *key, DBT *data, unsigned int flags)
}
static int
-keydb_Sync(DB *db, unsigned int flags)
+keydb_Sync(NSSLOWKEYDBHandle *kdb, unsigned int flags)
{
PRStatus prstat;
int ret;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
@@ -2772,10 +2831,12 @@ keydb_Sync(DB *db, unsigned int flags)
}
static int
-keydb_Del(DB *db, DBT *key, unsigned int flags)
+keydb_Del(NSSLOWKEYDBHandle *kdb, DBT *key, unsigned int flags)
{
PRStatus prstat;
int ret;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
@@ -2788,10 +2849,12 @@ keydb_Del(DB *db, DBT *key, unsigned int flags)
}
static int
-keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags)
+keydb_Seq(NSSLOWKEYDBHandle *kdb, DBT *key, DBT *data, unsigned int flags)
{
PRStatus prstat;
int ret;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
@@ -2804,9 +2867,11 @@ keydb_Seq(DB *db, DBT *key, DBT *data, unsigned int flags)
}
static void
-keydb_Close(DB *db)
+keydb_Close(NSSLOWKEYDBHandle *kdb)
{
PRStatus prstat;
+ PRLock *kdbLock = kdb->lock;
+ DB *db = kdb->db;
PORT_Assert(kdbLock != NULL);
PZ_Lock(kdbLock);
diff --git a/security/nss/lib/softoken/keydbi.h b/security/nss/lib/softoken/keydbi.h
index 1c9c2699a..f7f427266 100644
--- a/security/nss/lib/softoken/keydbi.h
+++ b/security/nss/lib/softoken/keydbi.h
@@ -56,6 +56,8 @@ struct NSSLOWKEYDBHandleStr {
char *appname; /* multiaccess app name */
char *dbname; /* name of the openned DB */
PRBool readOnly; /* is the DB read only */
+ PRLock *lock;
+ PRInt32 ref; /* reference count */
};
/*
diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c
index 8d2ff55d0..cb048307d 100644
--- a/security/nss/lib/softoken/lowcert.c
+++ b/security/nss/lib/softoken/lowcert.c
@@ -449,6 +449,7 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, char *nickname)
cert->subjectKeyID.len = 0;
cert->dbEntry = NULL;
cert ->trust = NULL;
+ cert ->dbhandle = NULL;
/* generate and save the database key for the cert */
rv = nsslowcert_KeyFromIssuerAndSNStatic(cert->certKeySpace,
diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn
index cab786a97..52d1f75cd 100644
--- a/security/nss/lib/softoken/manifest.mn
+++ b/security/nss/lib/softoken/manifest.mn
@@ -58,6 +58,7 @@ EXPORTS = \
PRIVATE_EXPORTS = \
pk11pars.h \
+ pkcs11ni.h \
$(NULL)
CSRCS = \
diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c
index e6954f737..4a7706378 100644
--- a/security/nss/lib/softoken/pcertdb.c
+++ b/security/nss/lib/softoken/pcertdb.c
@@ -60,6 +60,7 @@
#include "plhash.h"
#include "cdbhdl.h"
+#include "pkcs11i.h"
/* forward declaration */
NSSLOWCERTCertificate *
@@ -3394,12 +3395,15 @@ AddCertToPermDB(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCertificate *cert,
state = 2;
- cert->dbhandle = handle;
+ /* "Change" handles if necessary */
+ if (cert->dbhandle) {
+ sftk_freeCertDB(cert->dbhandle);
+ }
+ cert->dbhandle = nsslowcert_reference(handle);
/* add to or create new subject entry */
if ( subjectEntry ) {
/* REWRITE BASED ON SUBJECT ENTRY */
- cert->dbhandle = handle;
rv = AddPermSubjectNode(subjectEntry, cert, nickname);
if ( rv != SECSuccess ) {
goto loser;
@@ -4321,7 +4325,7 @@ DecodeACert(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry)
goto loser;
}
- cert->dbhandle = handle;
+ cert->dbhandle = nsslowcert_reference(handle);
cert->dbEntry = entry;
cert->trust = &entry->trust;
@@ -4375,7 +4379,7 @@ DecodeTrustEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryCert *entry,
if (trust == NULL) {
return trust;
}
- trust->dbhandle = handle;
+ trust->dbhandle = nsslowcert_reference(handle);
trust->dbEntry = entry;
trust->dbKey.data = pkcs11_copyStaticData(dbKey->data,dbKey->len,
trust->dbKeySpace, sizeof(trust->dbKeySpace));
@@ -5009,6 +5013,9 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
*/
if ( lockdb && handle ) {
nsslowcert_LockDB(handle);
+ /* keep a reference until we unlock, so handle won't disappear
+ * before we are through with it */
+ nsslowcert_reference(handle);
}
nsslowcert_LockCertRefCount(cert);
@@ -5042,11 +5049,15 @@ DestroyCertificate(NSSLOWCERTCertificate *cert, PRBool lockdb)
certListHead = cert;
}
nsslowcert_UnlockFreeList();
+ if (handle) {
+ sftk_freeCertDB(handle);
+ }
cert = NULL;
}
if ( lockdb && handle ) {
nsslowcert_UnlockDB(handle);
+ sftk_freeCertDB(handle);
}
}
diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c
index edf0d3103..49ae19739 100644
--- a/security/nss/lib/softoken/pk11db.c
+++ b/security/nss/lib/softoken/pk11db.c
@@ -120,9 +120,9 @@ secmod_parseTokens(char *tokenParams, sftk_parameters *parsed)
tokenIndex += next;
tokens[i].slotID = secmod_argDecodeNumber(name);
- tokens[i].readOnly = PR_TRUE;
- tokens[i].noCertDB = PR_TRUE;
- tokens[i].noKeyDB = PR_TRUE;
+ tokens[i].readOnly = PR_FALSE;
+ tokens[i].noCertDB = PR_FALSE;
+ tokens[i].noKeyDB = PR_FALSE;
if (!secmod_argIsBlank(*tokenIndex)) {
char *args = secmod_argFetchValue(tokenIndex,&next);
tokenIndex += next;
diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h
index 6e01b7ffb..7a2b028eb 100644
--- a/security/nss/lib/softoken/pk11pars.h
+++ b/security/nss/lib/softoken/pk11pars.h
@@ -194,14 +194,21 @@ secmod_argFetchValue(char *string, int *pcount)
char *end = secmod_argFindEnd(string);
char *retString, *copyString;
PRBool lastEscape = PR_FALSE;
+ int len;
- *pcount = (end - string)+1;
+ len = end - string;
+ if (len == 0) {
+ *pcount = 0;
+ return NULL;
+ }
- if (*pcount == 0) return NULL;
+ copyString = retString = (char *)PORT_Alloc(len+1);
- copyString = retString = (char *)PORT_Alloc(*pcount);
+ if (*end) len++;
+ *pcount = len;
if (retString == NULL) return NULL;
+
if (secmod_argIsQuote(*string)) string++;
for (; string < end; string++) {
if (secmod_argIsEscape(*string) && !lastEscape) {
diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c
index 22adce5b6..10a7bcfb7 100644
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -55,6 +55,7 @@
#include "secitem.h"
#include "pkcs11.h"
#include "pkcs11i.h"
+#include "pkcs11p.h"
#include "softoken.h"
#include "lowkeyi.h"
#include "blapi.h"
@@ -273,7 +274,7 @@ static const struct mechanismList mechanisms[] = {
{CKM_RSA_PKCS_KEY_PAIR_GEN,{RSA_MIN_MODULUS_BITS,CK_MAX,
CKF_GENERATE_KEY_PAIR},PR_TRUE},
{CKM_RSA_PKCS, {RSA_MIN_MODULUS_BITS,CK_MAX,
- CKF_DUZ_IT_ALL}, PR_TRUE},
+ CKF_DUZ_IT_ALL}, PR_TRUE},
#ifdef SFTK_RSA9796_SUPPORTED
{CKM_RSA_9796, {RSA_MIN_MODULUS_BITS,CK_MAX,
CKF_DUZ_IT_ALL}, PR_TRUE},
@@ -665,8 +666,10 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
char *email = NULL;
SECStatus rv;
PRBool inDB = PR_TRUE;
+ NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot);
+ NSSLOWKEYDBHandle *keyHandle = NULL;
- if (slot->certDB == NULL) {
+ if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
@@ -680,25 +683,31 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
label = sftk_getString(object,CKA_LABEL);
- cert = nsslowcert_FindCertByDERCert(slot->certDB, &derCert);
- if (cert == NULL) {
+ cert = nsslowcert_FindCertByDERCert(certHandle, &derCert);
+ if (cert == NULL) {
cert = nsslowcert_DecodeDERCertificate(&derCert, label);
inDB = PR_FALSE;
}
if (cert == NULL) {
if (label) PORT_Free(label);
sftk_FreeAttribute(attribute);
+ sftk_freeCertDB(certHandle);
return CKR_ATTRIBUTE_VALUE_INVALID;
}
- if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) {
- trust = &userTrust;
+ keyHandle = sftk_getKeyDB(slot);
+ if (keyHandle) {
+ if (nsslowkey_KeyForCertExists(keyHandle,cert)) {
+ trust = &userTrust;
+ }
+ sftk_freeKeyDB(keyHandle);
}
+
if (!inDB) {
if (!trust) trust = &defTrust;
- rv = nsslowcert_AddPermCert(slot->certDB, cert, label, trust);
+ rv = nsslowcert_AddPermCert(certHandle, cert, label, trust);
} else {
- rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) :
+ rv = trust ? nsslowcert_ChangeCertTrust(certHandle,cert,trust) :
SECSuccess;
}
@@ -706,6 +715,7 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
sftk_FreeAttribute(attribute);
if (rv != SECSuccess) {
+ sftk_freeCertDB(certHandle);
nsslowcert_DestroyCertificate(cert);
return CKR_DEVICE_ERROR;
}
@@ -717,15 +727,16 @@ sftk_handleCertObject(SFTKSession *session,SFTKObject *object)
if (email) {
certDBEntrySMime *entry;
- entry = nsslowcert_ReadDBSMimeEntry(slot->certDB,email);
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle,email);
if (!entry) {
- nsslowcert_SaveSMimeProfile(slot->certDB, email,
+ nsslowcert_SaveSMimeProfile(certHandle, email,
&cert->derSubject, NULL, NULL);
} else {
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(email);
}
+ sftk_freeCertDB(certHandle);
object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_CERT);
nsslowcert_DestroyCertificate(cert);
}
@@ -798,11 +809,12 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
CK_BBOOL stepUp;
NSSLOWCERTCertTrust dbTrust = { 0 };
SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle = sftk_getCertDB(slot);
-
- if (slot->certDB == NULL) {
+ if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
+
issuer = sftk_FindAttribute(object,CKA_ISSUER);
PORT_Assert(issuer);
issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue;
@@ -813,11 +825,12 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue;
issuerSN.serialNumber.len = serial->attrib.ulValueLen ;
- cert = nsslowcert_FindCertByIssuerAndSN(slot->certDB,&issuerSN);
+ cert = nsslowcert_FindCertByIssuerAndSN(certHandle,&issuerSN);
sftk_FreeAttribute(serial);
sftk_FreeAttribute(issuer);
if (cert == NULL) {
+ sftk_freeCertDB(certHandle);
return CKR_ATTRIBUTE_VALUE_INVALID;
}
@@ -879,9 +892,10 @@ sftk_handleTrustObject(SFTKSession *session,SFTKObject *object)
dbTrust.sslFlags |= CERTDB_GOVT_APPROVED_CA;
}
- rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&dbTrust);
+ rv = nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);
object->handle=sftk_mkHandle(slot,&cert->certKey,SFTK_TOKEN_TYPE_TRUST);
nsslowcert_DestroyCertificate(cert);
+ sftk_freeCertDB(certHandle);
if (rv != SECSuccess) {
return CKR_DEVICE_ERROR;
}
@@ -918,9 +932,12 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object)
char *email = NULL;
SFTKAttribute *subject,*profile,*time;
SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle;
PORT_Assert(slot);
- if (slot->certDB == NULL) {
+ certHandle = sftk_getCertDB(slot);
+
+ if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
@@ -953,9 +970,9 @@ sftk_handleSMimeObject(SFTKSession *session,SFTKObject *object)
email = sftk_getString(object,CKA_NETSCAPE_EMAIL);
/* Store CRL by SUBJECT */
- rv = nsslowcert_SaveSMimeProfile(slot->certDB, email, &derSubj,
+ rv = nsslowcert_SaveSMimeProfile(certHandle, email, &derSubj,
pRawProfile,pRawTime);
-
+ sftk_freeCertDB(certHandle);
sftk_FreeAttribute(subject);
if (profile) sftk_FreeAttribute(profile);
if (time) sftk_FreeAttribute(time);
@@ -1000,9 +1017,12 @@ sftk_handleCrlObject(SFTKSession *session,SFTKObject *object)
char *url = NULL;
SFTKAttribute *subject,*crl;
SECStatus rv;
+ NSSLOWCERTCertDBHandle *certHandle;
PORT_Assert(slot);
- if (slot->certDB == NULL) {
+ certHandle = sftk_getCertDB(slot);
+
+ if (certHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
@@ -1023,7 +1043,8 @@ sftk_handleCrlObject(SFTKSession *session,SFTKObject *object)
isKRL = sftk_isTrue(object,CKA_NETSCAPE_KRL);
/* Store CRL by SUBJECT */
- rv = nsslowcert_AddCrl(slot->certDB, &derCrl, &derSubj, url, isKRL);
+ rv = nsslowcert_AddCrl(certHandle, &derCrl, &derSubj, url, isKRL);
+ sftk_freeCertDB(certHandle);
if (url) {
PORT_Free(url);
@@ -1162,16 +1183,18 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
SFTKSlot *slot = session->slot;
NSSLOWKEYPrivateKey *priv;
SECItem pubKey;
+ NSSLOWKEYDBHandle *keyHandle = NULL;
crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr);
if (crv != CKR_OK) return crv;
PORT_Assert(pubKey.data);
- if (slot->keyDB == NULL) {
+ keyHandle = sftk_getKeyDB(slot);
+ if (keyHandle == NULL) {
PORT_Free(pubKey.data);
return CKR_TOKEN_WRITE_PROTECTED;
}
- if (slot->keyDB->version != 3) {
+ if (keyHandle->version != 3) {
unsigned char buf[SHA1_LENGTH];
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
@@ -1179,11 +1202,11 @@ sftk_handlePublicKeyObject(SFTKSession *session, SFTKObject *object,
}
/* make sure the associated private key already exists */
/* only works if we are logged in */
- priv = nsslowkey_FindKeyByPublicKey(slot->keyDB, &pubKey,
- slot->password);
+ priv = nsslowkey_FindKeyByPublicKey(keyHandle, &pubKey, slot->password);
+ sftk_freeKeyDB(keyHandle);
if (priv == NULL) {
PORT_Free(pubKey.data);
- return CKR_ATTRIBUTE_VALUE_INVALID;
+ return crv;
}
nsslowkey_DestroyPrivateKey(priv);
@@ -1321,9 +1344,11 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
NSSLOWKEYPrivateKey *privKey;
char *label;
SECStatus rv = SECSuccess;
+ CK_RV crv = CKR_DEVICE_ERROR;
SECItem pubKey;
+ NSSLOWKEYDBHandle *keyHandle = sftk_getKeyDB(slot);
- if (slot->keyDB == NULL) {
+ if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
@@ -1333,11 +1358,11 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
crv = sftk_Attribute2SSecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB);
if (crv != CKR_OK) {
- if (label) PORT_Free(label);
- nsslowkey_DestroyPrivateKey(privKey);
- return CKR_TEMPLATE_INCOMPLETE;
+ crv = CKR_TEMPLATE_INCOMPLETE;
+ rv = SECFailure;
+ goto fail;
}
- if (slot->keyDB->version != 3) {
+ if (keyHandle->version != 3) {
unsigned char buf[SHA1_LENGTH];
SHA1_HashBuf(buf,pubKey.data,pubKey.len);
PORT_Memcpy(pubKey.data,buf,sizeof(buf));
@@ -1350,15 +1375,16 @@ sftk_handlePrivateKeyObject(SFTKSession *session,SFTKObject *object,CK_KEY_TYPE
goto fail;
}
}
- rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB,
- privKey, &pubKey, label, object->slot->password);
+ rv = nsslowkey_StoreKeyByPublicKey(keyHandle, privKey, &pubKey,
+ label, slot->password);
fail:
+ sftk_freeKeyDB(keyHandle);
if (label) PORT_Free(label);
object->handle = sftk_mkHandle(slot,&pubKey,SFTK_TOKEN_TYPE_PRIV);
if (pubKey.data) PORT_Free(pubKey.data);
nsslowkey_DestroyPrivateKey(privKey);
- if (rv != SECSuccess) return CKR_DEVICE_ERROR;
+ if (rv != SECSuccess) return crv;
} else {
object->objectInfo = sftk_mkPrivKey(object,key_type,&crv);
if (object->objectInfo == NULL) return crv;
@@ -1522,7 +1548,8 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
CK_KEY_TYPE key_type, PRBool isFIPS)
{
CK_RV crv;
- NSSLOWKEYPrivateKey *privKey = NULL;
+ NSSLOWKEYPrivateKey *privKey = NULL;
+ NSSLOWKEYDBHandle *keyHandle = NULL;
SECItem pubKey;
char *label = NULL;
@@ -1536,8 +1563,9 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
if (sftk_isTrue(object,CKA_TOKEN)) {
SFTKSlot *slot = session->slot;
SECStatus rv = SECSuccess;
+ keyHandle = sftk_getKeyDB(slot);
- if (slot->keyDB == NULL) {
+ if (keyHandle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
@@ -1553,21 +1581,20 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
PORT_Free(pubKey.data);
pubKey.data = NULL;
}
- crv = sftk_GenerateSecretCKA_ID(slot->keyDB, &pubKey, label);
+ crv = sftk_GenerateSecretCKA_ID(keyHandle, &pubKey, label);
if (crv != CKR_OK) goto loser;
crv = sftk_forceAttribute(object, CKA_ID, pubKey.data, pubKey.len);
if (crv != CKR_OK) goto loser;
}
- privKey=sftk_mkSecretKeyRep(object);
+ privKey = sftk_mkSecretKeyRep(object);
if (privKey == NULL) {
crv = CKR_HOST_MEMORY;
goto loser;
}
- PORT_Assert(slot->keyDB);
- rv = nsslowkey_StoreKeyByPublicKey(slot->keyDB,
+ rv = nsslowkey_StoreKeyByPublicKey(keyHandle,
privKey, &pubKey, label, slot->password);
if (rv != SECSuccess) {
crv = CKR_DEVICE_ERROR;
@@ -1578,6 +1605,7 @@ sftk_handleSecretKeyObject(SFTKSession *session,SFTKObject *object,
}
loser:
+ if (keyHandle) sftk_freeKeyDB(keyHandle);
if (label) PORT_Free(label);
if (privKey) nsslowkey_DestroyPrivateKey(privKey);
if (pubKey.data) PORT_Free(pubKey.data);
@@ -2095,10 +2123,8 @@ sftk_GetPrivKey(SFTKObject *object,CK_KEY_TYPE key_type, CK_RV *crvp)
SFTKTokenObject *to = sftk_narrowToTokenObject(object);
PORT_Assert(to);
- PORT_Assert(object->slot->keyDB);
- priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey,
- object->slot->password);
- *crvp = priv ? CKR_OK : CKR_DEVICE_ERROR;
+ priv = sftk_FindKeyByPublicKey(object->slot, &to->dbKey);
+ *crvp = (priv == NULL) ? CKR_DEVICE_ERROR : CKR_OK;
} else {
priv = sftk_mkPrivKey(object, key_type, crvp);
}
@@ -2347,7 +2373,7 @@ static PLHashTable *nscSlotHashTable[2] = {NULL, NULL};
static int
sftk_GetModuleIndex(CK_SLOT_ID slotID)
{
- if ((slotID == FIPS_SLOT_ID) || (slotID > 100)) {
+ if ((slotID == FIPS_SLOT_ID) || (slotID >= SFTK_MIN_FIPS_USER_SLOT_ID)) {
return NSC_FIPS_MODULE;
}
return NSC_NON_FIPS_MODULE;
@@ -2355,12 +2381,18 @@ sftk_GetModuleIndex(CK_SLOT_ID slotID)
/* look up a slot structure from the ID (used to be a macro when we only
* had two slots) */
+/* if all is true, return the slot even if it has been 'unloaded' */
+/* if all is false, only return the slots which are present */
SFTKSlot *
-sftk_SlotFromID(CK_SLOT_ID slotID)
+sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all)
{
+ SFTKSlot *slot;
int index = sftk_GetModuleIndex(slotID);
- return (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index],
+ slot = (SFTKSlot *)PL_HashTableLookupConst(nscSlotHashTable[index],
(void *)slotID);
+ /* cleared slots shouldn't 'show up' */
+ if (slot && !all && !slot->present) slot = NULL;
+ return slot;
}
SFTKSlot *
@@ -2373,7 +2405,7 @@ sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle)
return NULL;
}
- return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex]);
+ return sftk_SlotFromID(nscSlotList[moduleIndex][slotIDIndex], PR_FALSE);
}
static CK_RV
@@ -2428,13 +2460,19 @@ sftk_RegisterSlot(SFTKSlot *slot, int moduleIndex)
return CKR_OK;
}
+typedef struct sftk_DBsStr {
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWKEYDBHandle *keyHandle;
+} sftkDBs;
+
static SECStatus
sftk_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg)
{
- SFTKSlot *slot = (SFTKSlot *)arg;
+ sftkDBs *param = (sftkDBs *)arg;
NSSLOWCERTCertTrust trust = *cert->trust;
- if (nsslowkey_KeyForCertExists(slot->keyDB,cert)) {
+ if (param->keyHandle &&
+ nsslowkey_KeyForCertExists(param->keyHandle,cert)) {
trust.sslFlags |= CERTDB_USER;
trust.emailFlags |= CERTDB_USER;
trust.objectSigningFlags |= CERTDB_USER;
@@ -2445,26 +2483,120 @@ sftk_set_user(NSSLOWCERTCertificate *cert, SECItem *dummy, void *arg)
}
if (PORT_Memcmp(&trust,cert->trust, sizeof (trust)) != 0) {
- nsslowcert_ChangeCertTrust(slot->certDB,cert, &trust);
+ nsslowcert_ChangeCertTrust(param->certHandle, cert, &trust);
}
/* should check for email address and make sure we have an s/mime profile */
return SECSuccess;
}
+/*
+ * this function fixes up old databases that may not have the CERTDB_USER
+ * flags set correctly. it expects the owner already has references to
+ * the cert and key handles.
+ */
static void
-sftk_DBVerify(SFTKSlot *slot)
+sftk_DBVerify(NSSLOWCERTCertDBHandle *certHandle, NSSLOWKEYDBHandle *keyHandle)
{
/* walk through all the certs and check to see if there are any
* user certs, and make sure there are s/mime profiles for all certs with
* email addresses */
- nsslowcert_TraversePermCerts(slot->certDB,sftk_set_user,slot);
+ sftkDBs param;
+ param.certHandle = certHandle;
+ param.keyHandle = keyHandle;
+
+ nsslowcert_TraversePermCerts(certHandle, sftk_set_user, &param);
return;
}
-/* forward static declaration. */
-static CK_RV sftk_DestroySlotData(SFTKSlot *slot);
+
+/*
+ * ths function has all the common initialization that happens whenever we
+ * create a new slot or repurpose an old slot (only valid for slotID's 4
+ * and greater).
+ *
+ * things that are not reinitialized are:
+ * slotID (can't change)
+ * slotDescription (can't change once defined)
+ * the locks and hash tables (difficult to change in running code, and
+ * unnecessary. hash tables and list are cleared on shutdown, but they
+ * are cleared in a 'friendly' way).
+ * session and object ID counters -- so any old sessions and objects in the
+ * application will get properly notified that the world has changed.
+ *
+ * things that are reinitialized:
+ * database (otherwise what would the point be;).
+ * state variables related to databases.
+ * session count stat info.
+ * tokenDescription.
+ *
+ * NOTE: slotID's 4 and greater show up as removable devices.
+ *
+ */
+CK_RV
+SFTK_SlotReInit(SFTKSlot *slot,
+ char *configdir,sftk_token_parameters *params, int moduleIndex)
+{
+ PRBool needLogin = !params->noKeyDB;
+ CK_RV crv;
+
+ slot->hasTokens = PR_FALSE;
+ slot->sessionIDConflict = 0;
+ slot->sessionCount = 0;
+ slot->rwSessionCount = 0;
+ slot->needLogin = PR_FALSE;
+ slot->isLoggedIn = PR_FALSE;
+ slot->ssoLoggedIn = PR_FALSE;
+ slot->DB_loaded = PR_FALSE;
+ slot->certDB = NULL;
+ slot->keyDB = NULL;
+ slot->minimumPinLen = 0;
+ slot->readOnly = params->readOnly;
+ sftk_setStringName(params->tokdes ? params->tokdes :
+ sftk_getDefTokName(slot->slotID), slot->tokDescription,
+ sizeof(slot->tokDescription));
+
+ if ((!params->noCertDB) || (!params->noKeyDB)) {
+ NSSLOWCERTCertDBHandle * certHandle = NULL;
+ NSSLOWKEYDBHandle *keyHandle = NULL;
+ crv = sftk_DBInit(params->configdir ? params->configdir : configdir,
+ params->certPrefix, params->keyPrefix, params->readOnly,
+ params->noCertDB, params->noKeyDB, params->forceOpen,
+ &certHandle, &keyHandle);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ if (nsslowcert_needDBVerify(certHandle)) {
+ sftk_DBVerify(certHandle, keyHandle);
+ }
+ slot->certDB = certHandle;
+ slot->keyDB = keyHandle;
+ }
+ if (needLogin) {
+ /* if the data base is initialized with a null password,remember that */
+ slot->needLogin =
+ (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password);
+ if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) {
+ slot->minimumPinLen = params->minPW;
+ }
+ if ((slot->minimumPinLen == 0) && (params->pwRequired)) {
+ slot->minimumPinLen = 1;
+ }
+ if ((moduleIndex == NSC_FIPS_MODULE) &&
+ (slot->minimumPinLen < FIPS_MIN_PIN)) {
+ slot->minimumPinLen = FIPS_MIN_PIN;
+ }
+ }
+
+ slot->present = PR_TRUE;
+ return CKR_OK;
+
+loser:
+ SFTK_ShutdownSlot(slot);
+ return crv;
+}
/*
* initialize one of the slot structures. figure out which by the ID
@@ -2474,9 +2606,15 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
{
unsigned int i;
CK_SLOT_ID slotID = params->slotID;
- SFTKSlot *slot = PORT_ZNew(SFTKSlot);
- PRBool needLogin = !params->noKeyDB;
- CK_RV crv;
+ SFTKSlot *slot;
+ CK_RV crv = CKR_HOST_MEMORY;
+
+ /*
+ * first we initialize everything that is 'permanent' with this slot.
+ * that is everything we aren't going to shutdown if we close this slot
+ * and open it up again with different databases */
+
+ slot = PORT_ZNew(SFTKSlot);
if (slot == NULL) {
return CKR_HOST_MEMORY;
@@ -2522,56 +2660,18 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
if (slot->tokenHashTable == NULL)
goto mem_loser;
- slot->password = NULL;
- slot->hasTokens = PR_FALSE;
slot->sessionIDCount = 0;
- slot->sessionIDConflict = 0;
- slot->sessionCount = 0;
- slot->rwSessionCount = 0;
slot->tokenIDCount = 1;
- slot->needLogin = PR_FALSE;
- slot->isLoggedIn = PR_FALSE;
- slot->ssoLoggedIn = PR_FALSE;
- slot->DB_loaded = PR_FALSE;
slot->slotID = slotID;
- slot->certDB = NULL;
- slot->keyDB = NULL;
- slot->minimumPinLen = 0;
- slot->readOnly = params->readOnly;
- sftk_setStringName(params->tokdes ? params->tokdes :
- sftk_getDefTokName(slotID), slot->tokDescription,
- sizeof(slot->tokDescription));
sftk_setStringName(params->slotdes ? params->slotdes :
- sftk_getDefSlotName(slotID), slot->slotDescription,
+ sftk_getDefSlotName(slotID), slot->slotDescription,
sizeof(slot->slotDescription));
- if ((!params->noCertDB) || (!params->noKeyDB)) {
- crv = sftk_DBInit(params->configdir ? params->configdir : configdir,
- params->certPrefix, params->keyPrefix, params->readOnly,
- params->noCertDB, params->noKeyDB, params->forceOpen,
- &slot->certDB, &slot->keyDB);
- if (crv != CKR_OK) {
- goto loser;
- }
-
- if (nsslowcert_needDBVerify(slot->certDB)) {
- sftk_DBVerify(slot);
- }
- }
- if (needLogin) {
- /* if the data base is initialized with a null password,remember that */
- slot->needLogin =
- (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password);
- if ((params->minPW >= 0) && (params->minPW <= SFTK_MAX_PIN)) {
- slot->minimumPinLen = params->minPW;
- }
- if ((slot->minimumPinLen == 0) && (params->pwRequired)) {
- slot->minimumPinLen = 1;
- }
- if ((moduleIndex == NSC_FIPS_MODULE) &&
- (slot->minimumPinLen < FIPS_MIN_PIN)) {
- slot->minimumPinLen = FIPS_MIN_PIN;
- }
+ /* call the reinit code to set everything that changes between token
+ * init calls */
+ crv = SFTK_SlotReInit(slot, configdir, params, moduleIndex);
+ if (crv != CKR_OK) {
+ goto loser;
}
crv = sftk_RegisterSlot(slot, moduleIndex);
if (crv != CKR_OK) {
@@ -2582,27 +2682,145 @@ SFTK_SlotInit(char *configdir,sftk_token_parameters *params, int moduleIndex)
mem_loser:
crv = CKR_HOST_MEMORY;
loser:
- sftk_DestroySlotData(slot);
+ SFTK_DestroySlotData(slot);
return crv;
}
-static PRIntn
-sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
+
+static CK_RV sft_CloseAllSession(SFTKSlot *slot)
{
- SECItem *item = (SECItem *)entry->value;
+ SECItem *pw = NULL;
+ SFTKSession *session;
+ unsigned int i;
+ /* first log out the card */
+ PZ_Lock(slot->slotLock);
+ pw = slot->password;
+ slot->isLoggedIn = PR_FALSE;
+ slot->password = NULL;
+ PZ_Unlock(slot->slotLock);
+ if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
- SECITEM_FreeItem(item, PR_TRUE);
- return HT_ENUMERATE_NEXT;
+ /* now close all the current sessions */
+ /* NOTE: If you try to open new sessions before NSC_CloseAllSessions
+ * completes, some of those new sessions may or may not be closed by
+ * NSC_CloseAllSessions... but any session running when this code starts
+ * will guarrenteed be close, and no session will be partially closed */
+ for (i=0; i < slot->sessHashSize; i++) {
+ PZLock *lock = SFTK_SESSION_LOCK(slot,i);
+ do {
+ PZ_Lock(lock);
+ session = slot->head[i];
+ /* hand deque */
+ /* this duplicates function of NSC_close session functions, but
+ * because we know that we are freeing all the sessions, we can
+ * do more efficient processing */
+ if (session) {
+ slot->head[i] = session->next;
+ if (session->next) session->next->prev = NULL;
+ session->next = session->prev = NULL;
+ PZ_Unlock(lock);
+ PZ_Lock(slot->slotLock);
+ --slot->sessionCount;
+ PZ_Unlock(slot->slotLock);
+ if (session->info.flags & CKF_RW_SESSION) {
+ PR_AtomicDecrement(&slot->rwSessionCount);
+ }
+ } else {
+ PZ_Unlock(lock);
+ }
+ if (session) sftk_FreeSession(session);
+ } while (session != NULL);
+ }
+ return CKR_OK;
+}
+
+/*
+ * shut down the databases.
+ * we get the slot lock (which also protects slot->certDB and slot->keyDB)
+ * and clear the values so the new users will not find the databases.
+ * once things are clear, we can release our references to the databases.
+ * The databases will close when the last reference is released.
+ *
+ * We use reference counts so that we don't crash if someone shuts down
+ * a token that another thread is actively using.
+ */
+static void
+sftk_DBShutdown(SFTKSlot *slot)
+{
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWKEYDBHandle *keyHandle;
+ PZ_Lock(slot->slotLock);
+ certHandle = slot->certDB;
+ slot->certDB = NULL;
+ keyHandle = slot->keyDB;
+ slot->keyDB = NULL;
+ PZ_Unlock(slot->slotLock);
+ if (certHandle) {
+ sftk_freeCertDB(certHandle);
+ }
+ if (keyHandle) {
+ sftk_freeKeyDB(keyHandle);
+ }
+}
+
+CK_RV
+SFTK_ShutdownSlot(SFTKSlot *slot)
+{
+ /* make sure no new PK11 calls work except C_GetSlotInfo */
+ slot->present = PR_FALSE;
+
+ /* close all outstanding sessions
+ * the sessHashSize variable guarentees we have all the session
+ * mechanism set up */
+ if (slot->head) {
+ sft_CloseAllSession(slot);
+ }
+
+ /* clear all objects.. session objects are cleared as a result of
+ * closing all the sessions. We just need to clear the token object
+ * cache. slot->tokenHashTable guarentees we have the token
+ * infrastructure set up. */
+ if (slot->tokenHashTable) {
+ SFTK_ClearTokenKeyHashTable(slot);
+ }
+
+ /* clear the slot description for the next guy */
+ PORT_Memset(slot->tokDescription, 0, sizeof(slot->tokDescription));
+
+ /* now shut down the databases. */
+ sftk_DBShutdown(slot);
+ return CKR_OK;
}
/*
* initialize one of the slot structures. figure out which by the ID
*/
-static CK_RV
-sftk_DestroySlotData(SFTKSlot *slot)
+CK_RV
+SFTK_DestroySlotData(SFTKSlot *slot)
{
unsigned int i;
+ SFTK_ShutdownSlot(slot);
+
+ if (slot->tokenHashTable) {
+ PL_HashTableDestroy(slot->tokenHashTable);
+ slot->tokenHashTable = NULL;
+ }
+
+ if (slot->tokObjects) {
+ PORT_Free(slot->tokObjects);
+ slot->tokObjects = NULL;
+ }
+ slot->tokObjHashSize = 0;
+
+ if (slot->head) {
+ PORT_Free(slot->head);
+ slot->head = NULL;
+ }
+ slot->sessHashSize = 0;
+
+ /* OK everything has been disassembled, now we can finally get rid
+ * of the locks */
if (slot->slotLock) {
PZ_DestroyLock(slot->slotLock);
slot->slotLock = NULL;
@@ -2625,36 +2843,6 @@ sftk_DestroySlotData(SFTKSlot *slot)
PR_DestroyLock(slot->pwCheckLock);
slot->pwCheckLock = NULL;
}
-
- if (slot->tokenHashTable) {
- PL_HashTableEnumerateEntries(slot->tokenHashTable,
- sftk_freeHashItem,NULL);
- PL_HashTableDestroy(slot->tokenHashTable);
- slot->tokenHashTable = NULL;
- }
-
- if (slot->tokObjects) {
- for(i=0; i < slot->tokObjHashSize; i++) {
- SFTKObject *object = slot->tokObjects[i];
- slot->tokObjects[i] = NULL;
- if (object) sftk_FreeObject(object);
- }
- PORT_Free(slot->tokObjects);
- slot->tokObjects = NULL;
- }
- slot->tokObjHashSize = 0;
- if (slot->head) {
- for(i=0; i < slot->sessHashSize; i++) {
- SFTKSession *session = slot->head[i];
- slot->head[i] = NULL;
- if (session) sftk_FreeSession(session);
- }
- PORT_Free(slot->head);
- slot->head = NULL;
- }
- slot->sessHashSize = 0;
- sftk_DBShutdown(slot->certDB,slot->keyDB);
-
PORT_Free(slot);
return CKR_OK;
}
@@ -2727,7 +2915,7 @@ static void nscFreeAllSlots(int moduleIndex)
PL_HashTableLookup(tmpSlotHashTable, (void *)slotID);
PORT_Assert(slot);
if (!slot) continue;
- sftk_DestroySlotData(slot);
+ SFTK_DestroySlotData(slot);
PL_HashTableRemove(tmpSlotHashTable, (void *)slotID);
}
PORT_Free(tmpSlotList);
@@ -2747,9 +2935,7 @@ sftk_closePeer(PRBool isFIPS)
if (slot == NULL) {
return;
}
- sftk_DBShutdown(slot->certDB,slot->keyDB);
- slot->certDB = NULL;
- slot->keyDB = NULL;
+ sftk_DBShutdown(slot);
return;
}
@@ -2839,8 +3025,8 @@ CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS)
}
for (i=0; i < paramStrings.token_count; i++) {
- crv =
- SFTK_SlotInit(paramStrings.configdir, &paramStrings.tokens[i],
+ crv = SFTK_SlotInit(paramStrings.configdir,
+ &paramStrings.tokens[i],
moduleIndex);
if (crv != CKR_OK) {
nscFreeAllSlots(moduleIndex);
@@ -2972,7 +3158,7 @@ CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent,
/* NSC_GetSlotInfo obtains information about a particular slot in the system. */
CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
{
- SFTKSlot *slot = sftk_SlotFromID(slotID);
+ SFTKSlot *slot = sftk_SlotFromID(slotID, PR_TRUE);
if (slot == NULL) return CKR_SLOT_ID_INVALID;
pInfo->firmwareVersion.major = 0;
@@ -2980,7 +3166,11 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32);
PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64);
- pInfo->flags = CKF_TOKEN_PRESENT;
+ pInfo->flags = (slot->present) ? CKF_TOKEN_PRESENT : 0;
+ /* all user defined slots are defined as removable */
+ if (slotID >= SFTK_MIN_USER_SLOT_ID) {
+ pInfo->flags |= CKF_REMOVABLE_DEVICE;
+ }
/* ok we really should read it out of the keydb file. */
/* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */
pInfo->hardwareVersion.major = NSS_VMAJOR;
@@ -2994,11 +3184,12 @@ CK_RV NSC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
* been changed underneath us.
*/
static PRBool
-sftk_checkNeedLogin(SFTKSlot *slot)
+sftk_checkNeedLogin(SFTKSlot *slot, NSSLOWKEYDBHandle *keyHandle)
{
if (slot->password) {
- if (nsslowkey_CheckKeyDBPassword(slot->keyDB,slot->password)
- == SECSuccess) {
+ SECStatus rv;
+ rv = nsslowkey_CheckKeyDBPassword(keyHandle,slot->password);
+ if ( rv == SECSuccess) {
return slot->needLogin;
} else {
SECITEM_FreeItem(slot->password, PR_TRUE);
@@ -3007,7 +3198,7 @@ sftk_checkNeedLogin(SFTKSlot *slot)
}
}
slot->needLogin =
- (PRBool)!sftk_hasNullPassword(slot->keyDB,&slot->password);
+ (PRBool)!sftk_hasNullPassword(keyHandle,&slot->password);
return (slot->needLogin);
}
@@ -3015,7 +3206,7 @@ sftk_checkNeedLogin(SFTKSlot *slot)
* the system. */
CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
{
- SFTKSlot *slot = sftk_SlotFromID(slotID);
+ SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
NSSLOWKEYDBHandle *handle;
if (slot == NULL) return CKR_SLOT_ID_INVALID;
@@ -3030,7 +3221,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->firmwareVersion.major = 0;
pInfo->firmwareVersion.minor = 0;
PORT_Memcpy(pInfo->label,slot->tokDescription,32);
- handle = slot->keyDB;
+ handle = sftk_getKeyDB(slot);
if (handle == NULL) {
pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE;
pInfo->ulMaxPinLen = 0;
@@ -3053,7 +3244,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
*/
if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
pInfo->flags = CKF_THREAD_SAFE | CKF_LOGIN_REQUIRED;
- } else if (!sftk_checkNeedLogin(slot)) {
+ } else if (!sftk_checkNeedLogin(slot,handle)) {
pInfo->flags = CKF_THREAD_SAFE | CKF_USER_PIN_INITIALIZED;
} else {
pInfo->flags = CKF_THREAD_SAFE |
@@ -3067,6 +3258,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)
pInfo->ulFreePrivateMemory = 1;
pInfo->hardwareVersion.major = CERT_DB_FILE_VERSION;
pInfo->hardwareVersion.minor = handle->version;
+ sftk_freeKeyDB(handle);
}
return CKR_OK;
}
@@ -3181,7 +3373,7 @@ sftk_TurnOffUser(NSSLOWCERTCertificate *cert, SECItem *k, void *arg)
/* NSC_InitToken initializes a token. */
CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_ULONG ulPinLen,CK_CHAR_PTR pLabel) {
- SFTKSlot *slot = sftk_SlotFromID(slotID);
+ SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
NSSLOWKEYDBHandle *handle;
NSSLOWCERTCertDBHandle *certHandle;
SECStatus rv;
@@ -3220,19 +3412,23 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
PZ_Unlock(slot->objectLock);
/* then clear out the key database */
- handle = slot->keyDB;
+ handle = sftk_getKeyDB(slot);
if (handle == NULL) {
return CKR_TOKEN_WRITE_PROTECTED;
}
- /* what to do on an error here? */
rv = nsslowkey_ResetKeyDB(handle);
+ sftk_freeKeyDB(handle);
+ if (rv != SECSuccess) {
+ return CKR_DEVICE_ERROR;
+ }
/* finally mark all the user certs as non-user certs */
- certHandle = slot->certDB;
+ certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) return CKR_OK;
nsslowcert_TraversePermCerts(certHandle,sftk_TurnOffUser, NULL);
+ sftk_freeCertDB(certHandle);
return CKR_OK; /*is this the right function for not implemented*/
}
@@ -3242,49 +3438,53 @@ CK_RV NSC_InitToken(CK_SLOT_ID slotID,CK_CHAR_PTR pPin,
CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
{
- SFTKSession *sp;
+ SFTKSession *sp = NULL;
SFTKSlot *slot;
- NSSLOWKEYDBHandle *handle;
+ NSSLOWKEYDBHandle *handle = NULL;
SECItem *newPin;
char newPinStr[SFTK_MAX_PIN+1];
SECStatus rv;
+ CK_RV crv = CKR_SESSION_HANDLE_INVALID;
sp = sftk_SessionFromHandle(hSession);
if (sp == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
+ goto loser;
}
slot = sftk_SlotFromSession(sp);
if (slot == NULL) {
- sftk_FreeSession(sp);
- return CKR_SESSION_HANDLE_INVALID;;
+ goto loser;
}
- handle = slot->keyDB;
+ handle = sftk_getKeyDB(slot);
if (handle == NULL) {
- sftk_FreeSession(sp);
- return CKR_PIN_LEN_RANGE;
+ crv = CKR_PIN_LEN_RANGE;
+ goto loser;
}
if (sp->info.state != CKS_RW_SO_FUNCTIONS) {
- sftk_FreeSession(sp);
- return CKR_USER_NOT_LOGGED_IN;
+ crv = CKR_USER_NOT_LOGGED_IN;
+ goto loser;
}
sftk_FreeSession(sp);
+ sp = NULL;
/* make sure the pins aren't too long */
if (ulPinLen > SFTK_MAX_PIN) {
- return CKR_PIN_LEN_RANGE;
+ crv = CKR_PIN_LEN_RANGE;
+ goto loser;
}
if (ulPinLen < (CK_ULONG)slot->minimumPinLen) {
- return CKR_PIN_LEN_RANGE;
+ crv = CKR_PIN_LEN_RANGE;
+ goto loser;
}
if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) {
- return CKR_DEVICE_ERROR;
+ crv = CKR_DEVICE_ERROR;
+ goto loser;
}
/* convert to null terminated string */
@@ -3297,6 +3497,8 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
/* change the data base */
rv = nsslowkey_SetKeyDBPassword(handle,newPin);
+ sftk_freeKeyDB(handle);
+ handle = NULL;
/* Now update our local copy of the pin */
if (rv == SECSuccess) {
@@ -3308,7 +3510,16 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
return CKR_OK;
}
SECITEM_ZfreeItem(newPin, PR_TRUE);
- return CKR_PIN_INCORRECT;
+ crv = CKR_PIN_INCORRECT;
+
+loser:
+ if (sp) {
+ sftk_FreeSession(sp);
+ }
+ if (handle) {
+ sftk_freeKeyDB(handle);
+ }
+ return crv;
}
@@ -3317,45 +3528,48 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession,
CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
{
- SFTKSession *sp;
+ SFTKSession *sp = NULL;
SFTKSlot *slot;
- NSSLOWKEYDBHandle *handle;
+ NSSLOWKEYDBHandle *handle = NULL;
SECItem *newPin;
SECItem *oldPin;
char newPinStr[SFTK_MAX_PIN+1],oldPinStr[SFTK_MAX_PIN+1];
SECStatus rv;
+ CK_RV crv = CKR_SESSION_HANDLE_INVALID;
sp = sftk_SessionFromHandle(hSession);
if (sp == NULL) {
- return CKR_SESSION_HANDLE_INVALID;
+ goto loser;
}
slot = sftk_SlotFromSession(sp);
if (!slot) {
- sftk_FreeSession(sp);
- return CKR_SESSION_HANDLE_INVALID;;
+ goto loser;
}
- handle = slot->keyDB;
+ handle = sftk_getKeyDB(slot);
if (handle == NULL) {
sftk_FreeSession(sp);
return CKR_PIN_LEN_RANGE;
}
if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) {
- sftk_FreeSession(sp);
- return CKR_USER_NOT_LOGGED_IN;
+ crv = CKR_USER_NOT_LOGGED_IN;
+ goto loser;
}
sftk_FreeSession(sp);
+ sp = NULL;
/* make sure the pins aren't too long */
if ((ulNewLen > SFTK_MAX_PIN) || (ulOldLen > SFTK_MAX_PIN)) {
- return CKR_PIN_LEN_RANGE;
+ crv = CKR_PIN_LEN_RANGE;
+ goto loser;
}
if (ulNewLen < (CK_ULONG)slot->minimumPinLen) {
- return CKR_PIN_LEN_RANGE;
+ crv = CKR_PIN_LEN_RANGE;
+ goto loser;
}
@@ -3374,6 +3588,8 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
/* change the data base password */
PR_Lock(slot->pwCheckLock);
rv = nsslowkey_ChangeKeyDBPassword(handle,oldPin,newPin);
+ sftk_freeKeyDB(handle);
+ handle = NULL;
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
PR_Sleep(loginWaitTime);
}
@@ -3390,7 +3606,15 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin,
return CKR_OK;
}
SECITEM_ZfreeItem(newPin, PR_TRUE);
- return CKR_PIN_INCORRECT;
+ crv = CKR_PIN_INCORRECT;
+loser:
+ if (sp) {
+ sftk_FreeSession(sp);
+ }
+ if (handle) {
+ sftk_freeKeyDB(handle);
+ }
+ return crv;
}
/* NSC_OpenSession opens a session between an application and a token. */
@@ -3402,7 +3626,7 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags,
SFTKSession *session;
SFTKSession *sameID;
- slot = sftk_SlotFromID(slotID);
+ slot = sftk_SlotFromID(slotID, PR_FALSE);
if (slot == NULL) return CKR_SLOT_ID_INVALID;
/* new session (we only have serial sessions) */
@@ -3493,56 +3717,15 @@ CK_RV NSC_CloseSession(CK_SESSION_HANDLE hSession)
CK_RV NSC_CloseAllSessions (CK_SLOT_ID slotID)
{
SFTKSlot *slot;
- SECItem *pw = NULL;
- SFTKSession *session;
- unsigned int i;
- slot = sftk_SlotFromID(slotID);
+ slot = sftk_SlotFromID(slotID, PR_FALSE);
if (slot == NULL) return CKR_SLOT_ID_INVALID;
- /* first log out the card */
- PZ_Lock(slot->slotLock);
- pw = slot->password;
- slot->isLoggedIn = PR_FALSE;
- slot->password = NULL;
- PZ_Unlock(slot->slotLock);
- if (pw) SECITEM_ZfreeItem(pw, PR_TRUE);
-
- /* now close all the current sessions */
- /* NOTE: If you try to open new sessions before NSC_CloseAllSessions
- * completes, some of those new sessions may or may not be closed by
- * NSC_CloseAllSessions... but any session running when this code starts
- * will guarrenteed be close, and no session will be partially closed */
- for (i=0; i < slot->sessHashSize; i++) {
- PZLock *lock = SFTK_SESSION_LOCK(slot,i);
- do {
- PZ_Lock(lock);
- session = slot->head[i];
- /* hand deque */
- /* this duplicates function of NSC_close session functions, but
- * because we know that we are freeing all the sessions, we can
- * do more efficient processing */
- if (session) {
- slot->head[i] = session->next;
- if (session->next) session->next->prev = NULL;
- session->next = session->prev = NULL;
- PZ_Unlock(lock);
- PZ_Lock(slot->slotLock);
- --slot->sessionCount;
- PZ_Unlock(slot->slotLock);
- if (session->info.flags & CKF_RW_SESSION) {
- PR_AtomicDecrement(&slot->rwSessionCount);
- }
- } else {
- PZ_Unlock(lock);
- }
- if (session) sftk_FreeSession(session);
- } while (session != NULL);
- }
- return CKR_OK;
+ return sft_CloseAllSession(slot);
}
+
/* NSC_GetSessionInfo obtains information about the session. */
CK_RV NSC_GetSessionInfo(CK_SESSION_HANDLE hSession,
CK_SESSION_INFO_PTR pInfo)
@@ -3565,9 +3748,10 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
SFTKSession *session;
NSSLOWKEYDBHandle *handle;
CK_FLAGS sessionFlags;
+ SECStatus rv;
+ CK_RV crv;
SECItem *pin;
char pinStr[SFTK_MAX_PIN+1];
- SECStatus rv;
/* get the slot */
@@ -3575,14 +3759,17 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
/* make sure the session is valid */
session = sftk_SessionFromHandle(hSession);
- if (session == NULL) return CKR_SESSION_HANDLE_INVALID;
+ if (session == NULL) {
+ return CKR_SESSION_HANDLE_INVALID;
+ }
sessionFlags = session->info.flags;
sftk_FreeSession(session);
session = NULL;
/* can't log into the Netscape Slot */
- if (slot->slotID == NETSCAPE_SLOT_ID)
+ if (slot->slotID == NETSCAPE_SLOT_ID) {
return CKR_USER_TYPE_INVALID;
+ }
if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN;
slot->ssoLoggedIn = PR_FALSE;
@@ -3593,7 +3780,7 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
PORT_Memcpy(pinStr,pPin,ulPinLen);
pinStr[ulPinLen] = 0;
- handle = slot->keyDB;
+ handle = sftk_getKeyDB(slot);
if (handle == NULL) {
return CKR_USER_TYPE_INVALID;
}
@@ -3603,7 +3790,8 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
* password if and only if we haven't initialized the KEY DB yet.
* We only allow this on a RW session.
*/
- if (nsslowkey_HasKeyDBPassword(handle) == SECFailure) {
+ rv = nsslowkey_HasKeyDBPassword(handle);
+ if (rv == SECFailure) {
/* allow SSO's to log in only if there is not password on the
* key database */
if (((userType == CKU_SO) && (sessionFlags & CKF_RW_SESSION))
@@ -3620,23 +3808,34 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
PZ_Unlock(slot->slotLock);
sftk_update_all_states(slot);
SECITEM_ZfreeItem(pw,PR_TRUE);
- return CKR_OK;
+ crv = CKR_OK;
+ goto done;
}
- return CKR_PIN_INCORRECT;
+ crv = CKR_PIN_INCORRECT;
+ goto done;
}
- return CKR_USER_TYPE_INVALID;
+ crv = CKR_USER_TYPE_INVALID;
+ goto done;
}
/* don't allow the SSO to log in if the user is already initialized */
- if (userType != CKU_USER) { return CKR_USER_TYPE_INVALID; }
+ if (userType != CKU_USER) {
+ crv = CKR_USER_TYPE_INVALID;
+ goto done;
+ }
/* build the hashed pins which we pass around */
pin = nsslowkey_HashPassword(pinStr,handle->global_salt);
- if (pin == NULL) return CKR_HOST_MEMORY;
+ if (pin == NULL) {
+ crv = CKR_HOST_MEMORY;
+ goto done;
+ }
PR_Lock(slot->pwCheckLock);
rv = nsslowkey_CheckKeyDBPassword(handle,pin);
+ sftk_freeKeyDB(handle);
+ handle = NULL;
if ((rv != SECSuccess) && (slot->slotID == FIPS_SLOT_ID)) {
PR_Sleep(loginWaitTime);
}
@@ -3656,7 +3855,12 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType,
}
SECITEM_ZfreeItem(pin, PR_TRUE);
- return CKR_PIN_INCORRECT;
+ crv = CKR_PIN_INCORRECT;
+done:
+ if (handle) {
+ sftk_freeKeyDB(handle);
+ }
+ return crv;
}
/* NSC_Logout logs a user out from a token. */
@@ -3685,6 +3889,98 @@ CK_RV NSC_Logout(CK_SESSION_HANDLE hSession)
return CKR_OK;
}
+/*
+ * Create a new slot on the fly. The slot that is passed in is the
+ * slot the request came from. Only the crypto or FIPS slots can
+ * be used. The resulting slot will live in the same module as
+ * the slot the request was passed to. object is the creation object
+ * that specifies the module spec for the new slot.
+ */
+static CK_RV sftk_CreateNewSlot(SFTKSlot *slot, CK_OBJECT_CLASS class,
+ SFTKObject *object)
+{
+ CK_SLOT_ID idMin, idMax;
+ PRBool isFIPS = PR_FALSE;
+ unsigned long moduleIndex;
+ SFTKAttribute *attribute;
+ sftk_parameters paramStrings;
+ char *paramString;
+ CK_SLOT_ID slotID = 0;
+ SFTKSlot *newSlot = NULL;
+ CK_RV crv = CKR_OK;
+
+ /* only the crypto or FIPS slots can create new slot objects */
+ if (slot->slotID == NETSCAPE_SLOT_ID) {
+ idMin = SFTK_MIN_USER_SLOT_ID;
+ idMax = SFTK_MAX_USER_SLOT_ID;
+ moduleIndex = NSC_NON_FIPS_MODULE;
+ isFIPS = PR_FALSE;
+ } else if (slot->slotID == FIPS_SLOT_ID) {
+ idMin = SFTK_MIN_FIPS_USER_SLOT_ID;
+ idMax = SFTK_MAX_FIPS_USER_SLOT_ID;
+ moduleIndex = NSC_FIPS_MODULE;
+ isFIPS = PR_TRUE;
+ } else {
+ return CKR_ATTRIBUTE_VALUE_INVALID;
+ }
+ attribute = sftk_FindAttribute(object,CKA_NETSCAPE_MODULE_SPEC);
+ if (attribute == NULL) {
+ return CKR_TEMPLATE_INCOMPLETE;
+ }
+ paramString = (unsigned char *)attribute->attrib.pValue;
+ crv = secmod_parseParameters(paramString, &paramStrings, isFIPS);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+
+ /* enforce only one at a time */
+ if (paramStrings.token_count != 1) {
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ goto loser;
+ }
+
+ slotID = paramStrings.tokens[0].slotID;
+
+ /* stay within the valid ID space */
+ if ((slotID < idMin) || (slotID > idMax)) {
+ crv = CKR_ATTRIBUTE_VALUE_INVALID;
+ goto loser;
+ }
+
+ /* unload any existing slot at this id */
+ newSlot = sftk_SlotFromID(slotID, PR_TRUE);
+ if (newSlot && newSlot->present) {
+ crv = SFTK_ShutdownSlot(newSlot);
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+ }
+
+ /* if we were just planning on deleting the slot, then do so now */
+ if (class == CKO_NETSCAPE_DELSLOT) {
+ /* sort of a unconventional use of this error code, be we are
+ * overusing CKR_ATTRIBUTE_VALUE_INVALID, and it does apply */
+ crv = newSlot ? CKR_OK : CKR_SLOT_ID_INVALID;
+ goto loser; /* really exit */
+ }
+
+ if (newSlot) {
+ crv = SFTK_SlotReInit(newSlot, paramStrings.configdir,
+ &paramStrings.tokens[0], moduleIndex);
+ } else {
+ crv = SFTK_SlotInit(paramStrings.configdir,
+ &paramStrings.tokens[0], moduleIndex);
+ }
+ if (crv != CKR_OK) {
+ goto loser;
+ }
+loser:
+ secmod_freeParams(&paramStrings);
+ sftk_FreeAttribute(attribute);
+
+ return crv;
+}
+
/* NSC_CreateObject creates a new object. */
CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
@@ -3694,9 +3990,11 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
SFTKSlot *slot = sftk_SlotFromSessionHandle(hSession);
SFTKSession *session;
SFTKObject *object;
+ CK_OBJECT_CLASS class;
CK_RV crv;
int i;
+ *phObject = CK_INVALID_HANDLE;
/*
* now lets create an object to hang the attributes off of
@@ -3715,6 +4013,9 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
sftk_FreeObject(object);
return crv;
}
+ if ((pTemplate[i].type == CKA_CLASS) && pTemplate[i].pValue) {
+ class = *(CK_OBJECT_CLASS *)pTemplate[i].pValue;
+ }
}
/* get the session */
@@ -3725,10 +4026,19 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
}
/*
+ * handle pseudo objects (CKO_NEWSLOT)
+ */
+ if ((class == CKO_NETSCAPE_NEWSLOT) || (class == CKO_NETSCAPE_DELSLOT)) {
+ crv = sftk_CreateNewSlot(slot, class, object);
+ goto done;
+ }
+
+ /*
* handle the base object stuff
*/
crv = sftk_handleObject(object,session);
*phObject = object->handle;
+done:
sftk_FreeSession(session);
sftk_FreeObject(object);
@@ -3736,6 +4046,7 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession,
}
+
/* NSC_CopyObject copies an object, creating a new object for the copy. */
CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession,
CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
@@ -4021,7 +4332,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl,
{
NSSLOWCERTCertDBHandle *certHandle = NULL;
- certHandle = slot->certDB;
+ certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) {
return;
}
@@ -4047,6 +4358,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl,
nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
sftk_crl_collect, (void *)&crlData);
}
+ sftk_freeCertDB(certHandle);
}
/*
@@ -4054,6 +4366,7 @@ sftk_searchCrls(SFTKSlot *slot, SECItem *derSubject, PRBool isKrl,
*/
typedef struct sftkKeyDataStr {
SFTKSlot *slot;
+ NSSLOWKEYDBHandle *keyHandle;
SFTKSearchResults *searchHandles;
SECItem *id;
CK_ATTRIBUTE *template;
@@ -4079,7 +4392,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg)
tmpDBKey.len = key->size;
tmpDBKey.type = siBuffer;
- PORT_Assert(slot->keyDB);
+ PORT_Assert(keyData->keyHandle);
if (!keyData->strict && keyData->id) {
SECItem result;
PRBool haveMatch= PR_FALSE;
@@ -4089,7 +4402,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg)
if (keyData->id->len == 0) {
/* Make sure this isn't a NSC_KEY */
- privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB,
+ privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
&tmpDBKey, keyData->slot->password);
if (privKey) {
haveMatch = isSecretKey(privKey) ?
@@ -4132,7 +4445,7 @@ sftk_key_collect(DBT *key, DBT *data, void *arg)
return SECSuccess;
}
- privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, &tmpDBKey,
+ privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey,
keyData->slot->password);
if ( privKey == NULL ) {
goto loser;
@@ -4177,7 +4490,7 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn,
sftkKeyData keyData;
PRBool found = PR_FALSE;
- keyHandle = slot->keyDB;
+ keyHandle = sftk_getKeyDB(slot);
if (keyHandle == NULL) {
return;
}
@@ -4204,19 +4517,20 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn,
}
/* don't do the traversal if we have an up to date db */
if (keyHandle->version != 3) {
- return;
+ goto loser;
}
/* don't do the traversal if it can't possibly be the correct id */
/* all soft token id's are SHA1_HASH_LEN's */
if (key_id->len != SHA1_LENGTH) {
- return;
+ goto loser;
}
if (found) {
/* if we already found some keys, don't do the traversal */
- return;
+ goto loser;
}
}
keyData.slot = slot;
+ keyData.keyHandle = keyHandle;
keyData.searchHandles = search;
keyData.id = key_id;
keyData.template = pTemplate;
@@ -4226,6 +4540,9 @@ sftk_searchKeys(SFTKSlot *slot, SECItem *key_id, PRBool isLoggedIn,
keyData.strict = mustStrict ? mustStrict : NSC_STRICT;
nsslowkey_TraverseKeys(keyHandle, sftk_key_collect, &keyData);
+loser:
+ sftk_freeKeyDB(keyHandle);
+
}
/*
@@ -4339,7 +4656,7 @@ sftk_searchCertsAndTrust(SFTKSlot *slot, SECItem *derCert, SECItem *name,
sftkCertData certData;
int i;
- certHandle = slot->certDB;
+ certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) return;
certData.slot = slot;
@@ -4425,10 +4742,11 @@ sftk_searchCertsAndTrust(SFTKSlot *slot, SECItem *derCert, SECItem *name,
} else {
/* we aren't filtering the certs, we are working on all, so turn
* on the strict filters. */
- certData.strict = PR_TRUE;
+ certData.strict = PR_TRUE;
sftk_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE);
nsslowcert_TraversePermCerts(certHandle, sftk_cert_collect2, &certData);
}
+ sftk_freeCertDB(certHandle);
/*
* build the handles
@@ -4459,13 +4777,14 @@ sftk_searchSMime(SFTKSlot *slot, SECItem *email, SFTKSearchResults *handles,
NSSLOWCERTCertDBHandle *certHandle = NULL;
certDBEntrySMime *entry;
- certHandle = slot->certDB;
+ certHandle = sftk_getCertDB(slot);
if (certHandle == NULL) return;
if (email->data != NULL) {
char *tmp_name = (char*)PORT_Alloc(email->len+1);
if (tmp_name == NULL) {
+ sftk_freeCertDB(certHandle);
return;
}
PORT_Memcpy(tmp_name,email->data,email->len);
@@ -4484,6 +4803,7 @@ sftk_searchSMime(SFTKSlot *slot, SECItem *email, SFTKSearchResults *handles,
}
PORT_Free(tmp_name);
}
+ sftk_freeCertDB(certHandle);
return;
}
diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h
index 3374d66e8..0eaf5bf37 100644
--- a/security/nss/lib/softoken/pkcs11i.h
+++ b/security/nss/lib/softoken/pkcs11i.h
@@ -325,39 +325,56 @@ struct SFTKSessionStr {
* password, isLoggedIn, ssoLoggedIn, and sessionCount,
* and pwCheckLock serializes the key database password checks in
* NSC_SetPIN and NSC_Login.
+ *
+ * Each of the fields below has the following lifetime as commented
+ * next to the fields:
+ * invariant - This value is set when the slot is first created and
+ * never changed until it is destroyed.
+ * per load - This value is set when the slot is first created, or
+ * when the slot is used to open another directory. Between open and close
+ * this field does not change.
+ * variable - This value changes through the normal process of slot operation.
+ * - reset. The value of this variable is cleared during an open/close
+ * cycles.
+ * - preserved. The value of this variable is preserved over open/close
+ * cycles.
*/
struct SFTKSlotStr {
- CK_SLOT_ID slotID;
- PZLock *slotLock;
- PZLock **sessionLock;
- unsigned int numSessionLocks;
- unsigned long sessionLockMask;
- PZLock *objectLock;
- PRLock *pwCheckLock;
- SECItem *password;
- PRBool hasTokens;
- PRBool isLoggedIn;
- PRBool ssoLoggedIn;
- PRBool needLogin;
- PRBool DB_loaded;
- PRBool readOnly;
- PRBool optimizeSpace;
- NSSLOWCERTCertDBHandle *certDB;
- NSSLOWKEYDBHandle *keyDB;
- int minimumPinLen;
- PRInt32 sessionIDCount; /* atomically incremented */
- int sessionIDConflict; /* not protected by a lock */
- int sessionCount;
- PRInt32 rwSessionCount; /* set by atomic operations */
- int tokenIDCount;
- int index;
- PLHashTable *tokenHashTable;
- SFTKObject **tokObjects;
- unsigned int tokObjHashSize;
- SFTKSession **head;
- unsigned int sessHashSize;
- char tokDescription[33];
- char slotDescription[64];
+ CK_SLOT_ID slotID; /* invariant */
+ PZLock *slotLock; /* invariant */
+ PZLock **sessionLock; /* invariant */
+ unsigned int numSessionLocks; /* invariant */
+ unsigned long sessionLockMask; /* invariant */
+ PZLock *objectLock; /* invariant */
+ PRLock *pwCheckLock; /* invariant */
+ SECItem *password; /* variable - reset */
+ PRBool present; /* variable -set */
+ PRBool hasTokens; /* per load */
+ PRBool isLoggedIn; /* variable - reset */
+ PRBool ssoLoggedIn; /* variable - reset */
+ PRBool needLogin; /* per load */
+ PRBool DB_loaded; /* per load */
+ PRBool readOnly; /* per load */
+ PRBool optimizeSpace; /* invariant */
+ NSSLOWCERTCertDBHandle *certDB; /* per load */
+ NSSLOWKEYDBHandle *keyDB; /* per load */
+ int minimumPinLen; /* per load */
+ PRInt32 sessionIDCount; /* atomically incremented */
+ /* (preserved) */
+ int sessionIDConflict; /* not protected by a lock */
+ /* (preserved) */
+ int sessionCount; /* variable - reset */
+ PRInt32 rwSessionCount; /* set by atomic operations */
+ /* (reset) */
+ int tokenIDCount; /* variable - perserved */
+ int index; /* invariant */
+ PLHashTable *tokenHashTable; /* invariant */
+ SFTKObject **tokObjects; /* variable - reset */
+ unsigned int tokObjHashSize; /* invariant */
+ SFTKSession **head; /* variable -reset */
+ unsigned int sessHashSize; /* invariant */
+ char tokDescription[33]; /* per load */
+ char slotDescription[64]; /* invariant */
};
/*
@@ -538,14 +555,21 @@ typedef struct sftk_parametersStr {
SEC_BEGIN_PROTOS
+/* shared functions between PKCS11.c and SFTKFIPS.c */
extern int nsf_init;
extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonFinalize(CK_VOID_PTR pReserved, PRBool isFIPS);
extern CK_RV nsc_CommonGetSlotList(CK_BBOOL tokPresent,
CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount, int moduleIndex);
-/* shared functions between PKCS11.c and SFTKFIPS.c */
-extern CK_RV SFTK_SlotInit(char *configdir,sftk_token_parameters *params,
- int moduleIndex);
+
+/* slot initialization, reinit, shutdown and destruction */
+extern CK_RV SFTK_SlotInit(char *configdir,
+ sftk_token_parameters *params, int moduleIndex);
+extern CK_RV SFTK_SlotReInit(SFTKSlot *slot, char *configdir,
+ sftk_token_parameters *params, int moduleIndex);
+extern CK_RV SFTK_DestroySlotData(SFTKSlot *slot);
+extern CK_RV SFTK_ShutdownSlot(SFTKSlot *slot);
+
/* internal utility functions used by pkcs11.c */
extern SFTKAttribute *sftk_FindAttribute(SFTKObject *object,
@@ -591,6 +615,9 @@ extern SFTKObject *sftk_ObjectFromHandle(CK_OBJECT_HANDLE handle,
SFTKSession *session);
extern void sftk_AddSlotObject(SFTKSlot *slot, SFTKObject *object);
extern void sftk_AddObject(SFTKSession *session, SFTKObject *object);
+/* clear out all the existing object ID to database key mappings.
+ * used to reinit a token */
+extern CK_RV SFTK_ClearTokenKeyHashTable(SFTKSlot *slot);
extern CK_RV sftk_searchObjectList(SFTKSearchResults *search,
SFTKObject **head, unsigned int size,
@@ -602,7 +629,7 @@ extern void sftk_FreeObjectList(SFTKObjectListElement *objectList);
extern void sftk_FreeSearch(SFTKSearchResults *search);
extern CK_RV sftk_handleObject(SFTKObject *object, SFTKSession *session);
-extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID);
+extern SFTKSlot *sftk_SlotFromID(CK_SLOT_ID slotID, PRBool all);
extern SFTKSlot *sftk_SlotFromSessionHandle(CK_SESSION_HANDLE handle);
extern SFTKSession *sftk_SessionFromHandle(CK_SESSION_HANDLE handle);
extern void sftk_FreeSession(SFTKSession *session);
@@ -658,9 +685,14 @@ CK_RV sftk_DBInit(const char *configdir, const char *certPrefix,
const char *keyPrefix, PRBool readOnly, PRBool noCertDB,
PRBool noKeyDB, PRBool forceOpen,
NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB);
-
-void sftk_DBShutdown(NSSLOWCERTCertDBHandle *certHandle,
- NSSLOWKEYDBHandle *keyHandle);
+NSSLOWCERTCertDBHandle *sftk_getCertDB(SFTKSlot *slot);
+NSSLOWKEYDBHandle *sftk_getKeyDB(SFTKSlot *slot);
+void sftk_freeCertDB(NSSLOWCERTCertDBHandle *certHandle);
+void sftk_freeKeyDB(NSSLOWKEYDBHandle *keyHandle);
+
+/* helper function which calls nsslowkey_FindKeyByPublicKey after safely
+ * acquiring a reference to the keydb from the slot */
+NSSLOWKEYPrivateKey *sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey);
const char *sftk_EvaluateConfigDir(const char *configdir, char **domain);
diff --git a/security/nss/lib/softoken/pkcs11n.h b/security/nss/lib/softoken/pkcs11n.h
index 31137c4d2..b1dce6c12 100644
--- a/security/nss/lib/softoken/pkcs11n.h
+++ b/security/nss/lib/softoken/pkcs11n.h
@@ -73,6 +73,8 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
#define CKO_NETSCAPE_SMIME (CKO_NETSCAPE + 2)
#define CKO_NETSCAPE_TRUST (CKO_NETSCAPE + 3)
#define CKO_NETSCAPE_BUILTIN_ROOT_LIST (CKO_NETSCAPE + 4)
+#define CKO_NETSCAPE_NEWSLOT (CKO_NETSCAPE + 5)
+#define CKO_NETSCAPE_DELSLOT (CKO_NETSCAPE + 6)
/*
* Netscape-defined key types
@@ -106,6 +108,7 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$";
#define CKA_NETSCAPE_PQG_SEED (CKA_NETSCAPE + 21)
#define CKA_NETSCAPE_PQG_H (CKA_NETSCAPE + 22)
#define CKA_NETSCAPE_PQG_SEED_BITS (CKA_NETSCAPE + 23)
+#define CKA_NETSCAPE_MODULE_SPEC (CKA_NETSCAPE + 24)
/*
* Trust attributes:
@@ -233,4 +236,11 @@ typedef CK_ULONG CK_TRUST;
typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function,
char *parameters, void *moduleSpec);
+/* softoken slot ID's */
+#define SFTK_MIN_USER_SLOT_ID 4
+#define SFTK_MAX_USER_SLOT_ID 100
+#define SFTK_MIN_FIPS_USER_SLOT_ID 101
+#define SFTK_MAX_FIPS_USER_SLOT_ID 127
+
+
#endif /* _PKCS11N_H_ */
diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c
index eb8f5b3e8..8e68587ce 100644
--- a/security/nss/lib/softoken/pkcs11u.c
+++ b/security/nss/lib/softoken/pkcs11u.c
@@ -240,10 +240,51 @@ static const SFTKAttribute sftk_StaticMustVerifyAttr =
SFTK_DEF_ATTRIBUTE(&sftk_staticMustVerifyValue,
sizeof(sftk_staticMustVerifyValue));
+/*
+ * helper functions which get the database and call the underlying
+ * low level database function.
+ */
+static char *
+sftk_FindKeyNicknameByPublicKey(SFTKSlot *slot, SECItem *dbKey)
+{
+ NSSLOWKEYDBHandle *keyHandle;
+ char * label;
+
+ keyHandle = sftk_getKeyDB(slot);
+ if (!keyHandle) {
+ return NULL;
+ }
+
+ label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey,
+ slot->password);
+ sftk_freeKeyDB(keyHandle);
+ return label;
+}
+
+
+NSSLOWKEYPrivateKey *
+sftk_FindKeyByPublicKey(SFTKSlot *slot, SECItem *dbKey)
+{
+ NSSLOWKEYPrivateKey *privKey;
+ NSSLOWKEYDBHandle *keyHandle;
+
+ keyHandle = sftk_getKeyDB(slot);
+ if (keyHandle == NULL) {
+ return NULL;
+ }
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, slot->password);
+ sftk_freeKeyDB(keyHandle);
+ if (privKey == NULL) {
+ return NULL;
+ }
+ return privKey;
+}
+
static certDBEntrySMime *
sftk_getSMime(SFTKTokenObject *object)
{
certDBEntrySMime *entry;
+ NSSLOWCERTCertDBHandle *certHandle;
if (object->obj.objclass != CKO_NETSCAPE_SMIME) {
return NULL;
@@ -252,10 +293,14 @@ sftk_getSMime(SFTKTokenObject *object)
return (certDBEntrySMime *)object->obj.objectInfo;
}
- entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB,
- (char *)object->dbKey.data);
+ certHandle = sftk_getCertDB(object->obj.slot);
+ if (!certHandle) {
+ return NULL;
+ }
+ entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)object->dbKey.data);
object->obj.objectInfo = (void *)entry;
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
+ sftk_freeCertDB(certHandle);
return entry;
}
@@ -264,6 +309,7 @@ sftk_getCrl(SFTKTokenObject *object)
{
certDBEntryRevocation *crl;
PRBool isKrl;
+ NSSLOWCERTCertDBHandle *certHandle;
if (object->obj.objclass != CKO_NETSCAPE_CRL) {
return NULL;
@@ -273,15 +319,20 @@ sftk_getCrl(SFTKTokenObject *object)
}
isKrl = (PRBool) (object->obj.handle == SFTK_TOKEN_KRL_HANDLE);
- crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,
- &object->dbKey, isKrl);
+ certHandle = sftk_getCertDB(object->obj.slot);
+ if (!certHandle) {
+ return NULL;
+ }
+
+ crl = nsslowcert_FindCrlByKey(certHandle, &object->dbKey, isKrl);
object->obj.objectInfo = (void *)crl;
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyDBEntry;
+ sftk_freeCertDB(certHandle);
return crl;
}
static NSSLOWCERTCertificate *
-sftk_getCert(SFTKTokenObject *object)
+sftk_getCert(SFTKTokenObject *object, NSSLOWCERTCertDBHandle *certHandle)
{
NSSLOWCERTCertificate *cert;
CK_OBJECT_CLASS objClass = object->obj.objclass;
@@ -292,7 +343,7 @@ sftk_getCert(SFTKTokenObject *object)
if (objClass == CKO_CERTIFICATE && object->obj.objectInfo) {
return (NSSLOWCERTCertificate *)object->obj.objectInfo;
}
- cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey);
+ cert = nsslowcert_FindCertByKey(certHandle, &object->dbKey);
if (objClass == CKO_CERTIFICATE) {
object->obj.objectInfo = (void *)cert;
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyCertificate ;
@@ -304,6 +355,7 @@ static NSSLOWCERTTrust *
sftk_getTrust(SFTKTokenObject *object)
{
NSSLOWCERTTrust *trust;
+ NSSLOWCERTCertDBHandle *certHandle;
if (object->obj.objclass != CKO_NETSCAPE_TRUST) {
return NULL;
@@ -311,9 +363,14 @@ sftk_getTrust(SFTKTokenObject *object)
if (object->obj.objectInfo) {
return (NSSLOWCERTTrust *)object->obj.objectInfo;
}
- trust = nsslowcert_FindTrustByKey(object->obj.slot->certDB,&object->dbKey);
+ certHandle = sftk_getCertDB(object->obj.slot);
+ if (!certHandle) {
+ return NULL;
+ }
+ trust = nsslowcert_FindTrustByKey(certHandle, &object->dbKey);
object->obj.objectInfo = (void *)trust;
object->obj.infoFree = (SFTKFree) nsslowcert_DestroyTrust ;
+ sftk_freeCertDB(certHandle);
return trust;
}
@@ -329,8 +386,7 @@ sftk_GetPublicKey(SFTKTokenObject *object)
if (object->obj.objectInfo) {
return (NSSLOWKEYPublicKey *)object->obj.objectInfo;
}
- privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB,
- &object->dbKey, object->obj.slot->password);
+ privKey = sftk_FindKeyByPublicKey(object->obj.slot, &object->dbKey);
if (privKey == NULL) {
return NULL;
}
@@ -341,8 +397,16 @@ sftk_GetPublicKey(SFTKTokenObject *object)
return pubKey;
}
+/*
+ * we need two versions of sftk_GetPrivateKey. One version that takes the
+ * DB handle so we can pass the handle we have already acquired in,
+ * rather than going through the 'getKeyDB' code again,
+ * which may fail the second time and another which just aquires
+ * the key handle from the slot (where we don't already have a key handle.
+ * This version does the former.
+ */
static NSSLOWKEYPrivateKey *
-sftk_GetPrivateKey(SFTKTokenObject *object)
+sftk_GetPrivateKeyWithDB(SFTKTokenObject *object, NSSLOWKEYDBHandle *keyHandle)
{
NSSLOWKEYPrivateKey *privKey;
@@ -353,8 +417,8 @@ sftk_GetPrivateKey(SFTKTokenObject *object)
if (object->obj.objectInfo) {
return (NSSLOWKEYPrivateKey *)object->obj.objectInfo;
}
- privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB,
- &object->dbKey, object->obj.slot->password);
+ privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &object->dbKey,
+ object->obj.slot->password);
if (privKey == NULL) {
return NULL;
}
@@ -363,6 +427,22 @@ sftk_GetPrivateKey(SFTKTokenObject *object)
return privKey;
}
+/* this version does the latter */
+static NSSLOWKEYPrivateKey *
+sftk_GetPrivateKey(SFTKTokenObject *object)
+{
+ NSSLOWKEYDBHandle *keyHandle;
+ NSSLOWKEYPrivateKey *privKey;
+
+ keyHandle = sftk_getKeyDB(object->obj.slot);
+ if (!keyHandle) {
+ return NULL;
+ }
+ privKey = sftk_GetPrivateKeyWithDB(object, keyHandle);
+ sftk_freeKeyDB(keyHandle);
+ return privKey;
+}
+
/* sftk_GetPubItem returns data associated with the public key.
* one only needs to free the public key. This comment is here
* because this sematic would be non-obvious otherwise. All callers
@@ -540,10 +620,11 @@ sftk_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type)
}
#endif /* NSS_ENABLE_ECC */
+
static SFTKAttribute *
sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
{
- NSSLOWKEYPublicKey *key;
+ NSSLOWKEYPublicKey *key;
SFTKAttribute *att = NULL;
char *label;
@@ -557,8 +638,8 @@ sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
case CKA_EXTRACTABLE:
return SFTK_CLONE_ATTR(type,sftk_StaticTrueAttr);
case CKA_LABEL:
- label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB,
- &object->dbKey, object->obj.slot->password);
+ label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
+ &object->dbKey);
if (label == NULL) {
return SFTK_CLONE_ATTR(type,sftk_StaticOneAttr);
}
@@ -595,7 +676,7 @@ sftk_FindPublicKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
static SFTKAttribute *
sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
{
- NSSLOWKEYPrivateKey *key;
+ NSSLOWKEYPrivateKey *key;
char *label;
unsigned char *keyString;
SFTKAttribute *att;
@@ -621,8 +702,8 @@ sftk_FindSecretKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
case CKA_NEVER_EXTRACTABLE:
return SFTK_CLONE_ATTR(type,sftk_StaticFalseAttr);
case CKA_LABEL:
- label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB,
- &object->dbKey, object->obj.slot->password);
+ label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
+ &object->dbKey);
if (label == NULL) {
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
}
@@ -889,7 +970,7 @@ sftk_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type)
static SFTKAttribute *
sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
{
- NSSLOWKEYPrivateKey *key;
+ NSSLOWKEYPrivateKey *key;
char *label;
SFTKAttribute *att;
@@ -905,8 +986,8 @@ sftk_FindPrivateKeyAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
case CKA_SUBJECT:
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
case CKA_LABEL:
- label = nsslowkey_FindKeyNicknameByPublicKey(object->obj.slot->keyDB,
- &object->dbKey, object->obj.slot->password);
+ label = sftk_FindKeyNicknameByPublicKey(object->obj.slot,
+ &object->dbKey);
if (label == NULL) {
return SFTK_CLONE_ATTR(type,sftk_StaticNullAttr);
}
@@ -1122,8 +1203,9 @@ sftk_FindCrlAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
static SFTKAttribute *
sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
{
- NSSLOWCERTCertificate *cert;
- NSSLOWKEYPublicKey *pubKey;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWKEYPublicKey *pubKey;
unsigned char hash[SHA1_LENGTH];
SECItem *item;
@@ -1146,7 +1228,14 @@ sftk_FindCertAttribute(SFTKTokenObject *object, CK_ATTRIBUTE_TYPE type)
default:
return NULL;
}
- cert = sftk_getCert(object);
+
+ certHandle = sftk_getCertDB(object->obj.slot);
+ if (certHandle == NULL) {
+ return NULL;
+ }
+
+ cert = sftk_getCert(object, certHandle);
+ sftk_freeCertDB(certHandle);
if (cert == NULL) {
return NULL;
}
@@ -1269,6 +1358,7 @@ sftk_GetLengthInBits(unsigned char *buf, unsigned int bufLen)
{
unsigned int size = bufLen * 8;
unsigned int i;
+
/* Get the real length in bytes */
for (i=0; i < bufLen; i++) {
unsigned char c = *buf++;
@@ -1300,7 +1390,7 @@ sftk_ConstrainAttribute(SFTKObject *object, CK_ATTRIBUTE_TYPE type,
int minLength, int maxLength, int minMultiple)
{
SFTKAttribute *attribute;
- unsigned int size;
+ int size;
unsigned char *ptr;
attribute = sftk_FindAttribute(object, type);
@@ -1462,9 +1552,11 @@ static CK_RV
sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
void *value, unsigned int len)
{
- NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
char *nickname = NULL;
SECStatus rv;
+ CK_RV crv;
/* we can't change the EMAIL values, but let the
* upper layers feel better about the fact we tried to set these */
@@ -1472,17 +1564,21 @@ sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
return CKR_OK;
}
- if (to->obj.slot->certDB == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
+ certHandle = sftk_getCertDB(to->obj.slot);
+ if (certHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
}
if ((type != CKA_LABEL) && (type != CKA_ID)) {
- return CKR_ATTRIBUTE_READ_ONLY;
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ goto done;
}
- cert = sftk_getCert(to);
+ cert = sftk_getCert(to, certHandle);
if (cert == NULL) {
- return CKR_OBJECT_HANDLE_INVALID;
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
}
/* if the app is trying to set CKA_ID, it's probably because it just
@@ -1493,33 +1589,45 @@ sftk_SetCertAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
((cert->trust->emailFlags & CERTDB_USER) == 0) &&
((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
SFTKSlot *slot = to->obj.slot;
-
- if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) {
- NSSLOWCERTCertTrust trust = *cert->trust;
- trust.sslFlags |= CERTDB_USER;
- trust.emailFlags |= CERTDB_USER;
- trust.objectSigningFlags |= CERTDB_USER;
- nsslowcert_ChangeCertTrust(slot->certDB,cert,&trust);
+ NSSLOWKEYDBHandle *keyHandle;
+
+ keyHandle = sftk_getKeyDB(slot);
+ if (keyHandle) {
+ if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
+ NSSLOWCERTCertTrust trust = *cert->trust;
+ trust.sslFlags |= CERTDB_USER;
+ trust.emailFlags |= CERTDB_USER;
+ trust.objectSigningFlags |= CERTDB_USER;
+ nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
+ }
+ sftk_freeKeyDB(keyHandle);
}
}
- return CKR_OK;
+ crv = CKR_OK;
+ goto done;
}
/* must be CKA_LABEL */
if (value != NULL) {
nickname = PORT_ZAlloc(len+1);
if (nickname == NULL) {
- return CKR_HOST_MEMORY;
+ crv = CKR_HOST_MEMORY;
+ goto done;
}
PORT_Memcpy(nickname,value,len);
nickname[len] = 0;
}
- rv = nsslowcert_AddPermNickname(to->obj.slot->certDB, cert, nickname);
- if (nickname) PORT_Free(nickname);
- if (rv != SECSuccess) {
- return CKR_DEVICE_ERROR;
+ rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+
+done:
+ if (nickname) {
+ PORT_Free(nickname);
}
- return CKR_OK;
+ if (certHandle) {
+ sftk_freeCertDB(certHandle);
+ }
+ return crv;
}
static CK_RV
@@ -1527,8 +1635,10 @@ sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
void *value, unsigned int len)
{
NSSLOWKEYPrivateKey *privKey;
+ NSSLOWKEYDBHandle *keyHandle;
char *nickname = NULL;
SECStatus rv;
+ CK_RV crv;
/* we can't change the ID and we don't store the subject, but let the
* upper layers feel better about the fact we tried to set these */
@@ -1536,32 +1646,41 @@ sftk_SetPrivateKeyAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
return CKR_OK;
}
- if (to->obj.slot->keyDB == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
+ keyHandle = sftk_getKeyDB(to->obj.slot);
+ if (keyHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
}
if (type != CKA_LABEL) {
- return CKR_ATTRIBUTE_READ_ONLY;
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ goto done;
}
- privKey = sftk_GetPrivateKey(to);
+ privKey = sftk_GetPrivateKeyWithDB(to, keyHandle);
if (privKey == NULL) {
- return CKR_OBJECT_HANDLE_INVALID;
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
}
if (value != NULL) {
nickname = PORT_ZAlloc(len+1);
if (nickname == NULL) {
- return CKR_HOST_MEMORY;
+ crv = CKR_HOST_MEMORY;
+ goto done;
}
PORT_Memcpy(nickname,value,len);
nickname[len] = 0;
}
- rv = nsslowkey_UpdateNickname(to->obj.slot->keyDB, privKey, &to->dbKey,
+ rv = nsslowkey_UpdateNickname(keyHandle, privKey, &to->dbKey,
nickname, to->obj.slot->password);
- if (nickname) PORT_Free(nickname);
- if (rv != SECSuccess) {
- return CKR_DEVICE_ERROR;
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+done:
+ if (nickname) {
+ PORT_Free(nickname);
}
- return CKR_OK;
+ if (keyHandle) {
+ sftk_freeKeyDB(keyHandle);
+ }
+ return crv;
}
static CK_RV
@@ -1570,22 +1689,29 @@ sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
{
unsigned int flags;
CK_TRUST trust;
- NSSLOWCERTCertificate *cert;
- NSSLOWCERTCertTrust dbTrust;
+ NSSLOWCERTCertificate *cert;
+ NSSLOWCERTCertDBHandle *certHandle;
+ NSSLOWCERTCertTrust dbTrust;
SECStatus rv;
+ CK_RV crv;
- if (to->obj.slot->certDB == NULL) {
- return CKR_TOKEN_WRITE_PROTECTED;
- }
if (len != sizeof (CK_TRUST)) {
return CKR_ATTRIBUTE_VALUE_INVALID;
}
trust = *(CK_TRUST *)value;
flags = sftk_MapTrust(trust, (PRBool) (type == CKA_TRUST_SERVER_AUTH));
- cert = sftk_getCert(to);
+ certHandle = sftk_getCertDB(to->obj.slot);
+
+ if (certHandle == NULL) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ goto done;
+ }
+
+ cert = sftk_getCert(to, certHandle);
if (cert == NULL) {
- return CKR_OBJECT_HANDLE_INVALID;
+ crv = CKR_OBJECT_HANDLE_INVALID;
+ goto done;
}
dbTrust = *cert->trust;
@@ -1607,14 +1733,17 @@ sftk_SetTrustAttribute(SFTKTokenObject *to, CK_ATTRIBUTE_TYPE type,
(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
break;
default:
- return CKR_ATTRIBUTE_READ_ONLY;
+ crv = CKR_ATTRIBUTE_READ_ONLY;
+ goto done;
}
- rv = nsslowcert_ChangeCertTrust(to->obj.slot->certDB,cert,&dbTrust);
- if (rv != SECSuccess) {
- return CKR_DEVICE_ERROR;
+ rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
+ crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
+done:
+ if (certHandle) {
+ sftk_freeCertDB(certHandle);
}
- return CKR_OK;
+ return crv;
}
static CK_RV
@@ -1957,12 +2086,18 @@ sftk_deleteTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
return rem ? SECSuccess : SECFailure;
}
+/* must be called holding sftk_tokenKeyLock(slot) */
static SECStatus
sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
{
PLHashEntry *entry;
SECItem *item;
+ /* don't add a new handle in the middle of closing down a slot */
+ if (!slot->present) {
+ return SECFailure;
+ }
+
item = SECITEM_DupItem(key);
if (item == NULL) {
return SECFailure;
@@ -1975,6 +2110,7 @@ sftk_addTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle, SECItem *key)
return SECSuccess;
}
+/* must be called holding sftk_tokenKeyLock(slot) */
static SECItem *
sftk_lookupTokenKeyByHandle(SFTKSlot *slot, CK_OBJECT_HANDLE handle)
{
@@ -1996,6 +2132,25 @@ sftk_tokenKeyUnlock(SFTKSlot *slot) {
PZ_Unlock(slot->objectLock);
}
+static PRIntn
+sftk_freeHashItem(PLHashEntry* entry, PRIntn index, void *arg)
+{
+ SECItem *item = (SECItem *)entry->value;
+
+ SECITEM_FreeItem(item, PR_TRUE);
+ return HT_ENUMERATE_NEXT;
+}
+
+CK_RV
+SFTK_ClearTokenKeyHashTable(SFTKSlot *slot)
+{
+ sftk_tokenKeyLock(slot);
+ PORT_Assert(!slot->present);
+ PL_HashTableEnumerateEntries(slot->tokenHashTable, sftk_freeHashItem, NULL);
+ sftk_tokenKeyUnlock(slot);
+ return CKR_OK;
+}
+
/* allocation hooks that allow us to recycle old object structures */
static SFTKObjectFreeList sessionObjectList = { NULL, NULL, 0 };
@@ -2349,6 +2504,9 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
sftkqueue_clear_deleted_element(object);
sftk_FreeObject(object); /* reduce it's reference count */
} else {
+ NSSLOWKEYDBHandle *keyHandle;
+ NSSLOWCERTCertDBHandle *certHandle;
+
PORT_Assert(to);
/* remove the objects from the real data base */
switch (object->handle & SFTK_TOKEN_TYPE_MASK) {
@@ -2356,30 +2514,57 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
case SFTK_TOKEN_TYPE_KEY:
/* KEYID is the public KEY for DSA and DH, and the MODULUS for
* RSA */
- PORT_Assert(slot->keyDB);
- rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey);
- if (rv != SECSuccess) crv= CKR_DEVICE_ERROR;
+ keyHandle = sftk_getKeyDB(slot);
+ if (!keyHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ rv = nsslowkey_DeleteKey(keyHandle, &to->dbKey);
+ sftk_freeKeyDB(keyHandle);
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ }
break;
case SFTK_TOKEN_TYPE_PUB:
break; /* public keys only exist at the behest of the priv key */
case SFTK_TOKEN_TYPE_CERT:
- cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey);
+ certHandle = sftk_getCertDB(slot);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ cert = nsslowcert_FindCertByKey(certHandle,&to->dbKey);
+ sftk_freeCertDB(certHandle);
if (cert == NULL) {
crv = CKR_DEVICE_ERROR;
break;
}
rv = nsslowcert_DeletePermCertificate(cert);
- if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
+ if (rv != SECSuccess) {
+ crv = CKR_DEVICE_ERROR;
+ }
nsslowcert_DestroyCertificate(cert);
break;
case SFTK_TOKEN_TYPE_CRL:
+ certHandle = sftk_getCertDB(slot);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
isKrl = (PRBool) (object->handle == SFTK_TOKEN_KRL_HANDLE);
- rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl);
+ rv = nsslowcert_DeletePermCRL(certHandle, &to->dbKey, isKrl);
+ sftk_freeCertDB(certHandle);
if (rv == SECFailure) crv = CKR_DEVICE_ERROR;
break;
case SFTK_TOKEN_TYPE_TRUST:
- cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey);
+ certHandle = sftk_getCertDB(slot);
+ if (!certHandle) {
+ crv = CKR_TOKEN_WRITE_PROTECTED;
+ break;
+ }
+ cert = nsslowcert_FindCertByKey(certHandle, &to->dbKey);
if (cert == NULL) {
+ sftk_freeCertDB(certHandle);
crv = CKR_DEVICE_ERROR;
break;
}
@@ -2390,7 +2575,8 @@ sftk_DeleteObject(SFTKSession *session, SFTKObject *object)
tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN;
tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN;
tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN;
- rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&tmptrust);
+ rv = nsslowcert_ChangeCertTrust(certHandle, cert, &tmptrust);
+ sftk_freeCertDB(certHandle);
if (rv != SECSuccess) crv = CKR_DEVICE_ERROR;
nsslowcert_DestroyCertificate(cert);
break;
@@ -2960,7 +3146,7 @@ sftk_NewSession(CK_SLOT_ID slotID, CK_NOTIFY notify, CK_VOID_PTR pApplication,
CK_FLAGS flags)
{
SFTKSession *session;
- SFTKSlot *slot = sftk_SlotFromID(slotID);
+ SFTKSlot *slot = sftk_SlotFromID(slotID, PR_FALSE);
if (slot == NULL) return NULL;
@@ -3034,7 +3220,10 @@ sftk_SessionFromHandle(CK_SESSION_HANDLE handle)
{
SFTKSlot *slot = sftk_SlotFromSessionHandle(handle);
SFTKSession *session;
- PZLock *lock = SFTK_SESSION_LOCK(slot,handle);
+ PZLock *lock;
+
+ if (!slot) return NULL;
+ lock = SFTK_SESSION_LOCK(slot,handle);
PZ_Lock(lock);
sftkqueue_find(session,handle,slot->head,slot->sessHashSize);