diff options
author | relyea%netscape.com <devnull@localhost> | 2001-10-31 02:48:09 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2001-10-31 02:48:09 +0000 |
commit | 90804aaa7f93b4ba8e638c66efc4646f0560019c (patch) | |
tree | 5ee4d2629af3908522dabe9cdb23bc0ac25acd6d | |
parent | 2993d46b81bf87d4a07ee66616e5ef1161b9c2bd (diff) | |
download | nss-hg-90804aaa7f93b4ba8e638c66efc4646f0560019c.tar.gz |
1) dead code removal.
2) changes to get key gen to work.
3) changes to allow initialization of multiple db's mapped to different tokens in the same module.
4) S/MIME profile support.
-rw-r--r-- | security/nss/lib/softoken/cdbhdl.h | 2 | ||||
-rw-r--r-- | security/nss/lib/softoken/dbinit.c | 91 | ||||
-rw-r--r-- | security/nss/lib/softoken/fipstokn.c | 71 | ||||
-rw-r--r-- | security/nss/lib/softoken/keydb.c | 30 | ||||
-rw-r--r-- | security/nss/lib/softoken/lowpbe.c (renamed from security/nss/lib/softoken/secpkcs5.c) | 12 | ||||
-rw-r--r-- | security/nss/lib/softoken/lowpbe.h (renamed from security/nss/lib/softoken/secpkcs5.h) | 0 | ||||
-rw-r--r-- | security/nss/lib/softoken/manifest.mn | 5 | ||||
-rw-r--r-- | security/nss/lib/softoken/pcert.h | 25 | ||||
-rw-r--r-- | security/nss/lib/softoken/pcertdb.c | 532 | ||||
-rw-r--r-- | security/nss/lib/softoken/pk11db.c | 189 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11.c | 833 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11c.c | 385 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11i.h | 50 | ||||
-rw-r--r-- | security/nss/lib/softoken/pkcs11u.c | 240 |
14 files changed, 1166 insertions, 1299 deletions
diff --git a/security/nss/lib/softoken/cdbhdl.h b/security/nss/lib/softoken/cdbhdl.h index 4f47d7bc3..b606e9876 100644 --- a/security/nss/lib/softoken/cdbhdl.h +++ b/security/nss/lib/softoken/cdbhdl.h @@ -48,8 +48,6 @@ */ struct NSSLOWCERTCertDBHandleStr { DB *permCertDB; - DB *tempCertDB; - void *spkDigestInfo; PZMonitor *dbMon; }; diff --git a/security/nss/lib/softoken/dbinit.c b/security/nss/lib/softoken/dbinit.c index 7f986416c..eac1b0c3a 100644 --- a/security/nss/lib/softoken/dbinit.c +++ b/security/nss/lib/softoken/dbinit.c @@ -104,17 +104,14 @@ pk11_keydb_name_cb(void *arg, int dbVersion) #define CKR_KEYDB_FAILED CKR_DEVICE_ERROR static CK_RV -pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly) +pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly, + NSSLOWCERTCertDBHandle **certdbPtr) { NSSLOWCERTCertDBHandle *certdb; - CK_RV crv = CKR_OK; + CK_RV crv = CKR_CERTDB_FAILED; SECStatus rv; char * name = NULL; - certdb = nsslowcert_GetDefaultCertDB(); /* find a better way?? 3.4 */ - if (certdb) - return CKR_OK; /* idempotency */ - if (prefix == NULL) { prefix = ""; } @@ -129,26 +126,24 @@ pk11_OpenCertDB(const char * configdir, const char *prefix, PRBool readOnly) /* fix when we get the DB in */ rv = nsslowcert_OpenCertDB(certdb, readOnly, pk11_certdb_name_cb, (void *)name, PR_FALSE); - if (rv == SECSuccess) - nsslowcert_SetDefaultCertDB(certdb); - else { - PR_Free(certdb); -loser: - crv = CKR_CERTDB_FAILED; + if (rv == SECSuccess) { + crv = CKR_OK; + *certdbPtr = certdb; + certdb = NULL; } +loser: + if (certdb) PR_Free(certdb); if (name) PORT_Free(name); return crv; } static CK_RV -pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly) +pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly, + NSSLOWKEYDBHandle **keydbPtr) { NSSLOWKEYDBHandle *keydb; char * name = NULL; - keydb = nsslowkey_GetDefaultKeyDB(); - if (keydb) - return SECSuccess; if (prefix == NULL) { prefix = ""; } @@ -156,33 +151,14 @@ pk11_OpenKeyDB(const char * configdir, const char *prefix, PRBool readOnly) if (name == NULL) return SECFailure; keydb = nsslowkey_OpenKeyDB(readOnly, pk11_keydb_name_cb, (void *)name); + PORT_Free(name); if (keydb == NULL) return CKR_KEYDB_FAILED; - nsslowkey_SetDefaultKeyDB(keydb); - PORT_Free(name); + *keydbPtr = keydb; return CKR_OK; } -static NSSLOWCERTCertDBHandle certhandle = { 0 }; - -static PRBool isInitialized = PR_FALSE; - -static CK_RV -pk11_OpenVolatileCertDB() { - SECStatus rv = SECSuccess; - /* now we want to verify the signature */ - /* Initialize the cert code */ - rv = nsslowcert_OpenCertDB(&certhandle, PR_FALSE, NULL, NULL, PR_TRUE); - if (rv != SECSuccess) { - return CKR_DEVICE_ERROR; - } - nsslowcert_SetDefaultCertDB(&certhandle); - return CKR_OK; -} - -/* forward declare so that a failure in the init case can shutdown */ -void pk11_Shutdown(void); /* * OK there are now lots of options here, lets go through them all: @@ -203,55 +179,37 @@ void pk11_Shutdown(void); */ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, - const char *keyPrefix, - const char *secmodName, PRBool readOnly, PRBool noCertDB, - PRBool noModDB, PRBool forceOpen) + const char *keyPrefix, PRBool readOnly, + PRBool noCertDB, PRBool noKeyDB, PRBool forceOpen, + NSSLOWCERTCertDBHandle **certdbPtr, NSSLOWKEYDBHandle **keydbPtr) { SECStatus rv = SECFailure; CK_RV crv = CKR_OK; - if( isInitialized ) { - return CKR_OK; - } - - rv = RNG_RNGInit(); /* initialize random number generator */ - if (rv != SECSuccess) { - crv = CKR_DEVICE_ERROR; - goto loser; - } - RNG_SystemInfoForRNG(); - if (noCertDB) { - crv = pk11_OpenVolatileCertDB(); - if (crv != CKR_OK) { - goto loser; - } - } else { - crv = pk11_OpenCertDB(configdir, certPrefix, readOnly); + if (!noCertDB) { + crv = pk11_OpenCertDB(configdir, certPrefix, readOnly, certdbPtr); if (crv != CKR_OK) { if (!forceOpen) goto loser; - crv = pk11_OpenVolatileCertDB(); - if (crv != CKR_OK) { - goto loser; - } + crv = CKR_OK; } + } + if (!noKeyDB) { - crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly); + crv = pk11_OpenKeyDB(configdir, keyPrefix, readOnly, keydbPtr); if (crv != CKR_OK) { if (!forceOpen) goto loser; + crv = CKR_OK; } } - isInitialized = PR_TRUE; loser: - if (crv != CKR_OK) { - pk11_Shutdown(); - } return crv; } +#ifdef notdef void pk11_Shutdown(void) { @@ -271,3 +229,4 @@ pk11_Shutdown(void) isInitialized = PR_FALSE; } +#endif diff --git a/security/nss/lib/softoken/fipstokn.c b/security/nss/lib/softoken/fipstokn.c index 909e8c167..5bc0ee4d7 100644 --- a/security/nss/lib/softoken/fipstokn.c +++ b/security/nss/lib/softoken/fipstokn.c @@ -53,28 +53,6 @@ #include "pkcs11.h" #include "pkcs11i.h" -/* The next two strings must be exactly 64 characters long, with the - first 32 characters meaningful */ -static char *slotDescription = - "Netscape Internal FIPS-140-1 Cryptographic Services "; -static char *privSlotDescription = - "Netscape FIPS-140-1 User Private Key Services "; - - -/* - * Configuration utils - */ -void -PK11_ConfigureFIPS(char *slotdes, char *pslotdes) -{ - if (slotdes && (PORT_Strlen(slotdes) == 65)) { - slotDescription = slotdes; - } - if (pslotdes && (PORT_Strlen(pslotdes) == 65)) { - privSlotDescription = pslotdes; - } - return; -} /* * ******************** Password Utilities ******************************* @@ -171,31 +149,24 @@ CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) { /* FC_Initialize initializes the PKCS #11 library. */ CK_RV FC_Initialize(CK_VOID_PTR pReserved) { - CK_RV rv; + CK_RV crv; static PRBool init= PR_FALSE; - rv = PK11_LowInitialize(pReserved); - - if (rv == CKR_OK && !init) { - init = PR_TRUE; - rv = PK11_SlotInit(FIPS_SLOT_ID,PR_TRUE,nsslowcert_GetDefaultCertDB(), - nsslowkey_GetDefaultKeyDB()); - /* fall through to check below */ - } + crv = nsc_CommonInitialize(pReserved, PR_TRUE); /* not an 'else' rv can be set by either PK11_LowInit or PK11_SlotInit*/ - if (rv != CKR_OK) { + if (crv != CKR_OK) { fatalError = PR_TRUE; - return rv; + return crv; } fatalError = PR_FALSE; /* any error has been reset */ - rv = pk11_fipsPowerUpSelfTest(); - if (rv != CKR_OK) { + crv = pk11_fipsPowerUpSelfTest(); + if (crv != CKR_OK) { fatalError = PR_TRUE; - return rv; + return crv; } return CKR_OK; @@ -216,11 +187,7 @@ CK_RV FC_GetInfo(CK_INFO_PTR pInfo) { /* FC_GetSlotList obtains a list of slots in the system. */ CK_RV FC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { - *pulCount = 1; - if (pSlotList != NULL) { - pSlotList[0] = FIPS_SLOT_ID; - } - return CKR_OK; + return NSC_GetSlotList(tokenPresent,pSlotList,pulCount); } /* FC_GetSlotInfo obtains information about a particular slot in the system. */ @@ -228,16 +195,11 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV crv; - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; - - /* Use NETSCAPE_SLOT_ID as a basis so that we get Library version number, - * not key_DB version number */ - crv = NSC_GetSlotInfo(NETSCAPE_SLOT_ID,pInfo); + crv = NSC_GetSlotInfo(slotID,pInfo); if (crv != CKR_OK) { return crv; } - PORT_Memcpy(pInfo->slotDescription,slotDescription,64); return CKR_OK; } @@ -246,13 +208,8 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) { CK_RV crv; - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; - - /* use PRIVATE_KEY_SLOT_ID so we get the correct - Authentication information */ - crv = NSC_GetTokenInfo(PRIVATE_KEY_SLOT_ID,pInfo); + crv = NSC_GetTokenInfo(slotID,pInfo); pInfo->flags |= CKF_RNG | CKF_LOGIN_REQUIRED; - /* yes virginia, FIPS can do random number generation:) */ return crv; } @@ -263,9 +220,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pusCount) { PK11_FIPSFATALCHECK(); - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; + if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID; /* FIPS Slot supports all functions */ - return NSC_GetMechanismList(NETSCAPE_SLOT_ID,pMechanismList,pusCount); + return NSC_GetMechanismList(slotID,pMechanismList,pusCount); } @@ -274,9 +231,9 @@ CK_RV FC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { CK_RV FC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { PK11_FIPSFATALCHECK(); - if (slotID != FIPS_SLOT_ID) return CKR_SLOT_ID_INVALID; + if (slotID == FIPS_SLOT_ID) slotID = NETSCAPE_SLOT_ID; /* FIPS Slot supports all functions */ - return NSC_GetMechanismInfo(NETSCAPE_SLOT_ID,type,pInfo); + return NSC_GetMechanismInfo(slotID,type,pInfo); } diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index ad21a733f..a4c7640c0 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -45,7 +45,7 @@ #include "secitem.h" #include "pcert.h" #include "mcom_db.h" -#include "secpkcs5.h" +#include "lowpbe.h" #include "secerr.h" #include "keydbi.h" @@ -1333,7 +1333,6 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, /* encrypt the private key */ rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname, PR_FALSE, algorithm); - SECITEM_ZfreeItem(pwitem, PR_TRUE); return(rv); } @@ -1587,7 +1586,6 @@ nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, namekey.size = modulus->len; pk = seckey_get_private_key(handle, &namekey, NULL, pwitem); - SECITEM_ZfreeItem(pwitem, PR_TRUE); /* no need to free dbkey, since its on the stack, and the data it * points to is owned by the database @@ -1686,22 +1684,24 @@ nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, } dest = nsspkcs5_CipherData(param, pwitem, &test_key, PR_TRUE, NULL); - if(dest != NULL) + if (dest == NULL) { - rv = SECITEM_CopyItem(arena, &dbkey->salt, salt); - if(rv == SECFailure) - goto loser; + rv = SECFailure; + goto loser; + } + + rv = SECITEM_CopyItem(arena, &dbkey->salt, salt); + if (rv == SECFailure) { + goto loser; + } - rv = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest); + rv = encodePWCheckEntry(arena, &dbkey->derPK, algorithm, dest); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE); - } else { - rv = SECFailure; + if ( rv != SECSuccess ) { + goto loser; } + + rv = put_dbkey(handle, &checkkey, dbkey, PR_TRUE); /* let success fall through */ loser: diff --git a/security/nss/lib/softoken/secpkcs5.c b/security/nss/lib/softoken/lowpbe.c index 2337e74ca..845638b74 100644 --- a/security/nss/lib/softoken/secpkcs5.c +++ b/security/nss/lib/softoken/lowpbe.c @@ -42,7 +42,7 @@ #include "hasht.h" #include "secasn1.h" #include "secder.h" -#include "secpkcs5.h" +#include "lowpbe.h" #include "secoid.h" #include "alghmac.h" #include "softoken.h" @@ -791,9 +791,11 @@ nsspkcs5_AlgidToParam(SECAlgorithmID *algid) case NSSPKCS5_PBKDF1: rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, NSSPKCS5PBEParameterTemplate, &algid->parameters); + break; case NSSPKCS5_PKCS12_V2: rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters); + break; case NSSPKCS5_PBKDF2: break; } @@ -1133,6 +1135,14 @@ nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm, if (algid == NULL) { goto loser; } + + if (pbe_param->iteration.data == NULL) { + dummy = SEC_ASN1EncodeInteger(pbe_param->poolp,&pbe_param->iteration, + pbe_param->iter); + if (dummy == NULL) { + goto loser; + } + } switch (pbe_param->pbeType) { case NSSPKCS5_PBKDF1: dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, diff --git a/security/nss/lib/softoken/secpkcs5.h b/security/nss/lib/softoken/lowpbe.h index 8ddee11a6..8ddee11a6 100644 --- a/security/nss/lib/softoken/secpkcs5.h +++ b/security/nss/lib/softoken/lowpbe.h diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index 065a1ccc3..db7e3d1d3 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -48,7 +48,6 @@ EXPORTS = \ pkcs11t.h \ pkcs11n.h \ pkcs11u.h \ - secpkcs5.h \ $(NULL) PRIVATE_EXPORTS = \ @@ -65,13 +64,13 @@ CSRCS = \ keydb.c \ lowcert.c \ lowkey.c \ + lowpbe.c \ padbuf.c \ + pcertdb.c \ pk11db.c \ pkcs11.c \ pkcs11c.c \ pkcs11u.c \ rawhash.c \ rsawrapr.c \ - secpkcs5.c \ - pcertdb.c \ $(NULL) diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index 9795899b4..b4392fb87 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -305,23 +305,11 @@ SEC_BEGIN_PROTOS ** "nickname" is the nickname to use for the cert ** "trust" is the trust parameters for the cert */ -SECStatus SEC_AddPermCertificate(NSSLOWCERTCertDBHandle *handle, SECItem *derCert, +SECStatus nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *handle, + NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust); -certDBEntryCert * -SEC_FindPermCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey); - -certDBEntryCert -*SEC_FindPermCertByName(NSSLOWCERTCertDBHandle *handle, SECItem *name); - -#ifdef notdef -SECStatus SEC_OpenPermCertDB(NSSLOWCERTCertDBHandle *handle, - PRBool readOnly, - NSSLOWCERTDBNameFunc namecb, - void *cbarg); -#endif - -SECStatus SEC_DeletePermCertificate(NSSLOWCERTCertificate *cert); +SECStatus nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert); typedef SECStatus (PR_CALLBACK * PermCertCallback)(NSSLOWCERTCertificate *cert, SECItem *k, void *pdata); @@ -402,6 +390,13 @@ nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *n SECStatus nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key); +certDBEntrySMime * +nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *certHandle, + char *emailAddr); +void +nsslowcert_DestroyDBEntry(certDBEntry *entry); + + SEC_END_PROTOS #endif /* _PCERTDB_H_ */ diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index 545963f95..1579692bd 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -69,7 +69,7 @@ nsslowcert_FindCertByDERCertNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *d static PZLock *dbLock = NULL; void -certdb_InitDBLock(void) +certdb_InitDBLock(NSSLOWCERTCertDBHandle *handle) { if (dbLock == NULL) { nss_InitLock(&dbLock, nssILockCertDB); @@ -1233,6 +1233,13 @@ DestroyDBEntry(certDBEntry *entry) return; } +void +nsslowcert_DestroyDBEntry(certDBEntry *entry) +{ + DestroyDBEntry(entry); + return; +} + /* * Encode a database nickname record */ @@ -1543,10 +1550,6 @@ loser: } -/* - * Encode a database smime record - */ -static SECStatus EncodeDBSMimeEntry(certDBEntrySMime *entry, PRArenaPool *arena, SECItem *dbitem) { @@ -1824,8 +1827,8 @@ loser: /* * Read a SMIME entry */ -static certDBEntrySMime * -ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr) +certDBEntrySMime * +nsslowcert_ReadDBSMimeEntry(NSSLOWCERTCertDBHandle *handle, char *emailAddr) { PRArenaPool *arena = NULL; PRArenaPool *tmparena = NULL; @@ -2420,25 +2423,29 @@ loser: } static SECStatus -UpdateSubjectWithEmailAddr(NSSLOWCERTCertificate *cert, char *emailAddr) +UpdateSubjectWithEmailAddr(NSSLOWCERTCertDBHandle *dbhandle, + SECItem *derSubject, char *emailAddr) { PRBool save = PR_FALSE, delold = PR_FALSE; certDBEntrySubject *entry; SECStatus rv; - - emailAddr = nsslowcert_FixupEmailAddr(emailAddr); - if ( emailAddr == NULL ) { - return(SECFailure); + + if (emailAddr) { + emailAddr = nsslowcert_FixupEmailAddr(emailAddr); + if (emailAddr == NULL) { + return SECFailure; + } } - entry = ReadDBSubjectEntry(cert->dbhandle,&cert->derSubject); + entry = ReadDBSubjectEntry(dbhandle,derSubject); if ( entry->emailAddr ) { - if ( PORT_Strcmp(entry->emailAddr, emailAddr) != 0 ) { + if ( (emailAddr == NULL) || + (PORT_Strcmp(entry->emailAddr, emailAddr) != 0) ) { save = PR_TRUE; delold = PR_TRUE; } - } else { + } else if (emailAddr) { save = PR_TRUE; } @@ -2448,35 +2455,39 @@ UpdateSubjectWithEmailAddr(NSSLOWCERTCertificate *cert, char *emailAddr) */ PORT_Assert(save); PORT_Assert(entry->emailAddr != NULL); - DeleteDBSMimeEntry(cert->dbhandle, entry->emailAddr); + DeleteDBSMimeEntry(dbhandle, entry->emailAddr); } if ( save ) { unsigned int len; PORT_Assert(entry != NULL); - len = PORT_Strlen(emailAddr) + 1; - entry->emailAddr = (char *)PORT_ArenaAlloc(entry->common.arena, len); - if ( entry->emailAddr == NULL ) { - goto loser; + if (emailAddr) { + len = PORT_Strlen(emailAddr) + 1; + entry->emailAddr = (char *)PORT_ArenaAlloc(entry->common.arena, len); + if ( entry->emailAddr == NULL ) { + goto loser; + } + PORT_Memcpy(entry->emailAddr, emailAddr, len); + } else { + entry->emailAddr = NULL; } - PORT_Memcpy(entry->emailAddr, emailAddr, len); /* delete the subject entry */ - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); + DeleteDBSubjectEntry(dbhandle, derSubject); /* write the new one */ - rv = WriteDBSubjectEntry(cert->dbhandle, entry); + rv = WriteDBSubjectEntry(dbhandle, entry); if ( rv != SECSuccess ) { goto loser; } } - PORT_Free(emailAddr); + if (emailAddr) PORT_Free(emailAddr); return(SECSuccess); loser: - PORT_Free(emailAddr); + if (emailAddr) PORT_Free(emailAddr); return(SECFailure); } @@ -2485,7 +2496,8 @@ loser: * have one */ static SECStatus -AddNicknameToSubject(NSSLOWCERTCertificate *cert, char *nickname) +AddNicknameToSubject(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) { certDBEntrySubject *entry; SECStatus rv; @@ -2494,7 +2506,7 @@ AddNicknameToSubject(NSSLOWCERTCertificate *cert, char *nickname) return(SECFailure); } - entry = ReadDBSubjectEntry(cert->dbhandle,&cert->derSubject); + entry = ReadDBSubjectEntry(dbhandle,&cert->derSubject); PORT_Assert(entry != NULL); if ( entry == NULL ) { goto loser; @@ -2505,17 +2517,18 @@ AddNicknameToSubject(NSSLOWCERTCertificate *cert, char *nickname) goto loser; } - entry->nickname = (nickname) ? PORT_ArenaStrdup(entry->common.arena, nickname) : NULL; + entry->nickname = (nickname) ? + PORT_ArenaStrdup(entry->common.arena, nickname) : NULL; if ( entry->nickname == NULL ) { goto loser; } /* delete the subject entry */ - DeleteDBSubjectEntry(cert->dbhandle, &cert->derSubject); + DeleteDBSubjectEntry(dbhandle, &cert->derSubject); /* write the new one */ - rv = WriteDBSubjectEntry(cert->dbhandle, entry); + rv = WriteDBSubjectEntry(dbhandle, entry); if ( rv != SECSuccess ) { goto loser; } @@ -2886,7 +2899,7 @@ nsslowcert_TraversePermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *ni if ( nnentry ) { derSubject = &nnentry->subjectName; } else { - smentry = ReadDBSMimeEntry(handle, nickname); + smentry = nsslowcert_ReadDBSMimeEntry(handle, nickname); if ( smentry ) { derSubject = &smentry->subjectName; } @@ -2931,7 +2944,8 @@ nsslowcert_NumPermCertsForNickname(NSSLOWCERTCertDBHandle *handle, char *nicknam * add a nickname to a cert that doesn't have one */ static SECStatus -AddNicknameToPermCert(NSSLOWCERTCertificate *cert, char *nickname) +AddNicknameToPermCert(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) { certDBEntryCert *entry; int rv; @@ -2944,7 +2958,7 @@ AddNicknameToPermCert(NSSLOWCERTCertificate *cert, char *nickname) entry->nickname = PORT_ArenaStrdup(entry->common.arena, nickname); - rv = WriteDBCertEntry(cert->dbhandle, entry); + rv = WriteDBCertEntry(dbhandle, entry); if ( rv ) { goto loser; } @@ -2961,12 +2975,13 @@ loser: * have one yet (it is probably an e-mail cert). */ SECStatus -nsslowcert_AddPermNickname(NSSLOWCERTCertificate *cert, char *nickname) +nsslowcert_AddPermNickname(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname) { SECStatus rv = SECFailure; certDBEntrySubject *entry = NULL; - nsslowcert_LockDB(cert->dbhandle); + nsslowcert_LockDB(dbhandle); PORT_Assert(cert->nickname == NULL); @@ -2975,22 +2990,22 @@ nsslowcert_AddPermNickname(NSSLOWCERTCertificate *cert, char *nickname) goto loser; } - entry = ReadDBSubjectEntry(cert->dbhandle, &cert->derSubject); + entry = ReadDBSubjectEntry(dbhandle, &cert->derSubject); if (entry == NULL) goto loser; if ( entry->nickname == NULL ) { /* no nickname for subject */ - rv = AddNicknameToSubject(cert, nickname); + rv = AddNicknameToSubject(dbhandle, cert, nickname); if ( rv != SECSuccess ) { goto loser; } - rv = AddNicknameToPermCert(cert, nickname); + rv = AddNicknameToPermCert(dbhandle, cert, nickname); if ( rv != SECSuccess ) { goto loser; } } else { /* subject already has a nickname */ - rv = AddNicknameToPermCert(cert, entry->nickname); + rv = AddNicknameToPermCert(dbhandle, cert, entry->nickname); if ( rv != SECSuccess ) { goto loser; } @@ -3001,7 +3016,7 @@ loser: if (entry) { DestroyDBEntry((certDBEntry *)entry); } - nsslowcert_UnlockDB(cert->dbhandle); + nsslowcert_UnlockDB(dbhandle); return(rv); } @@ -3251,7 +3266,7 @@ UpdateV6DB(NSSLOWCERTCertDBHandle *handle, DB *updatedb) emailAddr = &((char *)key.data)[1]; /* get the matching smime entry in the new DB */ - emailEntry = ReadDBSMimeEntry(handle, emailAddr); + emailEntry = nsslowcert_ReadDBSMimeEntry(handle, emailAddr); if ( emailEntry == NULL ) { goto endloop; } @@ -3450,95 +3465,21 @@ nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle) namekey.data = keyitem.data; namekey.size = keyitem.len; - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - if ( ret == 0 ) { /* found in temp database */ - goto loser; - } else { /* not found in temporary database */ - ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); - if ( ret == 0 ) { - goto loser; - } - } - - PORT_FreeArena(arena, PR_FALSE); - - return(PR_FALSE); -loser: - if ( arena ) { - PORT_FreeArena(arena, PR_FALSE); - } - - return(PR_TRUE); -} - -#ifdef notdef - -/* - * return true if a subject name conflict exists - * NOTE: caller must have already made sure that this exact cert - * doesn't exist in the DB - */ -PRBool -SEC_CertSubjectConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle) -{ - SECStatus rv; - DBT tmpdata; - DBT namekey; - int ret; - SECItem keyitem; - PRArenaPool *arena = NULL; - SECItem derName; - - derName.data = NULL; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - goto loser; - } - - /* get the subject name of the cert */ - rv = nsslowcert_NameFromDERCert(derCert, &derName); - if ( rv != SECSuccess ) { - goto loser; - } - - rv = EncodeDBSubjectKey(&derName, arena, &keyitem); - if ( rv != SECSuccess ) { + ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); + if ( ret == 0 ) { goto loser; } - - namekey.data = keyitem.data; - namekey.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get(handle->tempCertDB, &namekey, &tmpdata, 0); - - if ( ret == 0 ) { /* found in temp database */ - return(PR_TRUE); - } else { /* not found in temporary database */ - ret = certdb_Get(handle->permCertDB, &namekey, &tmpdata, 0); - if ( ret == 0 ) { - return(PR_TRUE); - } - } PORT_FreeArena(arena, PR_FALSE); - PORT_Free(derName.data); return(PR_FALSE); loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } - if ( derName.data ) { - PORT_Free(derName.data); - } return(PR_TRUE); } -#endif /* * return true if a nickname conflict exists @@ -3780,7 +3721,7 @@ nsslowcert_DeletePermCertificate(NSSLOWCERTCertificate *cert) * Traverse all of the entries in the database of a particular type * call the given function for each one. */ -static SECStatus +SECStatus nsslowcert_TraverseDBEntries(NSSLOWCERTCertDBHandle *handle, certDBEntryType type, SECStatus (* callback)(SECItem *data, SECItem *key, @@ -4063,8 +4004,8 @@ done: SECStatus -nsslowcert_AddPermCert(NSSLOWCERTCertificate *cert, char *nickname, - NSSLOWCERTCertTrust *trust) +nsslowcert_AddPermCert(NSSLOWCERTCertDBHandle *dbhandle, + NSSLOWCERTCertificate *cert, char *nickname, NSSLOWCERTCertTrust *trust) { char *oldnn; certDBEntryCert *entry; @@ -4072,15 +4013,13 @@ nsslowcert_AddPermCert(NSSLOWCERTCertificate *cert, char *nickname, PRBool conflict; SECStatus ret; - PORT_Assert(cert->dbhandle); - - nsslowcert_LockDB(cert->dbhandle); + nsslowcert_LockDB(dbhandle); PORT_Assert(!cert->dbEntry); /* don't add a conflicting nickname */ conflict = nsslowcert_CertNicknameConflict(nickname, &cert->derSubject, - cert->dbhandle); + dbhandle); if ( conflict ) { ret = SECFailure; goto done; @@ -4089,7 +4028,7 @@ nsslowcert_AddPermCert(NSSLOWCERTCertificate *cert, char *nickname, /* save old nickname so that we can delete it */ oldnn = cert->nickname; - entry = AddCertToPermDB(cert->dbhandle, cert, nickname, trust); + entry = AddCertToPermDB(dbhandle, cert, nickname, trust); if ( entry == NULL ) { ret = SECFailure; @@ -4102,7 +4041,7 @@ nsslowcert_AddPermCert(NSSLOWCERTCertificate *cert, char *nickname, ret = SECSuccess; done: - nsslowcert_UnlockDB(cert->dbhandle); + nsslowcert_UnlockDB(dbhandle); return(ret); } @@ -4115,28 +4054,13 @@ nsslowcert_OpenCertDB(NSSLOWCERTCertDBHandle *handle, PRBool readOnly, NSSLOWCERTDBNameFunc namecb, void *cbarg, PRBool openVolatile) { int rv; -#define DBM_DEFAULT 0 - static const HASHINFO hashInfo = { - DBM_DEFAULT, /* bucket size */ - DBM_DEFAULT, /* fill factor */ - DBM_DEFAULT, /* number of elements */ - 256 * 1024, /* bytes to cache */ - DBM_DEFAULT, /* hash function */ - DBM_DEFAULT /* byte order */ - }; - - certdb_InitDBLock(); + + certdb_InitDBLock(handle); handle->dbMon = PZ_NewMonitor(nssILockCertDB); PORT_Assert(handle->dbMon != NULL); - if (openVolatile) { - handle->permCertDB = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, - &hashInfo ); - rv = handle->permCertDB ? SECSuccess : SECFailure; - } else { - rv = nsslowcert_OpenPermCertDB(handle, readOnly, namecb, cbarg); - } + rv = nsslowcert_OpenPermCertDB(handle, readOnly, namecb, cbarg); if ( rv ) { goto loser; } @@ -4454,313 +4378,63 @@ nsslowcert_hasTrust(NSSLOWCERTCertificate *cert) (trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN)); } -#ifdef notdef -/* - * find a cert by email address - * - * pick one that is a valid recipient, meaning that it is an encryption - * cert. - * - */ -static NSSLOWCERTCertificate* -find_smime_recipient_cert(NSSLOWCERTCertDBHandle* handle, const char* email_addr) -{ - NSSLOWCERTCertificate* cert = NULL; - NSSLOWCERTCertList* certList = NULL; - SECStatus rv; - - certList = nsslowcert_CreateEmailAddrCertList(NULL, handle, (char*)email_addr, - PR_Now(), PR_TRUE); - if (certList == NULL) { - return NULL; - } - - rv = nsslowcert_FilterCertListByUsage(certList, certUsageEmailRecipient, - PR_FALSE); - - if (!nsslowcert_LIST_END(nsslowcert_LIST_HEAD(certList), certList)) { - cert = nsslowcert_DupCertificate(nsslowcert_LIST_HEAD(certList)->cert); - } - - nsslowcert_DestroyCertList(certList); - - return cert; /* cert may point to a cert or may be NULL */ -} - /* * This function has the logic that decides if another person's cert and * email profile from an S/MIME message should be saved. It can deal with * the case when there is no profile. */ SECStatus -nsslowcert_SaveSMimeProfile(NSSLOWCERTCertificate *cert, SECItem *emailProfile, - SECItem *profileTime) +nsslowcert_SaveSMimeProfile(NSSLOWCERTCertDBHandle *dbhandle, char *emailAddr, + SECItem *derSubject, SECItem *emailProfile, SECItem *profileTime) { - certDBEntrySMime *entry = NULL, *oldentry = NULL; - int64 oldtime; - int64 newtime; - SECStatus rv; - NSSLOWCERTCertificate *oldcert = NULL; - PRBool saveit; - NSSLOWCERTCertTrust trust; - NSSLOWCERTCertTrust tmptrust; - char *emailAddr; - - emailAddr = cert->emailAddr; - - PORT_Assert(emailAddr); - if ( emailAddr == NULL ) { - goto loser; - } - - saveit = PR_FALSE; - - oldcert = find_smime_recipient_cert(cert->dbhandle, emailAddr); - if (oldcert) { - /* see if there is an entry already */ - oldentry = ReadDBSMimeEntry(cert->dbhandle, emailAddr); - } - - /* both profileTime and emailProfile have to exist or not exist */ - if ( emailProfile == NULL ) { - profileTime = NULL; - } else if ( profileTime == NULL ) { - emailProfile = NULL; - } - - if ( oldentry == NULL ) { - /* no old entry for this address */ - PORT_Assert(oldcert == NULL); - saveit = PR_TRUE; - } else { - /* there was already a profile for this email addr */ - if ( profileTime ) { - /* we have an old and new profile - save whichever is more recent*/ - if ( oldentry->optionsDate.len == 0 ) { - /* always replace if old entry doesn't have a time */ - oldtime = LL_MININT; - } else { - rv = DER_UTCTimeToTime(&oldtime, &oldentry->optionsDate); - if ( rv != SECSuccess ) { - goto loser; - } - } - - rv = DER_UTCTimeToTime(&newtime, profileTime); - if ( rv != SECSuccess ) { - goto loser; - } - - if ( LL_CMP(newtime, >, oldtime ) ) { - /* this is a newer profile, save it and cert */ - saveit = PR_TRUE; - } - } else { - /* we don't have a new profile or time */ - if ( oldentry->optionsDate.len == 0 ) { - /* the old entry doesn't have a time either, so compare certs*/ - if ( nsslowcert_IsNewer(cert, oldcert) ) { - /* new cert is newer, use it instead */ - saveit = PR_TRUE; - } - } else { - if (oldcert) { - if (nsslowcert_IsNewer(cert, oldcert)) { - saveit = PR_TRUE; - } - } else { - saveit = PR_TRUE; - } - } - } - } - - if ( saveit ) { - if ( oldcert && ( oldcert != cert ) ) { - /* old cert is different from new cert */ - if ( PORT_Memcmp(oldcert->trust, &trust, sizeof(trust)) == 0 ) { - /* old cert is only for e-mail, so delete it */ - SEC_DeletePermCertificate(oldcert); - } else { - /* old cert is for other things too, so just change trust */ - tmptrust = *oldcert->trust; - tmptrust.emailFlags &= ( ~CERTDB_VALID_PEER ); - rv = nsslowcert_ChangeCertTrust(oldcert->dbhandle, oldcert, - &tmptrust); - if ( rv != SECSuccess ) { - goto loser; - } - } - } - -/* Subroutine */ - /* now save the entry */ - entry = NewDBSMimeEntry(emailAddr, &cert->derSubject, emailProfile, - profileTime, 0); - if ( entry == NULL ) { - goto loser; - } + certDBEntrySMime *entry = NULL; + SECStatus rv = SECFailure;; - nsslowcert_LockDB(cert->dbhandle); + /* find our existing entry */ + entry = nsslowcert_ReadDBSMimeEntry(dbhandle, emailAddr); - rv = DeleteDBSMimeEntry(cert->dbhandle, emailAddr); - /* if delete fails, try to write new entry anyway... */ - - rv = WriteDBSMimeEntry(cert->dbhandle, entry); - if ( rv != SECSuccess ) { - nsslowcert_UnlockDB(cert->dbhandle); - goto loser; - } - - /* link subject entry back here */ - rv = UpdateSubjectWithEmailAddr(cert, emailAddr); - if ( rv != SECSuccess ) { - nsslowcert_UnlockDB(cert->dbhandle); - goto loser; - } - - nsslowcert_UnlockDB(cert->dbhandle); -/* End Subroutine */ - } - - rv = SECSuccess; - goto done; - -loser: - rv = SECFailure; - -done: - if ( oldcert ) { - nsslowcert_DestroyCertificate(oldcert); - } - if ( entry ) { + /* keep our old db entry consistant for old applications. */ + if (!SECITEM_ItemsAreEqual(derSubject, &entry->subjectName)) { + UpdateSubjectWithEmailAddr(dbhandle, &entry->subjectName, NULL); + } DestroyDBEntry((certDBEntry *)entry); + entry = NULL; } - if ( oldentry ) { - DestroyDBEntry((certDBEntry *)oldentry); - } - - return(rv); -} - -/* - * find the smime symmetric capabilities profile for a given cert - */ -SECItem * -nsslowcert_FindSMimeProfile(NSSLOWCERTCertificate *cert) -{ - certDBEntrySMime *entry; - SECItem *retitem = NULL; - - PORT_Assert(cert->emailAddr != NULL); - - if ( cert->emailAddr == NULL ) { - return(NULL); - } - - entry = ReadDBSMimeEntry(cert->dbhandle, cert->emailAddr); - if ( entry ) { - /* May not be for this cert... */ - if (SECITEM_ItemsAreEqual(&cert->derSubject, &entry->subjectName)) - retitem = SECITEM_DupItem(&entry->smimeOptions); - DestroyDBEntry((certDBEntry *)entry); + /* now save the entry */ + entry = NewDBSMimeEntry(emailAddr, derSubject, emailProfile, + profileTime, 0); + if ( entry == NULL ) { + rv = SECFailure; + goto loser; } - return(retitem); -} - -SECStatus -nsslowcert_ChangeCertTrustByUsage(NSSLOWCERTCertDBHandle *certdb, - NSSLOWCERTCertificate *cert, SECCertUsage usage) -{ - SECStatus rv; - NSSLOWCERTCertTrust trust; - NSSLOWCERTCertTrust tmptrust; - unsigned int certtype; - PRBool saveit; - - saveit = PR_TRUE; - - PORT_Memset((void *)&trust, 0, sizeof(trust)); - - certtype = cert->nsCertType; - - /* if no app bits in cert type, then set all app bits */ - if ( ! ( certtype & NS_CERT_TYPE_APP ) ) { - certtype |= NS_CERT_TYPE_APP; - } + nsslowcert_LockDB(dbhandle); - switch ( usage ) { - case certUsageEmailSigner: - case certUsageEmailRecipient: - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - if ( ! ( cert->rawKeyUsage & KU_KEY_ENCIPHERMENT ) ) { - /* don't save it if KeyEncipherment is not allowed */ - saveit = PR_FALSE; - } - } - break; - case certUsageUserCertImport: - if ( certtype & NS_CERT_TYPE_EMAIL ) { - trust.emailFlags = CERTDB_VALID_PEER; - } - /* VALID_USER is already set if the cert was imported, - * in the case that the cert was already in the database - * through SMIME or other means, we should set the USER - * flags, if they are not already set. - */ - if( cert->isperm ) { - if ( certtype & NS_CERT_TYPE_SSL_CLIENT ) { - if( !(cert->trust->sslFlags & CERTDB_USER) ) { - trust.sslFlags |= CERTDB_USER; - } - } - - if ( certtype & NS_CERT_TYPE_EMAIL ) { - if( !(cert->trust->emailFlags & CERTDB_USER) ) { - trust.emailFlags |= CERTDB_USER; - } - } - - if ( certtype & NS_CERT_TYPE_OBJECT_SIGNING ) { - if( !(cert->trust->objectSigningFlags & CERTDB_USER) ) { - trust.objectSigningFlags |= CERTDB_USER; - } - } - } - break; - default: /* XXX added to quiet warnings; no other cases needed? */ - break; - } + rv = DeleteDBSMimeEntry(dbhandle, emailAddr); + /* if delete fails, try to write new entry anyway... */ - if ( (trust.sslFlags | trust.emailFlags | trust.objectSigningFlags) == 0 ){ - saveit = PR_FALSE; + /* link subject entry back here */ + rv = UpdateSubjectWithEmailAddr(dbhandle, derSubject, emailAddr); + if ( rv != SECSuccess ) { + nsslowcert_UnlockDB(dbhandle); + goto loser; } - - if ( saveit && cert->isperm ) { - /* Cert already in the DB. Just adjust flags */ - tmptrust = *cert->trust; - tmptrust.sslFlags |= trust.sslFlags; - tmptrust.emailFlags |= trust.emailFlags; - tmptrust.objectSigningFlags |= trust.objectSigningFlags; - - rv = nsslowcert_ChangeCertTrust(cert->dbhandle, cert, - &tmptrust); - if ( rv != SECSuccess ) { + + rv = WriteDBSMimeEntry(dbhandle, entry); + if ( rv != SECSuccess ) { + nsslowcert_UnlockDB(dbhandle); goto loser; - } } - rv = SECSuccess; - goto done; + nsslowcert_UnlockDB(dbhandle); + rv = SECSuccess; + loser: - rv = SECFailure; -done: - + if ( entry ) { + DestroyDBEntry((certDBEntry *)entry); + } return(rv); } -#endif diff --git a/security/nss/lib/softoken/pk11db.c b/security/nss/lib/softoken/pk11db.c index d5a4a7b0c..a5cb842e4 100644 --- a/security/nss/lib/softoken/pk11db.c +++ b/security/nss/lib/softoken/pk11db.c @@ -43,64 +43,205 @@ #define FREE_CLEAR(p) if (p) { PORT_Free(p); p = NULL; } static void -secmod_parseFlags(char *tmp, pk11_parameters *parsed) { +secmod_parseTokenFlags(char *tmp, pk11_token_parameters *parsed) { parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp); parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp); + parsed->noKeyDB = pk11_argHasFlag("flags","noKeyDB",tmp); + parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp); + parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp); + return; +} + +static void +secmod_parseFlags(char *tmp, pk11_parameters *parsed) { parsed->noModDB = pk11_argHasFlag("flags","noModDB",tmp); + parsed->readOnly = pk11_argHasFlag("flags","readOnly",tmp); + /* keep legacy interface working */ + parsed->noCertDB = pk11_argHasFlag("flags","noCertDB",tmp); parsed->forceOpen = pk11_argHasFlag("flags","forceOpen",tmp); parsed->pwRequired = pk11_argHasFlag("flags","passwordRequired",tmp); return; } +CK_RV +secmod_parseTokenParameters(char *param, pk11_token_parameters *parsed) +{ + int next; + char *tmp; + char *index; + index = pk11_argStrip(param); + + while (*index) { + PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;) + PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;) + PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;) + PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"tokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"slotDescription=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=", + if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); }) + PK11_HANDLE_STRING_ARG(index,tmp,"flags=", + if(tmp) { secmod_parseTokenFlags(param,parsed); PORT_Free(tmp); }) + PK11_HANDLE_FINAL_ARG(index) + } + return CKR_OK; +} + +static void +secmod_parseTokens(char *tokenParams, pk11_parameters *parsed) +{ + char *tokenIndex; + pk11_token_parameters *tokens = NULL; + int i=0,count = 0,next; + + if ((tokenParams == NULL) || (*tokenParams == 0)) return; + /* first count the number of slots */ + for (tokenIndex = pk11_argStrip(tokenParams); *tokenIndex; + tokenIndex = pk11_argStrip(pk11_argSkipParameter(tokenIndex))) { + count++; + } + + /* get the data structures */ + tokens = (pk11_token_parameters *) + PORT_ZAlloc(count*sizeof(pk11_token_parameters)); + if (tokens == NULL) return; + + for (tokenIndex = pk11_argStrip(tokenParams), i = 0; + *tokenIndex && i < count ; i++ ) { + char *name; + name = pk11_argGetName(tokenIndex,&next); + tokenIndex += next; + + tokens[i].slotID = pk11_argDecodeNumber(name); + tokens[i].readOnly = PR_TRUE; + tokens[i].noCertDB = PR_TRUE; + tokens[i].noKeyDB = PR_TRUE; + if (!pk11_argIsBlank(*tokenIndex)) { + char *args = pk11_argFetchValue(tokenIndex,&next); + tokenIndex += next; + if (args) { + secmod_parseTokenParameters(args,&tokens[i]); + PORT_Free(args); + } + } + if (name) PORT_Free(name); + tokenIndex = pk11_argStrip(tokenIndex); + } + parsed->token_count = i; + parsed->tokens = tokens; + return; +} CK_RV -secmod_parseParameters(char *param, pk11_parameters *parsed) +secmod_parseParameters(char *param, pk11_parameters *parsed, PRBool isFIPS) { int next; char *tmp; char *index; + char *certPrefix = NULL, *keyPrefix = NULL; + char *tokdes = NULL, *ptokdes = NULL; + char *slotdes = NULL, *pslotdes = NULL; + char *fslotdes = NULL, *fpslotdes = NULL; + char *minPW = NULL; index = pk11_argStrip(param); PORT_Memset(parsed, 0, sizeof(pk11_parameters)); while (*index) { PK11_HANDLE_STRING_ARG(index,parsed->configdir,"configdir=",;) - PK11_HANDLE_STRING_ARG(index,parsed->certPrefix,"certprefix=",;) - PK11_HANDLE_STRING_ARG(index,parsed->keyPrefix,"keyprefix=",;) PK11_HANDLE_STRING_ARG(index,parsed->secmodName,"secmod=",;) PK11_HANDLE_STRING_ARG(index,parsed->man,"manufactureID=",;) PK11_HANDLE_STRING_ARG(index,parsed->libdes,"libraryDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->tokdes,"cryptoTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->ptokdes,"dbTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->slotdes,"cryptoSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->pslotdes,"dbSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->fslotdes,"FIPSSlotDescription=",;) - PK11_HANDLE_STRING_ARG(index,parsed->fpslotdes,"FIPSTokenDescription=",;) - PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=", - if(tmp) { parsed->minPW=atoi(tmp); PORT_Free(tmp); }) + /* constructed values, used so legacy interfaces still work */ + PK11_HANDLE_STRING_ARG(index,certPrefix,"certprefix=",;) + PK11_HANDLE_STRING_ARG(index,keyPrefix,"keyprefix=",;) + PK11_HANDLE_STRING_ARG(index,tokdes,"cryptoTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,ptokdes,"dbTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,slotdes,"cryptoSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,pslotdes,"dbSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,fslotdes,"FIPSSlotDescription=",;) + PK11_HANDLE_STRING_ARG(index,minPW,"FIPSTokenDescription=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"minPWLen=",;) + PK11_HANDLE_STRING_ARG(index,tmp,"flags=", if(tmp) { secmod_parseFlags(param,parsed); PORT_Free(tmp); }) + PK11_HANDLE_STRING_ARG(index,tmp,"tokens=", + if(tmp) { secmod_parseTokens(tmp,parsed); PORT_Free(tmp); }) PK11_HANDLE_FINAL_ARG(index) - } - return CKR_OK; + } + if (parsed->tokens == NULL) { + int count = isFIPS ? 1 : 2; + int index = count-1; + pk11_token_parameters *tokens = NULL; + + tokens = (pk11_token_parameters *) + PORT_ZAlloc(count*sizeof(pk11_token_parameters)); + if (tokens == NULL) { + goto loser; + } + parsed->tokens = tokens; + parsed->token_count = 2; + tokens[index].slotID = isFIPS ? FIPS_SLOT_ID : PRIVATE_KEY_SLOT_ID; + tokens[index].certPrefix = certPrefix; + tokens[index].keyPrefix = keyPrefix; + tokens[index].minPW = minPW ? atoi(minPW) : 0; + tokens[index].readOnly = parsed->readOnly; + tokens[index].noCertDB = parsed->noCertDB; + tokens[index].forceOpen = parsed->forceOpen; + tokens[index].pwRequired = parsed->pwRequired; + certPrefix = NULL; + keyPrefix = NULL; + if (isFIPS) { + tokens[index].tokdes = fslotdes; + tokens[index].slotdes = fpslotdes; + fslotdes = NULL; + fpslotdes = NULL; + } else { + tokens[index].tokdes = ptokdes; + tokens[index].slotdes = pslotdes; + tokens[0].slotID = NETSCAPE_SLOT_ID; + tokens[0].tokdes = tokdes; + tokens[0].slotdes = slotdes; + tokens[0].noCertDB = PR_TRUE; + tokens[0].noKeyDB = PR_TRUE; + ptokdes = NULL; + pslotdes = NULL; + tokdes = NULL; + slotdes = NULL; + } + } + +loser: + FREE_CLEAR(certPrefix); + FREE_CLEAR(keyPrefix); + FREE_CLEAR(tokdes); + FREE_CLEAR(ptokdes); + FREE_CLEAR(slotdes); + FREE_CLEAR(pslotdes); + FREE_CLEAR(fslotdes); + FREE_CLEAR(fpslotdes); + FREE_CLEAR(minPW); + return CKR_OK; } void secmod_freeParams(pk11_parameters *params) { + int i; + + for (i=0; i < params->token_count; i++) { + FREE_CLEAR(params->tokens[i].configdir); + FREE_CLEAR(params->tokens[i].certPrefix); + FREE_CLEAR(params->tokens[i].keyPrefix); + FREE_CLEAR(params->tokens[i].tokdes); + FREE_CLEAR(params->tokens[i].slotdes); + } + FREE_CLEAR(params->configdir); - FREE_CLEAR(params->certPrefix); - FREE_CLEAR(params->keyPrefix); FREE_CLEAR(params->secmodName); FREE_CLEAR(params->man); FREE_CLEAR(params->libdes); - FREE_CLEAR(params->tokdes); - FREE_CLEAR(params->ptokdes); - FREE_CLEAR(params->slotdes); - FREE_CLEAR(params->pslotdes); - FREE_CLEAR(params->fslotdes); - FREE_CLEAR(params->fpslotdes); + FREE_CLEAR(params->tokens); } @@ -463,7 +604,7 @@ secmod_DecodeData(char *defParams, DBT *data, PRBool *retInternal) trustOrder = 20; } - slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags, + slotStrings[i] = pk11_mkSlotString(slotID,defaultFlags, timeout,slots[i].askpw,hasRootCerts,hasRootTrust); } @@ -489,7 +630,7 @@ static DB *secmod_OpenDB(char *dbName, PRBool readOnly) { if (readOnly) return NULL; pkcs11db = dbopen( dbName, - O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); + O_RDWR | O_CREAT | O_TRUNC, 0600, DB_HASH, 0 ); if (pkcs11db) (* pkcs11db->sync)(pkcs11db, 0); } return pkcs11db; diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 76960cfce..8d0f4a786 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -70,6 +70,7 @@ static char *manufacturerID = "mozilla.org "; static char manufacturerID_space[33]; static char *libraryDescription = "NSS Internal Crypto Services "; static char libraryDescription_space[33]; +#ifdef notdef static char *tokDescription = "NSS Generic Crypto Services "; static char tokDescription_space[33]; static char *privTokDescription = "NSS Certificate DB "; @@ -82,7 +83,13 @@ static char slotDescription_space[65]; static char *privSlotDescription = "NSS User Private Key and Certificate Services "; static char privSlotDescription_space[65]; -static int minimumPinLen = 0; +/* The next two strings must be exactly 64 characters long, with the + first 32 characters meaningful */ +static char *slotDescription = + "Netscape Internal FIPS-140-1 Cryptographic Services "; +static char *privSlotDescription = + "Netscape FIPS-140-1 User Private Key Services "; +#endif #define __PASTE(x,y) x##y @@ -424,9 +431,7 @@ pk11_setStringName(char *inString, char *buffer, int buffer_length) { * Configuration utils */ static CK_RV -pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, - char *slotdes, char *pslotdes, char *fslotdes, char *fpslotdes, - int minPwd, int pwRequired) +pk11_configure(char *man, char *libdes) { /* make sure the internationalization was done correctly... */ @@ -438,32 +443,6 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, libraryDescription = pk11_setStringName(libdes, libraryDescription_space, sizeof(libraryDescription_space)); } - if (tokdes) { - tokDescription = pk11_setStringName(tokdes,tokDescription_space, - sizeof(tokDescription_space)); - } - if (ptokdes) { - privTokDescription = pk11_setStringName(ptokdes, - privTokDescription_space, sizeof(privTokDescription_space)); - } - if (slotdes) { - slotDescription = pk11_setStringName(slotdes,slotDescription_space, - sizeof(slotDescription_space)); - } - if (pslotdes) { - privSlotDescription = pk11_setStringName(pslotdes, - privSlotDescription_space, sizeof(privSlotDescription_space)); - } - - if (minimumPinLen <= PK11_MAX_PIN) { - minimumPinLen = minPwd; - } - if ((minimumPinLen == 0) && (pwRequired) && - (minimumPinLen <= PK11_MAX_PIN)) { - minimumPinLen = 1; - } - - PK11_ConfigureFIPS(fslotdes,fpslotdes); return CKR_OK; } @@ -633,7 +612,7 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object) } if (!nsslowcert_CertDBKeyConflict(&derCert,slot->certDB)) { if (!trust) trust = &defTrust; - rv = nsslowcert_AddPermCert(cert,label, trust); + rv = nsslowcert_AddPermCert(slot->certDB, cert, label, trust); } else { rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) : SECSuccess; @@ -806,6 +785,88 @@ pk11_handleTrustObject(PK11Session *session,PK11Object *object) * check the consistancy and initialize a Trust Object */ static CK_RV +pk11_handleSMimeObject(PK11Session *session,PK11Object *object) +{ + char *label; + + /* we can't store any certs private */ + if (pk11_isTrue(object,CKA_PRIVATE)) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + /* certificates must have a type */ + if ( !pk11_hasAttribute(object,CKA_SUBJECT) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_NETSCAPE_EMAIL) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_VALUE) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + PRBool isKRL = PR_FALSE; + SECItem derSubj,rawProfile,rawTime,emailKey; + char *email = NULL; + PK11Attribute *subject,*profile,*time; + SECStatus rv; + + PORT_Assert(slot); + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + + /* lookup SUBJECT */ + subject = pk11_FindAttribute(object,CKA_SUBJECT); + PORT_Assert(subject); + derSubj.data = (unsigned char *)subject->attrib.pValue; + derSubj.len = subject->attrib.ulValueLen ; + + /* lookup VALUE */ + profile = pk11_FindAttribute(object,CKA_VALUE); + PORT_Assert(profile); + rawProfile.data = (unsigned char *)profile->attrib.pValue; + rawProfile.len = profile->attrib.ulValueLen ; + + /* lookup Time */ + time = pk11_FindAttribute(object,CKA_NETSCAPE_SMIME_TIMESTAMP); + PORT_Assert(time); + rawTime.data = (unsigned char *)time->attrib.pValue; + rawTime.len = time->attrib.ulValueLen ; + + + email = pk11_getString(object,CKA_NETSCAPE_EMAIL); + + /* Store CRL by SUBJECT */ + rv = nsslowcert_SaveSMimeProfile(slot->certDB, email, &derSubj, + &rawProfile,&rawTime); + + pk11_FreeAttribute(profile); + pk11_FreeAttribute(subject); + pk11_FreeAttribute(time); + if (rv != SECSuccess) { + PORT_Free(email); + return CKR_DEVICE_ERROR; + } + emailKey.data = (unsigned char *)email; + emailKey.len = PORT_Strlen(email)+1; + + object->handle = pk11_mkHandle(slot, &emailKey, PK11_TOKEN_TYPE_SMIME); + PORT_Free(email); + } + + return CKR_OK; +} + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV pk11_handleCrlObject(PK11Session *session,PK11Object *object) { char *label; @@ -864,7 +925,8 @@ pk11_handleCrlObject(PK11Session *session,PK11Object *object) return CKR_DEVICE_ERROR; } - object->handle = pk11_mkHandle(slot,&derSubj,PK11_TOKEN_TYPE_CRL); + object->handle = pk11_mkHandle(slot,&derSubj, + isKRL ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL); pk11_FreeAttribute(subject); } @@ -947,7 +1009,7 @@ pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object, NSSLOWKEYPrivateKey *priv; SECItem pubKey; - crv = pk11_Attribute2SecItem(NULL,&pubKey,object,pubKeyAttr); + crv = pk11_Attribute2SSecItem(NULL,&pubKey,object,pubKeyAttr); if (crv != CKR_OK) return crv; PORT_Assert(pubKey.data); @@ -1101,15 +1163,15 @@ pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE object->objectInfo = pk11_mkPrivKey(object,key_type); if (object->objectInfo == NULL) return CKR_HOST_MEMORY; object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey; - } - /* now NULL out the sensitive attributes */ - if (pk11_isTrue(object,CKA_SENSITIVE)) { - pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT); - pk11_nullAttribute(object,CKA_PRIME_1); - pk11_nullAttribute(object,CKA_PRIME_2); - pk11_nullAttribute(object,CKA_EXPONENT_1); - pk11_nullAttribute(object,CKA_EXPONENT_2); - pk11_nullAttribute(object,CKA_COEFFICIENT); + /* now NULL out the sensitive attributes */ + if (pk11_isTrue(object,CKA_SENSITIVE)) { + pk11_nullAttribute(object,CKA_PRIVATE_EXPONENT); + pk11_nullAttribute(object,CKA_PRIME_1); + pk11_nullAttribute(object,CKA_PRIME_2); + pk11_nullAttribute(object,CKA_EXPONENT_1); + pk11_nullAttribute(object,CKA_EXPONENT_2); + pk11_nullAttribute(object,CKA_COEFFICIENT); + } } return CKR_OK; } @@ -1305,8 +1367,8 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object) /* * Handle Object does all the object consistancy checks, automatic attribute * generation, attribute defaulting, etc. If handleObject succeeds, the object - * will be assigned an object handle, and the object pointer will be adopted - * by the session. (that is don't free object). + * will be assigned an object handle, and the object installed in the session + * or stored in the DB. */ CK_RV pk11_handleObject(PK11Object *object, PK11Session *session) @@ -1369,6 +1431,9 @@ pk11_handleObject(PK11Object *object, PK11Session *session) case CKO_NETSCAPE_CRL: crv = pk11_handleCrlObject(session,object); break; + case CKO_NETSCAPE_SMIME: + crv = pk11_handleSMimeObject(session,object); + break; case CKO_PRIVATE_KEY: case CKO_PUBLIC_KEY: case CKO_SECRET_KEY: @@ -1780,14 +1845,140 @@ pk11_HashNumber(const void *key) } /* + * eventually I'd like to expunge all occurances of XXX_SLOT_ID and + * just go with the info in the slot. This is one place, however, + * where it might be a little difficult. + */ +char * +pk11_getDefTokName(CK_SLOT_ID slotID) +{ + static char buf[33]; + + switch (slotID) { + case NETSCAPE_SLOT_ID: + return "NSS Generic Crypto Services "; + case PRIVATE_KEY_SLOT_ID: + return "NSS Certificate DB "; + case FIPS_SLOT_ID: + return "NSS FIPS-140-1 Cerificate DB "; + default: + break; + } + sprintf(buf,"NSS Application Token %08x ",slotID); + return buf; +} + +char * +pk11_getDefSlotName(CK_SLOT_ID slotID) +{ + static char buf[65]; + + switch (slotID) { + case NETSCAPE_SLOT_ID: + return + "NSS Internal Cryptographic Services Version 3.4 "; + case PRIVATE_KEY_SLOT_ID: + return + "NSS User Private Key and Certificate Services "; + case FIPS_SLOT_ID: + return + "Netscape FIPS-140-1 User Private Key Services "; + default: + break; + } + sprintf(buf, + "NSS Application Slot %08x ",slotID); + return buf; +} + +static CK_ULONG nscSlotCount = 0; +static CK_SLOT_ID_PTR nscSlotList = NULL; +static CK_ULONG nscSlotListSize = 0; +static PLHashTable *nscSlotHashTable = NULL; + +/* look up a slot structure from the ID (used to be a macro when we only + * had two slots) */ +PK11Slot * +pk11_SlotFromID(CK_SLOT_ID slotID) +{ + return (PK11Slot *)PL_HashTableLookupConst(nscSlotHashTable, + (void *)slotID); +} + +PK11Slot * +pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle) +{ + int slotIDIndex = (handle >> 24) & 0xff; + + if (slotIDIndex >= nscSlotCount) { + return NULL; + } + + return pk11_SlotFromID(nscSlotList[slotIDIndex]); +} + +PK11Slot * pk11_NewSlotFromID(CK_SLOT_ID slotID) +{ + PK11Slot *slot = NULL; + PLHashEntry *entry; + + if (nscSlotList == NULL) { + nscSlotListSize = NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList = (CK_SLOT_ID *) + PORT_ZAlloc(nscSlotListSize*sizeof(CK_SLOT_ID)); + if (nscSlotList == NULL) { + return NULL; + } + } + if (nscSlotCount >= nscSlotListSize) { + nscSlotListSize += NSC_SLOT_LIST_BLOCK_SIZE; + nscSlotList = (CK_SLOT_ID *) PORT_Realloc(nscSlotList, + nscSlotListSize*sizeof(CK_SLOT_ID)); + if (nscSlotList == NULL) { + return NULL; + } + } + + if (nscSlotHashTable == NULL) { + nscSlotHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues, + PL_CompareValues, NULL, 0); + if (nscSlotHashTable == NULL) { + return NULL; + } + } + + slot = (PK11Slot *) PORT_ZAlloc(sizeof(PK11Slot)); + if (slot == NULL) { + return NULL; + } + + entry = PL_HashTableAdd(nscSlotHashTable,(void *)slotID,slot); + if (entry == NULL) { + PORT_Free(slot); + return NULL; + } + slot->index = nscSlotCount; + nscSlotList[nscSlotCount++] = slotID; + + return slot; +} + +/* * initialize one of the slot structures. figure out which by the ID */ CK_RV -PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin, - NSSLOWCERTCertDBHandle *certDB, NSSLOWKEYDBHandle *keyDB) +PK11_SlotInit(char *configdir,pk11_token_parameters *params) { int i; - PK11Slot *slot = pk11_SlotFromID(slotID); + CK_SLOT_ID slotID = params->slotID; + PK11Slot *slot = pk11_NewSlotFromID(slotID); + PRBool needLogin = !params->noKeyDB; + CK_RV crv; + + if (slot == NULL) { + return CKR_HOST_MEMORY; + } + #ifdef PKCS11_USE_THREADS slot->sessionLock = PZ_NewLock(nssILockSession); if (slot->sessionLock == NULL) return CKR_HOST_MEMORY; @@ -1819,64 +2010,39 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin, slot->ssoLoggedIn = PR_FALSE; slot->DB_loaded = PR_FALSE; slot->slotID = slotID; - slot->certDB = certDB; - slot->keyDB = keyDB; - if (needLogin) { - /* if the data base is initialized with a null password,remember that */ - slot->needLogin = (PRBool)!pk11_hasNullPassword(keyDB,&slot->password); - } - return CKR_OK; -} - - -/* - * common initialization routines between PKCS #11 and FIPS - */ -CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved) -{ - CK_RV crv = CKR_OK; - CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; - - /* NOTE: - * we should be getting out mutexes from this list, not statically binding - * them from NSPR. This should happen before we allow the internal to split - * off from the rest on NSS. - */ - - /* initialize the key and cert db's */ - nsslowkey_SetDefaultKeyDBAlg - (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); - - if ((init_args && init_args->LibraryParameters)) { - pk11_parameters paramStrings; - - crv = secmod_parseParameters - ((char *)init_args->LibraryParameters,¶mStrings); + slot->certDB = NULL; + slot->keyDB = NULL; + slot->minimumPinLen = 0; + slot->readOnly = params->readOnly; + pk11_setStringName(params->tokdes ? params->tokdes : + pk11_getDefTokName(slotID), slot->tokDescription, + sizeof(slot->tokDescription)); + pk11_setStringName(params->slotdes ? params->slotdes : + pk11_getDefSlotName(slotID), slot->slotDescription, + sizeof(slot->slotDescription)); + + if ((!params->noCertDB) || (!params->noKeyDB)) { + crv = pk11_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) { + /* shoutdown slot? */ return crv; } - - crv = pk11_DBInit(paramStrings.configdir,paramStrings.certPrefix, - paramStrings.keyPrefix,paramStrings.secmodName, paramStrings.readOnly,paramStrings.noCertDB, - paramStrings.noModDB, paramStrings.forceOpen); - if (crv != CKR_OK) { - secmod_freeParams(¶mStrings); - return crv; + } + if (needLogin) { + /* if the data base is initialized with a null password,remember that */ + slot->needLogin = + (PRBool)!pk11_hasNullPassword(slot->keyDB,&slot->password); + if (params->minPW <= PK11_MAX_PIN) { + slot->minimumPinLen = params->minPW; } - crv = pk11_configure(paramStrings.man, paramStrings.libdes, - paramStrings.tokdes,paramStrings.ptokdes,paramStrings.slotdes, - paramStrings.pslotdes,paramStrings.fslotdes, - paramStrings.fpslotdes, paramStrings.minPW, - paramStrings.pwRequired); - secmod_freeParams(¶mStrings); - if (crv != CKR_OK) { - return crv; + if ((slot->minimumPinLen == 0) && (params->pwRequired) && + (slot->minimumPinLen <= PK11_MAX_PIN)) { + slot->minimumPinLen = 1; } - } else { - return CKR_ARGUMENTS_BAD; } - - return CKR_OK; } @@ -1907,26 +2073,67 @@ NSC_ModuleDBFunc(unsigned long function,char *parameters, char *args) /* NSC_Initialize initializes the Cryptoki library. */ -CK_RV NSC_Initialize(CK_VOID_PTR pReserved) +CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS) { static PRBool init = PR_FALSE; CK_RV crv = CKR_OK; + SECStatus rv; + CK_C_INITIALIZE_ARGS *init_args = (CK_C_INITIALIZE_ARGS *) pReserved; + int i; - crv = PK11_LowInitialize(pReserved); - if (crv != CKR_OK) return crv; + if (init) { + return crv; + } - /* intialize all the slots */ - if (!init) { - crv = PK11_SlotInit(NETSCAPE_SLOT_ID,PR_FALSE,NULL,NULL); - if (crv != CKR_OK) return crv; - crv = PK11_SlotInit(PRIVATE_KEY_SLOT_ID,PR_TRUE, - nsslowcert_GetDefaultCertDB(), nsslowkey_GetDefaultKeyDB()); - init = PR_TRUE; + rv = RNG_RNGInit(); /* initialize random number generator */ + if (rv != SECSuccess) { + crv = CKR_DEVICE_ERROR; + goto loser; + } + RNG_SystemInfoForRNG(); + + + /* NOTE: + * we should be getting out mutexes from this list, not statically binding + * them from NSPR. This should happen before we allow the internal to split + * off from the rest on NSS. + */ + + /* initialize the key and cert db's */ + nsslowkey_SetDefaultKeyDBAlg + (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); + crv = CKR_ARGUMENTS_BAD; + if ((init_args && init_args->LibraryParameters)) { + pk11_parameters paramStrings; + + crv = secmod_parseParameters + ((char *)init_args->LibraryParameters,¶mStrings, isFIPS); + if (crv != CKR_OK) { + return crv; + } + crv = pk11_configure(paramStrings.man, paramStrings.libdes); + if (crv != CKR_OK) { + goto loser; + } + + for (i=0; i < paramStrings.token_count; i++) { + crv = + PK11_SlotInit(paramStrings.configdir,¶mStrings.tokens[i]); + if (crv != CKR_OK) break; + } +loser: + secmod_freeParams(¶mStrings); } + init = (PRBool) (crv == CKR_OK); return crv; } +CK_RV NSC_Initialize(CK_VOID_PTR pReserved) +{ + return nsc_CommonInitialize(pReserved,PR_FALSE); +} + /* NSC_Finalize indicates that an application is done with the * Cryptoki library.*/ CK_RV NSC_Finalize (CK_VOID_PTR pReserved) @@ -1952,10 +2159,9 @@ CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) CK_RV NSC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { - *pulCount = 2; + *pulCount = nscSlotCount; if (pSlotList != NULL) { - pSlotList[0] = NETSCAPE_SLOT_ID; - pSlotList[1] = PRIVATE_KEY_SLOT_ID; + PORT_Memcpy(pSlotList,nscSlotList,nscSlotCount*sizeof(CK_SLOT_ID)); } return CKR_OK; } @@ -1963,28 +2169,19 @@ 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) { + PK11Slot *slot = pk11_SlotFromID(slotID); + if (slot == NULL) return CKR_SLOT_ID_INVALID; + pInfo->firmwareVersion.major = 0; pInfo->firmwareVersion.minor = 0; - switch (slotID) { - case NETSCAPE_SLOT_ID: - PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->slotDescription,slotDescription,64); - pInfo->flags = CKF_TOKEN_PRESENT; - pInfo->hardwareVersion.major = 3; - pInfo->hardwareVersion.minor = 2; - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: - PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->slotDescription,privSlotDescription,64); - pInfo->flags = CKF_TOKEN_PRESENT; - /* ok we really should read it out of the keydb file. */ - pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; - pInfo->hardwareVersion.minor = 0; - return CKR_OK; - default: - break; - } - return CKR_SLOT_ID_INVALID; + PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); + PORT_Memcpy(pInfo->slotDescription,slot->slotDescription,64); + pInfo->flags = CKF_TOKEN_PRESENT; + /* ok we really should read it out of the keydb file. */ + /* pInfo->hardwareVersion.major = NSSLOWKEY_DB_FILE_VERSION; */ + pInfo->hardwareVersion.major = 3; + pInfo->hardwareVersion.minor = 2; + return CKR_OK; } #define CKF_THREAD_SAFE 0x8000 /* for now */ @@ -1999,7 +2196,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) if (slot == NULL) return CKR_SLOT_ID_INVALID; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); - PORT_Memcpy(pInfo->model,"Libsec 4.0 ",16); + PORT_Memcpy(pInfo->model,"NSS 3 ",16); PORT_Memcpy(pInfo->serialNumber,"0000000000000000",16); pInfo->ulMaxSessionCount = 0; /* arbitrarily large */ pInfo->ulSessionCount = slot->sessionCount; @@ -2007,9 +2204,9 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->ulRwSessionCount = slot->rwSessionCount; pInfo->firmwareVersion.major = 0; pInfo->firmwareVersion.minor = 0; - switch (slotID) { - case NETSCAPE_SLOT_ID: - PORT_Memcpy(pInfo->label,tokDescription,32); + PORT_Memcpy(pInfo->label,slot->tokDescription,32); + handle = slot->keyDB; + if (handle == NULL) { pInfo->flags= CKF_RNG | CKF_WRITE_PROTECTED | CKF_THREAD_SAFE; pInfo->ulMaxPinLen = 0; pInfo->ulMinPinLen = 0; @@ -2019,10 +2216,7 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) pInfo->ulFreePrivateMemory = 0; pInfo->hardwareVersion.major = 4; pInfo->hardwareVersion.minor = 0; - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: - PORT_Memcpy(pInfo->label,privTokDescription,32); - handle = slot->keyDB; + } else { /* * we have three possible states which we may be in: * (1) No DB password has been initialized. This also means we @@ -2042,8 +2236,8 @@ CK_RV NSC_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo) } pInfo->ulMaxPinLen = PK11_MAX_PIN; pInfo->ulMinPinLen = 0; - if (minimumPinLen > 0) { - pInfo->ulMinPinLen = (CK_ULONG)minimumPinLen; + if (slot->minimumPinLen > 0) { + pInfo->ulMinPinLen = (CK_ULONG)slot->minimumPinLen; } pInfo->ulTotalPublicMemory = 1; pInfo->ulFreePublicMemory = 1; @@ -2051,11 +2245,8 @@ 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 = 0; - return CKR_OK; - default: - break; } - return CKR_SLOT_ID_INVALID; + return CKR_OK; } @@ -2075,8 +2266,8 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, pMechanismList[i] = mechanisms[i].type; } } - return CKR_OK; - case PRIVATE_KEY_SLOT_ID: + break; + default: *pulCount = 0; for (i=0; i < (int) mechanismCount; i++) { if (mechanisms[i].privkey) { @@ -2086,11 +2277,9 @@ CK_RV NSC_GetMechanismList(CK_SLOT_ID slotID, } } } - return CKR_OK; - default: break; } - return CKR_SLOT_ID_INVALID; + return CKR_OK; } @@ -2106,11 +2295,9 @@ CK_RV NSC_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, case NETSCAPE_SLOT_ID: isPrivateKey = PR_FALSE; break; - case PRIVATE_KEY_SLOT_ID: + default: isPrivateKey = PR_TRUE; break; - default: - return CKR_SLOT_ID_INVALID; } for (i=0; i < (int) mechanismCount; i++) { if (type == mechanisms[i].type) { @@ -2211,7 +2398,7 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, PK11Slot *slot; NSSLOWKEYDBHandle *handle; SECItem *newPin; - char newPinStr[256]; + char newPinStr[PK11_MAX_PIN+1]; SECStatus rv; @@ -2220,35 +2407,34 @@ CK_RV NSC_InitPIN(CK_SESSION_HANDLE hSession, return CKR_SESSION_HANDLE_INVALID; } - if (sp->info.slotID == NETSCAPE_SLOT_ID) { + slot = pk11_SlotFromSession(sp); + if (slot == NULL) { pk11_FreeSession(sp); - return CKR_PIN_LEN_RANGE; + return CKR_SESSION_HANDLE_INVALID;; } - /* should be an assert */ - if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || - (sp->info.slotID == FIPS_SLOT_ID)) ) { + handle = slot->keyDB; + if (handle == NULL) { pk11_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + return CKR_PIN_LEN_RANGE; } + if (sp->info.state != CKS_RW_SO_FUNCTIONS) { pk11_FreeSession(sp); return CKR_USER_NOT_LOGGED_IN; } - slot = pk11_SlotFromSession(sp); pk11_FreeSession(sp); /* make sure the pins aren't too long */ - if (ulPinLen > 255) { + if (ulPinLen > PK11_MAX_PIN) { return CKR_PIN_LEN_RANGE; } - - handle = slot->keyDB; - if (handle == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + if (ulPinLen < slot->minimumPinLen) { + return CKR_PIN_LEN_RANGE; } + if (nsslowkey_HasKeyDBPassword(handle) != SECFailure) { return CKR_DEVICE_ERROR; } @@ -2288,7 +2474,7 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, NSSLOWKEYDBHandle *handle; SECItem *newPin; SECItem *oldPin; - char newPinStr[256],oldPinStr[256]; + char newPinStr[PK11_MAX_PIN+1],oldPinStr[PK11_MAX_PIN+1]; SECStatus rv; @@ -2297,20 +2483,18 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, return CKR_SESSION_HANDLE_INVALID; } - if (sp->info.slotID == NETSCAPE_SLOT_ID) { + slot = pk11_SlotFromSession(sp); + if (!slot) { pk11_FreeSession(sp); - return CKR_PIN_LEN_RANGE; + return CKR_SESSION_HANDLE_INVALID;; } - /* should be an assert */ - /* should be an assert */ - if (!((sp->info.slotID == PRIVATE_KEY_SLOT_ID) || - (sp->info.slotID == FIPS_SLOT_ID)) ) { + handle = slot->keyDB; + if (handle == NULL) { pk11_FreeSession(sp); - return CKR_SESSION_HANDLE_INVALID;; + return CKR_PIN_LEN_RANGE; } - slot = pk11_SlotFromSession(sp); if (slot->needLogin && sp->info.state != CKS_RW_USER_FUNCTIONS) { pk11_FreeSession(sp); return CKR_USER_NOT_LOGGED_IN; @@ -2319,16 +2503,14 @@ CK_RV NSC_SetPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pOldPin, pk11_FreeSession(sp); /* make sure the pins aren't too long */ - if ((ulNewLen > 255) || (ulOldLen > 255)) { + if ((ulNewLen > PK11_MAX_PIN) || (ulOldLen > PK11_MAX_PIN)) { return CKR_PIN_LEN_RANGE; } - - - handle = slot->keyDB; - if (handle == NULL) { - return CKR_TOKEN_WRITE_PROTECTED; + if (ulNewLen < slot->minimumPinLen) { + return CKR_PIN_LEN_RANGE; } + /* convert to null terminated string */ PORT_Memcpy(newPinStr,pNewPin,ulNewLen); newPinStr[ulNewLen] = 0; @@ -2375,12 +2557,8 @@ CK_RV NSC_OpenSession(CK_SLOT_ID slotID, CK_FLAGS flags, if (session == NULL) return CKR_HOST_MEMORY; PK11_USE_THREADS(PZ_Lock(slot->sessionLock);) - sessionID = slot->sessionIDCount++; - if (slotID == PRIVATE_KEY_SLOT_ID) { - sessionID |= PK11_PRIVATE_KEY_FLAG; - } else if (slotID == FIPS_SLOT_ID) { - sessionID |= PK11_FIPS_FLAG; - } else if (flags & CKF_RW_SESSION) { + sessionID = slot->sessionIDCount++ | (slot->index << 24); + if (slot->readOnly && (flags & CKF_RW_SESSION)) { /* NETSCAPE_SLOT_ID is Read ONLY */ session->info.flags &= ~CKF_RW_SESSION; } @@ -2504,7 +2682,7 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, PK11Session *session; NSSLOWKEYDBHandle *handle; SECItem *pin; - char pinStr[256]; + char pinStr[PK11_MAX_PIN+1]; /* get the slot */ @@ -2524,7 +2702,7 @@ CK_RV NSC_Login(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, if (slot->isLoggedIn) return CKR_USER_ALREADY_LOGGED_IN; slot->ssoLoggedIn = PR_FALSE; - if (ulPinLen > 255) return CKR_PIN_LEN_RANGE; + if (ulPinLen > PK11_MAX_PIN) return CKR_PIN_LEN_RANGE; /* convert to null terminated string */ PORT_Memcpy(pinStr,pPin,ulPinLen); @@ -2659,14 +2837,11 @@ CK_RV NSC_CreateObject(CK_SESSION_HANDLE hSession, * handle the base object stuff */ crv = pk11_handleObject(object,session); + *phObject = object->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(object); - return crv; - } + pk11_FreeObject(object); - *phObject = object->handle; - return CKR_OK; + return crv; } @@ -2747,12 +2922,9 @@ CK_RV NSC_CopyObject(CK_SESSION_HANDLE hSession, crv = pk11_handleObject(destObject,session); *phNewObject = destObject->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(destObject); - return crv; - } + pk11_FreeObject(destObject); - return CKR_OK; + return crv; } @@ -2918,6 +3090,71 @@ CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession, /* * structure to collect key handles. */ +typedef struct pk11CrlDataStr { + PK11Slot *slot; + PK11SearchResults *searchHandles; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; +} pk11CrlData; + + +static SECStatus +pk11_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg) +{ + pk11CrlData *crlData; + CK_OBJECT_HANDLE class_handle; + PK11Slot *slot; + + crlData = (pk11CrlData *)arg; + slot = crlData->slot; + + class_handle = (type == certDBEntryTypeRevocation) ? PK11_TOKEN_TYPE_CRL : + PK11_TOKEN_KRL_HANDLE; + if (pk11_tokenMatch(slot, key, class_handle, + crlData->template, crlData->templ_count)) { + pk11_addHandle(crlData->searchHandles, + pk11_mkHandle(slot,key,class_handle)); + } + return(SECSuccess); +} + +static void +pk11_searchCrls(PK11Slot *slot, SECItem *derSubject, PRBool isKrl, + unsigned long classFlags, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) +{ + NSSLOWCERTCertDBHandle *certHandle = NULL; + + certHandle = slot->certDB; + if (certHandle == NULL) { + return; + } + if (derSubject->data != NULL) { + SECItem *crl = + nsslowcert_FindCrlByKey(certHandle,derSubject,NULL,isKrl); + + if (crl != NULL) { + pk11_addHandle(search, pk11_mkHandle(slot,derSubject, + isKrl ? PK11_TOKEN_KRL_HANDLE : PK11_TOKEN_TYPE_CRL)); + } + } else { + pk11CrlData crlData; + + /* traverse */ + crlData.slot = slot; + crlData.searchHandles = search; + crlData.template = pTemplate; + crlData.templ_count = ulCount; + nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation, + pk11_crl_collect, (void *)&crlData); + nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation, + pk11_crl_collect, (void *)&crlData); + } +} + +/* + * structure to collect key handles. + */ typedef struct pk11KeyDataStr { PK11Slot *slot; PK11SearchResults *searchHandles; @@ -2929,19 +3166,6 @@ typedef struct pk11KeyDataStr { PRBool strict; } pk11KeyData; -/* - * structure to collect certs into - */ -typedef struct pk11CertDataStr { - PK11Slot *slot; - int cert_count; - int max_cert_count; - NSSLOWCERTCertificate **certs; - CK_ATTRIBUTE *template; - CK_ULONG templ_count; - unsigned long classFlags; - PRBool strict; -} pk11CertData; static SECStatus pk11_key_collect(DBT *key, DBT *data, void *arg) @@ -3013,6 +3237,58 @@ loser: } return(SECSuccess); } + +static void +pk11_searchKeys(PK11Slot *slot, SECItem *key_id, PRBool isLoggedIn, + unsigned long classFlags, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) +{ + NSSLOWKEYDBHandle *keyHandle = NULL; + NSSLOWKEYPrivateKey *privKey; + pk11KeyData keyData; + + keyHandle = slot->keyDB; + if (keyHandle == NULL) { + return; + } + + if (key_id->data && (classFlags & NSC_KEY)) { + privKey = nsslowkey_FindKeyByPublicKey(keyHandle,key_id, slot->password); + if (privKey) { + pk11_addHandle(search,pk11_mkHandle(slot,key_id,PK11_TOKEN_TYPE_KEY)); + nsslowkey_DestroyPrivateKey(privKey); + } + if ( !(classFlags & (NSC_PRIVATE|NSC_PUBLIC)) ) { + /* skip the traverse, nothing new to find */ + return; + } + } + keyData.slot = slot; + keyData.searchHandles = search; + keyData.id = key_id; + keyData.template = pTemplate; + keyData.templ_count = ulCount; + keyData.isLoggedIn = isLoggedIn; + keyData.classFlags = classFlags; + keyData.strict = NSC_STRICT; + + nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData); +} + +/* + * structure to collect certs into + */ +typedef struct pk11CertDataStr { + PK11Slot *slot; + int cert_count; + int max_cert_count; + NSSLOWCERTCertificate **certs; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; + unsigned long classFlags; + PRBool strict; +} pk11CertData; + /* * collect all the certs from the traverse call. */ @@ -3183,6 +3459,42 @@ pk11_searchCertsAndTrust(PK11Slot *slot, SECItem *derCert, SECItem *name, return; } +static void +pk11_searchSMime(PK11Slot *slot, SECItem *email, PK11SearchResults *handles, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) +{ + NSSLOWCERTCertDBHandle *certHandle = NULL; + certDBEntrySMime *entry; + + certHandle = slot->certDB; + if (certHandle == NULL) return; + + if (email->data != NULL) { + char *tmp_name = (char*)PORT_Alloc(email->len+1); + int count; + + if (tmp_name == NULL) { + return; + } + PORT_Memcpy(tmp_name,email->data,email->len); + tmp_name[email->len] = 0; + + entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name); + if (entry) { + SECItem emailKey; + + emailKey.data = (unsigned char *)tmp_name; + emailKey.len = PORT_Strlen(tmp_name)+1; + pk11_addHandle(handles, + pk11_mkHandle(slot,&emailKey,PK11_TOKEN_TYPE_SMIME)); + nsslowcert_DestroyDBEntry((certDBEntry *)entry); + } + PORT_Free(tmp_name); + } + return; +} + + static CK_RV pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount, @@ -3193,6 +3505,7 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, SECItem derCert = { siBuffer, NULL, 0 }; SECItem derSubject = { siBuffer, NULL, 0 }; SECItem name = { siBuffer, NULL, 0 }; + SECItem email = { siBuffer, NULL, 0 }; SECItem key_id = { siBuffer, NULL, 0 }; SECItem cert_sha1_hash = { siBuffer, NULL, 0 }; SECItem cert_md5_hash = { siBuffer, NULL, 0 }; @@ -3209,19 +3522,19 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, classFlags &= ~(NSC_PRIVATE|NSC_KEY); } - /* - * look for things to search on certs for. We only need one of these - * items. If we find all the certs that match that item, import them - * (as long as they are user certs). We'll let find objects filter out - * the ones that don't apply. + * look for things to search on token objects for. If the right options + * are specified, we can use them as direct indeces into the database + * (rather than using linear searches. We can also use the attributes to + * limit the kinds of objects we are searching for. Later we can use this + * array to filter the remaining objects more finely. */ for (i=0 ;classFlags && i < (int)ulCount; i++) { switch (pTemplate[i].type) { case CKA_SUBJECT: copy = &derSubject; - classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC); + classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC|NSC_SMIME); break; case CKA_ISSUER: copy = &issuerSN.derIssuer; @@ -3233,11 +3546,18 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, break; case CKA_VALUE: copy = &derCert; - classFlags &= (NSC_CERT|NSC_CRL); + classFlags &= (NSC_CERT|NSC_CRL|NSC_SMIME); break; case CKA_LABEL: copy = &name; break; + case CKA_NETSCAPE_EMAIL: + copy = &email; + classFlags &= NSC_SMIME; + break; + case CKA_NETSCAPE_SMIME_TIMESTAMP: + classFlags &= NSC_SMIME; + break; case CKA_CLASS: if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) { classFlags = 0; @@ -3253,6 +3573,9 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, case CKO_NETSCAPE_CRL: classFlags &= NSC_CRL; break; + case CKO_NETSCAPE_SMIME: + classFlags &= NSC_SMIME; + break; case CKO_PRIVATE_KEY: classFlags &= NSC_PRIVATE; break; @@ -3313,10 +3636,15 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, } break; case CKA_ID: - copy = &key_id; break; + copy = &key_id; + classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_KEY|NSC_PUBLIC); + break; case CKA_NETSCAPE_KRL: + if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { + classFlags = 0; + } classFlags &= NSC_CRL; - isKrl = PR_TRUE; + isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE); break; case CKA_MODIFIABLE: break; @@ -3366,64 +3694,19 @@ pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, /* keys */ if (classFlags & (NSC_PRIVATE|NSC_PUBLIC|NSC_KEY)) { - NSSLOWKEYDBHandle *keyHandle = NULL; - NSSLOWKEYPrivateKey *privKey; - pk11KeyData keyData; - - keyHandle = slot->keyDB; - if (keyHandle == NULL) { - goto key_loser; - } - - if (key_id.data && (classFlags & NSC_KEY)) { - privKey = nsslowkey_FindKeyByPublicKey(keyHandle,&key_id, - slot->password); - if (privKey) { - pk11_addHandle(search,pk11_mkHandle(slot,&key_id, - PK11_TOKEN_TYPE_KEY)); - nsslowkey_DestroyPrivateKey(privKey); - } - if ( !(classFlags & (NSC_PRIVATE|NSC_PUBLIC)) ) { - /* skip the traverse, nothing new to find */ - goto key_loser; - } - } - keyData.slot = slot; - keyData.searchHandles = search; - keyData.id = &key_id; - keyData.template = pTemplate; - keyData.templ_count = ulCount; - keyData.isLoggedIn = isLoggedIn; - keyData.classFlags = classFlags; - keyData.strict = NSC_STRICT; - - nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData); + pk11_searchKeys(slot, &key_id, isLoggedIn, classFlags, search, + pTemplate, ulCount); } -key_loser: /* crl's */ if (classFlags & NSC_CRL) { - NSSLOWCERTCertDBHandle *certHandle = NULL; - - certHandle = slot->certDB; - if (certHandle == NULL) { - goto crl_loser; - } - if (derSubject.data != NULL) { - SECItem *crl = - nsslowcert_FindCrlByKey(certHandle,&derSubject,NULL,isKrl); - - if (crl != NULL) { - pk11_addHandle(search, - pk11_mkHandle(slot,&derSubject,PK11_TOKEN_TYPE_CRL)); - } - } else { - /* traverse */ - PORT_Assert(0); - } + pk11_searchCrls(slot, &derSubject, isKrl, classFlags, search, + pTemplate, ulCount); } -crl_loser: /* Add S/MIME entry stuff */ + if (classFlags & NSC_SMIME) { + pk11_searchSMime(slot, &email, search, pTemplate, ulCount); + } return CKR_OK; } diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index f1ab1df0c..6da00d8b8 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -58,7 +58,7 @@ #include "sechash.h" #include "secder.h" #include "secdig.h" -#include "secpkcs5.h" /* We do PBE below */ +#include "lowpbe.h" /* We do PBE below */ #include "pkcs11t.h" #include "secoid.h" #include "alghmac.h" @@ -119,11 +119,6 @@ pk11_Space(void *data, PRBool freeit) PORT_Free(data); } -static void pk11_FreeSignInfo(PK11HashSignInfo *data, PRBool freeit) -{ - nsslowkey_DestroyPrivateKey(data->key); - PORT_Free(data); -} /* * turn a CDMF key into a des key. CDMF is an old IBM scheme to export DES by @@ -176,9 +171,9 @@ pk11_cdmf2des(unsigned char *cdmfkey, unsigned char *deskey) static CK_RV -pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, +pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype, - PK11ContextType contextType); + PK11ContextType contextType, PRBool isEncrypt); /* * Calculate a Lynx checksum for CKM_LYNX_WRAP mechanism. */ @@ -206,7 +201,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey, /* encrypt with key 1 */ - crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT, + PR_TRUE); if (crv != CKR_OK) return crv; crv = NSC_Encrypt(hSession,key,len,E,&Elen); @@ -215,7 +211,8 @@ pk11_calcLynxChecksum(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hWrapKey, E[8] = (sum2 >> 8) & 0xff; E[9] = sum2 & 0xff; - crv = pk11_EncryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession,&mech,hWrapKey,CKA_WRAP, PK11_ENCRYPT, + PR_TRUE); if (crv != CKR_OK) return crv; crv = NSC_Encrypt(hSession,&E[2],len,C,&Clen); @@ -422,18 +419,19 @@ pk11_InitGeneric(PK11Session *session,PK11SessionContext **contextPtr, context->hashInfo = NULL; context->doPad = PR_FALSE; context->padDataLength = 0; + context->key = key; *contextPtr = context; return CKR_OK; } -/* NSC_EncryptInit initializes an encryption operation. */ +/* NSC_CryptInit initializes an encryption/Decryption operation. */ /* This function is used by NSC_EncryptInit and NSC_WrapKey. The only difference * in their uses if whether or not etype is CKA_ENCRYPT or CKA_WRAP */ static CK_RV -pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, +pk11_CryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE etype, - PK11ContextType contextType) + PK11ContextType contextType, PRBool isEncrypt) { PK11Session *session; PK11Object *key; @@ -456,7 +454,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, if (session == NULL) return CKR_SESSION_HANDLE_INVALID; crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type, - CKO_PUBLIC_KEY, etype); + isEncrypt ?CKO_PUBLIC_KEY:CKO_PRIVATE_KEY, etype); if (crv != CKR_OK) { pk11_FreeSession(session); @@ -472,14 +470,22 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, break; } context->multi = PR_FALSE; - pubKey = pk11_GetPubKey(key,CKK_RSA); - if (pubKey == NULL) { + context->cipherInfo = isEncrypt ? + (void *)pk11_GetPubKey(key,CKK_RSA) : + (void *)pk11_GetPrivKey(key,CKK_RSA); + if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->cipherInfo = pubKey; - context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509 - ? RSA_EncryptRaw : RSA_EncryptBlock); + if (isEncrypt) { + context->update = (PK11Cipher) + (pMechanism->mechanism == CKM_RSA_X_509 + ? RSA_EncryptRaw : RSA_EncryptBlock); + } else { + context->update = (PK11Cipher) + (pMechanism->mechanism == CKM_RSA_X_509 + ? RSA_DecryptRaw : RSA_DecryptBlock); + } context->destroy = pk11_Null; break; case CKM_RC2_CBC_PAD: @@ -509,7 +515,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) RC2_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC2_Encrypt : RC2_Decrypt); context->destroy = (PK11Destroy) RC2_DestroyContext; break; #if NSS_SOFTOKEN_DOES_RC5 @@ -541,7 +547,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) RC5_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC5_Encrypt : RC5_Decrypt); context->destroy = (PK11Destroy) RC5_DestroyContext; break; #endif @@ -563,7 +569,7 @@ pk11_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, crv = CKR_HOST_MEMORY; /* WRONG !!! */ break; } - context->update = (PK11Cipher) RC4_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? RC4_Encrypt : RC4_Decrypt); context->destroy = (PK11Destroy) RC4_DestroyContext; break; case CKM_CDMF_CBC_PAD: @@ -630,13 +636,13 @@ finish_des: } context->cipherInfo = DES_CreateContext( useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter,t, PR_TRUE); + (unsigned char*)pMechanism->pParameter,t, isEncrypt); pk11_FreeAttribute(att); if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) DES_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? DES_Encrypt : DES_Decrypt); context->destroy = (PK11Destroy) DES_DestroyContext; break; @@ -659,13 +665,13 @@ finish_des: (unsigned char*)att->attrib.pValue, (unsigned char*)pMechanism->pParameter, pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC, - PR_TRUE, att->attrib.ulValueLen, 16); + isEncrypt, att->attrib.ulValueLen, 16); pk11_FreeAttribute(att); if (context->cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; } - context->update = (PK11Cipher) AES_Encrypt; + context->update = (PK11Cipher) (isEncrypt ? AES_Encrypt : AES_Decrypt); context->destroy = (PK11Destroy) AES_DestroyContext; break; @@ -674,7 +680,6 @@ finish_des: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { pk11_FreeContext(context); pk11_FreeSession(session); @@ -689,8 +694,8 @@ finish_des: CK_RV NSC_EncryptInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { - return pk11_EncryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, - PK11_ENCRYPT); + return pk11_CryptInit(hSession, pMechanism, hKey, CKA_ENCRYPT, + PK11_ENCRYPT, PR_TRUE); } /* NSC_EncryptUpdate continues a multiple-part encryption operation. */ @@ -846,258 +851,11 @@ CK_RV NSC_Encrypt (CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, */ /* NSC_DecryptInit initializes a decryption operation. */ -static CK_RV pk11_DecryptInit( CK_SESSION_HANDLE hSession, - CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, CK_ATTRIBUTE_TYPE dtype, - PK11ContextType contextType) -{ - PK11Session *session; - PK11Object *key; - PK11Attribute *att; - PK11SessionContext *context; - CK_RC2_CBC_PARAMS *rc2_param; -#if NSS_SOFTOKEN_DOES_RC5 - CK_RC5_CBC_PARAMS *rc5_param; - SECItem rc5Key; -#endif - CK_KEY_TYPE key_type; - CK_RV crv = CKR_OK; - unsigned effectiveKeyLength; - NSSLOWKEYPrivateKey *privKey; - unsigned char newdeskey[8]; - PRBool useNewKey=PR_FALSE; - int t; - - session = pk11_SessionFromHandle(hSession); - if (session == NULL) return CKR_SESSION_HANDLE_INVALID; - - crv = pk11_InitGeneric(session,&context,contextType,&key,hKey,&key_type, - CKO_PRIVATE_KEY,dtype); - if (crv != CKR_OK) { - pk11_FreeSession(session); - return crv; - } - - /* - * now handle each mechanism - */ - switch(pMechanism->mechanism) { - case CKM_RSA_PKCS: - case CKM_RSA_X_509: - if (key_type != CKK_RSA) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - context->multi = PR_FALSE; - privKey = pk11_GetPrivKey(key,CKK_RSA); - if (privKey == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->cipherInfo = privKey; - context->update = (PK11Cipher) (pMechanism->mechanism == CKM_RSA_X_509 - ? RSA_DecryptRaw : RSA_DecryptBlock); - context->destroy = (context->cipherInfo == key->objectInfo) ? - (PK11Destroy) pk11_Null : (PK11Destroy) pk11_FreePrivKey; - break; - case CKM_RC2_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_RC2_ECB: - case CKM_RC2_CBC: - if (key_type != CKK_RC2) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - rc2_param = (CK_RC2_CBC_PARAMS *)pMechanism->pParameter; - effectiveKeyLength = (rc2_param->ulEffectiveBits+7)/8; - context->cipherInfo = RC2_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen, rc2_param->iv, - pMechanism->mechanism == CKM_RC2_ECB ? NSS_RC2 : - NSS_RC2_CBC, effectiveKeyLength); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC2_Decrypt; - context->destroy = (PK11Destroy) RC2_DestroyContext; - break; -#if NSS_SOFTOKEN_DOES_RC5 - case CKM_RC5_CBC_PAD: - context->doPad = PR_TRUE; - /* fall thru */ - case CKM_RC5_ECB: - case CKM_RC5_CBC: - if (key_type != CKK_RC5) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - rc5_param = (CK_RC5_CBC_PARAMS *)pMechanism->pParameter; - if (context->doPad) { - context->blockSize = rc5_param->ulWordsize*2; - } - rc5Key.data = (unsigned char*)att->attrib.pValue; - rc5Key.len = att->attrib.ulValueLen; - context->cipherInfo = RC5_CreateContext(&rc5Key,rc5_param->ulRounds, - rc5_param->ulWordsize,rc5_param->pIv, - pMechanism->mechanism == CKM_RC5_ECB ? NSS_RC5 : NSS_RC5_CBC); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC5_Decrypt; - context->destroy = (PK11Destroy) RC5_DestroyContext; - break; -#endif - case CKM_RC4: - if (key_type != CKK_RC4) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - context->cipherInfo = - RC4_CreateContext((unsigned char*)att->attrib.pValue, - att->attrib.ulValueLen); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) RC4_Decrypt; - context->destroy = (PK11Destroy) RC4_DestroyContext; - break; - case CKM_CDMF_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_CDMF_ECB: - case CKM_CDMF_CBC: - if (key_type != CKK_CDMF) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = (pMechanism->mechanism == CKM_CDMF_ECB) ? NSS_DES : NSS_DES_CBC; - useNewKey = PR_TRUE; - if (crv != CKR_OK) break; - goto finish_des; - case CKM_DES_ECB: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES; - goto finish_des; - case CKM_DES_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_DES_CBC: - if (key_type != CKK_DES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_CBC; - goto finish_des; - case CKM_DES3_ECB: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3; - goto finish_des; - case CKM_DES3_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 8; - /* fall thru */ - case CKM_DES3_CBC: - if ((key_type != CKK_DES2) && (key_type != CKK_DES3)) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - t = NSS_DES_EDE3_CBC; -finish_des: - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - if (useNewKey) { - crv = pk11_cdmf2des((unsigned char*)att->attrib.pValue,newdeskey); - if (crv != CKR_OK) { - pk11_FreeAttribute(att); - break; - } - } - context->cipherInfo = DES_CreateContext( - useNewKey ? newdeskey : (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter,t, PR_FALSE); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) DES_Decrypt; - context->destroy = (PK11Destroy) DES_DestroyContext; - - break; - case CKM_AES_CBC_PAD: - context->doPad = PR_TRUE; - context->blockSize = 16; - /* fall thru */ - case CKM_AES_ECB: - case CKM_AES_CBC: - if (key_type != CKK_AES) { - crv = CKR_KEY_TYPE_INCONSISTENT; - break; - } - att = pk11_FindAttribute(key,CKA_VALUE); - if (att == NULL) { - crv = CKR_KEY_HANDLE_INVALID; - break; - } - context->cipherInfo = AES_CreateContext( - (unsigned char*)att->attrib.pValue, - (unsigned char*)pMechanism->pParameter, - pMechanism->mechanism == CKM_AES_ECB ? NSS_AES : NSS_AES_CBC, - PR_FALSE, att->attrib.ulValueLen,16); - pk11_FreeAttribute(att); - if (context->cipherInfo == NULL) { - crv = CKR_HOST_MEMORY; - break; - } - context->update = (PK11Cipher) AES_Decrypt; - context->destroy = (PK11Destroy) AES_DestroyContext; - - break; - default: - crv = CKR_MECHANISM_INVALID; - break; - } - - pk11_FreeObject(key); - if (crv != CKR_OK) { - pk11_FreeContext(context); - pk11_FreeSession(session); - return crv; - } - pk11_SetContextByType(session, contextType, context); - pk11_FreeSession(session); - return CKR_OK; -} - -/* NSC_DecryptInit initializes a decryption operation. */ CK_RV NSC_DecryptInit( CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { - return pk11_DecryptInit(hSession,pMechanism,hKey,CKA_DECRYPT,PK11_DECRYPT); + return pk11_CryptInit(hSession, pMechanism, hKey, CKA_DECRYPT, + PK11_DECRYPT, PR_FALSE); } /* NSC_DecryptUpdate continues a multiple-part decryption operation. */ @@ -1867,8 +1625,8 @@ pk11_InitCBCMac(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, return CKR_FUNCTION_NOT_SUPPORTED; } - crv = pk11_EncryptInit(hSession, &cbc_mechanism, hKey, keyUsage, - contextType); + crv = pk11_CryptInit(hSession, &cbc_mechanism, hKey, keyUsage, + contextType, PR_TRUE); if (crv != CKR_OK) return crv; crv = pk11_GetContext(hSession,&context,contextType,PR_TRUE,NULL); @@ -2063,23 +1821,14 @@ finish_rsa: /* OK, info is allocated only if we're doing hash and sign mechanism. * It's necessary to be able to set the correct OID in the final * signature. - * Second, what's special about privKey == key->objectInfo? - * Well we don't 'cache' token versions - * of private keys because (1) it's sensitive data, and (2) it never - * gets destroyed. Instead we grab the key out of the database as - * necessary, but now the key is our context, and we need to free - * it when we are done. Non-token private keys will get freed when - * the user destroys the session object (or the session the session - * object lives in) */ + */ if (info) { info->key = privKey; context->cipherInfo = info; - context->destroy = (privKey == key->objectInfo) ? - (PK11Destroy)pk11_Space:(PK11Destroy)pk11_FreeSignInfo; + context->destroy = (PK11Destroy)pk11_Space; } else { context->cipherInfo = privKey; - context->destroy = (privKey == key->objectInfo) ? - (PK11Destroy)pk11_Null:(PK11Destroy)pk11_FreePrivKey; + context->destroy = (PK11Destroy)pk11_Null; } break; @@ -2141,9 +1890,8 @@ finish_rsa: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { - PORT_Free(context); + pk11_FreeContext(context); pk11_FreeSession(session); return crv; } @@ -2546,7 +2294,6 @@ finish_rsa: break; } - pk11_FreeObject(key); if (crv != CKR_OK) { PORT_Free(context); pk11_FreeSession(session); @@ -2688,7 +2435,6 @@ CK_RV NSC_VerifyRecoverInit(CK_SESSION_HANDLE hSession, break; } - pk11_FreeObject(key); if (crv != CKR_OK) { PORT_Free(context); pk11_FreeSession(session); @@ -3134,10 +2880,6 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, */ crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(key); - return crv; - } if (pk11_isTrue(key,CKA_SENSITIVE)) { pk11_forceAttribute(key,CKA_ALWAYS_SENSITIVE,&cktrue,sizeof(CK_BBOOL)); } @@ -3146,7 +2888,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, } *phKey = key->handle; - return CKR_OK; + pk11_FreeObject(key); + return crv; } @@ -3471,7 +3214,7 @@ dhgn_done: /* * handle the base object cleanup for the public Key */ - crv = pk11_handleObject(publicKey,session); + crv = pk11_handleObject(privateKey,session); if (crv != CKR_OK) { pk11_FreeSession(session); pk11_FreeObject(privateKey); @@ -3484,11 +3227,12 @@ dhgn_done: * If we have any problems, we destroy the public Key we've * created and linked. */ - crv = pk11_handleObject(privateKey,session); + crv = pk11_handleObject(publicKey,session); pk11_FreeSession(session); if (crv != CKR_OK) { + pk11_FreeObject(publicKey); + NSC_DestroyObject(hSession,privateKey->handle); pk11_FreeObject(privateKey); - NSC_DestroyObject(hSession,publicKey->handle); return crv; } if (pk11_isTrue(privateKey,CKA_SENSITIVE)) { @@ -3509,6 +3253,8 @@ dhgn_done: } *phPrivateKey = privateKey->handle; *phPublicKey = publicKey->handle; + pk11_FreeObject(publicKey); + pk11_FreeObject(privateKey); return CKR_OK; } @@ -3656,8 +3402,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, len = *pulWrappedKeyLen; } - crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, PK11_ENCRYPT, PR_TRUE); if (crv != CKR_OK) { pk11_FreeAttribute(attribute); break; @@ -3688,8 +3434,8 @@ CK_RV NSC_WrapKey(CK_SESSION_HANDLE hSession, break; } - crv = pk11_EncryptInit(hSession, pMechanism, hWrappingKey, - CKA_WRAP, PK11_ENCRYPT); + crv = pk11_CryptInit(hSession, pMechanism, hWrappingKey, + CKA_WRAP, PK11_ENCRYPT, PR_TRUE); if(crv != CKR_OK) { SECITEM_ZfreeItem(bpki, PR_TRUE); crv = CKR_KEY_TYPE_INCONSISTENT; @@ -3948,8 +3694,8 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, ulWrappedKeyLen -= 2; /* don't decrypt the checksum */ } - crv = pk11_DecryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, - PK11_DECRYPT); + crv = pk11_CryptInit(hSession,pMechanism,hUnwrappingKey,CKA_UNWRAP, + PK11_DECRYPT, PR_FALSE); if (crv != CKR_OK) { pk11_FreeObject(key); return pk11_mapWrap(crv); @@ -4026,14 +3772,11 @@ CK_RV NSC_UnwrapKey(CK_SESSION_HANDLE hSession, * handle the base object stuff */ crv = pk11_handleObject(key,session); + *phKey = key->handle; pk11_FreeSession(session); - if (crv != CKR_OK) { - pk11_FreeObject(key); - return crv; - } + pk11_FreeObject(key); - *phKey = key->handle; - return CKR_OK; + return crv; } @@ -4091,10 +3834,7 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey, crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv == CKR_OK) { - *keyHandle = key->handle; - return crv; - } + *keyHandle = key->handle; loser: if (key) pk11_FreeObject(key); return crv; @@ -5212,10 +4952,7 @@ key_and_mac_derive_fail: crv = pk11_handleObject(key,session); pk11_FreeSession(session); - if (crv == CKR_OK) { - *phKey = key->handle; - return crv; - } + *phKey = key->handle; pk11_FreeObject(key); } return crv; diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index 102fb5738..c09b2635e 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -88,6 +88,8 @@ /* default search block allocations and increments */ #define NSC_CERT_BLOCK_SIZE 50 #define NSC_SEARCH_BLOCK_SIZE 5 +#define NSC_SLOT_LIST_BLOCK_SIZE 10 + /* these are data base storage hashes, not cryptographic hashes.. The define * the effective size of the various object hash tables */ #define ATTRIBUTE_HASH_SIZE 32 @@ -278,6 +280,7 @@ struct PK11SessionContextStr { PK11Destroy hashdestroy; PK11Verify verify; unsigned int maxLen; + PK11Object *key; }; /* @@ -315,15 +318,20 @@ struct PK11SlotStr { PRBool ssoLoggedIn; PRBool needLogin; PRBool DB_loaded; + PRBool readOnly; NSSLOWCERTCertDBHandle *certDB; NSSLOWKEYDBHandle *keyDB; + int minimumPinLen; int sessionIDCount; int sessionCount; int rwSessionCount; int tokenIDCount; + int index; PLHashTable *tokenHashTable; PK11Object *tokObjects[TOKEN_OBJECT_HASH_SIZE]; PK11Session *head[SESSION_HASH_SIZE]; + char tokDescription[33]; + char slotDescription[64]; }; /* @@ -354,8 +362,7 @@ struct PK11SSLMACInfoStr { /* * session handle modifiers */ -#define PK11_PRIVATE_KEY_FLAG 0x80000000L -#define PK11_FIPS_FLAG 0x40000000L +#define PK11_SESSION_SLOT_MASK 0xff000000L /* * object handle modifiers @@ -373,6 +380,7 @@ struct PK11SSLMACInfoStr { #define PK11_TOKEN_TYPE_SMIME 0x60000000L #define PK11_TOKEN_TYPE_CERT 0x70000000L +#define PK11_TOKEN_KRL_HANDLE (PK11_TOKEN_MAGIC|PK11_TOKEN_TYPE_CRL|0) /* how big a password/pin we can deal with */ #define PK11_MAX_PIN 255 @@ -411,27 +419,36 @@ struct PK11SSLMACInfoStr { #define pk11_attr_expand(ap) (ap)->type,(ap)->pValue,(ap)->ulValueLen #define pk11_item_expand(ip) (ip)->data,(ip)->len -typedef struct pk11_parametersStr { +typedef struct pk11_token_parametersStr { + CK_SLOT_ID slotID; char *configdir; char *certPrefix; char *keyPrefix; - char *secmodName; - char *man; - char *libdes; char *tokdes; - char *ptokdes; char *slotdes; - char *pslotdes; - char *fslotdes; - char *fpslotdes; int minPW; PRBool readOnly; PRBool noCertDB; + PRBool noKeyDB; + PRBool forceOpen; + PRBool pwRequired; +} pk11_token_parameters; + +typedef struct pk11_parametersStr { + char *configdir; + char *secmodName; + char *man; + char *libdes; + PRBool readOnly; PRBool noModDB; + PRBool noCertDB; PRBool forceOpen; PRBool pwRequired; + pk11_token_parameters *tokens; + int token_count; } pk11_parameters; + /* machine dependent path stuff used by dbinit.c and pk11db.c */ #ifdef macintosh #define PATH_SEPARATOR ":" @@ -447,10 +464,9 @@ typedef struct pk11_parametersStr { SEC_BEGIN_PROTOS +extern CK_RV nsc_CommonInitialize(CK_VOID_PTR pReserved, PRBool isFIPS); /* shared functions between PKCS11.c and PK11FIPS.c */ -extern CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved); -extern CK_RV PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin, - NSSLOWCERTCertDBHandle *certdb, NSSLOWKEYDBHandle *keydb); +extern CK_RV PK11_SlotInit(char *configdir,pk11_token_parameters *params); /* internal utility functions used by pkcs11.c */ extern PK11Attribute *pk11_FindAttribute(PK11Object *object, @@ -518,7 +534,8 @@ extern void pk11_FormatDESKey(unsigned char *key, int length); extern PRBool pk11_CheckDESKey(unsigned char *key); extern PRBool pk11_IsWeakKey(unsigned char *key,CK_KEY_TYPE key_type); -extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed); +extern CK_RV secmod_parseParameters(char *param, pk11_parameters *parsed, + PRBool isFIPS); extern void secmod_freeParams(pk11_parameters *params); extern char *secmod_getSecmodName(char *params, PRBool *rw); extern char ** secmod_ReadPermDB(char *dbname, char *params, PRBool rw); @@ -542,8 +559,9 @@ extern SECStatus secmod_AddPermDB(char *dbname, char *module, PRBool rw); * be opened. */ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, - const char *keyPrefix, const char *secmodName, PRBool readOnly, - PRBool noCertDB, PRBool noModDB, PRBool forceOpen); + const char *keyPrefix, PRBool readOnly, PRBool noCertDB, + PRBool noKeyDB, PRBool forceOpen, + NSSLOWCERTCertDBHandle **certDB, NSSLOWKEYDBHandle **keyDB); /* * narrow objects diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 1abdbe131..16f7a4ee0 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -40,15 +40,6 @@ #include "pcert.h" #include "secasn1.h" - -/* declare the internal pkcs11 slot structures: - * There are threee: - * slot 0 is the generic crypto service token. - * slot 1 is the Database service token. - * slot 2 is the FIPS token (both generic and database). - */ -static PK11Slot pk11_slot[3]; - /* * ******************** Attribute Utilities ******************************* */ @@ -313,10 +304,35 @@ static const PK11Attribute pk11_StaticMustVerifyAttr = PK11_DEF_ATTRIBUTE(&pk11_staticMustVerifyValue, sizeof(pk11_staticMustVerifyValue)); -SECItem * +static void pk11_FreeItem(SECItem *item) +{ + SECITEM_FreeItem(item, PR_TRUE); +} + +static certDBEntrySMime * +pk11_getSMime(PK11TokenObject *object) +{ + certDBEntrySMime *entry; + + if (object->obj.objclass != CKO_NETSCAPE_SMIME) { + return NULL; + } + if (object->obj.objectInfo) { + return (certDBEntrySMime *)object->obj.objectInfo; + } + + entry = nsslowcert_ReadDBSMimeEntry(object->obj.slot->certDB, + (char *)object->dbKey.data); + object->obj.objectInfo = (void *)entry; + object->obj.infoFree = (PK11Free) nsslowcert_DestroyDBEntry; + return entry; +} + +static SECItem * pk11_getCrl(PK11TokenObject *object) { SECItem *crl; + PRBool isKrl; if (object->obj.objclass != CKO_NETSCAPE_CRL) { return NULL; @@ -324,14 +340,39 @@ pk11_getCrl(PK11TokenObject *object) if (object->obj.objectInfo) { return (SECItem *)object->obj.objectInfo; } + + isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE; crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey, - NULL,PR_FALSE); + NULL,isKrl); object->obj.objectInfo = (void *)crl; - object->obj.infoFree = (PK11Free) SECITEM_FreeItem; + object->obj.infoFree = (PK11Free) pk11_FreeItem; return crl; } -NSSLOWCERTCertificate * +static char * +pk11_getUrl(PK11TokenObject *object) +{ + SECItem *crl; + PRBool isKrl; + char *url = NULL; + + if (object->obj.objclass != CKO_NETSCAPE_CRL) { + return NULL; + } + + isKrl = (PRBool) object->obj.handle == PK11_TOKEN_KRL_HANDLE; + crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey, + &url,isKrl); + if (object->obj.objectInfo == NULL) { + object->obj.objectInfo = (void *)crl; + object->obj.infoFree = (PK11Free) pk11_FreeItem; + } else { + if (crl) SECITEM_FreeItem(crl,PR_TRUE); + } + return url; +} + +static NSSLOWCERTCertificate * pk11_getCert(PK11TokenObject *object) { NSSLOWCERTCertificate *cert; @@ -349,7 +390,7 @@ pk11_getCert(PK11TokenObject *object) return cert; } -NSSLOWKEYPublicKey * +static NSSLOWKEYPublicKey * pk11_GetPublicKey(PK11TokenObject *object) { NSSLOWKEYPublicKey *pubKey; @@ -370,12 +411,12 @@ pk11_GetPublicKey(PK11TokenObject *object) return pubKey; } -NSSLOWKEYPrivateKey * +static NSSLOWKEYPrivateKey * pk11_GetPrivateKey(PK11TokenObject *object) { NSSLOWKEYPrivateKey *privKey; - if (object->obj.objclass != CKO_PUBLIC_KEY) { + if (object->obj.objclass != CKO_PRIVATE_KEY) { return NULL; } if (object->obj.objectInfo) { @@ -418,7 +459,7 @@ static const SEC_ASN1Template pk11_SerialTemplate[] = { { 0 } }; -PK11Attribute * +static PK11Attribute * pk11_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) { unsigned char hash[SHA1_LENGTH]; @@ -448,7 +489,8 @@ pk11_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) } return NULL; } -PK11Attribute * + +static PK11Attribute * pk11_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) { unsigned char hash[SHA1_LENGTH]; @@ -486,7 +528,8 @@ pk11_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) } return NULL; } -PK11Attribute * + +static PK11Attribute * pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) { unsigned char hash[SHA1_LENGTH]; @@ -520,15 +563,20 @@ pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWKEYPublicKey *key; switch (type) { case CKA_PRIVATE: - case CKA_MODIFIABLE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_NEVER_EXTRACTABLE: return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + case CKA_EXTRACTABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; default: break; } @@ -550,7 +598,8 @@ pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * + +static PK11Attribute * pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWKEYPrivateKey *key; @@ -592,7 +641,7 @@ pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) { @@ -630,7 +679,8 @@ pk11_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, } return NULL; } -PK11Attribute * + +static PK11Attribute * pk11_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) { @@ -669,7 +719,7 @@ pk11_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) { unsigned char hash[SHA1_LENGTH]; @@ -702,7 +752,7 @@ pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWKEYPrivateKey *key; @@ -711,9 +761,9 @@ pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) case CKA_SENSITIVE: case CKA_ALWAYS_SENSITIVE: case CKA_EXTRACTABLE: + case CKA_MODIFIABLE: return (PK11Attribute *) &pk11_StaticTrueAttr; case CKA_NEVER_EXTRACTABLE: - case CKA_MODIFIABLE: return (PK11Attribute *) &pk11_StaticFalseAttr; default: break; @@ -736,21 +786,42 @@ pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindSMIMEAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { + certDBEntrySMime *entry; NSSLOWCERTCertificate *cert; switch (type) { case CKA_PRIVATE: case CKA_MODIFIABLE: return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_NETSCAPE_EMAIL: + return pk11_NewTokenAttribute(type,object->dbKey.data, + object->dbKey.len, PR_FALSE); + default: + break; + } + entry = pk11_getSMime(object); + if (entry == NULL) { + return NULL; + } + switch (type) { + case CKA_NETSCAPE_SMIME_TIMESTAMP: + return pk11_NewTokenAttribute(type,entry->optionsDate.data, + entry->optionsDate.len, PR_FALSE); + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,entry->subjectName.data, + entry->subjectName.len, PR_FALSE); + case CKA_VALUE: + return pk11_NewTokenAttribute(type,entry->smimeOptions.data, + entry->smimeOptions.len, PR_FALSE); default: break; } return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindTrustAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWCERTCertificate *cert; @@ -819,15 +890,25 @@ trust: return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { SECItem *crl; + char *url; switch (type) { case CKA_PRIVATE: case CKA_MODIFIABLE: return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_NETSCAPE_KRL: + return (PK11Attribute *) ((object->obj.handle == PK11_TOKEN_KRL_HANDLE) + ? &pk11_StaticTrueAttr : &pk11_StaticFalseAttr); + case CKA_NETSCAPE_URL: + url = pk11_getUrl(object); + if (url == NULL) { + return (PK11Attribute *) &pk11_StaticNullAttr; + } + return pk11_NewTokenAttribute(type, url, PORT_Strlen(url)+1, PR_TRUE); case CKA_VALUE: crl = pk11_getCrl(object); if (crl == NULL) break; @@ -841,7 +922,7 @@ pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) { NSSLOWCERTCertificate *cert; @@ -900,7 +981,7 @@ pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) return NULL; } -PK11Attribute * +static PK11Attribute * pk11_FindTokenAttribute(PK11TokenObject *object,CK_ATTRIBUTE_TYPE type) { /* handle the common ones */ @@ -976,6 +1057,7 @@ pk11_hasAttributeToken(PK11TokenObject *object) { return PR_FALSE; } + /* * return true if object has attribute */ @@ -1115,6 +1197,33 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) pk11_FreeAttribute(attribute); } +static CK_RV +pk11_forceTokenAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, + void *value, unsigned int len) +{ + PK11Attribute *attribute; + + /* if we are just setting it to the value we already have, + * allow it to happen. */ + attribute=pk11_FindAttribute(object,type); + if ((attribute->attrib.ulValueLen == len) && + PORT_Memcmp(attribute->attrib.pValue,value,len) == 0) { + pk11_FreeAttribute(attribute); + return CKR_OK; + } + + switch (object->objclass) { + case CKO_CERTIFICATE: + /* change NICKNAME, EMAIL, */ + break; + case CKO_NETSCAPE_CRL: + /* change URL */ + break; + } + pk11_FreeAttribute(attribute); + return CKR_ATTRIBUTE_READ_ONLY; +} + /* * force an attribute to a spaecif value. */ @@ -1126,6 +1235,9 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, void *att_val = NULL; PRBool freeData = PR_FALSE; + if (pk11_isToken(object->handle)) { + return pk11_forceTokenAttribute(object,type,value,len); + } attribute=pk11_FindAttribute(object,type); if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len); @@ -1172,6 +1284,7 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, attribute->attrib.ulValueLen = len; attribute->freeData = freeData; } + pk11_FreeAttribute(attribute); return CKR_OK; } @@ -1742,6 +1855,7 @@ pk11_AddObject(PK11Session *session, PK11Object *object) PK11_USE_THREADS(PZ_Unlock(session->objectLock);) } pk11_AddSlotObject(slot,object); + pk11_ReferenceObject(object); } /* @@ -1757,6 +1871,7 @@ pk11_DeleteObject(PK11Session *session, PK11Object *object) SECStatus rv; NSSLOWCERTCertificate *cert; NSSLOWCERTCertTrust tmptrust; + PRBool isKrl; /* Handle Token case */ if (so && so->session) { @@ -1768,6 +1883,7 @@ pk11_DeleteObject(PK11Session *session, PK11Object *object) pk11queue_delete(object,object->handle,slot->tokObjects, TOKEN_OBJECT_HASH_SIZE); PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) + pk11_FreeObject(object); /* reduce it's reference count */ } else { PORT_Assert(to); /* remove the objects from the real data base */ @@ -1793,12 +1909,9 @@ pk11_DeleteObject(PK11Session *session, PK11Object *object) nsslowcert_DestroyCertificate(cert); break; case PK11_TOKEN_TYPE_CRL: - rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,PR_FALSE); - if (rv == SECFailure) { - /* must be a KRL */ - rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,PR_TRUE); - if (rv == SECFailure) crv = CKR_DEVICE_ERROR; - } + isKrl = (PRBool) (object->handle == PK11_TOKEN_KRL_HANDLE); + rv = nsslowcert_DeletePermCRL(slot->certDB,&to->dbKey,isKrl); + if (rv == SECFailure) crv = CKR_DEVICE_ERROR; break; case PK11_TOKEN_TYPE_TRUST: cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); @@ -1824,7 +1937,6 @@ pk11_DeleteObject(PK11Session *session, PK11Object *object) pk11_deleteTokenKeyByHandle(object->slot,object->handle); pk11_tokenKeyUnlock(object->slot); } - pk11_FreeObject(object); } /* @@ -2028,37 +2140,11 @@ pk11_FreeContext(PK11SessionContext *context) if (context->hashInfo) { (*context->hashdestroy)(context->hashInfo,PR_TRUE); } - PORT_Free(context); -} - -/* look up a slot structure from the ID (used to be a macro when we only - * had two slots) */ -PK11Slot * -pk11_SlotFromID(CK_SLOT_ID slotID) -{ - switch (slotID) { - case NETSCAPE_SLOT_ID: - return &pk11_slot[0]; - case PRIVATE_KEY_SLOT_ID: - return &pk11_slot[1]; - case FIPS_SLOT_ID: - return &pk11_slot[2]; - default: - break; /* fall through to NULL */ - } - return NULL; -} - -PK11Slot * -pk11_SlotFromSessionHandle(CK_SESSION_HANDLE handle) -{ - if (handle & PK11_PRIVATE_KEY_FLAG) { - return &pk11_slot[1]; - } - if (handle & PK11_FIPS_FLAG) { - return &pk11_slot[2]; + if (context->key) { + pk11_FreeObject(context->key); + context->key = NULL; } - return &pk11_slot[0]; + PORT_Free(context); } /* @@ -2192,10 +2278,20 @@ pk11_mkHandle(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class) CK_OBJECT_HANDLE handle; SECItem *key; - SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len); - handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | + handle = class; + /* there is only one KRL, use a fixed handle for it */ + if (handle != PK11_TOKEN_KRL_HANDLE) { + SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len); + handle = (hashBuf[0] << 24) | (hashBuf[1] << 16) | (hashBuf[2] << 8) | hashBuf[3]; - handle = PK11_TOKEN_MASK | class | (handle & ~PK11_TOKEN_TYPE_MASK); + handle = PK11_TOKEN_MAGIC | class | + (handle & ~(PK11_TOKEN_TYPE_MASK|PK11_TOKEN_MASK)); + /* we have a CRL who's handle has randomly matched the reserved KRL + * handle, increment it */ + if (handle == PK11_TOKEN_KRL_HANDLE) { + handle++; + } + } pk11_tokenKeyLock(slot); while (key = pk11_lookupTokenKeyByHandle(slot,handle)) { |