diff options
author | relyea%netscape.com <devnull@localhost> | 2001-10-22 17:54:20 +0000 |
---|---|---|
committer | relyea%netscape.com <devnull@localhost> | 2001-10-22 17:54:20 +0000 |
commit | 2604a8216cecec79d0f034064252368919160ccb (patch) | |
tree | 2caaf2269366eedcf4410116a94449c028cb6755 | |
parent | 11000f66863c5fe6fa83b6489e53bc875c1ed936 (diff) | |
download | nss-hg-2604a8216cecec79d0f034064252368919160ccb.tar.gz |
1) Get nss3.dll and ssl3.dll to build.
2) Implement several of the CERT stub functions to go directly to pkcs #11.
3) updates to searching token objects.
54 files changed, 4620 insertions, 5214 deletions
diff --git a/security/nss/lib/certdb/cert.h b/security/nss/lib/certdb/cert.h index 5a70d7302..431341f89 100644 --- a/security/nss/lib/certdb/cert.h +++ b/security/nss/lib/certdb/cert.h @@ -397,26 +397,7 @@ extern void CERT_DestroyCrl (CERTSignedCrl *crl); ** Decode a certificate and put it into the temporary certificate database */ extern CERTCertificate * -CERT_NewTempCertificate (CERTCertDBHandle *handle, SECItem *derCert, - char *nickname, PRBool isperm, PRBool copyDER); - -/* -** Add a certificate to the temporary database. -** "dbCert" is the certificate from the perm database. -** "isperm" indicates if the cert is in the permanent database. -*/ -extern CERTCertificate * -CERT_AddTempCertificate (CERTCertDBHandle *handle, certDBEntryCert *entry, - PRBool isperm); - -/* -** Add a temporary certificate to the permanent database. -** "cert" is the temporary cert -** "nickname" is the permanent nickname to use -** "trust" is the certificate trust parameters to assign to the cert -*/ -extern SECStatus -CERT_AddTempCertToPerm (CERTCertificate *cert, char *nickname, CERTCertTrust *trust); +CERT_DecodeCertificate (SECItem *derCert, char *nickname,PRBool copyDER); /* ** Find a certificate in the database @@ -425,16 +406,6 @@ CERT_AddTempCertToPerm (CERTCertificate *cert, char *nickname, CERTCertTrust *tr extern CERTCertificate *CERT_FindCertByKey(CERTCertDBHandle *handle, SECItem *key); /* - * Lookup a certificate in the databases without locking - * "certKey" is the database key to look for - * - * XXX - this should be internal, but pkcs 11 needs to call it during a - * traversal. - */ -CERTCertificate * -CERT_FindCertByKeyNoLocking(CERTCertDBHandle *handle, SECItem *certKey); - -/* ** Find a certificate in the database by name ** "name" is the distinguished name to look up */ @@ -470,6 +441,7 @@ CERT_FindCertByIssuerAndSN (CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAnd */ extern CERTCertificate * CERT_FindCertByNickname (CERTCertDBHandle *handle, char *nickname); + /* ** Find a certificate in the database by a DER encoded certificate ** "derCert" is the DER encoded certificate @@ -505,17 +477,6 @@ CERTCertificate * CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage); /* -** Delete a certificate from the temporary database -** "cert" is the certificate to be deleted -*/ -extern SECStatus CERT_DeleteTempCertificate(CERTCertificate *cert); - -/* -** Flush and close the permanent database. -*/ -extern void CERT_ClosePermCertDB(CERTCertDBHandle *handle); - -/* ** Check the validity times of a certificate vs. time 't', allowing ** some slop for broken clocks and stuff. ** "cert" is the certificate to be checked @@ -641,6 +602,14 @@ extern char *CERT_HTMLCertInfo(CERTCertificate *cert, PRBool showImages, */ extern SECItem *CERT_DecodeAVAValue(SECItem *derAVAValue); +/* + * take a DER certificate and decode it into a certificate structure + */ +CERTCertificate * +CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, + char *nickname); + + /* ** extract various element strings from a distinguished name. @@ -926,32 +895,6 @@ extern void CERT_DestroyCertificateList(CERTCertificateList *list); /* is cert a newer than cert b? */ PRBool CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb); -typedef SECStatus (* CERTCertCallback)(CERTCertificate *cert, void *arg); - -SECStatus -CERT_TraversePermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject, - CERTCertCallback cb, void *cbarg); -int -CERT_NumPermCertsForSubject(CERTCertDBHandle *handle, SECItem *derSubject); - -SECStatus -CERT_TraversePermCertsForNickname(CERTCertDBHandle *handle, char *nickname, - CERTCertCallback cb, void *cbarg); - -int -CERT_NumPermCertsForNickname(CERTCertDBHandle *handle, char *nickname); - -int -CERT_NumCertsForCertSubject(CERTCertificate *cert); - -int -CERT_NumPermCertsForCertSubject(CERTCertificate *cert); - -SECStatus -CERT_TraverseCertsForSubject(CERTCertDBHandle *handle, - CERTSubjectList *subjectList, - CERTCertCallback cb, void *cbarg); - /* currently a stub for address book */ PRBool CERT_IsCertRevoked(CERTCertificate *cert); @@ -1009,12 +952,6 @@ CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, SECItem * CERT_FindSMimeProfile(CERTCertificate *cert); -int -CERT_GetDBContentVersion(CERTCertDBHandle *handle); - -void -CERT_SetDBContentVersion(int version, CERTCertDBHandle *handle); - SECStatus CERT_AddNewCerts(CERTCertDBHandle *handle); @@ -1370,6 +1307,8 @@ CERT_GetStatusConfig(CERTCertDBHandle *handle); void CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *config); + + /* * Acquire the cert reference count lock * There is currently one global lock for all certs, but I'm putting a cert diff --git a/security/nss/lib/certdb/certdb.c b/security/nss/lib/certdb/certdb.c index a0c970164..06c5a5d15 100644 --- a/security/nss/lib/certdb/certdb.c +++ b/security/nss/lib/certdb/certdb.c @@ -49,7 +49,7 @@ #include "keyhi.h" #include "secitem.h" #include "mcom_db.h" -#include "certtrust.h" +#include "certrust.h" #include "prprf.h" #include "sechash.h" #include "prlong.h" @@ -58,6 +58,7 @@ #include "secerr.h" #include "sslerr.h" #include "nsslocks.h" +#include "pk11func.h" /* * Certificate database handling code @@ -456,7 +457,7 @@ fortezzaIsCA( CERTCertificate *cert) { unsigned char *end; int len; - rawkey = spki->subjectPublicKey; + rawkey = spki->subjectPublicKey; DER_ConvertBitString(&rawkey); rawptr = rawkey.data; end = rawkey.data + rawkey.len; @@ -483,7 +484,7 @@ fortezzaIsCA( CERTCertificate *cert) { /* DSSPrivilege (the string up to the first byte with the hi-bit on */ if (*rawptr & 0x30) isCA = PR_TRUE; - + } return isCA; } @@ -621,12 +622,12 @@ CERT_GetCertType(CERTCertificate *cert) cert->nsCertType = NS_CERT_TYPE_SSL_CLIENT | NS_CERT_TYPE_SSL_SERVER | NS_CERT_TYPE_EMAIL; - /* if the basic constraint extension says the cert is a CA, then + /* if the basic constraint extension says the cert is a CA, then allow SSL CA and EMAIL CA and Status Responder */ if ((basicConstraintPresent == PR_TRUE) && (basicConstraint.isCA)) { - cert->nsCertType |= NS_CERT_TYPE_SSL_CA; - cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; + cert->nsCertType |= NS_CERT_TYPE_SSL_CA; + cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; } else if (CERT_IsCACert(cert, NULL) == PR_TRUE) { cert->nsCertType |= EXT_KEY_USAGE_STATUS_RESPONDER; @@ -634,8 +635,8 @@ CERT_GetCertType(CERTCertificate *cert) /* if the cert is a fortezza CA cert, then allow SSL CA and EMAIL CA */ if (fortezzaIsCA(cert)) { - cert->nsCertType |= NS_CERT_TYPE_SSL_CA; - cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; + cert->nsCertType |= NS_CERT_TYPE_SSL_CA; + cert->nsCertType |= NS_CERT_TYPE_EMAIL_CA; } } @@ -682,9 +683,9 @@ cert_GetKeyID(CERTCertificate *cert) cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, 8); if ( cert->subjectKeyID.data != NULL ) { - PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8); - cert->subjectKeyID.len = 8; - cert->keyIDGenerated = PR_FALSE; + PORT_Memcpy(cert->subjectKeyID.data, key->u.fortezza.KMID, 8); + cert->subjectKeyID.len = 8; + cert->keyIDGenerated = PR_FALSE; } } @@ -699,7 +700,7 @@ cert_GetKeyID(CERTCertificate *cert) */ cert->subjectKeyID.data = (unsigned char *)PORT_ArenaAlloc(cert->arena, SHA1_LENGTH); if ( cert->subjectKeyID.data != NULL ) { - rv = SHA1_HashBuf(cert->subjectKeyID.data, + rv = PK11_HashBuf(SEC_OID_SHA1,cert->subjectKeyID.data, cert->derPublicKey.data, cert->derPublicKey.len); if ( rv == SECSuccess ) { @@ -719,7 +720,7 @@ cert_GetKeyID(CERTCertificate *cert) * take a DER certificate and decode it into a certificate structure */ CERTCertificate * -__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, +CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, char *nickname) { CERTCertificate *cert; @@ -827,7 +828,7 @@ __CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, cert->referenceCount = 1; cert->slot = NULL; - cert->pkcs11ID = CK_INVALID_KEY; + cert->pkcs11ID = CK_INVALID_HANDLE; cert->dbnickname = NULL; return(cert); @@ -842,12 +843,13 @@ loser: } CERTCertificate * -CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, +__CERT_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, char *nickname) { - return(__CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname)); + return CERT_DecodeDERCertificate(derSignedCert, copyDER, nickname); } + /* ** Amount of time that a certifiate is allowed good before it is actually ** good. This is used for pending certificates, ones that are about to be @@ -903,7 +905,7 @@ CERT_CheckCertValidTimes(CERTCertificate *c, PRTime t, PRBool allowOverride) /* if cert is already marked OK, then don't bother to check */ if ( allowOverride && c->timeOK ) { - return(secCertTimeValid); + return(secCertTimeValid); } rv = CERT_GetCertTimes(c, ¬Before, ¬After); @@ -1178,68 +1180,6 @@ CERT_GetDefaultCertDB(void) return(default_cert_db_handle); } -/* - * Open volatile certificate database and index databases. This is a - * fallback if the real databases can't be opened or created. It is only - * resident in memory, so it will not be persistent. We do this so that - * we don't crash if the databases can't be created. - */ -SECStatus -CERT_OpenVolatileCertDB(CERTCertDBHandle *handle) -{ -#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 */ - }; - /* - * Open the memory resident perm cert database. - */ - handle->permCertDB = dbopen(0, O_RDWR | O_CREAT, 0600, DB_HASH, &hashInfo); - if ( !handle->permCertDB ) { - goto loser; - } - - /* - * Open the memory resident decoded cert database. - */ - handle->tempCertDB = dbopen(0, O_RDWR | O_CREAT, 0600, DB_HASH, &hashInfo); - if ( !handle->tempCertDB ) { - goto loser; - } - - handle->dbMon = PZ_NewMonitor(nssILockCertDB); - PORT_Assert(handle->dbMon != NULL); - - handle->spkDigestInfo = NULL; - handle->statusConfig = NULL; - - /* initialize the cert database */ - (void) CERT_InitCertDB(handle); - - return (SECSuccess); - -loser: - - PORT_SetError(SEC_ERROR_BAD_DATABASE); - - if ( handle->permCertDB ) { - (* handle->permCertDB->close)(handle->permCertDB); - handle->permCertDB = 0; - } - - if ( handle->tempCertDB ) { - (* handle->tempCertDB->close)(handle->tempCertDB); - handle->tempCertDB = 0; - } - - return(SECFailure); -} - /* XXX this would probably be okay/better as an xp routine? */ static void sec_lower_string(char *s) @@ -1264,14 +1204,14 @@ SECStatus CERT_AddOKDomainName(CERTCertificate *cert, const char *hn) { CERTOKDomainName *domainOK; - int newNameLen; + int newNameLen; if (!hn || !(newNameLen = strlen(hn))) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } domainOK = (CERTOKDomainName *)PORT_ArenaZAlloc(cert->arena, - (sizeof *domainOK) + newNameLen); + (sizeof *domainOK) + newNameLen); if (!domainOK) return SECFailure; /* error code is already set. */ @@ -1697,14 +1637,12 @@ CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype) return(ret); } - PRBool CERT_IsCADERCert(SECItem *derCert, unsigned int *type) { CERTCertificate *cert; PRBool isCA; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return PR_FALSE; isCA = CERT_IsCACert(cert,type); @@ -1953,8 +1891,8 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, /* decode all of the certs into the temporary DB */ for ( i = 0, fcerts= 0; i < ncerts; i++) { - certs[fcerts] = CERT_NewTempCertificate(certdb, derCerts[i], NULL, - PR_FALSE, PR_TRUE); + certs[fcerts] = CERT_DecodeDERCertificate(derCerts[i], PR_FALSE, + NULL); if (certs[fcerts]) fcerts++; } @@ -1967,10 +1905,11 @@ CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, * otherwise if there are more than one cert, we don't * know which cert it belongs to. */ - rv = CERT_SaveImportedCert(certs[i], usage, caOnly, NULL); + rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], + CK_INVALID_HANDLE,NULL,PR_TRUE); } else { - rv = CERT_SaveImportedCert(certs[i], usage, caOnly, - nickname); + rv = PK11_ImportCert(PK11_GetInternalKeySlot(),certs[i], + CK_INVALID_HANDLE,nickname,PR_TRUE); } /* don't care if it fails - keep going */ } @@ -2313,36 +2252,6 @@ loser: return(SECFailure); } -/* - * Acquire the global lock on the cert database. - * This lock is currently used for the following operations: - * adding or deleting a cert to either the temp or perm databases - * converting a temp to perm or perm to temp - * changing(maybe just adding !?) the trust of a cert - * chaning the DB status checking Configuration - */ -void -CERT_LockDB(CERTCertDBHandle *handle) -{ - PZ_EnterMonitor(handle->dbMon); - return; -} - -/* - * Free the global cert database lock. - */ -void -CERT_UnlockDB(CERTCertDBHandle *handle) -{ - PRStatus prstat; - - prstat = PZ_ExitMonitor(handle->dbMon); - - PORT_Assert(prstat == PR_SUCCESS); - - return; -} - static PZLock *certRefCountLock = NULL; /* @@ -2424,7 +2333,12 @@ CERT_UnlockCertTrust(CERTCertificate *cert) CERTStatusConfig * CERT_GetStatusConfig(CERTCertDBHandle *handle) { +#ifdef notdef return handle->statusConfig; +#else + PORT_Assert(0); + return NULL; +#endif } /* @@ -2434,7 +2348,210 @@ CERT_GetStatusConfig(CERTCertDBHandle *handle) void CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *statusConfig) { +#ifdef notdef PORT_Assert(handle->statusConfig == NULL); - handle->statusConfig = statusConfig; +#else + PORT_Assert(0); +#endif +} + +typedef struct cert_buildCertListArgsStr { + CERTCertList *certList; + int64 sorttime; + PRBool validOnly; + SECStatus status; +} cert_buildCertListArgs; + +SECStatus +cert_buildCertList(CERTCertificate *cert, void *inArgs) +{ + cert_buildCertListArgs *args = (cert_buildCertListArgs *)inArgs; + + if (args->status != SECSuccess) { + return args->status; + } + /* if validOnly, then check validity period before adding to list*/ + if ( ( !args->validOnly ) || + ( CERT_CheckCertValidTimes(cert, args->sorttime, PR_FALSE) + == secCertTimeValid ) ) { + args->status = CERT_AddCertToListSorted(args->certList, cert, + CERT_SortCBValidity, (void *)&args->sorttime); + } + + return args->status; +} + + +/* + * Creates or adds to a list of all certs with a give subject name, sorted by + * validity time, newest first. Invalid certs are considered older than + * valid certs. If validOnly is set, do not include invalid certs on list. + */ +CERTCertList * +CERT_CreateSubjectCertList(CERTCertList *inCertList, CERTCertDBHandle *handle, + SECItem *name, int64 sorttime, PRBool validOnly) +{ + CERTCertList *certList = NULL; + cert_buildCertListArgs args; + CERTCertificate subjectCert; + + certList = (inCertList) ? inCertList : CERT_NewCertList(); + + if ( certList == NULL ) { + goto loser; + } + + subjectCert.derSubject.data=name->data; + subjectCert.derSubject.len=name->len; + subjectCert.slot = NULL; + + args.certList = certList; + args.sorttime = sorttime; + args.validOnly = validOnly; + args.status = SECSuccess; + + PK11_TraverseCertsForSubject(&subjectCert,cert_buildCertList,&args); + + if (args.status == SECFailure) { + goto loser; + } + + return(certList); + +loser: + if (( inCertList == NULL ) && ( certList != NULL )) { + CERT_DestroyCertList(certList); + } + + return NULL; +} + + +/* + * Find Cert calls + */ +CERTCertificate * +CERT_FindCertByName(CERTCertDBHandle *handle,SECItem *derSubj) +{ + CERTCertList *list = + CERT_CreateSubjectCertList(NULL,handle,derSubj,0,PR_FALSE); + CERTCertificate *cert = NULL; + + if (list) { + CERTCertListNode *node = CERT_LIST_HEAD(list); + if (node) { + cert = CERT_DupCertificate(node->cert); + } + CERT_DestroyCertList(list); + } + + return cert; +} + +/* + * Lookup a certificate in the database by name and key ID + */ +CERTCertificate * +CERT_FindCertByKeyID(CERTCertDBHandle *handle, SECItem *name, SECItem *keyID) +{ + CERTCertList *list = + CERT_CreateSubjectCertList(NULL,handle,name,0,PR_FALSE); + CERTCertificate *cert = NULL; + CERTCertListNode *node = CERT_LIST_HEAD(list); + + if (list == NULL) return NULL; + + for (node = CERT_LIST_HEAD(list); node ; node = CERT_LIST_NEXT(node)) { + if (SECITEM_ItemsAreEqual(&cert->subjectKeyID, keyID) ) { + cert = CERT_DupCertificate(node->cert); + break; + } + } + return cert; +} + + +CERTCertificate * +CERT_FindCertByIssuerAndSN(CERTCertDBHandle *handle, CERTIssuerAndSN *issuerSN) +{ + PK11SlotInfo *slot; + CERTCertificate *cert; + + cert = PK11_FindCertByIssuerAndSN(&slot,issuerSN,NULL); + if (slot) { + PK11_FreeSlot(slot); + } + + return cert; +} + + +CERTCertificate * +CERT_FindCertByNickname(CERTCertDBHandle *handle, char *nickname) +{ + return PK11_FindCertFromNickname(nickname, NULL); +} + +CERTCertificate * +CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, char *nickname) +{ + return PK11_FindCertFromNickname(nickname, NULL); +} + +CERTCertificate * +CERT_FindCertByDERCert(CERTCertDBHandle *handle, SECItem *derCert) +{ + PK11SlotList *list; + PK11SlotListElement *le; + CERTCertificate *cert; + CERTCertificate fake_cert; + SECStatus rv; + + /* get them all! */ + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); + if (list == NULL) return NULL; + + /* horible hack! */ + fake_cert.derCert.data = derCert->data; + fake_cert.derCert.len = derCert->len; + + /* look at each slot and authenticate as necessary */ + for (le = list->head ; le; le = le->next) { + cert = PK11_FindCertFromDERCert(le->slot,&fake_cert,NULL); + if (cert) break; + } + + PK11_FreeSlotList(list); + + return SECSuccess; +} + +void +CERT_DestroyCertificate(CERTCertificate *cert) +{ + int refCount; + CERTCertDBHandle *handle; + + if ( cert ) { + CERT_LockCertRefCount(cert); + PORT_Assert(cert->referenceCount > 0); + refCount = --cert->referenceCount; + CERT_UnlockCertRefCount(cert); + + if ( ( refCount == 0 ) && !cert->keepSession ) { + PRArenaPool * arena = cert->arena; + + /* zero cert before freeing. Any stale references to this cert + * after this point will probably cause an exception. */ + PORT_Memset(cert, 0, sizeof *cert); + + cert = NULL; + + /* free the arena that contains the cert. */ + PORT_FreeArena(arena, PR_FALSE); + } + } + + return; } diff --git a/security/nss/lib/certdb/certinit.c b/security/nss/lib/certdb/certinit.c deleted file mode 100644 index 85b7713c2..000000000 --- a/security/nss/lib/certdb/certinit.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ - -#include "cert.h" -#include "base64.h" -#include "mcom_db.h" -#include "certrust.h" - -#ifdef STATIC_CERT_INIT -static char example_com_server_ca[] = -"MIICBTCCAW6gAwIBAgIBATANBgkqhkiG9w0BAQQFADA+MREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRIwEAYDVQQDEwlTZXJ2ZXIgQ0Ew" -"HhcNMDAwMjAzMjIyMDA3WhcNMTAwNTAzMjIyMDA3WjA+MREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRIwEAYDVQQDEwlTZXJ2ZXIgQ0Ew" -"gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALGiKEvTd2k4ZJbdAVWokfFlB6Hz" -"WJXveXm8+IgmFlgtAnicZI11z5wAutFRvDpun7WmRLgHxvEhU3tLoiACGYdGJXPw" -"+lI2pzHzFSd63B0qcA/NVAW3EOBJeaEFwy0jkUaCIki8qQV06g8RosNX/zv6a+OF" -"d5NMpS0fecK4fEvdAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcN" -"AQEEBQADgYEAi5rFiG6afWS1PHigssk2LwAJws5cszPbVIeIMHCBbtu259V7uWts" -"gNxUPJRjeQBsK0ItAfinC0xxLeuMbRfIdZoRYv/OYDxCwGW7hUcNLi+fHlGnJNXH" -"TWaCRdOwkljnws4v8ABas2DYA/k7xUFAygkIJd9NtE29ZrdrWpfSavI="; - -static char example_com_individual_ca[] = -"MIICDTCCAXagAwIBAgIBAjANBgkqhkiG9w0BAQQFADBCMREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRYwFAYDVQQDEw1JbmRpdmlkdWFs" -"IENBMB4XDTAwMDIwMzIyMjE1NFoXDTEwMDUwMzIyMjE1NFowQjERMA8GCAmSJvWY" -"HmQBEwNjb20xFTATBggJkib1mB5kARMHRXhhbXBsZTEWMBQGA1UEAxMNSW5kaXZp" -"ZHVhbCBDQTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAu5syfboe93MOkGec" -"dOuJholyX42wcaH/RgnL3C/8NnZp9WWaTaguvn7KrbCj4TAMzu0pabUN8apB3J60" -"9C/FlixjXF7r73OzbyTCM5ja6/bPfmHMPmDl9l/9tKqhh+loFvRizXDaWSFRViDS" -"XvKNeQztwwAOpEAqnJwyTkn4FjECAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN" -"BgkqhkiG9w0BAQQFAAOBgQB1XK+5pXdXYq3O3TC/ZY5LWlZ7zuoWUO75OpuMY7XF" -"iW/jeXbVT5IYZXoRGXJFGGaDmnAuK1/m6FTDhjSTG0XUmd5tg4aFieI+LY4rkYEv" -"mbJElxKabXl5hVD4mg2bwYlFY7XBmifTa1Ll3HDX3VZM0DC1bm4KCHBnY0qXjSYq" -"PA=="; - -static char example_com_objsign_ca[] = -"MIICETCCAXqgAwIBAgIBAzANBgkqhkiG9w0BAQQFADBEMREwDwYICZIm9ZgeZAET" -"A2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRgwFgYDVQQDEw9Db2RlIFNpZ25p" -"bmcgQ0EwHhcNMDAwMjAzMjIyMzEzWhcNMTAwNTAzMjIyMzEzWjBEMREwDwYICZIm" -"9ZgeZAETA2NvbTEVMBMGCAmSJvWYHmQBEwdFeGFtcGxlMRgwFgYDVQQDEw9Db2Rl" -"IFNpZ25pbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALcy76InmpM9" -"S9K2MlNSjusx6nkYWWbx7eDRTV+xhRPeDxW4t8jtKPqDF5LTusyM9WCI/nneqsIP" -"7iTSHpxlGx37J1VbqKX5fZsfJ3wKv6ZIylzeRuFY9MFypPA2UmVd1ACDOUB3YDvY" -"mrCVkOPEhjnZKbq4FfCpf8KNL2A5EBcZAgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB" -"Af8wDQYJKoZIhvcNAQEEBQADgYEAI0IXzwgBRXvow3JQi8Y4YdG2wZc4BWRGW87x" -"2zOD7GOA0CWN149vb6rEchECykDsJj9LoBl6o1aRxk9WkIFnXmMOJSuJA+ilCe//" -"81a5OhKbe0p7ym6rh190BLwh2VePFeyabq6NipfZlN6qgWUzoepf+jVblufW/2EI" -"fbMSylc="; -#endif - -/* This is the cert->certKey (serial number and issuer name) of - * the cert that we want to revoke. - */ -static unsigned char revoked_system_principal_key[] = { -0x40, 0x18, 0xf2, 0x35, 0x86, 0x06, 0x78, 0xce, 0x87, 0x89, -0x0c, 0x5d, 0x68, 0x67, 0x33, 0x09, 0x30, 0x81, 0xc1, 0x31, -0x1f, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x16, -0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x54, -0x72, 0x75, 0x73, 0x74, 0x20, 0x4e, 0x65, 0x74, 0x77, 0x6f, -0x72, 0x6b, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, -0x0b, 0x13, 0x0e, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, -0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 0x31, 0x3a, 0x30, -0x38, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x31, 0x56, 0x65, -0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x4f, 0x62, 0x6a, -0x65, 0x63, 0x74, 0x20, 0x53, 0x69, 0x67, 0x6e, 0x69, 0x6e, -0x67, 0x20, 0x43, 0x41, 0x20, 0x2d, 0x20, 0x43, 0x6c, 0x61, -0x73, 0x73, 0x20, 0x33, 0x20, 0x4f, 0x72, 0x67, 0x61, 0x6e, -0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x49, 0x30, -0x47, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x40, 0x77, 0x77, -0x77, 0x2e, 0x76, 0x65, 0x72, 0x69, 0x73, 0x69, 0x67, 0x6e, -0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x43, 0x50, 0x53, 0x20, 0x49, -0x6e, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x62, 0x79, 0x20, 0x52, -0x65, 0x66, 0x2e, 0x20, 0x4c, 0x49, 0x41, 0x42, 0x49, 0x4c, -0x49, 0x54, 0x59, 0x20, 0x4c, 0x54, 0x44, 0x2e, 0x28, 0x63, -0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, -0x67, 0x6e -}; - -SECStatus -CERT_CheckForEvilCert(CERTCertificate *cert) -{ - if ( cert->certKey.len == sizeof(revoked_system_principal_key) ) { - if ( PORT_Memcmp(cert->certKey.data, - revoked_system_principal_key, - sizeof(revoked_system_principal_key)) == 0 ) { - return(SECFailure); - } - } - - return(SECSuccess); -} - -#ifdef STATIC_CERT_INIT - -#define DEFAULT_TRUST_FLAGS (CERTDB_VALID_CA | \ - CERTDB_TRUSTED_CA | \ - CERTDB_NS_TRUSTED_CA) - -typedef enum { - certUpdateNone, - certUpdateAdd, - certUpdateDelete, - certUpdateAddTrust, - certUpdateRemoveTrust, - certUpdateSetTrust -} certUpdateOp; - -typedef struct { - char *cert; - char *nickname; - CERTCertTrust trust; - int updateVersion; - certUpdateOp op; - CERTCertTrust trustDelta; -} certInitEntry; - -static certInitEntry initialcerts[] = { - { - example_com_server_ca, - "Example.com Server CA", - { DEFAULT_TRUST_FLAGS | CERTDB_GOVT_APPROVED_CA, 0, 0 }, - 1, - certUpdateAdd, - { 0, 0, 0 } - }, - { - example_com_server_ca, - "Example.com Server CA", - { DEFAULT_TRUST_FLAGS | CERTDB_GOVT_APPROVED_CA, 0, 0 }, - 2, - certUpdateAddTrust, - { CERTDB_GOVT_APPROVED_CA, 0, 0 } - }, - - { - example_com_individual_ca, - "Example.com Individual CA", - { 0, DEFAULT_TRUST_FLAGS, 0 }, - 1, - certUpdateAdd, - { 0, 0, 0 } - }, - { - example_com_individual_ca, - "Example.com Individual CA", - { 0, DEFAULT_TRUST_FLAGS, 0 }, - 2, - certUpdateRemoveTrust, - { 0, 0, DEFAULT_TRUST_FLAGS } - }, - - { - example_com_objsign_ca, - "Example.com Code Signing CA", - { 0, 0, DEFAULT_TRUST_FLAGS }, - 2, - certUpdateAdd, - { 0, 0, 0 } - }, - - { - 0, 0 - } -}; - - -static SECStatus -ConvertAndCheckCertificate(CERTCertDBHandle *handle, char *asciicert, - char *nickname, CERTCertTrust *trust) -{ - SECItem sdder; - SECStatus rv; - CERTCertificate *cert; - PRBool conflict; - SECItem derSubject; - - /* First convert ascii to binary */ - rv = ATOB_ConvertAsciiToItem (&sdder, asciicert); - if (rv != SECSuccess) { - return(rv); - } - - /* - ** Inside the ascii is a Signed Certificate. - */ - - cert = NULL; - - /* make sure that no conflicts exist */ - conflict = SEC_CertDBKeyConflict(&sdder, handle); - if ( conflict ) { - goto done; - } - - rv = CERT_NameFromDERCert(&sdder, &derSubject); - if ( rv != SECSuccess ) { - goto loser; - } - - conflict = SEC_CertNicknameConflict(nickname, &derSubject, handle); - if ( conflict ) { - goto done; - } - - cert = CERT_NewTempCertificate(handle, &sdder, NULL, PR_FALSE, PR_TRUE); - if ( cert == NULL ) { - goto loser; - } - - rv = CERT_AddTempCertToPerm(cert, nickname, trust); - - CERT_DestroyCertificate(cert); - - if (rv == SECSuccess) { - /* - ** XXX should verify signatures too, if we have the certificate for - ** XXX its issuer... - */ - } - -done: - PORT_Free(sdder.data); - return(rv); - -loser: - return(SECFailure); -} - -#endif - -extern void certdb_InitDBLock(void); - -SECStatus -CERT_InitCertDB(CERTCertDBHandle *handle) -{ -#ifdef STATIC_CERT_INIT - SECStatus rv; - certInitEntry *entry; - certdb_InitDBLock(); - - entry = initialcerts; - - while ( entry->cert != NULL) { - if ( entry->op != certUpdateDelete ) { - rv = ConvertAndCheckCertificate(handle, entry->cert, - entry->nickname, &entry->trust); - /* keep going */ - } - - entry++; - } -done: - CERT_SetDBContentVersion(CERT_DB_CONTENT_VERSION, handle); - return(rv); -#else - certdb_InitDBLock(); - CERT_SetDBContentVersion(0, handle); - return(SECSuccess); -#endif -} - -#ifdef STATIC_CERT_INIT -static CERTCertificate * -CertFromEntry(CERTCertDBHandle *handle, char *asciicert) -{ - SECItem sdder; - SECStatus rv; - CERTCertificate *cert; - - /* First convert ascii to binary */ - rv = ATOB_ConvertAsciiToItem (&sdder, asciicert); - if (rv != SECSuccess) { - return(NULL); - } - - /* - ** Inside the ascii is a Signed Certificate. - */ - - cert = CERT_NewTempCertificate(handle, &sdder, NULL, PR_FALSE, PR_TRUE); - - return(cert); -} -#endif - -SECStatus -CERT_AddNewCerts(CERTCertDBHandle *handle) -{ -#ifdef STATIC_CERT_INIT - int oldversion; - int newversion; - certInitEntry *entry; - CERTCertTrust tmptrust; - SECStatus rv; - CERTCertificate *cert; - - newversion = CERT_DB_CONTENT_VERSION; - - oldversion = CERT_GetDBContentVersion(handle); - - if ( newversion > oldversion ) { - entry = initialcerts; - - while ( entry->cert != NULL ) { - if ( entry->updateVersion > oldversion ) { - switch ( entry->op ) { - default: - break; - case certUpdateAdd: - rv = ConvertAndCheckCertificate(handle, entry->cert, - entry->nickname, - &entry->trust); - break; - case certUpdateDelete: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - rv = SEC_DeletePermCertificate(cert); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateAddTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags |= entry->trustDelta.sslFlags; - tmptrust.emailFlags |= - entry->trustDelta.emailFlags; - tmptrust.objectSigningFlags |= - entry->trustDelta.objectSigningFlags; - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateRemoveTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags &= - (~entry->trustDelta.sslFlags); - tmptrust.emailFlags &= - (~entry->trustDelta.emailFlags); - tmptrust.objectSigningFlags &= - (~entry->trustDelta.objectSigningFlags); - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - case certUpdateSetTrust: - cert = CertFromEntry(handle, entry->cert); - if ( cert != NULL ) { - if ( cert->isperm ) { - tmptrust = *cert->trust; - tmptrust.sslFlags = entry->trustDelta.sslFlags; - tmptrust.emailFlags = - entry->trustDelta.emailFlags; - tmptrust.objectSigningFlags = - entry->trustDelta.objectSigningFlags; - rv = CERT_ChangeCertTrust(handle, cert, -&tmptrust); - } - CERT_DestroyCertificate(cert); - } - break; - } - } - - entry++; - } - - CERT_SetDBContentVersion(newversion, handle); - } - -#endif - return(SECSuccess); -} diff --git a/security/nss/lib/certdb/certt.h b/security/nss/lib/certdb/certt.h index 71ad723b1..b82a7f28c 100644 --- a/security/nss/lib/certdb/certt.h +++ b/security/nss/lib/certdb/certt.h @@ -392,8 +392,10 @@ struct CERTCrlKeyStr { struct CERTSignedCrlStr { PRArenaPool *arena; CERTCrl crl; - certDBEntryRevocation *dbEntry; /* database entry struct */ - PRBool keep; /* keep this crl in the cache for the session*/ + /*certDBEntryRevocation *dbEntry; database entry struct */ + PK11SlotInfo *slot; + /* PRBool keep; keep this crl in the cache for the session*/ + CK_OBJECT_HANDLE pkcs11ID; PRBool isperm; PRBool istemp; int referenceCount; diff --git a/security/nss/lib/certdb/crl.c b/security/nss/lib/certdb/crl.c index 957d72fb5..13877aab1 100644 --- a/security/nss/lib/certdb/crl.c +++ b/security/nss/lib/certdb/crl.c @@ -41,10 +41,11 @@ #include "secder.h" #include "secasn1.h" #include "secoid.h" -#include "certtrust.h" +#include "certrust.h" #include "certxutl.h" #include "prtime.h" #include "secerr.h" +#include "pk11func.h" const SEC_ASN1Template SEC_CERTExtensionTemplate[] = { { SEC_ASN1_SEQUENCE, @@ -389,6 +390,189 @@ loser: return(0); } +/* + * Lookup a CRL in the databases. We mirror the same fast caching data base + * caching stuff used by certificates....? + */ +CERTSignedCrl * +SEC_FindCrlByKeyOnSlot(PK11SlotInfo *slot, SECItem *crlKey, int type) +{ + CERTSignedCrl *crl = NULL; + SECItem *derCrl; + CK_OBJECT_HANDLE crlHandle; + + if (slot) { + PK11_ReferenceSlot(slot); + } + + derCrl = PK11_FindCrlByName(&slot, &crlHandle, crlKey,type); + if (derCrl == NULL) { + goto loser; + } + + crl = CERT_DecodeDERCrl(NULL, derCrl, type); + if (crl) { + crl->slot = slot; + slot = NULL; /* adopt it */ + } + +loser: + if (slot) { + PK11_FreeSlot(slot); + } + return(crl); +} + +SECStatus SEC_DestroyCrl(CERTSignedCrl *crl); + +CERTSignedCrl * +crl_storeCRL (PK11SlotInfo *slot,char *url, + CERTSignedCrl *newCrl, SECItem *derCrl, int type) +{ + CERTSignedCrl *oldCrl = NULL, *crl = NULL; + PRArenaPool *arena = NULL; + SECStatus rv; + CK_OBJECT_HANDLE crlHandle; + + oldCrl = SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type); + + /* if there is an old crl, make sure the one we are installing + * is newer. If not, exit out, otherwise delete the old crl. + */ + if (oldCrl != NULL) { + if (!SEC_CrlIsNewer(&newCrl->crl,&oldCrl->crl)) { + + if (type == SEC_CRL_TYPE) { + PORT_SetError(SEC_ERROR_OLD_CRL); + } else { + PORT_SetError(SEC_ERROR_OLD_KRL); + } + + goto done; + } + + if ((SECITEM_CompareItem(&newCrl->crl.derName, + &oldCrl->crl.derName) != SECEqual) && + (type == SEC_KRL_TYPE) ) { + + PORT_SetError(SEC_ERROR_CKL_CONFLICT); + goto done; + } + + /* if we have a url in the database, use that one */ + if (oldCrl->url) { + url = oldCrl->url; + } + + + /* really destroy this crl */ + /* first drum it out of the permanment Data base */ + SEC_DeletePermCRL(oldCrl); + } + + /* Write the new entry into the data base */ + crlHandle = PK11_PutCrl(slot, derCrl, &newCrl->crl.derName, url, type); + if (crlHandle != CK_INVALID_HANDLE) { + crl = newCrl; + crl->slot = PK11_ReferenceSlot(slot); + crl->pkcs11ID = crlHandle; + } + +done: + if (oldCrl) SEC_DestroyCrl(oldCrl); + + return crl; +} + +CERTSignedCrl * +SEC_FindCrlByName(CERTCertDBHandle *handle, SECItem *crlKey, int type) +{ + return SEC_FindCrlByKeyOnSlot(NULL,crlKey,type); +} + +/* + * + * create a new CRL from DER material. + * + * The signature on this CRL must be checked before you + * load it. ??? + */ +CERTSignedCrl * +SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type) +{ + CERTSignedCrl *newCrl = NULL, *crl = NULL; + PK11SlotInfo *slot; + + /* make this decode dates! */ + newCrl = CERT_DecodeDERCrl(NULL, derCrl, type); + if (newCrl == NULL) { + if (type == SEC_CRL_TYPE) { + PORT_SetError(SEC_ERROR_CRL_INVALID); + } else { + PORT_SetError(SEC_ERROR_KRL_INVALID); + } + goto done; + } + + slot = PK11_GetInternalKeySlot(); + crl = crl_storeCRL(slot, url, newCrl, derCrl, type); + PK11_FreeSlot(slot); + + +done: + if (crl == NULL) { + if (newCrl) { + PORT_FreeArena(newCrl->arena, PR_FALSE); + } + } + + return crl; +} + + +CERTSignedCrl * +SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type) +{ + PRArenaPool *arena; + SECItem crlKey; + SECStatus rv; + CERTSignedCrl *crl = NULL; + + /* create a scratch arena */ + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if ( arena == NULL ) { + return(NULL); + } + + /* extract the database key from the cert */ + rv = CERT_KeyFromDERCrl(arena, derCrl, &crlKey); + if ( rv != SECSuccess ) { + goto loser; + } + + /* find the crl */ + crl = SEC_FindCrlByName(handle, &crlKey, type); + +loser: + PORT_FreeArena(arena, PR_FALSE); + return(crl); +} + + +SECStatus +SEC_DestroyCrl(CERTSignedCrl *crl) +{ + if (crl) { + if (crl->referenceCount-- <= 1) { + if (crl->slot) { + PK11_FreeSlot(crl->slot); + } + PORT_FreeArena(crl->arena, PR_FALSE); + } + } + return SECSuccess; +} + /* These functions simply return the address of the above-declared templates. ** This is necessary for Windows DLLs. Sigh. */ diff --git a/security/nss/lib/certdb/manifest.mn b/security/nss/lib/certdb/manifest.mn index 8f2cc51ab..9b5ae12a0 100644 --- a/security/nss/lib/certdb/manifest.mn +++ b/security/nss/lib/certdb/manifest.mn @@ -35,24 +35,21 @@ CORE_DEPTH = ../../.. EXPORTS = \ cert.h \ certt.h \ + certrust.h \ $(NULL) PRIVATE_EXPORTS = \ genname.h \ xconst.h \ certxutl.h \ - certrust.h \ $(NULL) MODULE = security -CERTINIT=certinit.c - CSRCS = \ alg1485.c \ certdb.c \ certv3.c \ - $(CERTINIT) \ certxutl.c \ crl.c \ genname.c \ diff --git a/security/nss/lib/certhigh/certhigh.c b/security/nss/lib/certhigh/certhigh.c index 094de1933..68294cfe0 100644 --- a/security/nss/lib/certhigh/certhigh.c +++ b/security/nss/lib/certhigh/certhigh.c @@ -418,18 +418,11 @@ CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx) names->what = what; names->totallen = 0; - rv = SEC_TraversePermCerts(handle, CollectNicknames, (void *)names); + rv = PK11_TraverseSlotCerts(CollectNicknames, (void *)names, wincx); if ( rv ) { goto loser; } - if ( wincx != NULL ) { - rv = PK11_TraverseSlotCerts(CollectNicknames, (void *)names, wincx); - if ( rv ) { - goto loser; - } - } - if ( names->numnicknames ) { names->nicknames = (char**)PORT_ArenaAlloc(arena, names->numnicknames * sizeof(char *)); @@ -562,7 +555,7 @@ CERT_GetSSLCACerts(CERTCertDBHandle *handle) names->names = NULL; /* collect the names from the database */ - rv = SEC_TraversePermCerts(handle, CollectDistNames, (void *)names); + rv = PK11_TraverseSlotCerts(CollectDistNames, (void *)names, NULL); if ( rv ) { goto loser; } @@ -781,22 +774,6 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool while (numcerts--) { derCert = certs; certs++; - - /* get the key (issuer+cn) from the cert */ - rv = CERT_KeyFromDERCert(arena, derCert, &certKey); - if ( rv != SECSuccess ) { - goto loser; - } - - /* same cert already exists in the database, don't need to do - * anything more with it - */ - cert = CERT_FindCertByKey(handle, &certKey); - if ( cert ) { - CERT_DestroyCertificate(cert); - cert = NULL; - continue; - } /* decode my certificate */ newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); @@ -860,7 +837,7 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool } } - cert = CERT_NewTempCertificate(handle, derCert, NULL, PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if ( cert == NULL ) { goto loser; } @@ -868,7 +845,10 @@ cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool /* get a default nickname for it */ nickname = CERT_MakeCANickname(cert); - rv = CERT_AddTempCertToPerm(cert, nickname, &trust); + cert->trust = &trust; + rv = PK11_ImportCert(PK11_GetInternalKeySlot(), cert, + CK_INVALID_HANDLE, nickname, PR_TRUE); + /* free the nickname */ if ( nickname ) { PORT_Free(nickname); diff --git a/security/nss/lib/certhigh/certvfy.c b/security/nss/lib/certhigh/certvfy.c index 1b8f37a47..982ec0b9e 100644 --- a/security/nss/lib/certhigh/certvfy.c +++ b/security/nss/lib/certhigh/certvfy.c @@ -351,14 +351,16 @@ CERT_FindCertIssuer(CERTCertificate *cert, int64 validTime, SECCertUsage usage) */ if (caName != NULL) { - rv = CERT_KeyFromIssuerAndSN(tmpArena, caName, - &authorityKeyID->authCertSerialNumber, - &issuerCertKey); - if ( rv == SECSuccess ) { - issuerCert = CERT_FindCertByKey(cert->dbhandle, - &issuerCertKey); - } - + CERTIssuerAndSN issuerSN; + + issuerSN.derIssuer.data = caName->data; + issuerSN.derIssuer.len = caName->len; + issuerSN.serialNumber.data = + authorityKeyID->authCertSerialNumber.data; + issuerSN.serialNumber.len = + authorityKeyID->authCertSerialNumber.len; + issuerCert = CERT_FindCertByIssuerAndSN(cert->dbhandle, + &issuerSN); if ( issuerCert == NULL ) { PORT_SetError (SEC_ERROR_UNKNOWN_ISSUER); goto loser; @@ -964,13 +966,15 @@ CERT_VerifyCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool allowOverride; SECCertTimeValidity validity; CERTStatusConfig *statusConfig; - + +#ifdef notdef /* check if this cert is in the Evil list */ rv = CERT_CheckForEvilCert(cert); if ( rv != SECSuccess ) { PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); LOG_ERROR_OR_EXIT(log,cert,0,0); } +#endif /* make sure that the cert is valid at time t */ allowOverride = (PRBool)((certUsage == certUsageSSLServer) || diff --git a/security/nss/lib/certhigh/ocsp.c b/security/nss/lib/certhigh/ocsp.c index 150977149..2dc75e474 100644 --- a/security/nss/lib/certhigh/ocsp.c +++ b/security/nss/lib/certhigh/ocsp.c @@ -653,6 +653,28 @@ ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time) if (rv != SECSuccess) { goto loser; } + certID->issuerSHA1NameHash.data = certID->issuerNameHash.data; + certID->issuerSHA1NameHash.len = certID->issuerNameHash.len; + /* cache the other two hash algorithms as well */ + if (SECITEM_AllocItem(arena, &(certID->issuerMD5NameHash), + MD5_LENGTH) == NULL) { + goto loser; + } + rv = PK11_HashBuf(SEC_OID_MD5, certID->issuerMD5NameHash.data, + tempItem->data, tempItem->len); + if (rv != SECSuccess) { + goto loser; + } + if (SECITEM_AllocItem(arena, &(certID->issuerMD2NameHash), + MD2_LENGTH) == NULL) { + goto loser; + } + rv = PK11_HashBuf(SEC_OID_MD2, certID->issuerMD2NameHash.data, + tempItem->data, tempItem->len); + if (rv != SECSuccess) { + goto loser; + } + SECITEM_FreeItem(tempItem, PR_TRUE); tempItem = NULL; @@ -660,6 +682,18 @@ ocsp_CreateCertID(PRArenaPool *arena, CERTCertificate *cert, int64 time) &(certID->issuerKeyHash)) == NULL) { goto loser; } + certID->issuerSHA1KeyHash.data = certID->issuerKeyHash.data; + certID->issuerSHA1KeyHash.len = certID->issuerKeyHash.len; + /* cache the other two hash algorithms as well */ + if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD5, + &(certID->issuerMD5KeyHash)) == NULL) { + goto loser; + } + if (CERT_SPKDigestValueForCert(arena, issuerCert, SEC_OID_MD2, + &(certID->issuerMD2KeyHash)) == NULL) { + goto loser; + } + /* now we are done with issuerCert */ CERT_DestroyCertificate(issuerCert); @@ -2368,6 +2402,40 @@ ocsp_CertHasNoCheckExtension(CERTCertificate *cert) } #endif /* LATER */ +static PRBool +ocsp_matchcert(SECItem *certIndex,CERTCertificate *testCert) +{ + SECItem item; + unsigned char buf[SHA1_LENGTH]; /* MAX Hash Len */ + + item.data = buf; + item.len = SHA1_LENGTH; + + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_SHA1, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD5, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + if (CERT_SPKDigestValueForCert(NULL,testCert,SEC_OID_MD2, &item) == NULL) { + return PR_FALSE; + } + if (SECITEM_ItemsAreEqual(certIndex,&item)) { + return PR_TRUE; + } + + return PR_FALSE; +} + +static CERTCertificate * +ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID); + /* * Check the signature on some OCSP data. This is a helper function that * can be used to check either a request or a response. The result is @@ -2397,15 +2465,18 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, const SEC_ASN1Template *encodeTemplate, CERTCertDBHandle *handle, SECCertUsage certUsage, int64 checkTime, PRBool lookupByName, void *certIndex, - void *pwArg, CERTCertificate **pSignerCert) + void *pwArg, CERTCertificate **pSignerCert, + CERTCertificate *issuer) { SECItem rawSignature; SECItem *encodedTBS = NULL; + CERTCertificate *responder = NULL; CERTCertificate *signerCert = NULL; SECKEYPublicKey *signerKey = NULL; CERTCertificate **certs = NULL; SECStatus rv = SECFailure; int certCount; + int i; /* * If this signature has already gone through verification, just @@ -2432,6 +2503,7 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, if (signature->derCerts != NULL) { for (; signature->derCerts[certCount] != NULL; certCount++) { /* just counting */ + /*IMPORT CERT TO SPKI TABLE */ } } rv = CERT_ImportCerts(handle, certUsage, certCount, @@ -2455,7 +2527,22 @@ ocsp_CheckSignature(ocspSignature *signature, void *tbs, signerCert = CERT_FindCertByName(handle, encodedName); SECITEM_FreeItem(encodedName, PR_TRUE); } else { - signerCert = CERT_FindCertBySPKDigest(handle, certIndex); + /* + * The signer is either 1) a known issuer CA we passed in, + * 2) the default OCSP responder, or 3) and intermediate CA + * passed in the cert list to use. Figure out which it is. + */ + responder = ocsp_CertGetDefaultResponder(handle,NULL); + if (responder && ocsp_matchcert(certIndex,responder)) { + signerCert = CERT_DupCertificate(responder); + } else if (issuer && ocsp_matchcert(certIndex,issuer)) { + signerCert = CERT_DupCertificate(issuer); + } + for (i=0; (signerCert == NULL) && (i < certCount); i++) { + if (ocsp_matchcert(certIndex,certs[i])) { + signerCert = CERT_DupCertificate(certs[i]); + } + } } if (signerCert == NULL) { @@ -2546,6 +2633,7 @@ finish: if (certs != NULL) CERT_DestroyCertArray(certs, certCount); + /* Free CERTS from SPKDigest Table */ return rv; } @@ -2583,7 +2671,8 @@ finish: SECStatus CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, - CERTCertificate **pSignerCert) + CERTCertificate **pSignerCert, + CERTCertificate *issuer) { ocspResponseData *tbsData; /* this is what is signed */ PRBool byName; @@ -2623,7 +2712,7 @@ CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, return ocsp_CheckSignature(ocsp_GetResponseSignature(response), tbsData, ocsp_ResponseDataTemplate, handle, certUsageStatusResponder, producedAt, - byName, certIndex, pwArg, pSignerCert); + byName, certIndex, pwArg, pSignerCert, issuer); } /* @@ -2635,12 +2724,10 @@ ocsp_CertIDsMatch(CERTCertDBHandle *handle, CERTOCSPCertID *certID1, CERTOCSPCertID *certID2) { PRBool match = PR_FALSE; - CERTCertificate *issuer1 = NULL; - CERTCertificate *issuer2 = NULL; SECItem *foundHash = NULL; - CERTCertificate *found; SECOidTag hashAlg; - SECItem *givenHash; + SECItem *keyHash; + SECItem *nameHash; /* * In order to match, they must have the same issuer and the same @@ -2668,63 +2755,34 @@ ocsp_CertIDsMatch(CERTCertDBHandle *handle, goto done; } - /* - * The hash algorithms are different; this is harder. We have - * to do a lookup of each one and compare them. - */ - issuer1 = CERT_FindCertBySPKDigest(handle, &certID1->issuerKeyHash); - issuer2 = CERT_FindCertBySPKDigest(handle, &certID2->issuerKeyHash); - - if (issuer1 == NULL && issuer2 == NULL) { - /* If we cannot find an issuer cert, we have no way to compare. */ - goto done; - } - - if (issuer1 != NULL && issuer2 != NULL) { - /* If we found a cert for each hash, we can just compare them. */ - if (issuer1 == issuer2) - match = PR_TRUE; - goto done; - } - - /* - * We found one issuer, but not both. So we have to use the other certID - * hash algorithm on the key in the found issuer cert to see if they match. - */ - - if (issuer1 != NULL) { - found = issuer1; - hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm); - givenHash = &certID2->issuerKeyHash; - } else { - found = issuer2; - hashAlg = SECOID_FindOIDTag(&certID1->hashAlgorithm.algorithm); - givenHash = &certID1->issuerKeyHash; + hashAlg = SECOID_FindOIDTag(&certID2->hashAlgorithm.algorithm); + switch (hashAlg) { + case SEC_OID_SHA1: + keyHash = &certID1->issuerSHA1KeyHash; + nameHash = &certID1->issuerSHA1NameHash; + break; + case SEC_OID_MD5: + keyHash = &certID1->issuerMD5KeyHash; + nameHash = &certID1->issuerMD5NameHash; + break; + case SEC_OID_MD2: + keyHash = &certID1->issuerMD2KeyHash; + nameHash = &certID1->issuerMD2NameHash; + break; + default: + foundHash == NULL; } - foundHash = CERT_SPKDigestValueForCert(NULL, found, hashAlg, NULL); if (foundHash == NULL) { goto done; } - if (SECITEM_CompareItem(foundHash, givenHash) == SECEqual) { - /* - * Strictly speaking, we should compare the issuerNameHash, too, - * but I think the added complexity doesn't actually buy anything. - */ + if ((SECITEM_CompareItem(nameHash, &certID2->issuerNameHash) == SECEqual) + && (SECITEM_CompareItem(keyHash, &certID2->issuerKeyHash) == SECEqual)) { match = PR_TRUE; } done: - if (issuer1 != NULL) { - CERT_DestroyCertificate(issuer1); - } - if (issuer2 != NULL) { - CERT_DestroyCertificate(issuer2); - } - if (foundHash != NULL) { - SECITEM_FreeItem(foundHash, PR_TRUE); - } return match; } @@ -2788,15 +2846,12 @@ ocsp_GetCheckingContext(CERTCertDBHandle *handle) return ocspcx; } - /* * Return true if the given signerCert is the default responder for * the given certID. If not, or if any error, return false. */ -static PRBool -ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, - CERTCertificate *signerCert, - CERTOCSPCertID *certID) +static CERTCertificate * +ocsp_CertGetDefaultResponder(CERTCertDBHandle *handle,CERTOCSPCertID *certID) { ocspCheckingContext *ocspcx; @@ -2814,12 +2869,26 @@ ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, */ if (ocspcx->useDefaultResponder) { PORT_Assert(ocspcx->defaultResponderCert != NULL); - if (ocspcx->defaultResponderCert == signerCert) - return PR_TRUE; + return ocspcx->defaultResponderCert; } loser: - return PR_FALSE; + return NULL; +} + +/* + * Return true if the given signerCert is the default responder for + * the given certID. If not, or if any error, return false. + */ +static PRBool +ocsp_CertIsDefaultResponderForCertID(CERTCertDBHandle *handle, + CERTCertificate *signerCert, + CERTOCSPCertID *certID) +{ + CERTCertificate *defaultResponderCert; + + defaultResponderCert = ocsp_CertGetDefaultResponder(handle, certID); + return (PRBool) (defaultResponderCert == signerCert); } /* @@ -3300,6 +3369,7 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, CERTOCSPRequest *request = NULL; CERTOCSPResponse *response = NULL; CERTCertificate *signerCert = NULL; + CERTCertificate *issuerCert = NULL; ocspResponseData *responseData; int64 producedAt; CERTOCSPCertID *certID; @@ -3413,7 +3483,9 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, * If we've made it this far, we expect a response with a good signature. * So, check for that. */ - rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert); + issuerCert = CERT_FindCertIssuer(cert, time, certUsageAnyCA); + rv = CERT_VerifyOCSPResponseSignature(response, handle, pwArg, &signerCert, + issuerCert); if (rv != SECSuccess) goto loser; @@ -3471,6 +3543,8 @@ CERT_CheckOCSPStatus(CERTCertDBHandle *handle, CERTCertificate *cert, rv = ocsp_CertHasGoodStatus(single, time); loser: + if (issuerCert != NULL) + CERT_DestroyCertificate(issuerCert); if (signerCert != NULL) CERT_DestroyCertificate(signerCert); if (response != NULL) @@ -3905,3 +3979,97 @@ CERT_DisableOCSPDefaultResponder(CERTCertDBHandle *handle) statusContext->useDefaultResponder = PR_FALSE; return SECSuccess; } +static const SECHashObject * +OidTagToDigestObject(SECOidTag digestAlg) +{ + const SECHashObject *rawDigestObject; + + switch (digestAlg) { + case SEC_OID_MD2: + rawDigestObject = &SECHashObjects[HASH_AlgMD2]; + break; + case SEC_OID_MD5: + rawDigestObject = &SECHashObjects[HASH_AlgMD5]; + break; + case SEC_OID_SHA1: + rawDigestObject = &SECHashObjects[HASH_AlgSHA1]; + break; + default: + PORT_SetError(SEC_ERROR_INVALID_ALGORITHM); + rawDigestObject = NULL; + break; + } + return(rawDigestObject); +} + +/* + * Digest the cert's subject public key using the specified algorithm. + * The necessary storage for the digest data is allocated. If "fill" is + * non-null, the data is put there, otherwise a SECItem is allocated. + * Allocation from "arena" if it is non-null, heap otherwise. Any problem + * results in a NULL being returned (and an appropriate error set). + */ +SECItem * +CERT_SPKDigestValueForCert(PRArenaPool *arena, CERTCertificate *cert, + SECOidTag digestAlg, SECItem *fill) +{ + const SECHashObject *digestObject; + void *digestContext; + SECItem *result = NULL; + void *mark = NULL; + SECItem spk; + + if ( arena != NULL ) { + mark = PORT_ArenaMark(arena); + } + + digestObject = OidTagToDigestObject(digestAlg); + if ( digestObject == NULL ) { + goto loser; + } + + if ((fill == NULL) || (fill->data == NULL)) { + result = SECITEM_AllocItem(arena, fill, digestObject->length); + if ( result == NULL ) { + goto loser; + } + fill = result; + } + + /* + * Copy just the length and data pointer (nothing needs to be freed) + * of the subject public key so we can convert the length from bits + * to bytes, which is what the digest function expects. + */ + spk = cert->subjectPublicKeyInfo.subjectPublicKey; + DER_ConvertBitString(&spk); + + /* + * Now digest the value, using the specified algorithm. + */ + digestContext = digestObject->create(); + if ( digestContext == NULL ) { + goto loser; + } + digestObject->begin(digestContext); + digestObject->update(digestContext, spk.data, spk.len); + digestObject->end(digestContext, fill->data, &(fill->len), fill->len); + digestObject->destroy(digestContext, PR_TRUE); + + if ( arena != NULL ) { + PORT_ArenaUnmark(arena, mark); + } + return(fill); + +loser: + if ( arena != NULL ) { + PORT_ArenaRelease(arena, mark); + } else { + if ( result != NULL ) { + SECITEM_FreeItem(result, (fill == NULL) ? PR_TRUE : PR_FALSE); + } + } + return(NULL); +} + + diff --git a/security/nss/lib/certhigh/ocsp.h b/security/nss/lib/certhigh/ocsp.h index 51f81e867..e4bd7dbdd 100644 --- a/security/nss/lib/certhigh/ocsp.h +++ b/security/nss/lib/certhigh/ocsp.h @@ -353,6 +353,8 @@ CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList, * Pointer to CERTCertDBHandle for certificate DB to use for verification. * void *pwArg * Pointer to argument for password prompting, if needed. + * CERTCertificate *issuerCert + * Issuer of the certificate that generated the OCSP request. * OUTPUTS: * CERTCertificate **pSignerCert * Pointer in which to store signer's certificate; only filled-in if @@ -371,7 +373,8 @@ CERT_GetEncodedOCSPResponse(PRArenaPool *arena, CERTCertList *certList, extern SECStatus CERT_VerifyOCSPResponseSignature(CERTOCSPResponse *response, CERTCertDBHandle *handle, void *pwArg, - CERTCertificate **pSignerCert); + CERTCertificate **pSignerCert, + CERTCertificate *issuerCert); /* * FUNCTION: CERT_GetOCSPAuthorityInfoAccessLocation diff --git a/security/nss/lib/certhigh/ocspti.h b/security/nss/lib/certhigh/ocspti.h index 5f530c4bf..9c739bef4 100644 --- a/security/nss/lib/certhigh/ocspti.h +++ b/security/nss/lib/certhigh/ocspti.h @@ -194,6 +194,12 @@ struct CERTOCSPCertIDStr { SECItem issuerNameHash; /* an OCTET STRING */ SECItem issuerKeyHash; /* an OCTET STRING */ SECItem serialNumber; /* an INTEGER */ + SECItem issuerSHA1NameHash; /* keep other hashes around when */ + SECItem issuerMD5NameHash; /* we have them */ + SECItem issuerMD2NameHash; + SECItem issuerSHA1KeyHash; /* keep other hashes around when */ + SECItem issuerMD5KeyHash; /* we have them */ + SECItem issuerMD2KeyHash; }; /* diff --git a/security/nss/lib/ckfw/ckt.h b/security/nss/lib/ckfw/ckt.h index 762a70a0b..20e7d4caf 100644 --- a/security/nss/lib/ckfw/ckt.h +++ b/security/nss/lib/ckfw/ckt.h @@ -128,6 +128,8 @@ static const char CKT_CVS_ID[] = "@(#) $RCSfile$ $Revision$ $Date$ $Name$"; #define CKA_TRUST_IPSEC_TUNNEL (CKA_TRUST + 13) #define CKA_TRUST_IPSEC_USER (CKA_TRUST + 14) #define CKA_TRUST_TIME_STAMPING (CKA_TRUST + 15) + +/* locate the Trust entry */ #define CKA_CERT_SHA1_HASH (CKA_TRUST + 100) #define CKA_CERT_MD5_HASH (CKA_TRUST + 101) @@ -187,6 +189,7 @@ typedef CK_ULONG CK_TRUST; #define CKT_NETSCAPE_TRUSTED (CKT_NETSCAPE + 1) #define CKT_NETSCAPE_TRUSTED_DELEGATOR (CKT_NETSCAPE + 2) #define CKT_NETSCAPE_UNTRUSTED (CKT_NETSCAPE + 3) +#define CKT_NETSCAPE_MUST_VERIFY (CKT_NETSCAPE + 4) /* * These may well remain Netscape-specific; I'm only using them diff --git a/security/nss/lib/cryptohi/seckey.c b/security/nss/lib/cryptohi/seckey.c index b486e7352..29e8b8de0 100644 --- a/security/nss/lib/cryptohi/seckey.c +++ b/security/nss/lib/cryptohi/seckey.c @@ -858,7 +858,7 @@ seckey_ExtractPublicKey(CERTSubjectPublicKeyInfo *spki) pubk->arena = arena; pubk->pkcs11Slot = 0; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; /* Convert bit string length from bits to bytes */ @@ -1034,7 +1034,7 @@ SECKEY_CopyPrivateKey(SECKEYPrivateKey *privk) if (privk->pkcs11IsTemp) { copyk->pkcs11ID = PK11_CopyKey(privk->pkcs11Slot,privk->pkcs11ID); - if (copyk->pkcs11ID == CK_INVALID_KEY) goto fail; + if (copyk->pkcs11ID == CK_INVALID_HANDLE) goto fail; } else { copyk->pkcs11ID = privk->pkcs11ID; } @@ -1069,7 +1069,7 @@ SECKEY_CopyPublicKey(SECKEYPublicKey *pubk) copyk->arena = arena; copyk->keyType = pubk->keyType; copyk->pkcs11Slot = NULL; /* go get own reference */ - copyk->pkcs11ID = CK_INVALID_KEY; + copyk->pkcs11ID = CK_INVALID_HANDLE; switch (pubk->keyType) { case rsaKey: rv = SECITEM_CopyItem(arena, ©k->u.rsa.modulus, @@ -1198,7 +1198,7 @@ SECKEY_ConvertToPublicKey(SECKEYPrivateKey *privk) } pubk->keyType = privk->keyType; pubk->pkcs11Slot = NULL; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; pubk->arena = arena; /* diff --git a/security/nss/lib/manifest.mn b/security/nss/lib/manifest.mn index 0518e7654..e20ffd4f3 100644 --- a/security/nss/lib/manifest.mn +++ b/security/nss/lib/manifest.mn @@ -36,8 +36,8 @@ DEPTH = ../.. DIRS = util freebl softoken \ certhigh pk11wrap cryptohi \ certdb crypto nss \ - pkcs12 pkcs7 smime\ ssl \ + pkcs12 pkcs7 smime\ base ckfw \ crmf jar \ fortcrypt diff --git a/security/nss/lib/nss/config.mk b/security/nss/lib/nss/config.mk index aa35a3775..c571f2278 100644 --- a/security/nss/lib/nss/config.mk +++ b/security/nss/lib/nss/config.mk @@ -48,25 +48,15 @@ ifeq ($(OS_ARCH), WINNT) SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib -DLLFLAGS += -DEF:nss.def -RES = $(OBJDIR)/nss.res -RESNAME = nss.rc +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = $(LIBRARY_NAME).rc # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) -CRYPTOLIB=$(DIST)/lib/freebl.lib -CRYPTODIR=../freebl -ifdef MOZILLA_SECURITY_BUILD - CRYPTOLIB=$(DIST)/lib/crypto.lib - CRYPTODIR=../crypto -endif - SHARED_LIBRARY_LIBS = \ $(DIST)/lib/certhi.lib \ $(DIST)/lib/cryptohi.lib \ $(DIST)/lib/pk11wrap.lib \ $(DIST)/lib/certdb.lib \ - $(DIST)/lib/softoken.lib \ - $(CRYPTOLIB) \ $(DIST)/lib/secutil.lib \ $(NULL) @@ -75,61 +65,31 @@ SHARED_LIBRARY_DIRS = \ ../cryptohi \ ../pk11wrap \ ../certdb \ - ../softoken \ - $(CRYPTODIR) \ ../util \ $(NULL) -EXTRA_LIBS += \ - $(DIST)/lib/dbm.lib \ - $(NULL) - -ifdef MOZILLA_BSAFE_BUILD - EXTRA_LIBS+=$(DIST)/lib/bsafe$(BSAFEVER).lib -endif - EXTRA_SHARED_LIBS += \ + $(DIST)/lib/softokn3.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plc4.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) - -# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS) -#OS_LIBS += \ -# wsock32.lib \ -# winmm.lib \ -# $(NULL) else # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) -CRYPTOLIB=$(DIST)/lib/libfreebl.$(LIB_SUFFIX) -CRYPTODIR=../freebl -ifdef MOZILLA_SECURITY_BUILD - CRYPTOLIB=$(DIST)/lib/libcrypto.$(LIB_SUFFIX) - CRYPTODIR=../crypto -endif SHARED_LIBRARY_LIBS = \ $(DIST)/lib/libcerthi.$(LIB_SUFFIX) \ $(DIST)/lib/libpk11wrap.$(LIB_SUFFIX) \ $(DIST)/lib/libcryptohi.$(LIB_SUFFIX) \ - $(DIST)/lib/libsoftoken.$(LIB_SUFFIX) \ $(DIST)/lib/libcertdb.$(LIB_SUFFIX) \ - $(CRYPTOLIB) \ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ $(NULL) -EXTRA_LIBS += \ - $(DIST)/lib/libdbm.$(LIB_SUFFIX) \ - $(NULL) -ifdef MOZILLA_BSAFE_BUILD - EXTRA_LIBS+=$(DIST)/lib/libbsafe.$(LIB_SUFFIX) -endif + SHARED_LIBRARY_DIRS = \ ../certhigh \ ../pk11wrap \ ../cryptohi \ - ../softoken \ ../certdb \ - $(CRYPTODIR) \ ../util \ $(NULL) @@ -137,49 +97,9 @@ SHARED_LIBRARY_DIRS = \ # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. EXTRA_SHARED_LIBS += \ -L$(DIST)/lib/ \ + -lsoftokn3 \ -lplc4 \ -lplds4 \ -lnspr4 \ $(NULL) endif - -ifeq ($(OS_ARCH),SunOS) -MAPFILE = $(OBJDIR)/nssmap.sun -ALL_TRASH += $(MAPFILE) -MKSHLIB += -M $(MAPFILE) -ifndef USE_64 -ifeq ($(CPU_ARCH),sparc) -# The -R '$ORIGIN' linker option instructs libnss3.so to search for its -# dependencies (libfreebl_*.so) in the same directory where it resides. -MKSHLIB += -R '$$ORIGIN' -endif -endif -endif - -ifeq ($(OS_ARCH),AIX) -MAPFILE = $(OBJDIR)/nssmap.aix -ALL_TRASH += $(MAPFILE) -EXPORT_RULES = -bexport:$(MAPFILE) -endif - -ifeq ($(OS_ARCH),HP-UX) -MAPFILE = $(OBJDIR)/nssmap.hp -ALL_TRASH += $(MAPFILE) -MKSHLIB += -c $(MAPFILE) -endif - -ifeq ($(OS_ARCH), OSF1) -MAPFILE = $(OBJDIR)/nssmap.osf -ALL_TRASH += $(MAPFILE) -MKSHLIB += -hidden -input $(MAPFILE) -endif - -ifeq ($(OS_ARCH),Linux) -MAPFILE = $(OBJDIR)/nssmap.linux -ALL_TRASH += $(MAPFILE) -MKSHLIB += -Wl,--version-script,$(MAPFILE) -endif - - - - diff --git a/security/nss/lib/nss/manifest.mn b/security/nss/lib/nss/manifest.mn index 5d822c170..1fbdc045d 100644 --- a/security/nss/lib/nss/manifest.mn +++ b/security/nss/lib/nss/manifest.mn @@ -49,5 +49,7 @@ CSRCS = \ REQUIRES = security dbm +MAPFILE = $(OBJDIR)/nss.def + LIBRARY_NAME = nss LIBRARY_VERSION = 3 diff --git a/security/nss/lib/pk11wrap/manifest.mn b/security/nss/lib/pk11wrap/manifest.mn index c043af789..6b87792ab 100644 --- a/security/nss/lib/pk11wrap/manifest.mn +++ b/security/nss/lib/pk11wrap/manifest.mn @@ -41,8 +41,7 @@ EXPORTS = \ $(NULL) PRIVATE_EXPORTS = \ - secmodi.h \ - secmodti.h \ + pk11init.h \ $(NULL) MODULE = security @@ -60,6 +59,7 @@ CSRCS = \ pk11sdr.c \ pk11pqg.c \ pk11pk12.c \ + pk11pbe.c \ $(NULL) REQUIRES = security dbm diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c index 6bb3aa8f4..7d5f952d0 100644 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ b/security/nss/lib/pk11wrap/pk11cert.c @@ -52,9 +52,6 @@ #include "secerr.h" #include "sslerr.h" -#define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */ -#include "ckt.h" - #define PK11_SEARCH_CHUNKSIZE 10 CK_OBJECT_HANDLE @@ -137,7 +134,7 @@ pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize if (crv != CKR_OK) { PK11_ExitSlotMonitor(slot); PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount); @@ -147,11 +144,11 @@ pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize /* shouldn't use SSL_ERROR... here */ PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) : SSL_ERROR_NO_CERTIFICATE); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* blow up if the PKCS #11 module returns us and invalid object handle */ - PORT_Assert(object != CK_INVALID_KEY); + PORT_Assert(object != CK_INVALID_HANDLE); return object; } @@ -239,13 +236,13 @@ PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID, /* now we need to create space for the public key */ arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return CK_INVALID_KEY; + if (arena == NULL) return CK_INVALID_HANDLE; crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize); if (crv != CKR_OK) { PORT_FreeArena(arena,PR_FALSE); PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -273,7 +270,7 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { theClass = CKO_PUBLIC_KEY; } - if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_KEY) { + if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_HANDLE) { return PR_TRUE; } @@ -310,7 +307,7 @@ PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, return PR_FALSE; } pk11_SignedToUnsigned(&theTemplate); - if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_KEY) { + if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_HANDLE) { SECKEY_DestroyPublicKey(pubKey); return PR_TRUE; } @@ -393,8 +390,7 @@ CERTCertificate /* figure out the nickname.... */ nickname = pk11_buildNickname(slot,label,privateLabel,id); - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert, nickname, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(&derCert, PR_FALSE, nickname); if (nickptr) { *nickptr = nickname; } else { @@ -438,11 +434,7 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust CK_OBJECT_HANDLE tobjID; unsigned char sha1_hash[SHA1_LENGTH]; - CK_TRUST serverAuth, codeSigning, emailProtection; -/* - CK_TRUST digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, - keyAgreement, keyCertSign, crlSign, serverAuth, clientAuth, codeSigning, - emailProtection, ipsecEndSystem, ipsecTunnel, ipsecUser, timeStamping; */ + CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth; PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len); @@ -452,7 +444,7 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, sizeof(tobjTemplate)/sizeof(tobjTemplate[0])); - if( CK_INVALID_KEY == tobjID ) { + if( CK_INVALID_HANDLE == tobjID ) { return PR_FALSE; } @@ -468,29 +460,16 @@ pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust /* We could verify CKA_EXPIRES here */ - /* "Usage" trust information */ - /* digitalSignature = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DIGITAL_SIGNATURE); */ - /* nonRepudiation = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_NON_REPUDIATION); */ - /* keyEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_ENCIPHERMENT); */ - /* dataEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DATA_ENCIPHERMENT); */ - /* keyAgreement = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_AGREEMENT); */ - /* keyCertSign = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_CERT_SIGN); */ - /* crlSign = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CRL_SIGN); */ /* "Purpose" trust information */ - serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH); - /* clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); */ - codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING); - emailProtection = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_EMAIL_PROTECTION); - /* ipsecEndSystem = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_END_SYSTEM); */ - /* ipsecTunnel = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_TUNNEL); */ - /* ipsecUser = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_USER); */ - /* timeStamping = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_TIME_STAMPING); */ - - /* Here's where the fun logic happens. We have to map back from the key usage, - * extended key usage, purpose, and possibly other trust values into the old - * trust-flags bits. - */ + serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH); + clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); + codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING); + emailProtection = pk11_GetTrustField(slot, arena, tobjID, + CKA_TRUST_EMAIL_PROTECTION); + /* Here's where the fun logic happens. We have to map back from the + * key usage, extended key usage, purpose, and possibly other trust values + * into the old trust-flags bits. */ /* First implementation: keep it simple for testing. We can study what other * mappings would be appropriate and add them later.. fgmr 20000724 */ @@ -562,6 +541,7 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, cert->ownSlot = PR_TRUE; } + if(! pk11_HandleTrustObject(slot, cert, trust) ) { if (cert->trust == NULL) { unsigned int type; @@ -572,14 +552,6 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, PORT_Memset(trust,0, sizeof(CERTCertTrust)); cert->trust = trust; /* build some cert trust flags */ - - /* First, see if there's a trust object for this cert. */ - /* For the first implementation, we'll just check this slot - * and worry about overriding trust info later. */ - if( pk11_HandleTrustObject(slot, cert, trust) ) { - ; - } else - if (CERT_IsCACert(cert, &type)) { unsigned int trustflags = CERTDB_VALID_CA; @@ -612,6 +584,7 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, } else { trust = cert->trust; } + } if (PK11_IsUserCert(slot,cert,certID)) { trust->sslFlags |= CERTDB_USER; @@ -619,29 +592,6 @@ PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, /* trust->objectSigningFlags |= CERTDB_USER; */ } - - /* if fortezza, write the root cert to the DB */ - if ((isFortezzaRootCA) && (!cert->isperm)) { - char *name = NULL; - if (swapNickname) { - nickname = cert->nickname; - cert->nickname = cert->dbnickname; - } - if (cert->nickname) { - name = PORT_Strdup(cert->nickname); - } - if (name == NULL) name = CERT_MakeCANickname(cert); - CERT_AddTempCertToPerm(cert,name,cert->trust); - if (name) PORT_Free(name); - if (swapNickname) { - if (cert->nickname != NULL) { - cert->dbnickname = cert->nickname; - } - cert->nickname = PORT_ArenaStrdup(cert->arena,nickname); - } - - } - return cert; loser: @@ -663,7 +613,7 @@ PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey) SECStatus rv; CERTCertificate *cert; - if (certID == CK_INVALID_KEY) { + if (certID == CK_INVALID_HANDLE) { /* couldn't find it on the card, look in our data base */ SECItem derSubject; @@ -722,7 +672,7 @@ PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID); PK11_DeleteTokenPrivateKey(privKey); } - if ((pubKey != CK_INVALID_KEY) && (slot != NULL)) { + if ((pubKey != CK_INVALID_HANDLE) && (slot != NULL)) { PK11_DestroyTokenObject(slot,pubKey); PK11_FreeSlot(slot); } @@ -774,13 +724,14 @@ PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, typedef struct pk11DoCertCallbackStr { SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *); SECStatus(* noslotcallback)(CERTCertificate*, void *); + SECStatus(* itemcallback)(CERTCertificate*, SECItem *, void *); void *callbackArg; } pk11DoCertCallback; /* * callback to map object handles to certificate structures. */ -SECStatus +static SECStatus pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) { CERTCertificate *cert; @@ -799,6 +750,9 @@ pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) if (certcb->noslotcallback) { (*certcb->noslotcallback)(cert, certcb->callbackArg); } + if (certcb->itemcallback) { + (*certcb->itemcallback)(cert, NULL, certcb->callbackArg); + } } CERT_DestroyCertificate(cert); @@ -884,191 +838,25 @@ typedef struct pk11CertCallbackStr { void *callbackArg; } pk11CertCallback; -static SECStatus -pk11_SaveCert(PK11SlotInfo *slot, CERTCertificate *cert, void *arg) -{ - pk11CertCallback *certcb = (pk11CertCallback *)arg; - SECStatus rv = SECSuccess; - - if (slot->cert_count == slot->array_size) return CKR_OK; - - slot->cert_array[slot->cert_count] = CERT_DupCertificate(cert); - if (slot->cert_array[slot->cert_count] == NULL) { - return SECFailure; - } - /* now the slot has a hold of the cert, free the slot's element in the - * cert.. */ - if (cert->ownSlot && (slot == cert->slot)) { - PK11_FreeSlot(cert->slot); - cert->ownSlot = PR_FALSE; - } - slot->cert_count++; - - if (certcb->callback) { - rv = (*certcb->callback)(cert, NULL, certcb->callbackArg); - } - return rv; -} - - -/* free the slots */ -void -PK11_FreeSlotCerts(PK11SlotInfo *slot) -{ - int i; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - /* if we point the cert on our array, the cert doesn't have a - * reference to use (otherwise you would never be able to free - * a slot :) */ - if ((slot->cert_array[i]->slot == slot) && - (!slot->cert_array[i]->ownSlot)) { - slot->cert_array[i]->slot = NULL; - } - CERT_DestroyCertificate(slot->cert_array[i]); - } - PORT_Free(slot->cert_array); - slot->cert_array = NULL; - slot->cert_count = 0; - } - return; -} - -/* - * Update PQG parameters for all the certs on a slot. - */ -static SECStatus -pk11_UpdateSlotPQG(PK11SlotInfo *slot) -{ - int i, tag; - CERTCertificate * cert; - SECOidData *oid; - SECStatus rv1 = SECSuccess; - SECStatus rv2 = SECSuccess; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - - cert = slot->cert_array[i]; - - oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm); - - if (oid != NULL) { - tag = oid->offset; - - /* Check if cert has a DSA or Fortezza public key */ - if ( (tag == SEC_OID_MISSI_KEA_DSS_OLD) || - (tag == SEC_OID_MISSI_DSS_OLD) || - (tag == SEC_OID_MISSI_KEA_DSS) || - (tag == SEC_OID_MISSI_DSS) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) || - (tag == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) { - - /* update PQG parameters */ - - rv1 = SECKEY_UpdateCertPQG(cert); - if (rv1 == SECFailure) { - rv2 = rv1; - } - } - } /* end of if oid != NULL */ - } /* end of for loop */ - } - return rv2; -} - - -/* - * Extract all the certs on a card from a slot. - */ -static SECStatus -pk11_ExtractCertsFromSlot(PK11SlotInfo *slot, void *arg) -{ - pk11TraverseSlot *slotcb = (pk11TraverseSlot*) arg; - int object_count; - SECStatus rv; - - rv = SECSuccess; - - PK11_FreeSlotCerts(slot); - - object_count = PK11_NumberObjectsFor(slot,slotcb->findTemplate, - slotcb->templateCount); - - /*Actually this isn't a failure... there just were no certs to be found*/ - if (object_count == 0) { - return SECSuccess; - } - - slot->cert_array = (CERTCertificate **) - PORT_Alloc(sizeof(CERTCertificate *)*object_count); - if (slot->cert_array == NULL) { - return SECFailure; - } - slot->cert_count = 0; - slot->array_size = object_count; - PK11_TraverseSlot(slot,arg); - - /* Update the PQG parameters for the extracted certs. */ - rv = pk11_UpdateSlotPQG(slot); - - return rv; -} - -/* - * read all the certs from a slot - */ -SECStatus -PK11_ReadSlotCerts(PK11SlotInfo *slot) -{ - - /* build slot list */ - pk11CertCallback caller; - pk11DoCertCallback saver; - pk11TraverseSlot creater; - CK_ATTRIBUTE theTemplate; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - - PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - - caller.callback = NULL; - caller.callbackArg = NULL; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; - creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; - creater.findTemplate = &theTemplate; - creater.templateCount = 1; - - return pk11_ExtractCertsFromSlot(slot, &creater); -} - /* * Extract all the certs on a card from a slot. */ static SECStatus -pk11_TraverseAllSlots(PRBool loadCerts, - SECStatus (*callback)(PK11SlotInfo *,void *),void *arg,void *wincx) { +pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), + void *arg,void *wincx) { PK11SlotList *list; PK11SlotListElement *le; SECStatus rv; /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,loadCerts,wincx); + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,wincx); if (list == NULL) return SECFailure; /* look at each slot and authenticate as necessary */ for (le = list->head ; le; le = le->next) { - /* don't nab internal slots */ - if ((!loadCerts) && le->slot->isInternal == PR_TRUE) { - continue; - } - if (loadCerts || !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, loadCerts, wincx); + if (!PK11_IsFriendly(le->slot)) { + rv = PK11_Authenticate(le->slot, PR_FALSE, wincx); if (rv != SECSuccess) continue; } (*callback)(le->slot,arg); @@ -1085,26 +873,23 @@ pk11_TraverseAllSlots(PRBool loadCerts, SECStatus PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), void *arg, void *wincx) { - pk11CertCallback caller; - pk11DoCertCallback saver; + pk11DoCertCallback caller; pk11TraverseSlot creater; CK_ATTRIBUTE theTemplate; CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - caller.callback = callback; + caller.callback = NULL; + caller.noslotcallback = NULL; + caller.itemcallback = callback; caller.callbackArg = arg; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; + creater.callbackArg = (void *) & caller; creater.findTemplate = &theTemplate; creater.templateCount = 1; - return pk11_TraverseAllSlots(PR_FALSE, pk11_ExtractCertsFromSlot, - &creater, wincx); + return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, wincx); } /*********************************************************************** @@ -1186,7 +971,7 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, *slotptr = slot = PK11_GetInternalKeySlot(); } if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } if (!PK11_IsFriendly(slot)) { @@ -1194,7 +979,7 @@ PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, if (rv != SECSuccess) { PK11_FreeSlot(slot); *slotptr = NULL; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } } @@ -1229,7 +1014,7 @@ PK11_FindCertFromNickname(char *nickname, void *wincx) { CKO_CERTIFICATE, &count, wincx); CERTCertificate *cert; - if (certID == CK_INVALID_KEY) return NULL; + if (certID == CK_INVALID_HANDLE) return NULL; cert = PK11_MakeCertFromHandle(slot,certID[0],NULL); PK11_FreeSlot(slot); PORT_Free(certID); @@ -1481,7 +1266,7 @@ pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, if (cert->slot == slot) { certh = cert->pkcs11ID; - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); cert->pkcs11ID = certh; } @@ -1522,11 +1307,11 @@ PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); - if (keyh == CK_INVALID_KEY) { return NULL; } + if (keyh == CK_INVALID_HANDLE) { return NULL; } return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); } @@ -1580,7 +1365,7 @@ PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, if (rv != SECSuccess) continue; key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); - if (key != CK_INVALID_KEY) { + if (key != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); if (keyPtr) *keyPtr = key; break; @@ -1602,8 +1387,7 @@ PK11_KeyForDERCertExists(SECItem *derCert, CK_OBJECT_HANDLE *keyPtr, CERTCertificate *cert; PK11SlotInfo *slot = NULL; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return NULL; slot = PK11_KeyForCertExists(cert, keyPtr, wincx); @@ -1635,8 +1419,7 @@ PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,void *wincx) { CERTCertificate *cert; PK11SlotInfo *slot = NULL; - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), derCert, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL); if (cert == NULL) return NULL; slot = PK11_ImportCertForKey(cert, nickname, wincx); @@ -1649,7 +1432,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, CK_ATTRIBUTE *searchTemplate, int count, void *wincx) { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; PK11SlotInfo *slot = NULL; SECStatus rv; @@ -1659,7 +1442,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } @@ -1671,7 +1454,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, } certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); break; } @@ -1680,7 +1463,7 @@ pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, PK11_FreeSlotList(list); if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *slotPtr = slot; return certHandle; @@ -1729,7 +1512,7 @@ pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipien ri->id.issuerAndSN->serialNumber.data,ri->id.issuerAndSN->serialNumber.len); certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); if (PK11_IsUserCert(slot,cert,certHandle)) { /* we've found a cert handle, now let's see if there is a key @@ -1744,7 +1527,7 @@ pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipien } } *rlIndex = -1; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -1758,14 +1541,14 @@ pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *winc { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; SECStatus rv; /* get them all! */ list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* Look for the slot that holds the Key */ @@ -1776,13 +1559,13 @@ pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *winc } certHandle = pk11_FindCertObjectByRecipientNew(le->slot, recipientlist, rlIndex); - if (certHandle != CK_INVALID_KEY) + if (certHandle != CK_INVALID_HANDLE) break; } PK11_FreeSlotList(list); - return (le == NULL) ? CK_INVALID_KEY : certHandle; + return (le == NULL) ? CK_INVALID_HANDLE : certHandle; } /* @@ -1822,7 +1605,7 @@ pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, ri->issuerAndSN->serialNumber.data,ri->issuerAndSN->serialNumber.len); certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); if (PK11_IsUserCert(slot,cert,certHandle)) { /* we've found a cert handle, now let's see if there is a key @@ -1836,7 +1619,7 @@ pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, } } *rip = NULL; - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } /* @@ -1848,7 +1631,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, void *wincx) { PK11SlotList *list; PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; PK11SlotInfo *slot = NULL; SECStatus rv; @@ -1858,7 +1641,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); if (list == NULL) { if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *rip = NULL; @@ -1872,7 +1655,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, certHandle = pk11_FindCertObjectByRecipient(le->slot, recipientArray,rip); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { slot = PK11_ReferenceSlot(le->slot); break; } @@ -1881,7 +1664,7 @@ pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, PK11_FreeSlotList(list); if (slot == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } *slotPtr = slot; return certHandle; @@ -1899,14 +1682,14 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip, SECKEYPrivateKey**privKey, void *wincx) { - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE keyHandle = CK_INVALID_HANDLE; CERTCertificate *cert = NULL; SECStatus rv; *privKey = NULL; certHandle = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } @@ -1918,7 +1701,7 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, } keyHandle = PK11_MatchItem(*slotPtr,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(*slotPtr); *slotPtr = NULL; return NULL; @@ -1949,13 +1732,13 @@ PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, int PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx) { - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE certHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE keyHandle = CK_INVALID_HANDLE; NSSCMSRecipient *rl; int rlIndex; certHandle = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return -1; } @@ -1972,7 +1755,7 @@ PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *win /* try to get a private key handle for the cert we found */ keyHandle = PK11_MatchItem(rl->slot, certHandle, CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(rl->slot); rl->slot = NULL; return -1; @@ -2003,13 +1786,16 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, { CK_OBJECT_HANDLE certHandle; CERTCertificate *cert = NULL; + CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; CK_ATTRIBUTE searchTemplate[] = { + { CKA_CLASS, NULL, 0 }, { CKA_ISSUER, NULL, 0 }, { CKA_SERIAL_NUMBER, NULL, 0} }; int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); CK_ATTRIBUTE *attrs = searchTemplate; + PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++; PK11_SETATTRS(attrs, CKA_ISSUER, issuerSN->derIssuer.data, issuerSN->derIssuer.len); attrs++; PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, issuerSN->serialNumber.data, @@ -2017,7 +1803,7 @@ PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, certHandle = pk11_FindCertObjectByTemplate (slotPtr,searchTemplate,count,wincx); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL); @@ -2039,14 +1825,14 @@ PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot) if (cert->slot) { certHandle = pk11_getcerthandle(cert->slot,cert,&searchTemplate,1); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { *pSlot = PK11_ReferenceSlot(cert->slot); return certHandle; } } certHandle = pk11_FindCertObjectByTemplate(pSlot,&searchTemplate,1,wincx); - if (certHandle != CK_INVALID_KEY) { + if (certHandle != CK_INVALID_HANDLE) { if (cert->slot == NULL) { cert->slot = PK11_ReferenceSlot(*pSlot); cert->pkcs11ID = certHandle; @@ -2067,7 +1853,7 @@ PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) SECStatus rv; certHandle = PK11_FindObjectForCert(cert, wincx, &slot); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } rv = PK11_Authenticate(slot, PR_TRUE, wincx); @@ -2076,7 +1862,7 @@ PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) return NULL; } keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(slot); return NULL; } @@ -2092,13 +1878,13 @@ pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx CK_OBJECT_HANDLE keyHandle; certHandle = PK11_FindObjectForCert(cert, wincx, slot); - if (certHandle == CK_INVALID_KEY) { - return CK_INVALID_KEY; + if (certHandle == CK_INVALID_HANDLE) { + return CK_INVALID_HANDLE; } keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { PK11_FreeSlot(*slot); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } return keyHandle; } @@ -2110,7 +1896,7 @@ PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx) SECKEYPrivateKey *privKey; keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return NULL; } privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); @@ -2134,8 +1920,18 @@ PK11_NumberCertsForCertSubject(CERTCertificate *cert) PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - if ((cert->slot == NULL) || (cert->slot->isInternal)) { - return 0; + if (cert->slot == NULL) { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + int count = 0; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + count += PK11_NumberObjectsFor(le->slot,theTemplate,templateSize); + } + PK11_FreeSlotList(list); + return count; } return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize); @@ -2151,6 +1947,19 @@ PK11_TraverseCertsForSubject(CERTCertificate *cert, if(!cert) { return SECFailure; } + if (cert->slot == NULL) { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + PK11_TraverseCertsForSubjectInSlot(cert,le->slot,callback,arg); + } + PK11_FreeSlotList(list); + return SECSuccess; + + } return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); } @@ -2172,11 +1981,12 @@ PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - if ((slot == NULL) || (slot->isInternal)) { + if (slot == NULL) { return SECSuccess; } caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2207,12 +2017,13 @@ PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len); - if ((slot == NULL) || (slot->isInternal)) { + if (slot == NULL) { return SECSuccess; } caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2243,6 +2054,7 @@ PK11_TraverseCertsInSlot(PK11SlotInfo *slot, caller.noslotcallback = callback; caller.callback = NULL; + caller.itemcallback = NULL; caller.callbackArg = arg; callarg.callback = pk11_DoCerts; callarg.callbackArg = (void *) & caller; @@ -2283,7 +2095,7 @@ PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } return PK11_MakeCertFromHandle(slot, certh, NULL); @@ -2323,7 +2135,7 @@ PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, } certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { + if (certh == CK_INVALID_HANDLE) { return NULL; } @@ -2343,15 +2155,15 @@ pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, SECStatus rv; if((slot == NULL) || (cert == NULL)) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } keyID = pk11_mkcertKeyID(cert); if(keyID == NULL) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } - key = CK_INVALID_KEY; + key = CK_INVALID_HANDLE; rv = PK11_Authenticate(slot, PR_TRUE, wincx); if (rv != SECSuccess) goto loser; @@ -2374,7 +2186,7 @@ PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, } keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return NULL; } @@ -2393,7 +2205,7 @@ PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, } keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { + if (keyHandle == CK_INVALID_HANDLE) { return SECFailure; } @@ -2548,7 +2360,7 @@ PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx) */ rv = PK11_Authenticate(slot, PR_TRUE, wincx); if (rv != SECSuccess) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } return pk11_getcerthandle(slot,cert,theTemplate,tsize); @@ -2567,7 +2379,7 @@ PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx) CK_RV crv; handle = PK11_FindObjectForCert(cert,wincx,&slot); - if (handle == CK_INVALID_KEY) { + if (handle == CK_INVALID_HANDLE) { goto loser; } @@ -2716,9 +2528,6 @@ PK11_ListCerts(PK11CertListType type, void *pwarg) listCerts.type = type; listCerts.certList = certList; - SEC_TraversePermCerts(CERT_GetDefaultCertDB(),pk11ListCertCallback, - &listCerts); - PK11_TraverseSlotCerts(pk11ListCertCallback,&listCerts,pwarg); if (CERT_LIST_HEAD(certList) == NULL) { @@ -2783,13 +2592,13 @@ PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, certHandle = pk11_getcerthandle(slot,cert,theTemplate,tsize); } else { certHandle = PK11_FindObjectForCert(cert, wincx, &slotRef); - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return pk11_mkcertKeyID(cert); } slot = slotRef; } - if (certHandle == CK_INVALID_KEY) { + if (certHandle == CK_INVALID_HANDLE) { return NULL; } @@ -2860,3 +2669,149 @@ PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot) return keys; } +/* + * return the certificate associated with a derCert + */ +SECItem * +PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, + SECItem *name, int type) +{ + CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_KRL, NULL, 0 }, + }; + CK_ATTRIBUTE crlData = { CKA_VALUE, NULL, 0 }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_BBOOL ck_true = CK_TRUE; + CK_BBOOL ck_false = CK_FALSE; + CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_RV crv; + SECStatus rv; + SECItem *derCrl = NULL; + + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? + &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; + + if (*slot) { + crlh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize); + } else { + PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, + PR_FALSE,PR_TRUE,NULL); + PK11SlotListElement *le; + + /* loop through all the fortezza tokens */ + for (le = list->head; le; le = le->next) { + crlh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize); + if (crlh != CK_INVALID_HANDLE) { + *slot = PK11_ReferenceSlot(le->slot); + break; + } + } + PK11_FreeSlotList(list); + } + + if (crlh == CK_INVALID_HANDLE) { + PORT_SetError(SEC_ERROR_NO_KRL); + return NULL; + } + crv = PK11_GetAttributes(NULL,*slot,crlh,&crlData,1); + if (crv != CKR_OK) { + PORT_SetError(PK11_MapError (crv)); + goto loser; + } + + derCrl = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); + if (derCrl == NULL) { + goto loser; + } + + derCrl->data = crlData.pValue; + derCrl->len = crlData.ulValueLen; + + if (crlHandle) { + *crlHandle = crlh; + } + +loser: + return derCrl; +} + +CK_OBJECT_HANDLE +PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, + char *url, int type) +{ + CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL; + CK_ATTRIBUTE theTemplate[] = { + { CKA_SUBJECT, NULL, 0 }, + { CKA_CLASS, NULL, 0 }, + { CKA_NETSCAPE_KRL, NULL, 0 }, + { CKA_NETSCAPE_URL, NULL, 0 }, + { CKA_VALUE, NULL, 0 } + }; + CK_ATTRIBUTE crlData = { CKA_VALUE, NULL, 0 }; + /* if you change the array, change the variable below as well */ + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); + CK_BBOOL ck_true = CK_TRUE; + CK_BBOOL ck_false = CK_FALSE; + CK_OBJECT_HANDLE crlh = CK_INVALID_HANDLE; + CK_ATTRIBUTE *attrs = theTemplate; + CK_SESSION_HANDLE rwsession; + CK_RV crv; + + PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++; + PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, (type == SEC_CRL_TYPE) ? + &ck_false : &ck_true, sizeof (CK_BBOOL)); attrs++; + PK11_SETATTRS(attrs, CKA_NETSCAPE_URL, url, PORT_Strlen(url)+1); attrs++; + PK11_SETATTRS(attrs, CKA_VALUE,crl->data,crl->len); attrs++; + + rwsession = PK11_GetRWSession(slot); + if (rwsession == CK_INVALID_SESSION) { + PORT_SetError(SEC_ERROR_READ_ONLY); + return crlh; + } + + crv = PK11_GETTAB(slot)-> + C_CreateObject(rwsession,attrs,tsize,&crlh); + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + } + + PK11_RestoreROSession(slot,rwsession); + return crlh; +} + + + +/* + * delete a cert and it's private key (if no other certs are pointing to the + * private key. + */ +SECStatus +SEC_DeletePermCRL(CERTSignedCrl *crl) +{ + PK11SlotInfo *slot = crl->slot; + CK_RV crv; + + if (slot == NULL) { + /* shouldn't happen */ + PORT_SetError( SEC_ERROR_CRL_INVALID); + return SECFailure; + } + + crv = PK11_DestroyTokenObject(slot,crl->pkcs11ID); + if (crv != CKR_OK) { + PORT_SetError( PK11_MapError(crv) ); + goto loser; + } + crl->slot = NULL; + PK11_FreeSlot(slot); +loser: + return SECSuccess; +} diff --git a/security/nss/lib/pk11wrap/pk11func.h b/security/nss/lib/pk11wrap/pk11func.h index 0a7c27812..d05e1045f 100644 --- a/security/nss/lib/pk11wrap/pk11func.h +++ b/security/nss/lib/pk11wrap/pk11func.h @@ -483,6 +483,14 @@ PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot, SECItem * PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *key); +SECItem * +PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *handle, + SECItem *derName, int type); + +CK_OBJECT_HANDLE +PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, + SECItem *name, char *url, int type); + SEC_END_PROTOS #endif diff --git a/security/nss/lib/pk11wrap/pk11kea.c b/security/nss/lib/pk11wrap/pk11kea.c index c50b9d8b6..b5b810d0b 100644 --- a/security/nss/lib/pk11wrap/pk11kea.c +++ b/security/nss/lib/pk11wrap/pk11kea.c @@ -85,8 +85,8 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* RSA */ if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) && PK11_DoesMechanism(slot,CKM_RSA_PKCS)) { - CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_KEY; + CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE; + CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE; SECKEYPublicKey *pubKey = NULL; SECKEYPrivateKey *privKey = NULL; SECItem wrapData; @@ -95,12 +95,12 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, /* find RSA Public Key on target */ pubKeyHandle = pk11_FindRSAPubKey(slot); - if (pubKeyHandle != CK_INVALID_KEY) { + if (pubKeyHandle != CK_INVALID_HANDLE) { privKeyHandle = PK11_MatchItem(slot,pubKeyHandle,CKO_PRIVATE_KEY); } /* if no key exists, generate a key pair */ - if (privKeyHandle == CK_INVALID_KEY) { + if (privKeyHandle == CK_INVALID_HANDLE) { unsigned int symKeyLength = PK11_GetKeyLength(symKey); PK11RSAGenParams rsaParams; @@ -125,7 +125,7 @@ pk11_KeyExchange(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, if (pubKey && pubKey->pkcs11Slot) { PK11_FreeSlot(pubKey->pkcs11Slot); pubKey->pkcs11Slot = NULL; - pubKey->pkcs11ID = CK_INVALID_KEY; + pubKey->pkcs11ID = CK_INVALID_HANDLE; } } } diff --git a/security/nss/lib/pk11wrap/pk11pk12.c b/security/nss/lib/pk11wrap/pk11pk12.c index df6646e04..ac34bbff5 100644 --- a/security/nss/lib/pk11wrap/pk11pk12.c +++ b/security/nss/lib/pk11wrap/pk11pk12.c @@ -106,9 +106,37 @@ struct SECKEYRawPrivateKeyStr { } u; }; typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey; -/*const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[];*/ +/* ASN1 Templates for new decoder/encoder */ +/* + * Attribute value for PKCS8 entries (static?) + */ +const SEC_ASN1Template SECKEY_AttributeTemplate[] = { + { SEC_ASN1_SEQUENCE, + 0, NULL, sizeof(SECKEYAttribute) }, + { SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) }, + { SEC_ASN1_SET_OF, offsetof(SECKEYAttribute, attrValue), + SEC_AnyTemplate }, + { 0 } +}; + +const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = { + { SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate }, +}; + +const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = { + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) }, + { SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo,version) }, + { SEC_ASN1_INLINE, offsetof(SECKEYPrivateKeyInfo,algorithm), + SECOID_AlgorithmIDTemplate }, + { SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo,privateKey) }, + { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, + offsetof(SECKEYPrivateKeyInfo,attributes), + SECKEY_SetOfAttributeTemplate }, + { 0 } +}; + const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) }, { SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey,u.rsa.version) }, diff --git a/security/nss/lib/pk11wrap/pk11pqg.c b/security/nss/lib/pk11wrap/pk11pqg.c index ef741198b..530548c36 100644 --- a/security/nss/lib/pk11wrap/pk11pqg.c +++ b/security/nss/lib/pk11wrap/pk11pqg.c @@ -42,7 +42,11 @@ */ extern SECStatus PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy) { +#ifdef notdef return PQG_ParamGen(j, pParams, pVfy); +#else + return SECFailure; +#endif } /* Generate PQGParams and PQGVerify structs. @@ -53,7 +57,11 @@ PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy) { extern SECStatus PK11_PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy) { +#ifdef notdef return PQG_ParamGenSeedLen(j, seedBytes, pParams, pVfy); +#else + return SECFailure; +#endif } /* Test PQGParams for validity as DSS PQG values. @@ -85,7 +93,11 @@ PK11_PQG_ParamGenSeedLen( unsigned int j, unsigned int seedBytes, extern SECStatus PK11_PQG_VerifyParams(const PQGParams *params, const PQGVerify *vfy, SECStatus *result) { +#ifdef notdef return PQG_VerifyParams(params, vfy, result); +#else + return SECFailure; +#endif } diff --git a/security/nss/lib/pk11wrap/pk11skey.c b/security/nss/lib/pk11wrap/pk11skey.c index c036e46a0..86d418fa2 100644 --- a/security/nss/lib/pk11wrap/pk11skey.c +++ b/security/nss/lib/pk11wrap/pk11skey.c @@ -225,7 +225,7 @@ PK11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, void *wincx) symKey->data.data = NULL; symKey->data.len = 0; symKey->owner = PR_TRUE; - symKey->objectID = CK_INVALID_KEY; + symKey->objectID = CK_INVALID_HANDLE; symKey->slot = slot; symKey->series = slot->series; symKey->cx = wincx; @@ -253,7 +253,7 @@ PK11_FreeSymKey(PK11SymKey *symKey) } PK11_USE_THREADS(PZ_Unlock(symKey->refLock);) if (destroy) { - if ((symKey->owner) && symKey->objectID != CK_INVALID_KEY) { + if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) { pk11_EnterKeyMonitor(symKey); (void) PK11_GETTAB(symKey->slot)-> C_DestroyObject(symKey->session, symKey->objectID); @@ -301,7 +301,7 @@ PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent, PK11Origin origin, { PK11SymKey *symKey; - if (keyID == CK_INVALID_KEY) { + if (keyID == CK_INVALID_HANDLE) { return NULL; } @@ -338,7 +338,7 @@ PK11_GetWrapKey(PK11SlotInfo *slot, int wrap, CK_MECHANISM_TYPE type, PK11SymKey *symKey = NULL; if (slot->series != series) return NULL; - if (slot->refKeys[wrap] == CK_INVALID_KEY) return NULL; + if (slot->refKeys[wrap] == CK_INVALID_HANDLE) return NULL; if (type == CKM_INVALID_MECHANISM) type = slot->wrapMechanism; symKey = PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, @@ -535,7 +535,7 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, /* what about fortezza??? */ default: PORT_SetError( SEC_ERROR_BAD_KEY ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } templateCount = attrs - theTemplate; @@ -547,7 +547,7 @@ PK11_ImportPublicKey(PK11SlotInfo *slot, SECKEYPublicKey *pubKey, rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, templateCount, isToken, &objectID); if ( rv != SECSuccess) { - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } } @@ -588,7 +588,7 @@ PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *keyID, PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); key_id = pk11_FindObjectByTemplate(slot,findTemp,tsize); - if (key_id == CK_INVALID_KEY) { + if (key_id == CK_INVALID_HANDLE) { return NULL; } return PK11_SymKeyFromHandle(slot, NULL, PK11_OriginDerive, type, key_id, @@ -1140,7 +1140,7 @@ PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject) PK11_ExitSlotMonitor(slot); if (crv == CKR_OK) return destObject; PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; + return CK_INVALID_HANDLE; } @@ -1374,7 +1374,7 @@ pk11_PairwiseConsistencyCheck(SECKEYPublicKey *pubKey, } id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); - if (id == CK_INVALID_KEY) { + if (id == CK_INVALID_HANDLE) { PK11_FreeSlot(slot); return SECFailure; } @@ -1702,7 +1702,7 @@ pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, if (pubKey->pkcs11Slot) { PK11_FreeSlot(pubKey->pkcs11Slot); pubKey->pkcs11Slot = NULL; - pubKey->pkcs11ID = CK_INVALID_KEY; + pubKey->pkcs11ID = CK_INVALID_HANDLE; } } @@ -2491,7 +2491,7 @@ PK11_MakeKEAPubKey(unsigned char *keyData,int length) pubk->arena = arena; pubk->pkcs11Slot = 0; - pubk->pkcs11ID = CK_INVALID_KEY; + pubk->pkcs11ID = CK_INVALID_HANDLE; pubk->keyType = fortezzaKey; rv = SECITEM_CopyItem(arena, &pubk->u.fortezza.KEAKey, &pkData); if (rv != SECSuccess) { @@ -3226,7 +3226,7 @@ pk11_restoreContext(PK11Context *context,void *space, unsigned long savedLength) { CK_RV crv; CK_OBJECT_HANDLE objectID = (context->key) ? context->key->objectID: - CK_INVALID_KEY; + CK_INVALID_HANDLE; PORT_Assert(space != NULL); if (space == NULL) { @@ -4096,9 +4096,10 @@ PK11_DestroyPBEParams(SECItem *params) SECAlgorithmID * PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt) { - SECAlgorithmID *algid; - + SECAlgorithmID *algid = NULL; +#ifdef notdef algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, iteration); +#endif return algid; } @@ -4372,7 +4373,9 @@ PK11_ExportEncryptedPrivateKeyInfo(PK11SlotInfo *slot, SECOidTag algTag, goto loser; } epki->arena = arena; +#ifdef notdef algid = SEC_PKCS5CreateAlgorithmID(algTag, NULL, iteration); +#endif if(algid == NULL) { rv = SECFailure; goto loser; diff --git a/security/nss/lib/pk11wrap/pk11slot.c b/security/nss/lib/pk11wrap/pk11slot.c index f468c217b..b2ade4304 100644 --- a/security/nss/lib/pk11wrap/pk11slot.c +++ b/security/nss/lib/pk11wrap/pk11slot.c @@ -50,8 +50,6 @@ #include "prlong.h" #include "secerr.h" #include "secpkcs5.h" -#define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */ -#include "ckt.h" /************************************************************* @@ -419,7 +417,7 @@ PK11_NewSlotInfo(void) slot->series = 0; slot->wrapKey = 0; slot->wrapMechanism = CKM_INVALID_MECHANISM; - slot->refKeys[0] = CK_INVALID_KEY; + slot->refKeys[0] = CK_INVALID_HANDLE; slot->reason = PK11_DIS_NONE; slot->readOnly = PR_TRUE; slot->needLogin = PR_FALSE; @@ -467,9 +465,6 @@ PK11_DestroySlot(PK11SlotInfo *slot) PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); } - /* now free up all the certificates we grabbed on this slot */ - PK11_FreeSlotCerts(slot); - /* free up the cached keys and sessions */ PK11_CleanKeyList(slot); @@ -1082,9 +1077,6 @@ PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx) if (rv != SECWouldBlock) break; } if (rv == SECSuccess) { - if ((loadCerts) && (!slot->isInternal) && (slot->cert_count == 0)) { - PK11_ReadSlotCerts(slot); - } rv = pk11_CheckVerifyTest(slot); } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD); return rv; @@ -1715,14 +1707,6 @@ PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts) if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); } - /*if we have cached slotcerts, free them they are almost certainly stale*/ - PK11_FreeSlotCerts(slot); - - if (loadCerts && (!slot->isInternal) && - ((!slot->needLogin) || (slot->defaultFlags & SECMOD_FRIENDLY_FLAG))) { - PK11_ReadSlotCerts(slot); - } - if (!(slot->needLogin)) { return pk11_CheckVerifyTest(slot); } @@ -1783,7 +1767,7 @@ pk11_isRootSlot(PK11SlotInfo *slot) PORT_Assert(tsize <= sizeof(findTemp)/sizeof(CK_ATTRIBUTE)); handle = pk11_FindObjectByTemplate(slot,findTemp,tsize); - if (handle == CK_INVALID_KEY) { + if (handle == CK_INVALID_HANDLE) { return PR_FALSE; } return PR_TRUE; @@ -1891,7 +1875,6 @@ pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts) PK11_GETTAB(slot)->C_CloseSession(slot->session); slot->session = CK_INVALID_SESSION; /* force certs to be freed */ - PK11_FreeSlotCerts(slot); } if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); return PR_FALSE; @@ -1904,7 +1887,6 @@ pk11_IsPresentCertLoad(PK11SlotInfo *slot, PRBool loadCerts) if (crv != CKR_OK) { PK11_GETTAB(slot)->C_CloseSession(slot->session); slot->session = CK_INVALID_SESSION; - PK11_FreeSlotCerts(slot); } } if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); @@ -3341,6 +3323,7 @@ static unsigned long rc2_unmap(unsigned long x) SECStatus pk11_pbe_decode(SECAlgorithmID *algid, SECItem *mech) { +#ifdef notdef CK_PBE_PARAMS *pbe_params = NULL; SEC_PKCS5PBEParameter *p5_param; SECItem *p5_misc = NULL; @@ -3385,6 +3368,7 @@ loser: } PORT_Free(pbe_params); SEC_PKCS5DestroyPBEParameter(p5_param); +#endif return SECFailure; } @@ -4285,7 +4269,6 @@ PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd) /* first shutdown the token. Existing sessions will get closed here */ PK11_GETTAB(slot)->C_CloseAllSessions(slot->slotID); slot->session = CK_INVALID_SESSION; - PK11_FreeSlotCerts(slot); /* now re-init the token */ crv = PK11_GETTAB(slot)->C_InitToken(slot->slotID, @@ -4357,6 +4340,7 @@ PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, SECAlgorithmID temp_algid; SECItem param, *iv; +#ifdef notdef if((pPBEMechanism == CK_NULL_PTR) || (pCryptoMechanism == CK_NULL_PTR)) { return CKR_HOST_MEMORY; } @@ -4392,6 +4376,7 @@ PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism, } } } +#endif switch(pPBEMechanism->mechanism) { case CKM_PBE_MD2_DES_CBC: diff --git a/security/nss/lib/pk11wrap/secmodt.h b/security/nss/lib/pk11wrap/secmodt.h index b36350ae6..de2ae10f3 100644 --- a/security/nss/lib/pk11wrap/secmodt.h +++ b/security/nss/lib/pk11wrap/secmodt.h @@ -162,8 +162,6 @@ struct PK11DefaultArrayEntryStr { #define CKM_FAKE_RANDOM 0x80000efeL #define CKM_INVALID_MECHANISM 0xffffffffL #define CKA_DIGEST 0x81000000L -#define CK_INVALID_KEY 0 -#define CK_INVALID_SESSION 0 /* Cryptographic module types */ #define SECMOD_EXTERNAL 0 /* external module */ @@ -206,11 +204,11 @@ typedef PRBool (*PK11IsLoggedInFunc)(PK11SlotInfo *slot, void *arg); /* ** Attributes */ -struct SECKEYPrivAttributeStr { +struct SECKEYAttributeStr { SECItem attrType; SECItem **attrValue; }; -typedef struct SECKEYPrivAttributeStr SECKEYPrivAttribute; +typedef struct SECKEYAttributeStr SECKEYAttribute; /* ** A PKCS#8 private key info object @@ -220,10 +218,9 @@ struct SECKEYPrivateKeyInfoStr { SECItem version; SECAlgorithmID algorithm; SECItem privateKey; - SECKEYPrivAttribute **attributes; + SECKEYAttribute **attributes; }; typedef struct SECKEYPrivateKeyInfoStr SECKEYPrivateKeyInfo; -#define SEC_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ /* ** A PKCS#8 private key info object diff --git a/security/nss/lib/pk11wrap/secmodti.h b/security/nss/lib/pk11wrap/secmodti.h index 789e63da1..beed44ed2 100644 --- a/security/nss/lib/pk11wrap/secmodti.h +++ b/security/nss/lib/pk11wrap/secmodti.h @@ -35,9 +35,12 @@ * pkcs11 specific client and server files. */ +#ifndef _SECMODTI_H_ +#define _SECMODTI_H_ 1 #include "prmon.h" #include "prtypes.h" #include "nssilckt.h" +#include "pk11init.h" /* internal data structures */ @@ -109,9 +112,7 @@ struct PK11SlotInfoStr { * token */ int mechanismCount; /* cache the certificates stored on the token of this slot */ -#ifdef HACK_IT /*!!! */ CERTCertificate **cert_array; -#endif int array_size; int cert_count; char serial[16]; @@ -125,29 +126,6 @@ struct PK11SlotInfoStr { CK_FLAGS RSAInfoFlags; }; -/* hold slot default flags until we initialize a slot. This structure is only - * useful between the time we define a module (either by hand or from the - * database) and the time the module is loaded. Not reference counted */ -struct PK11PreSlotInfoStr { - CK_SLOT_ID slotID; /* slot these flags are for */ - unsigned long defaultFlags; /* bit mask of default implementation this slot - * provides */ - int askpw; /* slot specific password bits */ - long timeout; /* slot specific timeout value */ - char hasRootCerts; /* is this the root cert PKCS #11 module? */ - char hasRootTrust; /* is this the root cert PKCS #11 module? */ -}; - -#define SECMOD_SLOT_FLAGS "slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES]" - -#define SECMOD_MAKE_NSS_FLAGS(fips,slot) \ -"Flags=internal,critical"fips" slotparams=("#slot"={"SECMOD_SLOT_FLAGS"})" - -#define SECMOD_INT_NAME "NSS Internal PKCS #11 Module" -#define SECMOD_INT_FLAGS SECMOD_MAKE_NSS_FLAGS("",1) -#define SECMOD_FIPS_NAME "NSS Internal FIPS PKCS #11 Module" -#define SECMOD_FIPS_FLAGS SECMOD_MAKE_NSS_FLAGS(",fips",3) - /* Symetric Key structure. Reference Counted */ struct PK11SymKeyStr { CK_MECHANISM_TYPE type; /* type of operation this key was created for*/ @@ -199,3 +177,4 @@ struct PK11ContextStr { * non-standard semantics*/ }; +#endif /* _SECMODTI_H_ */ diff --git a/security/nss/lib/pkcs12/p12d.c b/security/nss/lib/pkcs12/p12d.c index 3a77578d7..64a0ea353 100644 --- a/security/nss/lib/pkcs12/p12d.c +++ b/security/nss/lib/pkcs12/p12d.c @@ -1875,15 +1875,6 @@ sec_pkcs12_get_existing_nick_for_dn(sec_PKCS12SafeBag *cert, void *wincx) /* if the token is local, first traverse the cert database * then traverse the token. */ - if(PK11_IsInternal(cert->slot)) { - if(CERT_TraversePermCertsForSubject(CERT_GetDefaultCertDB(), - &tempCert->derSubject, gatherNicknames, - nickArg) != SECSuccess) { - returnDn = NULL; - goto loser; - } - } - if(PK11_TraverseCertsForSubjectInSlot(tempCert, cert->slot, gatherNicknames, (void *)nickArg) != SECSuccess) { returnDn = NULL; @@ -1944,12 +1935,6 @@ sec_pkcs12_certs_for_nickname_exist(SECItem *nickname, PK11SlotInfo *slot) } /* we want to check the local database first if we are importing to it */ - if(PK11_IsInternal(slot)) { - CERT_TraversePermCertsForNickname(CERT_GetDefaultCertDB(), - (char *)nickname->data, - countCertificate, (void *)&nCerts); - } - PK11_TraverseCertsForNicknameInSlot(nickname, slot, countCertificate, (void *)&nCerts); if(nCerts) return PR_TRUE; diff --git a/security/nss/lib/softoken/alghmac.c b/security/nss/lib/softoken/alghmac.c index aef81a76b..60abd73d0 100644 --- a/security/nss/lib/softoken/alghmac.c +++ b/security/nss/lib/softoken/alghmac.c @@ -31,10 +31,10 @@ * GPL. */ -#include "alghmac.h" #include "sechash.h" -#include "secoid.h" #include "secport.h" +#include "alghmac.h" +/*#include "secoid.h"*/ #define HMAC_PAD_SIZE 64 @@ -57,8 +57,7 @@ HMAC_Destroy(HMACContext *cx) } HMACContext * -HMAC_Create(SECOidTag hash_alg, - const unsigned char *secret, +HMAC_Create(const SECHashObject *hash_obj, const unsigned char *secret, unsigned int secret_len) { HMACContext *cx; @@ -68,20 +67,7 @@ HMAC_Create(SECOidTag hash_alg, cx = (HMACContext*)PORT_ZAlloc(sizeof(HMACContext)); if (cx == NULL) return NULL; - - switch (hash_alg) { - case SEC_OID_MD5: - cx->hashobj = &SECRawHashObjects[HASH_AlgMD5]; - break; - case SEC_OID_MD2: - cx->hashobj = &SECRawHashObjects[HASH_AlgMD2]; - break; - case SEC_OID_SHA1: - cx->hashobj = &SECRawHashObjects[HASH_AlgSHA1]; - break; - default: - goto loser; - } + cx->hashobj = hash_obj; cx->hash = cx->hashobj->create(); if (cx->hash == NULL) diff --git a/security/nss/lib/softoken/alghmac.h b/security/nss/lib/softoken/alghmac.h index 10d598267..3cb1a74dc 100644 --- a/security/nss/lib/softoken/alghmac.h +++ b/security/nss/lib/softoken/alghmac.h @@ -34,8 +34,6 @@ #ifndef _ALGHMAC_H_ #define _ALGHMAC_H_ -#include "secoid.h" - typedef struct HMACContextStr HMACContext; SEC_BEGIN_PROTOS @@ -53,7 +51,7 @@ HMAC_Destroy(HMACContext *cx); * NULL is returned if an error occurs or the secret is > 64 bytes. */ extern HMACContext * -HMAC_Create(SECOidTag hash_alg, const unsigned char *secret, +HMAC_Create(const SECHashObject *hashObj, const unsigned char *secret, unsigned int secret_len); /* reset HMAC for a fresh round */ diff --git a/security/nss/lib/softoken/config.mk b/security/nss/lib/softoken/config.mk index d5f06c3ed..702802b8c 100644 --- a/security/nss/lib/softoken/config.mk +++ b/security/nss/lib/softoken/config.mk @@ -48,9 +48,8 @@ ifeq ($(OS_ARCH), WINNT) SHARED_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).dll IMPORT_LIBRARY = $(OBJDIR)/$(LIBRARY_NAME)$(LIBRARY_VERSION).lib -DLLFLAGS += -DEF:nss.def -RES = $(OBJDIR)/nss.res -RESNAME = nss.rc +RES = $(OBJDIR)/$(LIBRARY_NAME).res +RESNAME = $(LIBRARY_NAME).rc # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) CRYPTOLIB=$(DIST)/lib/freebl.lib @@ -65,11 +64,6 @@ EXTRA_SHARED_LIBRARY_LIBS += \ $(DIST)/lib/secutil.lib \ $(NULL) -#SHARED_LIBRARY_DIRS = \ -# $(CRYPTODIR) \ -# ../util \ -# $(NULL) - EXTRA_LIBS += \ $(DIST)/lib/dbm.lib \ $(NULL) @@ -83,12 +77,6 @@ EXTRA_SHARED_LIBS += \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)plds4.lib \ $(DIST)/lib/$(NSPR31_LIB_PREFIX)nspr4.lib \ $(NULL) - -# $(PROGRAM) has NO explicit dependencies on $(OS_LIBS) -#OS_LIBS += \ -# wsock32.lib \ -# winmm.lib \ -# $(NULL) else # $(PROGRAM) has explicit dependencies on $(EXTRA_LIBS) @@ -101,17 +89,11 @@ endif EXTRA_LIBS += \ $(CRYPTOLIB) \ $(DIST)/lib/libsecutil.$(LIB_SUFFIX) \ - $(NULL) -EXTRA_LIBS += \ $(DIST)/lib/libdbm.$(LIB_SUFFIX) \ $(NULL) ifdef MOZILLA_BSAFE_BUILD EXTRA_LIBS+=$(DIST)/lib/libbsafe.$(LIB_SUFFIX) endif -#SHARED_LIBRARY_DIRS = \ -# $(CRYPTODIR) \ -# ../util \ -# $(NULL) # $(PROGRAM) has NO explicit dependencies on $(EXTRA_SHARED_LIBS) # $(EXTRA_SHARED_LIBS) come before $(OS_LIBS), except on AIX. @@ -123,43 +105,12 @@ EXTRA_SHARED_LIBS += \ $(NULL) endif -#ifeq ($(OS_ARCH),SunOS) -#MAPFILE = $(OBJDIR)/nssmap.sun -#ALL_TRASH += $(MAPFILE) -#MKSHLIB += -M $(MAPFILE) -#ifndef USE_64 -#ifeq ($(CPU_ARCH),sparc) -## The -R '$ORIGIN' linker option instructs libnss3.so to search for its -## dependencies (libfreebl_*.so) in the same directory where it resides. -#MKSHLIB += -R '$$ORIGIN' -#endif -#endif -#endif -# -#ifeq ($(OS_ARCH),AIX) -#MAPFILE = $(OBJDIR)/nssmap.aix -#ALL_TRASH += $(MAPFILE) -#EXPORT_RULES = -bexport:$(MAPFILE) -#endif -# -#ifeq ($(OS_ARCH),HP-UX) -#MAPFILE = $(OBJDIR)/nssmap.hp -#ALL_TRASH += $(MAPFILE) -#MKSHLIB += -c $(MAPFILE) -#endif -# -#ifeq ($(OS_ARCH), OSF1) -#MAPFILE = $(OBJDIR)/nssmap.osf -#ALL_TRASH += $(MAPFILE) -#MKSHLIB += -hidden -input $(MAPFILE) -#endif -# -#ifeq ($(OS_ARCH),Linux) -#MAPFILE = $(OBJDIR)/nssmap.linux -#ALL_TRASH += $(MAPFILE) -#MKSHLIB += -Wl,--version-script,$(MAPFILE) -#endif -# -# - - +ifeq ($(OS_ARCH),SunOS) +ifndef USE_64 +ifeq ($(CPU_ARCH),sparc) +# The -R '$ORIGIN' linker option instructs libnss3.so to search for its +# dependencies (libfreebl_*.so) in the same directory where it resides. +MKSHLIB += -R '$$ORIGIN' +endif +endif +endif diff --git a/security/nss/lib/softoken/keydb.c b/security/nss/lib/softoken/keydb.c index 8ad3d7674..eed5b9173 100644 --- a/security/nss/lib/softoken/keydb.c +++ b/security/nss/lib/softoken/keydb.c @@ -64,22 +64,6 @@ #define SALT_LENGTH 16 /* ASN1 Templates for new decoder/encoder */ -/* - * Attribute value for PKCS8 entries (static?) - */ -const SEC_ASN1Template nsslowkey_AttributeTemplate[] = { - { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(NSSLOWKEYAttribute) }, - { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) }, - { SEC_ASN1_SET_OF, offsetof(NSSLOWKEYAttribute, attrValue), - SEC_AnyTemplate }, - { 0 } -}; - -const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = { - { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate }, -}; - const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) }, @@ -90,9 +74,6 @@ const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = { SECOID_AlgorithmIDTemplate }, { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) }, - { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0, - offsetof(NSSLOWKEYPrivateKeyInfo,attributes), - nsslowkey_SetOfAttributeTemplate }, { 0 } }; @@ -799,10 +780,10 @@ nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle, NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - NSSLOWKEYGetPasswordKey f, void *arg) + SECItem *arg) { - return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, nickname, - f, arg, nsslowkey_GetDefaultKeyDBAlg()); + return nsslowkey_StoreKeyByPublicKeyAlg(handle, privkey, pubKeyData, + nickname, arg, nsslowkey_GetDefaultKeyDBAlg()); } /* see if the public key for this cert is in the database filed @@ -853,47 +834,6 @@ nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cer } /* - * find the private key for a cert - */ -NSSLOWKEYPrivateKey * -nsslowkey_FindKeyByCert(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert, - NSSLOWKEYGetPasswordKey f, void *arg) -{ - NSSLOWKEYPublicKey *pubkey = NULL; - SECItem *keyItem = NULL; - NSSLOWKEYPrivateKey *privKey = NULL; - - /* get cert's public key */ - pubkey = nsslowcert_ExtractPublicKey(cert); - if ( !pubkey ) { - goto loser; - } - - /* TNH - make record key from NSSLOWKEYPublicKey (again) */ - switch (pubkey->keyType) { - case NSSLOWKEYRSAKey: - keyItem = &pubkey->u.rsa.modulus; - break; - case NSSLOWKEYDSAKey: - keyItem = &pubkey->u.dsa.publicValue; - break; - case NSSLOWKEYDHKey: - keyItem = &pubkey->u.dh.publicValue; - break; - case NSSLOWKEYNullKey: - goto loser; - } - PORT_Assert( keyItem != NULL ); - - privKey = nsslowkey_FindKeyByPublicKey(handle, keyItem, f, arg); - - /* success falls through */ -loser: - nsslowkey_DestroyPublicKey(pubkey); - return(privKey); -} - -/* * check to see if the user has a password */ SECStatus @@ -934,19 +874,6 @@ nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) nsslowkey_GetDefaultKeyDBAlg()); } -/* - * Re-encrypt the entire key database with a new password. - * NOTE: This really should create a new database rather than doing it - * in place in the original - */ -SECStatus -nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle, - SECItem *oldpwitem, SECItem *newpwitem) -{ - return nsslowkey_ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, - nsslowkey_GetDefaultKeyDBAlg()); -} - static SECStatus HashPassword(unsigned char *hashresult, char *pw, SECItem *salt) { @@ -1124,7 +1051,7 @@ seckey_create_rc4_salt(void) } SECItem * -seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) +seckey_rc4_decode(SECItem *key, SECItem *src) { SECItem *dest = NULL; RC4Context *ctxt = NULL; @@ -1144,11 +1071,7 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) ctxt = RC4_CreateContext(key->data, key->len); if(ctxt != NULL) { - if(encrypt == PR_TRUE) - rv = RC4_Encrypt(ctxt, dest->data, &dest->len, - src->len + 64, src->data, src->len); - else - rv = RC4_Decrypt(ctxt, dest->data, &dest->len, + rv = RC4_Decrypt(ctxt, dest->data, &dest->len, src->len + 64, src->data, src->len); RC4_DestroyContext(ctxt, PR_TRUE); } @@ -1169,16 +1092,18 @@ seckey_rc4_cipher(SECItem *key, SECItem *src, PRBool encrypt) NSSLOWKEYEncryptedPrivateKeyInfo * seckey_encrypt_private_key( NSSLOWKEYPrivateKey *pk, SECItem *pwitem, NSSLOWKEYDBHandle *keydb, - SECOidTag algorithm) + SECOidTag algorithm, SECItem **salt) { NSSLOWKEYEncryptedPrivateKeyInfo *epki = NULL; NSSLOWKEYPrivateKeyInfo *pki = NULL; SECStatus rv = SECFailure; - SECAlgorithmID *algid = NULL; PLArenaPool *temparena = NULL, *permarena = NULL; - SECItem *key = NULL, *salt = NULL, *der_item = NULL; + SECItem *key = NULL, *der_item = NULL; + NSSPKCS5PBEParameter *param; SECItem *dummy = NULL, *dest = NULL; + SECAlgorithmID *algid; + *salt = NULL; permarena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); if(permarena == NULL) return NULL; @@ -1200,7 +1125,7 @@ seckey_encrypt_private_key( /* setup private key info */ dummy = SEC_ASN1EncodeInteger(temparena, &(pki->version), - SEC_PRIVATE_KEY_INFO_VERSION); + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); if(dummy == NULL) goto loser; @@ -1272,72 +1197,59 @@ seckey_encrypt_private_key( } rv = SECFailure; /* assume failure */ - switch(algorithm) - { - case SEC_OID_RC4: - salt = seckey_create_rc4_salt(); - if(salt != NULL) - { - key = seckey_create_rc4_key(pwitem, salt); - if(key != NULL) - { - dest = seckey_rc4_cipher(key, der_item, PR_TRUE); - if(dest != NULL) - { - rv = SECITEM_CopyItem(permarena, &epki->encryptedData, - dest); - if(rv == SECSuccess) - rv = SECOID_SetAlgorithmID(permarena, - &epki->algorithm, SEC_OID_RC4, salt); - } - } - } - if(dest != NULL) - SECITEM_FreeItem(dest, PR_TRUE); - if(key != NULL) - SECITEM_ZfreeItem(key, PR_TRUE); - break; - default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, NULL, 1); - if(algid != NULL) - { - dest = SEC_PKCS5CipherData(algid, pwitem, - der_item, PR_TRUE, NULL); - if(dest != NULL) - { - rv = SECITEM_CopyItem(permarena, &epki->encryptedData, - dest); - if(rv == SECSuccess) - rv = SECOID_CopyAlgorithmID(permarena, - &epki->algorithm, algid); - } - } - if(dest != NULL) - SECITEM_FreeItem(dest, PR_TRUE); - if(algid != NULL) - SECOID_DestroyAlgorithmID(algid, PR_TRUE); - break; + *salt = seckey_create_rc4_salt(); + if (*salt == NULL) { + goto loser; } - /* let success fall through */ + param = nsspkcs5_NewParam(algorithm,*salt,1); + if (param == NULL) { + goto loser; + } + + dest = nsspkcs5_CipherData(param, pwitem, der_item, PR_TRUE, NULL); + if (dest == NULL) { + goto loser; + } + + rv = SECITEM_CopyItem(permarena, &epki->encryptedData, dest); + if (rv != SECSuccess) { + goto loser; + } + + algid = nsspkcs5_CreateAlgorithmID(permarena, algorithm, param); + if (algid == NULL) { + rv = SECFailure; + goto loser; + } + + rv = SECOID_CopyAlgorithmID(permarena, &epki->algorithm, algid); + SECOID_DestroyAlgorithmID(algid, PR_TRUE); + loser: + if(dest != NULL) + SECITEM_FreeItem(dest, PR_TRUE); + + if(param != NULL) + nsspkcs5_DestroyPBEParameter(param); + + /* let success fall through */ if(rv == SECFailure) { PORT_FreeArena(permarena, PR_TRUE); - epki = NULL; + epki = NULL; + if(*salt != NULL) + SECITEM_FreeItem(*salt, PR_TRUE); } if(temparena != NULL) PORT_FreeArena(temparena, PR_TRUE); - - if(salt != NULL) - SECITEM_FreeItem(salt, PR_TRUE); return epki; } -SECStatus +static SECStatus seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, NSSLOWKEYPrivateKey *pk, char *nickname, PRBool update, SECOidTag algorithm) @@ -1365,29 +1277,15 @@ seckey_put_private_key(NSSLOWKEYDBHandle *keydb, DBT *index, SECItem *pwitem, /* TNH - for RC4, the salt should be created here */ - epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm); + epki = seckey_encrypt_private_key(pk, pwitem, keydb, algorithm, &salt); if(epki == NULL) goto loser; temparena = epki->arena; - /* extract salt for db key */ - switch(algorithm) + if(salt != NULL) { - case SEC_OID_RC4: - rv = SECITEM_CopyItem(permarena, &(dbkey->salt), - &(epki->algorithm.parameters)); - epki->algorithm.parameters.len = 0; - epki->algorithm.parameters.data = NULL; - break; - default: - /* TNH - this should not be necessary */ - salt = SEC_PKCS5GetSalt(&epki->algorithm); - if(salt != NULL) - { - rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt); - SECITEM_ZfreeItem(salt, PR_TRUE); - } - break; + rv = SECITEM_CopyItem(permarena, &(dbkey->salt), salt); + SECITEM_ZfreeItem(salt, PR_TRUE); } dummy = SEC_ASN1EncodeItem(permarena, &(dbkey->derPK), epki, @@ -1417,11 +1315,10 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - NSSLOWKEYGetPasswordKey f, void *arg, + SECItem *pwitem, SECOidTag algorithm) { DBT namekey; - SECItem *pwitem = NULL; SECStatus rv; if (handle == NULL) { @@ -1433,11 +1330,6 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, namekey.data = pubKeyData->data; namekey.size = pubKeyData->len; - pwitem = (*f )(arg, handle); - if ( pwitem == NULL ) { - return(SECFailure); - } - /* encrypt the private key */ rv = seckey_put_private_key(handle, &namekey, pwitem, privkey, nickname, PR_FALSE, algorithm); @@ -1456,6 +1348,7 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, SECOidTag algorithm; PLArenaPool *temparena = NULL, *permarena = NULL; SECItem *salt = NULL, *dest = NULL, *key = NULL; + NSSPKCS5PBEParameter *param; if((epki == NULL) || (pwitem == NULL)) goto loser; @@ -1488,8 +1381,7 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, key = seckey_create_rc4_key(pwitem, salt); if(key != NULL) { - dest = seckey_rc4_cipher(key, &epki->encryptedData, - PR_FALSE); + dest = seckey_rc4_decode(key, &epki->encryptedData); } } if(salt != NULL) @@ -1501,8 +1393,13 @@ seckey_decrypt_private_key(NSSLOWKEYEncryptedPrivateKeyInfo *epki, /* we depend on the fact that if this key was encoded with * DES, that the pw was also encoded with DES, so we don't have * to do the update here, the password code will handle it. */ - dest = SEC_PKCS5CipherData(&epki->algorithm, pwitem, - &epki->encryptedData, PR_FALSE, NULL); + param = nsspkcs5_AlgidToParam(&epki->algorithm); + if (param == NULL) { + break; + } + dest = nsspkcs5_CipherData(param, pwitem, &epki->encryptedData, + PR_FALSE, NULL); + nsspkcs5_DestroyPBEParameter(param); break; } @@ -1675,11 +1572,10 @@ nsslowkey_DecryptKey(DBT *key, SECItem *pwitem, */ NSSLOWKEYPrivateKey * nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, - NSSLOWKEYGetPasswordKey f, void *arg) + SECItem *pwitem) { DBT namekey; NSSLOWKEYPrivateKey *pk = NULL; - SECItem *pwitem = NULL; if (handle == NULL) { PORT_SetError(SEC_ERROR_BAD_DATABASE); @@ -1690,11 +1586,6 @@ nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, namekey.data = modulus->data; namekey.size = modulus->len; - pwitem = (*f )(arg, handle); - if ( pwitem == NULL ) { - return(NULL); - } - pk = seckey_get_private_key(handle, &namekey, NULL, pwitem); SECITEM_ZfreeItem(pwitem, PR_TRUE); @@ -1753,7 +1644,7 @@ nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, SECItem *pwitem, SECOidTag algorithm) { DBT checkkey; - SECAlgorithmID *algid = NULL; + NSSPKCS5PBEParameter *param = NULL; SECStatus rv = SECFailure; NSSLOWKEYDBKey *dbkey = NULL; PLArenaPool *arena; @@ -1788,24 +1679,13 @@ nsslowkey_SetKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, goto loser; } - switch(algorithm) - { - case SEC_OID_RC4: - key = seckey_create_rc4_key(pwitem, salt); - if(key != NULL) - { - dest = seckey_rc4_cipher(key, &test_key, PR_TRUE); - SECITEM_FreeItem(key, PR_TRUE); - } - break; - default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, salt, 1); - if(algid != NULL) - dest = SEC_PKCS5CipherData(algid, pwitem, &test_key, - PR_TRUE, NULL); - break; + param = nsspkcs5_NewParam(algorithm, salt, 1); + if (param != NULL) { + rv = SECFailure; + goto loser; } + dest = nsspkcs5_CipherData(param, pwitem, &test_key, PR_TRUE, NULL); if(dest != NULL) { rv = SECITEM_CopyItem(arena, &dbkey->salt, salt); @@ -1836,6 +1716,10 @@ loser: if ( salt != NULL ) { SECITEM_ZfreeItem(salt, PR_TRUE); } + + if (param != NULL) { + nsspkcs5_DestroyPBEParameter(param); + } return(rv); } @@ -1954,7 +1838,7 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) { DBT checkkey; DBT checkdata; - SECAlgorithmID *algid = NULL; + NSSPKCS5PBEParameter *param = NULL; SECStatus rv = SECFailure; NSSLOWKEYDBKey *dbkey = NULL; SECItem *key = NULL; @@ -2017,14 +1901,13 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) case SEC_OID_RC4: key = seckey_create_rc4_key(pwitem, &dbkey->salt); if(key != NULL) { - dest = seckey_rc4_cipher(key, &encstring, PR_FALSE); + dest = seckey_rc4_decode(key, &encstring); SECITEM_FreeItem(key, PR_TRUE); } break; default: - algid = SEC_PKCS5CreateAlgorithmID(algorithm, - &dbkey->salt, 1); - if(algid != NULL) { + param = nsspkcs5_NewParam(algorithm, &dbkey->salt, 1); + if (param != NULL) { /* Decrypt - this function implements a workaround for * a previous coding error. It will decrypt values using * DES rather than 3DES, if the initial try at 3DES @@ -2032,9 +1915,9 @@ nsslowkey_CheckKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem) * set to TRUE. This indication is used later to force * an update of the database to "real" 3DES encryption. */ - dest = SEC_PKCS5CipherData(algid, pwitem, + dest = nsspkcs5_CipherData(param, pwitem, &encstring, PR_FALSE, &update); - SECOID_DestroyAlgorithmID(algid, PR_TRUE); + nsspkcs5_DestroyPBEParameter(param); } break; } @@ -2141,7 +2024,6 @@ ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, newkey.size = privkey->u.dh.publicValue.len; break; default: - /* XXX We don't do Fortezza. */ return SECFailure; } @@ -2177,9 +2059,8 @@ loser: * in place in the original */ SECStatus -nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, - SECItem *oldpwitem, SECItem *newpwitem, - SECOidTag new_algorithm) +nsslowkey_ChangeKeyDBPassword(NSSLOWKEYDBHandle *handle, + SECItem *oldpwitem, SECItem *newpwitem) { SECStatus rv; @@ -2194,7 +2075,8 @@ nsslowkey_ChangeKeyDBPasswordAlg(NSSLOWKEYDBHandle *handle, return(SECFailure); /* return rv? */ } - rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, new_algorithm); + rv = ChangeKeyDBPasswordAlg(handle, oldpwitem, newpwitem, + nsslowkey_GetDefaultKeyDBAlg()); loser: return(rv); @@ -2203,7 +2085,7 @@ loser: /* * Second pass of updating the key db. This time we have a password. */ -SECStatus +static SECStatus nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle, SECItem *pwitem) { SECStatus rv; @@ -2217,7 +2099,7 @@ nsslowkey_UpdateKeyDBPass2(NSSLOWKEYDBHandle *handle, SECItem *pwitem) /* * currently updates key database from v2 to v3 */ -SECStatus +static SECStatus nsslowkey_UpdateKeyDBPass1(NSSLOWKEYDBHandle *handle) { SECStatus rv; @@ -2473,12 +2355,3 @@ done: return (errors == 0 ? SECSuccess : SECFailure); } - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -*/ -SEC_ASN1_CHOOSER_IMPLEMENT(nsslowkey_PrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(nsslowkey_PointerToPrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(nsslowkey_EncryptedPrivateKeyInfoTemplate) -SEC_ASN1_CHOOSER_IMPLEMENT(nsslowkey_PointerToEncryptedPrivateKeyInfoTemplate) - diff --git a/security/nss/lib/softoken/lowcert.c b/security/nss/lib/softoken/lowcert.c index 774f1d996..c376f9643 100644 --- a/security/nss/lib/softoken/lowcert.c +++ b/security/nss/lib/softoken/lowcert.c @@ -45,6 +45,7 @@ #include "lowkeyi.h" #include "pcert.h" #include "secasn1.h" +#include "secoid.h" /* should have been in a 'util' header */ extern const SEC_ASN1Template CERT_ValidityTemplate[]; @@ -313,7 +314,7 @@ nsslowcert_DecodeDERCertificate(SECItem *derSignedCert, PRBool copyDER, rv = SEC_ASN1DecodeItem(arena, cert, nsslowcert_SignedCertificateTemplate, &cert->derCert); - /* cert->subjectKeyID; /* x509v3 subject key identifier */ + /* cert->subjectKeyID; x509v3 subject key identifier */ cert->dbEntry = NULL; cert ->trust = NULL; diff --git a/security/nss/lib/softoken/lowkeyi.h b/security/nss/lib/softoken/lowkeyi.h index b84c0729a..9227e250b 100644 --- a/security/nss/lib/softoken/lowkeyi.h +++ b/security/nss/lib/softoken/lowkeyi.h @@ -118,17 +118,12 @@ extern SECStatus nsslowkey_StoreKeyByPublicKey(NSSLOWKEYDBHandle *handle, NSSLOWKEYPrivateKey *pk, SECItem *pubKeyData, char *nickname, - NSSLOWKEYGetPasswordKey f, - void *arg); + SECItem *arg); /* does the key for this cert exist in the database filed by modulus */ extern SECStatus nsslowkey_KeyForCertExists(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert); -NSSLOWKEYPrivateKey * -nsslowkey_FindKeyByCert(NSSLOWKEYDBHandle *handle, NSSLOWCERTCertificate *cert, - NSSLOWKEYGetPasswordKey f, void *arg); - extern SECStatus nsslowkey_HasKeyDBPassword(NSSLOWKEYDBHandle *handle); extern SECStatus nsslowkey_SetKeyDBPassword(NSSLOWKEYDBHandle *handle, SECItem *pwitem); @@ -226,7 +221,7 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, NSSLOWKEYPrivateKey *privkey, SECItem *pubKeyData, char *nickname, - NSSLOWKEYGetPasswordKey f, void *arg, + SECItem *arg, SECOidTag algorithm); /* Find key by modulus. This function is the inverse of store key @@ -237,7 +232,7 @@ nsslowkey_StoreKeyByPublicKeyAlg(NSSLOWKEYDBHandle *handle, */ extern NSSLOWKEYPrivateKey * nsslowkey_FindKeyByPublicKey(NSSLOWKEYDBHandle *handle, SECItem *modulus, - NSSLOWKEYGetPasswordKey f, void *arg); + SECItem *arg); /* Make a copy of a low private key in it's own arena. * a return of NULL indicates an error. diff --git a/security/nss/lib/softoken/lowkeyti.h b/security/nss/lib/softoken/lowkeyti.h index 248940a62..b8941bb0d 100644 --- a/security/nss/lib/softoken/lowkeyti.h +++ b/security/nss/lib/softoken/lowkeyti.h @@ -64,9 +64,6 @@ typedef struct NSSLOWKEYDBHandleStr NSSLOWKEYDBHandle; /* ** Typedef for callback to get a password "key". */ -typedef SECItem * (* NSSLOWKEYGetPasswordKey)(void *arg, - NSSLOWKEYDBHandle *handle); - extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[]; extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[]; extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[]; @@ -76,20 +73,7 @@ extern const SEC_ASN1Template nsslowkey_DHPrivateKeyExportTemplate[]; extern const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[]; extern const SEC_ASN1Template nsslowkey_EncryptedPrivateKeyInfoTemplate[]; -extern const SEC_ASN1Template nsslowkey_AttributeTemplate[]; - -/* These functions simply return the address of the above-declared templates. -** This is necessary for Windows DLLs. Sigh. -extern SEC_ASN1TemplateChooser NSS_Get_nsslowkey_EncryptedPrivateKeyInfoTemplate; */ -/* -** Attributes -*/ -struct NSSLOWKEYAttributeStr { - SECItem attrType; - SECItem **attrValue; -}; -typedef struct NSSLOWKEYAttributeStr NSSLOWKEYAttribute; /* ** A PKCS#8 private key info object @@ -99,10 +83,9 @@ struct NSSLOWKEYPrivateKeyInfoStr { SECItem version; SECAlgorithmID algorithm; SECItem privateKey; - NSSLOWKEYAttribute **attributes; }; typedef struct NSSLOWKEYPrivateKeyInfoStr NSSLOWKEYPrivateKeyInfo; -#define NSS_LOW_KEY_INFO_VERSION 0 /* what we *create* */ +#define NSSLOWKEY_PRIVATE_KEY_INFO_VERSION 0 /* what we *create* */ /* ** A PKCS#8 private key info object diff --git a/security/nss/lib/softoken/manifest.mn b/security/nss/lib/softoken/manifest.mn index f385f88a9..065a1ccc3 100644 --- a/security/nss/lib/softoken/manifest.mn +++ b/security/nss/lib/softoken/manifest.mn @@ -36,8 +36,9 @@ MODULE = security REQUIRES = dbm -LIBRARY_NAME = softoken +LIBRARY_NAME = softokn LIBRARY_VERSION = 3 +MAPFILE = $(OBJDIR)/softokn.def EXPORTS = \ @@ -45,6 +46,7 @@ EXPORTS = \ pkcs11f.h \ pkcs11p.h \ pkcs11t.h \ + pkcs11n.h \ pkcs11u.h \ secpkcs5.h \ $(NULL) @@ -73,5 +75,3 @@ CSRCS = \ secpkcs5.c \ pcertdb.c \ $(NULL) - - diff --git a/security/nss/lib/softoken/pcert.h b/security/nss/lib/softoken/pcert.h index 3d92c88d8..9795899b4 100644 --- a/security/nss/lib/softoken/pcert.h +++ b/security/nss/lib/softoken/pcert.h @@ -288,6 +288,14 @@ typedef union { #define CERTDB_TRUSTED_CLIENT_CA (1<<7) /* trusted for issuing client certs */ #define CERTDB_INVISIBLE_CA (1<<8) /* don't show in UI */ #define CERTDB_GOVT_APPROVED_CA (1<<9) /* can do strong crypto in export ver */ +#define CERTDB_NOT_TRUSTED (1<<10) /* explicitly don't trust this cert */ +#define CERTDB_TRUSTED_UNKNOWN (1<<11) /* accept trust from another source */ + +/* bits not affected by the CKO_NETSCAPE_TRUST object */ +#define CERTDB_PRESERVE_TRUST_BITS (CERTDB_USER | CERTDB_VALID_PEER | \ + CERTDB_NS_TRUSTED_CA | CERTDB_VALID_CA | CERTDB_INVISIBLE_CA | \ + CERTDB_GOVT_APPROVED_CA) + SEC_BEGIN_PROTOS @@ -328,73 +336,19 @@ nsslowcert_TraversePermCerts(NSSLOWCERTCertDBHandle *handle, PermCertCallback certfunc, void *udata ); -SECStatus -SEC_AddTempNickname(NSSLOWCERTCertDBHandle *handle, char *nickname, SECItem *certKey); - -SECStatus -SEC_DeleteTempNickname(NSSLOWCERTCertDBHandle *handle, char *nickname); - -PRBool -SEC_CertNicknameConflict(char *nickname, SECItem *derSubject, - NSSLOWCERTCertDBHandle *handle); - PRBool -SEC_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle); - -SECStatus -SEC_GetCrlTimes(NSSLOWCERTCrl *dates, PRTime *notBefore, PRTime *notAfter); - -SECCertTimeValidity -SEC_CheckCrlTimes(NSSLOWCERTCrl *crl, PRTime t); - -PRBool -SEC_CrlIsNewer(NSSLOWCERTCrl *inNew, NSSLOWCERTCrl *old); - -NSSLOWCERTSignedCrl * -SEC_AddPermCrlToTemp(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry); - -SECStatus -SEC_DeleteTempCrl(NSSLOWCERTSignedCrl *crl); - -NSSLOWCERTSignedCrl * -SEC_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, int type); +nsslowcert_CertDBKeyConflict(SECItem *derCert, NSSLOWCERTCertDBHandle *handle); -NSSLOWCERTSignedCrl * -SEC_FindCrlByName(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, int type); +SECItem * +nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, + char **urlp, PRBool isKRL); -NSSLOWCERTSignedCrl * -SEC_FindCrlByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, int type); - -SECStatus -SEC_DestroyCrl(NSSLOWCERTSignedCrl *crl); - -NSSLOWCERTSignedCrl * -SEC_NewCrl(NSSLOWCERTCertDBHandle *handle, char *url, SECItem *derCrl, int type); - -NSSLOWCERTSignedCrl * -cert_DBInsertCRL - (NSSLOWCERTCertDBHandle *handle, char *url, - NSSLOWCERTSignedCrl *newCrl, SECItem *derCrl, int type); - -#ifdef ntodef SECStatus -SEC_CheckKRL(NSSLOWCERTCertDBHandle *handle,NSSLOWKEYPublicKey *key, - NSSLOWCERTCertificate *rootCert, int64 t, void *wincx); - +nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle,SECItem *derName, + PRBool isKRL); SECStatus -SEC_CheckCRL(NSSLOWCERTCertDBHandle *handle,NSSLOWCERTCertificate *cert, - NSSLOWCERTCertificate *caCert, int64 t, void *wincx); - -SECStatus -SEC_DeletePermCRL(NSSLOWCERTSignedCrl *crl); - - -SECStatus -SEC_LookupCrls(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTCrlHeadNode **nodes, int type); - -SECStatus -SEC_CrlReplaceUrl(NSSLOWCERTSignedCrl *crl,char *url); -#endif +nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl , + SECItem *derKey, char *url, PRBool isKRL); NSSLOWCERTCertDBHandle *nsslowcert_GetDefaultCertDB(); NSSLOWKEYPublicKey *nsslowcert_ExtractPublicKey(NSSLOWCERTCertificate *); @@ -414,7 +368,7 @@ void nsslowcert_DestroyCertificate(NSSLOWCERTCertificate *cert); * traversal. */ NSSLOWCERTCertificate * -nsslowcert_FindCertByKeyNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *certKey); +nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey); /* ** Generate a certificate key from the issuer and serialnumber, then look it @@ -444,21 +398,10 @@ char *nsslowcert_FixupEmailAddr(char *emailAddr); */ extern NSSLOWCERTCertificate * nsslowcert_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname); -/* -** Decode a DER encoded CRL/KRL into an NSSLOWCERTSignedCrl structure -** "derSignedCrl" is the DER encoded signed crl/krl. -** "type" is this a CRL or KRL. -*/ -#define SEC_CRL_TYPE 1 -#define SEC_KRL_TYPE 0 - -extern NSSLOWCERTSignedCrl * -nsslowcert_DecodeDERCrl (PRArenaPool *arena, SECItem *derSignedCrl,int type); SECStatus nsslowcert_KeyFromDERCert(PRArenaPool *arena, SECItem *derCert, SECItem *key); - SEC_END_PROTOS #endif /* _PCERTDB_H_ */ diff --git a/security/nss/lib/softoken/pcertdb.c b/security/nss/lib/softoken/pcertdb.c index 9ea42dd87..545963f95 100644 --- a/security/nss/lib/softoken/pcertdb.c +++ b/security/nss/lib/softoken/pcertdb.c @@ -1078,11 +1078,12 @@ loser: static SECStatus -WriteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry ) +WriteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry, + SECItem *crlKey ) { SECItem dbkey; PRArenaPool *tmparena = NULL; - SECItem tmpitem,encodedEntry; + SECItem encodedEntry; SECStatus rv; tmparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); @@ -1090,18 +1091,12 @@ WriteDBCrlEntry(NSSLOWCERTCertDBHandle *handle, certDBEntryRevocation *entry ) goto loser; } - /* get the database key and format it */ - rv = nsslowcert_KeyFromDERCrl(tmparena, &entry->derCrl, &tmpitem); - if ( rv == SECFailure ) { - goto loser; - } - rv = EncodeDBCrlEntry(entry, tmparena, &encodedEntry); if ( rv == SECFailure ) { goto loser; } - rv = EncodeDBGenericKey(&tmpitem, tmparena, &dbkey, entry->common.type); + rv = EncodeDBGenericKey(crlKey, tmparena, &dbkey, entry->common.type); if ( rv == SECFailure ) { goto loser; } @@ -2769,7 +2764,7 @@ AddPermSubjectNode(certDBEntrySubject *entry, NSSLOWCERTCertificate *cert, } for ( i = 0; i < ncerts; i++ ) { - cmpcert = nsslowcert_FindCertByKeyNoLocking(cert->dbhandle, + cmpcert = nsslowcert_FindCertByKey(cert->dbhandle, &entry->certKeys[i]); PORT_Assert(cmpcert); if ( nsslowcert_IsNewer(cert, cmpcert) ) { @@ -2846,7 +2841,7 @@ nsslowcert_TraversePermCertsForSubject(NSSLOWCERTCertDBHandle *handle, } for( i = 0; i < entry->ncerts; i++ ) { - cert = nsslowcert_FindCertByKeyNoLocking(handle, &entry->certKeys[i]); + cert = nsslowcert_FindCertByKey(handle, &entry->certKeys[i]); rv = (* cb)(cert, cbarg); nsslowcert_DestroyCertificate(cert); if ( rv == SECFailure ) { @@ -4215,7 +4210,7 @@ loser: * Lookup a certificate in the databases without locking */ NSSLOWCERTCertificate * -nsslowcert_FindCertByKeyNoLocking(NSSLOWCERTCertDBHandle *handle, SECItem *certKey) +nsslowcert_FindCertByKey(NSSLOWCERTCertDBHandle *handle, SECItem *certKey) { return(FindCertByKey(handle, certKey, PR_FALSE)); } @@ -4245,7 +4240,7 @@ nsslowcert_FindCertByIssuerAndSN(NSSLOWCERTCertDBHandle *handle, NSSLOWCERTIssue PORT_Memcpy( &certKey.data[issuerAndSN->serialNumber.len], issuerAndSN->derIssuer.data, issuerAndSN->derIssuer.len); - cert = nsslowcert_FindCertByKeyNoLocking(handle, &certKey); + cert = nsslowcert_FindCertByKey(handle, &certKey); PORT_Free(certKey.data); @@ -4276,7 +4271,7 @@ nsslowcert_FindCertByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCert) } /* find the certificate */ - cert = nsslowcert_FindCertByKeyNoLocking(handle, &certKey); + cert = nsslowcert_FindCertByKey(handle, &certKey); loser: PORT_FreeArena(arena, PR_FALSE); @@ -4345,24 +4340,24 @@ nsslowcert_DestroyCertificateNoLocking(NSSLOWCERTCertificate *cert) return; } -#ifdef notdef /* * Lookup a CRL in the databases. We mirror the same fast caching data base * caching stuff used by certificates....? */ -NSSLOWCERTSignedCrl * -SEC_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, int type) +SECItem * +nsslowcert_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, + char **url, PRBool isKRL) { DBT tmpdata; int ret; SECItem keyitem; DBT key; SECStatus rv; - NSSLOWCERTSignedCrl *crl = NULL; + SECItem *crl = NULL; PRArenaPool *arena = NULL; certDBEntryRevocation *entry; - certDBEntryType crlType = (type == SEC_CRL_TYPE) ? - certDBEntryTypeRevocation : certDBEntryTypeKeyRevocation; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if ( arena == NULL ) { @@ -4376,199 +4371,90 @@ SEC_FindCrlByKey(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, int type) key.data = keyitem.data; key.size = keyitem.len; - - /* lookup in the temporary database */ - ret = certdb_Get( handle->tempCertDB, &key, &tmpdata, 0 ); - /* error accessing the database */ - if ( ret < 0 ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); + /* find in perm database */ + entry = ReadDBCrlEntry(handle, crlKey, crlType); + + if ( entry == NULL ) { goto loser; } - if ( ret == 0 ) { /* found in temp database */ - if ( tmpdata.size != sizeof(NSSLOWCERTSignedCrl *) ) { - PORT_SetError(SEC_ERROR_BAD_DATABASE); - goto loser; - } - - PORT_Memcpy(&crl, tmpdata.data, tmpdata.size); - crl->referenceCount++; - } else { /* not found in temporary database */ - - /* find in perm database */ - entry = ReadDBCrlEntry(handle, crlKey, crlType); - - if ( entry == NULL ) { - goto loser; - } + if (entry->url) { + *url = PORT_Strdup(entry->url); } + crl = SECITEM_DupItem(&entry->derCrl); + loser: if ( arena ) { PORT_FreeArena(arena, PR_FALSE); } - - return(crl); -} - - -NSSLOWCERTSignedCrl * -SEC_FindCrlByName(NSSLOWCERTCertDBHandle *handle, SECItem *crlKey, int type) -{ - return SEC_FindCrlByKey(handle,crlKey,type); -} - -NSSLOWCERTSignedCrl * -SEC_FindCrlByDERCert(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, int type) -{ - PRArenaPool *arena; - SECItem crlKey; - SECStatus rv; - NSSLOWCERTSignedCrl *crl = NULL; - - /* create a scratch arena */ - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( arena == NULL ) { - return(NULL); - } - - /* extract the database key from the cert */ - rv = nsslowcert_KeyFromDERCrl(arena, derCrl, &crlKey); - if ( rv != SECSuccess ) { - goto loser; + if (entry) { + DestroyDBEntry((certDBEntry *)entry); } - - /* find the crl */ - crl = SEC_FindCrlByKey(handle, &crlKey, type); -loser: - PORT_FreeArena(arena, PR_FALSE); return(crl); } - -SECStatus -SEC_DestroyCrl(NSSLOWCERTSignedCrl *crl) -{ - if (crl) { - if (crl->referenceCount-- <= 1) { - if (!crl->keep) { - if (crl->dbEntry) { - DestroyDBEntry((certDBEntry *)crl->dbEntry); - } - PORT_FreeArena(crl->arena, PR_FALSE); - } - } - } - return SECSuccess; -} - -NSSLOWCERTSignedCrl * -cert_DBInsertCRL (NSSLOWCERTCertDBHandle *handle, char *url, - NSSLOWCERTSignedCrl *newCrl, SECItem *derCrl, int type) -{ - NSSLOWCERTSignedCrl *oldCrl = NULL, *crl = NULL; - certDBEntryRevocation *entry = NULL; - PRArenaPool *arena = NULL; - SECCertTimeValidity validity; - certDBEntryType crlType = (type == SEC_CRL_TYPE) ? - certDBEntryTypeRevocation : certDBEntryTypeKeyRevocation; - SECStatus rv; - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) goto done; - - oldCrl = SEC_FindCrlByKey(handle, derName, type); - - /* if there is an old crl, make sure the one we are installing - * is newer. If not, exit out, otherwise delete the old crl. - */ - if (oldCrl != NULL) { - if (!SEC_CrlIsNewer(derNewCRL,oldEntry->crl)) { - - if (type == SEC_CRL_TYPE) { - PORT_SetError(SEC_ERROR_OLD_CRL); - } else { - PORT_SetError(SEC_ERROR_OLD_KRL); - } - - goto done; - } - - if ((SECITEM_CompareItem(derName,derOldName) != SECEqual) && - (type == SEC_KRL_TYPE) ) { - - PORT_SetError(SEC_ERROR_CKL_CONFLICT); - goto done; - } - - /* if we have a url in the database, use that one */ - if (oldEntry->url) { - int nnlen = PORT_Strlen(oldCrl->url) + 1; - url = (char *)PORT_ArenaAlloc(arena, nnlen); - if ( url != NULL ) { - PORT_Memcpy(url, oldCrl->url, nnlen); - } - } - - - /* really destroy this crl */ - /* first drum it out of the permanment Data base */ - SEC_DeletePermCRL(oldCrl); - - } - - /* Write the new entry into the data base */ - entry = NewDBCrlEntry(derCrl, url, crlType, 0); - if (entry == NULL) goto done; - - rv = WriteDBCrlEntry(handle, entry); - if (rv != SECSuccess) goto done; - -done: - if (entry) DestroyDBEntry((certDBEntry *)entry); - if (arena) PORT_FreeArena(arena, PR_FALSE); - if (oldCrl) /* SEC_DestroyCrl(oldCrl); */ - - return crl; -} - /* * replace the existing URL in the data base with a new one */ SECStatus -NSSLOWCERT_CrlReplaceUrl(NSSLOWCERTDBHandle *handle, SECItem *derCrl,char *url, - int type) +nsslowcert_AddCrl(NSSLOWCERTCertDBHandle *handle, SECItem *derCrl, + SECItem *crlKey, char *url, PRBool isKRL) { SECStatus rv = SECFailure; certDBEntryRevocation *entry = NULL; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; int nnlen=0; - SEC_DeletePermCRL(crl); + DeleteDBCrlEntry(handle, crlKey, crlType); /* Write the new entry into the data base */ - entry = NewDBCrlEntry(derCrl, url, type, 0); + entry = NewDBCrlEntry(derCrl, url, crlType, 0); if (entry == NULL) goto done; - rv = WriteDBCrlEntry(handle, entry); + rv = WriteDBCrlEntry(handle, entry, crlKey); if (rv != SECSuccess) goto done; done: + if (entry) { + DestroyDBEntry((certDBEntry *)entry); + } return rv; } SECStatus -NSSLOWCERT_DeletePermCRL(NSSLOWCERTDBHandle *handle,SECItem *derName,int type) +nsslowcert_DeletePermCRL(NSSLOWCERTCertDBHandle *handle, SECItem *derName, + PRBool isKRL) { SECStatus rv; + certDBEntryType crlType = isKRL ? certDBEntryTypeKeyRevocation + : certDBEntryTypeRevocation; - rv = DeleteDBCrlEntry(handle, derName, type); + rv = DeleteDBCrlEntry(handle, derName, crlType); if (rv != SECSuccess) goto done; done: return rv; } + +PRBool +nsslowcert_hasTrust(NSSLOWCERTCertificate *cert) +{ + NSSLOWCERTCertTrust *trust; + + if (cert->trust == NULL) { + return PR_FALSE; + } + trust = cert->trust; + return !((trust->sslFlags & CERTDB_TRUSTED_UNKNOWN) && + (trust->emailFlags & CERTDB_TRUSTED_UNKNOWN) && + (trust->objectSigningFlags & CERTDB_TRUSTED_UNKNOWN)); +} + +#ifdef notdef /* * find a cert by email address * diff --git a/security/nss/lib/softoken/pcertt.h b/security/nss/lib/softoken/pcertt.h index f5afb22eb..69cc361ce 100644 --- a/security/nss/lib/softoken/pcertt.h +++ b/security/nss/lib/softoken/pcertt.h @@ -41,7 +41,7 @@ #include "prclist.h" #include "pkcs11t.h" #include "seccomon.h" -#include "secmodt.h" +/*#include "secmodt.h" */ #include "secoidt.h" #include "plarena.h" #include "prcvar.h" @@ -115,21 +115,6 @@ struct NSSLOWCERTCertTrustStr { }; /* - * defined the types of trust that exist - */ -typedef enum { - trustSSL = 0, - trustEmail = 1, - trustObjectSigning = 2, - trustTypeNone = 3 -} SECTrustType; - -#define SEC_GET_TRUST_FLAGS(trust,type) \ - (((type)==trustSSL)?((trust)->sslFlags): \ - (((type)==trustEmail)?((trust)->emailFlags): \ - (((type)==trustObjectSigning)?((trust)->objectSigningFlags):0))) - -/* ** An X.509 certificate object (the unsigned form) */ struct NSSLOWCERTCertificateStr { diff --git a/security/nss/lib/softoken/pk11pars.h b/security/nss/lib/softoken/pk11pars.h index 683e4f02d..9e273f104 100644 --- a/security/nss/lib/softoken/pk11pars.h +++ b/security/nss/lib/softoken/pk11pars.h @@ -46,7 +46,7 @@ #include "seccomon.h" #include "prprf.h" #include "secmodt.h" -#include "secmodti.h" +#include "pk11init.h" #define PK11_ARG_LIBRARY_PARAMETER "library=" #define PK11_ARG_NAME_PARAMETER "name=" diff --git a/security/nss/lib/softoken/pkcs11.c b/security/nss/lib/softoken/pkcs11.c index 9d1b217a9..4105b552f 100644 --- a/security/nss/lib/softoken/pkcs11.c +++ b/security/nss/lib/softoken/pkcs11.c @@ -103,7 +103,7 @@ static int minimumPinLen = 0; /* build the crypto module table */ -static CK_FUNCTION_LIST pk11_funcList = { +static const CK_FUNCTION_LIST pk11_funcList = { { 1, 10 }, #undef CK_PKCS11_FUNCTION_INFO @@ -123,7 +123,7 @@ static CK_FUNCTION_LIST pk11_funcList = { /* List of DES Weak Keys */ typedef unsigned char desKey[8]; -static desKey pk11_desWeakTable[] = { +static const desKey pk11_desWeakTable[] = { #ifdef noParity /* weak */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, @@ -177,12 +177,12 @@ static desKey pk11_desWeakTable[] = { }; -static int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/ +static const int pk11_desWeakTableSize = sizeof(pk11_desWeakTable)/ sizeof(pk11_desWeakTable[0]); /* DES KEY Parity conversion table. Takes each byte/2 as an index, returns * that byte with the proper parity bit set */ -static unsigned char parityTable[256] = { +static const unsigned char parityTable[256] = { /* Even...0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e */ /* E */ 0x01,0x02,0x04,0x07,0x08,0x0b,0x0d,0x0e, /* Odd....0x10,0x12,0x14,0x16,0x18,0x1a,0x1c,0x1e */ @@ -238,7 +238,9 @@ struct mechanismList { #define CKF_SN_VR_RE CKF_SN_VR | CKF_SN_RE #define CKF_DUZ_IT_ALL CKF_EN_DE_WR_UN | CKF_SN_VR_RE -static struct mechanismList mechanisms[] = { +#define CK_MAX 0xffffffff + +static const struct mechanismList mechanisms[] = { /* * PKCS #11 Mechanism List. @@ -261,16 +263,16 @@ static struct mechanismList mechanisms[] = { */ /* ------------------------- RSA Operations ---------------------------*/ - {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,0xffffffff,CKF_GENERATE_KEY_PAIR},PR_TRUE}, - {CKM_RSA_PKCS, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_PKCS_KEY_PAIR_GEN,{128,CK_MAX,CKF_GENERATE_KEY_PAIR},PR_TRUE}, + {CKM_RSA_PKCS, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, #ifdef PK11_RSA9796_SUPPORTED - {CKM_RSA_9796, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_9796, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, #endif - {CKM_RSA_X_509, {128,0xffffffff, CKF_DUZ_IT_ALL},PR_TRUE}, + {CKM_RSA_X_509, {128,CK_MAX,CKF_DUZ_IT_ALL}, PR_TRUE}, /* -------------- RSA Multipart Signing Operations -------------------- */ - {CKM_MD2_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, - {CKM_MD5_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, - {CKM_SHA1_RSA_PKCS, {128,0xffffffff, CKF_SN_VR}, PR_TRUE}, + {CKM_MD2_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, + {CKM_MD5_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, + {CKM_SHA1_RSA_PKCS, {128,CK_MAX,CKF_SN_VR}, PR_TRUE}, /* ------------------------- DSA Operations --------------------------- */ {CKM_DSA_KEY_PAIR_GEN, {512, 1024, CKF_GENERATE_KEY_PAIR}, PR_TRUE}, {CKM_DSA, {512, 1024, CKF_SN_VR}, PR_TRUE}, @@ -329,7 +331,7 @@ static struct mechanismList mechanisms[] = { {CKM_SHA_1_HMAC_GENERAL, {1, 128, CKF_SN_VR}, PR_FALSE}, {CKM_TLS_PRF_GENERAL, {0, 512, CKF_SN_VR}, PR_FALSE}, /* ------------------------- CAST Operations --------------------------- */ -#ifdef PK11_CAST_SUPPORTED +#ifdef NSS_SOFTOKEN_DOES_CAST /* Cast operations are not supported ( yet? ) */ {CKM_CAST_KEY_GEN, {1, 8, CKF_GENERATE}, PR_FALSE}, {CKM_CAST_ECB, {1, 8, CKF_EN_DE_WR_UN}, PR_FALSE}, @@ -353,13 +355,13 @@ static struct mechanismList mechanisms[] = { #if NSS_SOFTOKEN_DOES_RC5 /* ------------------------- RC5 Operations --------------------------- */ {CKM_RC5_KEY_GEN, {1, 32, CKF_GENERATE}, PR_FALSE}, - {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, + {CKM_RC5_ECB, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, {CKM_RC5_CBC, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, {CKM_RC5_MAC, {1, 32, CKF_SN_VR}, PR_FALSE}, {CKM_RC5_MAC_GENERAL, {1, 32, CKF_SN_VR}, PR_FALSE}, {CKM_RC5_CBC_PAD, {1, 32, CKF_EN_DE_WR_UN}, PR_FALSE}, #endif -#ifdef PK11_IDEA_SUPPORTED +#ifdef NSS_SOFTOKEN_DOES_IDEA /* ------------------------- IDEA Operations -------------------------- */ {CKM_IDEA_KEY_GEN, {16, 16, CKF_GENERATE}, PR_FALSE}, {CKM_IDEA_ECB, {16, 16, CKF_EN_DE_WR_UN}, PR_FALSE}, @@ -393,12 +395,7 @@ static struct mechanismList mechanisms[] = { {CKM_PBE_MD5_DES_CBC, {8, 8, CKF_DERIVE}, PR_TRUE}, /* ------------------ NETSCAPE PBE Key Derivations ------------------- */ {CKM_NETSCAPE_PBE_SHA1_DES_CBC, { 8, 8, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4, {40,40, CKF_GENERATE}, PR_TRUE}, - {CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4, {128,128, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_DES3_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_DES2_EDE_CBC, {24,24, CKF_GENERATE}, PR_TRUE}, {CKM_PBE_SHA1_RC2_40_CBC, {40,40, CKF_GENERATE}, PR_TRUE}, @@ -410,9 +407,6 @@ static struct mechanismList mechanisms[] = { {CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN, {1,32, CKF_GENERATE}, PR_TRUE}, }; static CK_ULONG mechanismCount = sizeof(mechanisms)/sizeof(mechanisms[0]); -/* load up our token database */ -static CK_RV pk11_importKeyDB(PK11Slot *slot); - static char * pk11_setStringName(char *inString, char *buffer, int buffer_length) { @@ -478,17 +472,6 @@ pk11_configure(char *man, char *libdes, char *tokdes, char *ptokdes, * ******************** Password Utilities ******************************* */ -/* Handle to give the password to the database. user arg should be a pointer - * to the slot. */ -static SECItem *pk11_givePass(void *sp,NSSLOWKEYDBHandle *handle) -{ - PK11Slot *slot = (PK11Slot *)sp; - - if (slot->password == NULL) return NULL; - - return SECITEM_DupItem(slot->password); -} - /* * see if the key DB password is enabled */ @@ -560,13 +543,13 @@ pk11_handleDataObject(PK11Session *session,PK11Object *object) static CK_RV pk11_handleCertObject(PK11Session *session,PK11Object *object) { - PK11Attribute *attribute; CK_CERTIFICATE_TYPE type; - SECItem derCert; + PK11Attribute *attribute; char *label; - NSSLOWCERTCertDBHandle *handle; - NSSLOWCERTCertificate *cert; CK_RV crv; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + PORT_Assert(sessObject); /* certificates must have a type */ if ( !pk11_hasAttribute(object,CKA_CERTIFICATE_TYPE) ) { @@ -600,73 +583,286 @@ pk11_handleCertObject(PK11Session *session,PK11Object *object) return CKR_TEMPLATE_INCOMPLETE; } - /* get the nickname */ - label = pk11_getString(object,CKA_LABEL); - object->label = label; - if (label == NULL) { - return CKR_HOST_MEMORY; + /* in PKCS #11, Issuer is a required field */ + if ( !pk11_hasAttribute(object,CKA_ISSUER) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + /* in PKCS #11, Serial is a required field */ + if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) { + return CKR_TEMPLATE_INCOMPLETE; } /* add it to the object */ - object->objectInfo = cert; - object->infoFree = (PK11Free) nsslowcert_DestroyCertificate; + object->objectInfo = NULL; + object->infoFree = (PK11Free) NULL; /* now just verify the required date fields */ crv = pk11_defaultAttribute(object, CKA_ID, NULL, 0); if (crv != CKR_OK) { return crv; } - crv = pk11_defaultAttribute(object,CKA_ISSUER, - pk11_item_expand(&cert->derIssuer)); - if (crv != CKR_OK) { return crv; } - crv = pk11_defaultAttribute(object,CKA_SERIAL_NUMBER, - pk11_item_expand(&cert->serialNumber)); - if (crv != CKR_OK) { return crv; } - if (pk11_isTrue(object,CKA_TOKEN)) { - NSSLOWCERTCertTrust trust = { CERTDB_USER, CERTDB_USER, CERTDB_USER }; PK11Slot *slot = session->slot; - PRBool isUser = PR_FALSE; + SECItem derCert; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertTrust *trust = NULL; + NSSLOWCERTCertTrust userTrust = + { CERTDB_USER, CERTDB_USER, CERTDB_USER }; + SECStatus rv; if (slot->certDB == NULL) { return CKR_TOKEN_WRITE_PROTECTED; } - if (slot->keyDB && - ((nsslowkey_KeyForCertExists(slot->keyDB, cert) == SECSuccess))) { - isUser = PR_TRUE; - } - /* get the der cert */ attribute = pk11_FindAttribute(object,CKA_VALUE); derCert.data = (unsigned char *)attribute->attrib.pValue; derCert.len = attribute->attrib.ulValueLen ; - if (nsslowcert_CertDBKeyConflict(&derCert,slot->certDB)) { - /* cert already exists in the database, update the status of the - * user bits */ - nsslowcert_ChangeCertTrust(cert->dbhandle,cert,&trust); + cert = nsslowcert_DecodeDERCertificate(&derCert,PR_FALSE,label); + if (cert == NULL) { + pk11_FreeAttribute(attribute); + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + if (slot->keyDB && nsslowkey_KeyForCertExists(slot->keyDB,cert)) { + trust = &userTrust; + } + if (!nsslowcert_CertDBKeyConflict(&derCert,slot->certDB)) { + rv = nsslowcert_AddPermCert(cert,label, trust); } else { - SECStatus rv; - cert = nsslowcert_DecodeDERCertificate(&derCert,PR_FALSE,label); - if (cert == NULL) { - pk11_FreeAttribute(attribute); - return CKR_ATTRIBUTE_VALUE_INVALID; - } - rv = nsslowcert_AddPermCert(cert,label,isUser ? &trust : NULL); + rv = trust ? nsslowcert_ChangeCertTrust(slot->certDB,cert,trust) : + SECSuccess; + } + + pk11_FreeAttribute(attribute); + if (rv != SECSuccess) { nsslowcert_DestroyCertificate(cert); - if (rv != SECSuccess) { - pk11_FreeAttribute(attribute); - return CKR_DEVICE_ERROR; + return CKR_DEVICE_ERROR; + } + object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT); + nsslowcert_DestroyCertificate(cert); + } + + return CKR_OK; +} +static unsigned int +pk11_MapTrust(CK_TRUST trust, PRBool clientAuth) +{ + unsigned int trustCA = clientAuth ? CERTDB_TRUSTED_CLIENT_CA : + CERTDB_TRUSTED_CA; + switch (trust) { + case CKT_NETSCAPE_TRUSTED: + return CERTDB_VALID_PEER|CERTDB_TRUSTED; + case CKT_NETSCAPE_TRUSTED_DELEGATOR: + return CERTDB_VALID_CA|trustCA; + case CKT_NETSCAPE_UNTRUSTED: + return CERTDB_NOT_TRUSTED; + case CKT_NETSCAPE_MUST_VERIFY: + return 0; + case CKT_NETSCAPE_VALID: /* implies must verify */ + return CERTDB_VALID_PEER; + case CKT_NETSCAPE_VALID_DELEGATOR: /* implies must verify */ + return CERTDB_VALID_CA; + default: + break; + } + return CERTDB_TRUSTED_UNKNOWN; +} + + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV +pk11_handleTrustObject(PK11Session *session,PK11Object *object) +{ + PK11Attribute *attribute; + CK_CERTIFICATE_TYPE type; + SECItem derCert; + char *label; + NSSLOWCERTCertDBHandle *handle; + NSSLOWCERTCertificate *cert; + NSSLOWCERTIssuerAndSN issuerSN; + CK_RV crv; + + /* 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_ISSUER) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_SERIAL_NUMBER) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_CERT_SHA1_HASH) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + if ( !pk11_hasAttribute(object,CKA_CERT_MD5_HASH) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + PK11Attribute *issuer = NULL; + PK11Attribute *serial = NULL; + NSSLOWCERTCertificate *cert = NULL; + PK11Attribute *trust; + CK_TRUST sslTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST clientTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST emailTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + CK_TRUST signTrust = CKT_NETSCAPE_TRUST_UNKNOWN; + NSSLOWCERTCertTrust dbTrust; + SECStatus rv; + + + if (slot->certDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + issuer = pk11_FindAttribute(object,CKA_ISSUER); + PORT_Assert(issuer); + issuerSN.derIssuer.data = (unsigned char *)issuer->attrib.pValue; + issuerSN.derIssuer.len = issuer->attrib.ulValueLen ; + + serial = pk11_FindAttribute(object,CKA_SERIAL_NUMBER); + PORT_Assert(serial); + issuerSN.serialNumber.data = (unsigned char *)serial->attrib.pValue; + issuerSN.serialNumber.len = serial->attrib.ulValueLen ; + + cert = nsslowcert_FindCertByIssuerAndSN(slot->certDB,&issuerSN); + pk11_FreeAttribute(serial); + pk11_FreeAttribute(issuer); + + if (cert == NULL) { + return CKR_ATTRIBUTE_VALUE_INVALID; + } + + trust = pk11_FindAttribute(object,CKA_TRUST_SERVER_AUTH); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&sslTrust,trust->attrib.pValue, sizeof(sslTrust)); } + pk11_FreeAttribute(trust); + } + trust = pk11_FindAttribute(object,CKA_TRUST_CLIENT_AUTH); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&clientTrust,trust->attrib.pValue, + sizeof(clientTrust)); + } + pk11_FreeAttribute(trust); + } + trust = pk11_FindAttribute(object,CKA_TRUST_EMAIL_PROTECTION); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&emailTrust,trust->attrib.pValue, + sizeof(emailTrust)); + } + pk11_FreeAttribute(trust); + } + trust = pk11_FindAttribute(object,CKA_TRUST_CODE_SIGNING); + if (trust) { + if (trust->attrib.ulValueLen == sizeof(CK_TRUST)) { + PORT_Memcpy(&signTrust,trust->attrib.pValue, + sizeof(signTrust)); + } + pk11_FreeAttribute(trust); + } + + /* preserve certain old fields */ + if (cert->trust) { + dbTrust.sslFlags = + cert->trust->sslFlags & CERTDB_PRESERVE_TRUST_BITS; + dbTrust.emailFlags= + cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS; + dbTrust.objectSigningFlags = + cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS; } - pk11_FreeAttribute(attribute); - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT); - object->inDB = PR_TRUE; + dbTrust.sslFlags = pk11_MapTrust(sslTrust,PR_FALSE); + dbTrust.sslFlags |= pk11_MapTrust(clientTrust,PR_TRUE); + dbTrust.emailFlags = pk11_MapTrust(emailTrust,PR_FALSE); + dbTrust.objectSigningFlags = pk11_MapTrust(signTrust,FALSE); + + rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&dbTrust); + object->handle=pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_TRUST); + nsslowcert_DestroyCertificate(cert); + if (rv != SECSuccess) { + return CKR_DEVICE_ERROR; + } + } + + return CKR_OK; +} + +/* + * check the consistancy and initialize a Trust Object + */ +static CK_RV +pk11_handleCrlObject(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_VALUE) ) { + return CKR_TEMPLATE_INCOMPLETE; + } + + if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; + PRBool isKRL = PR_FALSE; + SECItem derSubj,derCrl; + char *url = NULL; + PK11Attribute *subject,*crl; + 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 */ + crl = pk11_FindAttribute(object,CKA_VALUE); + PORT_Assert(crl); + derCrl.data = (unsigned char *)crl->attrib.pValue; + derCrl.len = crl->attrib.ulValueLen ; - /* label has been adopted by object->label */ - /*PORT_Free(label); */ + + url = pk11_getString(object,CKA_NETSCAPE_URL); + isKRL = pk11_isTrue(object,CKA_NETSCAPE_KRL); + + /* Store CRL by SUBJECT */ + rv = nsslowcert_AddCrl(slot->certDB, &derCrl, &derSubj, url, isKRL); + + if (url) { + PORT_Free(label); + } + pk11_FreeAttribute(crl); + if (rv != SECSuccess) { + pk11_FreeAttribute(subject); + return CKR_DEVICE_ERROR; + } + + object->handle = pk11_mkHandle(slot,&derSubj,PK11_TOKEN_TYPE_CRL); + pk11_FreeAttribute(subject); + } return CKR_OK; } @@ -676,12 +872,16 @@ NSSLOWKEYPublicKey * pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key); * check the consistancy and initialize a Public Key Object */ static CK_RV -pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) +pk11_handlePublicKeyObject(PK11Session *session, PK11Object *object, + CK_KEY_TYPE key_type) { CK_BBOOL cktrue = CK_TRUE; CK_BBOOL encrypt = CK_TRUE; CK_BBOOL recover = CK_TRUE; CK_BBOOL wrap = CK_TRUE; + CK_BBOOL derive = CK_FALSE; + CK_BBOOL verify = CK_TRUE; + CK_ATTRIBUTE_TYPE pubKeyAttr = CKA_VALUE; CK_RV crv; switch (key_type) { @@ -692,6 +892,7 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if ( !pk11_hasAttribute(object, CKA_PUBLIC_EXPONENT)) { return CKR_TEMPLATE_INCOMPLETE; } + pubKeyAttr = CKA_MODULUS; break; case CKK_DSA: if ( !pk11_hasAttribute(object, CKA_SUBPRIME)) { @@ -707,6 +908,10 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if ( !pk11_hasAttribute(object, CKA_VALUE)) { return CKR_TEMPLATE_INCOMPLETE; } + if (key_type == CKK_DH) { + verify = CK_FALSE; + derive = CK_TRUE; + } encrypt = CK_FALSE; recover = CK_FALSE; wrap = CK_FALSE; @@ -720,147 +925,47 @@ pk11_handlePublicKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_ENCRYPT,&encrypt,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; - crv = pk11_defaultAttribute(object,CKA_VERIFY,&cktrue,sizeof(CK_BBOOL)); + crv = pk11_defaultAttribute(object,CKA_VERIFY,&verify,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_VERIFY_RECOVER, &recover,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; crv = pk11_defaultAttribute(object,CKA_WRAP,&wrap,sizeof(CK_BBOOL)); if (crv != CKR_OK) return crv; + crv = pk11_defaultAttribute(object,CKA_DERIVE,&derive,sizeof(CK_BBOOL)); + if (crv != CKR_OK) return crv; object->objectInfo = pk11_GetPubKey(object,key_type); object->infoFree = (PK11Free) nsslowkey_DestroyPublicKey; if (pk11_isTrue(object,CKA_TOKEN)) { - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB); - } - - return CKR_OK; -} -/* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ -static SECItem * -pk11_GetPubItem(NSSLOWKEYPublicKey *pubKey) { - SECItem *pubItem = NULL; - /* get value to compare from the cert's public key */ - switch ( pubKey->keyType ) { - case NSSLOWKEYRSAKey: - pubItem = &pubKey->u.rsa.modulus; - break; - case NSSLOWKEYDSAKey: - pubItem = &pubKey->u.dsa.publicValue; - break; - case NSSLOWKEYDHKey: - pubItem = &pubKey->u.dh.publicValue; - break; - default: - break; - } - return pubItem; -} - -typedef struct { - NSSLOWCERTCertificate *cert; - SECItem *pubKey; -} find_cert_callback_arg; - -static SECStatus -find_cert_by_pub_key(NSSLOWCERTCertificate *cert, SECItem *k, void *arg) -{ - find_cert_callback_arg *cbarg; - NSSLOWKEYPublicKey *pubKey = NULL; - SECItem *pubItem; - - if((cert == NULL) || (arg == NULL)) { - return SECFailure; - } - - /* if this cert doesn't look like a user cert, we aren't interested */ - if (!((cert->trust) && - (( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER )) && - ( cert->nickname != NULL ) ) ) { - goto done; - } - - /* get cert's public key */ - pubKey = nsslowcert_ExtractPublicKey(cert); - if ( pubKey == NULL ) { - goto done; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ - pubItem = pk11_GetPubItem(pubKey); - if (pubItem == NULL) goto done; - - cbarg = (find_cert_callback_arg *)arg; - - if(SECITEM_CompareItem(pubItem, cbarg->pubKey) == SECEqual) { - cbarg->cert = nsslowcert_DupCertificate(cert); - return SECFailure; - } - -done: - if ( pubKey ) { - nsslowkey_DestroyPublicKey(pubKey); - } - - return (SECSuccess); -} - -static PK11Object *pk11_importCertificate(PK11Slot *slot,NSSLOWCERTCertificate *cert, - unsigned char *data, unsigned int size, PRBool needCert); -/* - * find a cert associated with the key and load it. - */ -static SECStatus -reload_existing_certificate(PK11Object *privKeyObject,SECItem *pubKey) -{ - find_cert_callback_arg cbarg; - SECItem nickName; - NSSLOWCERTCertificate *cert = NULL; - CK_RV crv; - SECStatus rv; + PK11Slot *slot = session->slot; + NSSLOWKEYPrivateKey *priv; + SECItem pubKey; - PORT_Assert(privKeyObject->slot->certDB); - if (privKeyObject->slot->certDB == NULL) return SECFailure; - - cbarg.pubKey = pubKey; - cbarg.cert = NULL; - nsslowcert_TraversePermCerts(privKeyObject->slot->certDB, - find_cert_by_pub_key, (void *)&cbarg); - if (cbarg.cert != NULL) { - NSSLOWCERTCertificate *cert = NULL; - cert = cbarg.cert; + crv = pk11_Attribute2SecItem(NULL,&pubKey,object,pubKeyAttr); + if (crv != CKR_OK) return crv; - if (cert && !cert->nickname) { - crv=pk11_Attribute2SecItem(NULL,&nickName,privKeyObject,CKA_LABEL); - if (crv != CKR_OK) { - goto loser; - } - rv = nsslowcert_AddPermNickname(cert, (char *)nickName.data); - SECITEM_ZfreeItem(&nickName, PR_FALSE); - if (rv != SECSuccess) { - goto loser; - } + PORT_Assert(pubKey.data); + if (slot->keyDB == NULL) { + PORT_Free(pubKey.data); + return CKR_TOKEN_WRITE_PROTECTED; + } + /* make sure the associated private key already exists */ + /* only works if we are logged in */ + priv = nsslowkey_FindKeyByPublicKey(slot->keyDB, &pubKey, + slot->password); + if (priv == NULL) { + PORT_Free(pubKey.data); + return CKR_ATTRIBUTE_VALUE_INVALID; } + nsslowkey_DestroyPrivateKey(priv); - /* associate the certificate with the key */ - pk11_importCertificate(privKeyObject->slot, cert, pubKey->data, - pubKey->len, PR_FALSE); + object->handle = pk11_mkHandle(slot, &pubKey, PK11_TOKEN_TYPE_PUB); + PORT_Free(pubKey.data); } - return SECSuccess; -loser: - if (cbarg.cert) nsslowcert_DestroyCertificate(cbarg.cert); - return SECFailure; + return CKR_OK; } static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key); @@ -868,7 +973,7 @@ static NSSLOWKEYPrivateKey * pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key); * check the consistancy and initialize a Private Key Object */ static CK_RV -pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type) +pk11_handlePrivateKeyObject(PK11Session *session,PK11Object *object,CK_KEY_TYPE key_type) { CK_BBOOL cktrue = CK_TRUE; CK_BBOOL encrypt = CK_TRUE; @@ -961,37 +1066,33 @@ pk11_handlePrivateKeyObject(PK11Object *object,CK_KEY_TYPE key_type) if (crv != CKR_OK) return crv; if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; NSSLOWKEYPrivateKey *privKey; char *label; SECStatus rv = SECSuccess; SECItem pubKey; + if (slot->keyDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } + privKey=pk11_mkPrivKey(object,key_type); if (privKey == NULL) return CKR_HOST_MEMORY; - label = object->label = pk11_getString(object,CKA_LABEL); + label = pk11_getString(object,CKA_LABEL); crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv == CKR_OK) { - PORT_Assert(object->slot->keyDB); - rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB, - privKey, &pubKey, label, - (NSSLOWKEYGetPasswordKey) pk11_givePass, object->slot); - - /* check for the existance of an existing certificate and activate - * it if necessary */ - if (rv == SECSuccess) { - reload_existing_certificate(object,&pubKey); - } - - if (pubKey.data) PORT_Free(pubKey.data); - } else { - rv = SECFailure; + if (crv != CKR_OK) { + nsslowkey_DestroyPrivateKey(privKey); + return CKR_TEMPLATE_INCOMPLETE; } + rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB, + privKey, &pubKey, label, object->slot->password); + + object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_PRIV); + if (pubKey.data) PORT_Free(pubKey.data); nsslowkey_DestroyPrivateKey(privKey); if (rv != SECSuccess) return CKR_DEVICE_ERROR; - object->inDB = PR_TRUE; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); } else { object->objectInfo = pk11_mkPrivKey(object,key_type); if (object->objectInfo == NULL) return CKR_HOST_MEMORY; @@ -1015,7 +1116,8 @@ static NSSLOWKEYPrivateKey *pk11_mkSecretKeyRep(PK11Object *object); /* Validate secret key data, and set defaults */ static CK_RV -validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) +validateSecretKey(PK11Session *session, PK11Object *object, + CK_KEY_TYPE key_type, PRBool isFIPS) { CK_RV crv; CK_BBOOL cktrue = CK_TRUE; @@ -1061,9 +1163,14 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) #if NSS_SOFTOKEN_DOES_RC5 case CKK_RC5: #endif +#ifdef NSS_SOFTOKEN_DOES_CAST case CKK_CAST: case CKK_CAST3: case CKK_CAST5: +#endif +#if NSS_SOFTOKEN_DOES_IDEA + case CKK_IDEA: +#endif attribute = pk11_FindAttribute(object,CKA_VALUE); /* shouldn't happen */ if (attribute == NULL) return CKR_TEMPLATE_INCOMPLETE; @@ -1093,8 +1200,8 @@ validateSecretKey(PK11Object *object, CK_KEY_TYPE key_type, PRBool isFIPS) * check the consistancy and initialize a Secret Key Object */ static CK_RV -pk11_handleSecretKeyObject(PK11Object *object,CK_KEY_TYPE key_type, - PRBool isFIPS) +pk11_handleSecretKeyObject(PK11Session *session,PK11Object *object, + CK_KEY_TYPE key_type, PRBool isFIPS) { CK_RV crv; NSSLOWKEYPrivateKey *privKey = NULL; @@ -1103,32 +1210,36 @@ pk11_handleSecretKeyObject(PK11Object *object,CK_KEY_TYPE key_type, pubKey.data = 0; /* First validate and set defaults */ - crv = validateSecretKey(object, key_type, isFIPS); + crv = validateSecretKey(session, object, key_type, isFIPS); if (crv != CKR_OK) goto loser; /* If the object is a TOKEN object, store in the database */ if (pk11_isTrue(object,CKA_TOKEN)) { + PK11Slot *slot = session->slot; char *label; SECStatus rv = SECSuccess; + if (slot->keyDB == NULL) { + return CKR_TOKEN_WRITE_PROTECTED; + } privKey=pk11_mkSecretKeyRep(object); if (privKey == NULL) return CKR_HOST_MEMORY; - label = object->label = pk11_getString(object,CKA_LABEL); + label = pk11_getString(object,CKA_LABEL); - crv = pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_ID); /* Should this be ID? */ + crv = pk11_Attribute2SecItem(NULL, &pubKey, object, CKA_ID); + /* Should this be ID? */ if (crv != CKR_OK) goto loser; - PORT_Assert(object->slot->keyDB); - rv = nsslowkey_StoreKeyByPublicKey(object->slot->keyDB, - privKey, &pubKey, label, - (NSSLOWKEYGetPasswordKey) pk11_givePass, object->slot); + PORT_Assert(slot->keyDB); + rv = nsslowkey_StoreKeyByPublicKey(slot->keyDB, + privKey, &pubKey, label, slot->password); if (rv != SECSuccess) { crv = CKR_DEVICE_ERROR; + goto loser; } - object->inDB = PR_TRUE; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); + object->handle = pk11_mkHandle(slot,&pubKey,PK11_TOKEN_TYPE_PRIV); } loser: @@ -1174,12 +1285,12 @@ pk11_handleKeyObject(PK11Session *session, PK11Object *object) switch (object->objclass) { case CKO_PUBLIC_KEY: - return pk11_handlePublicKeyObject(object,key_type); + return pk11_handlePublicKeyObject(session,object,key_type); case CKO_PRIVATE_KEY: - return pk11_handlePrivateKeyObject(object,key_type); + return pk11_handlePrivateKeyObject(session,object,key_type); case CKO_SECRET_KEY: /* make sure the required fields exist */ - return pk11_handleSecretKeyObject(object,key_type, + return pk11_handleSecretKeyObject(session,object,key_type, (PRBool)(session->slot->slotID == FIPS_SLOT_ID)); default: break; @@ -1224,17 +1335,6 @@ pk11_handleObject(PK11Object *object, PK11Session *session) (pk11_isTrue(object,CKA_TOKEN))) { return CKR_SESSION_READ_ONLY; } - - if (pk11_isTrue(object, CKA_TOKEN)) { - if (slot->DB_loaded == PR_FALSE) { - /* we are creating a token object, make sure we load the database - * first so we don't get duplicates.... - * ... NOTE: This assumes we are logged in as well! - */ - pk11_importKeyDB(slot); - slot->DB_loaded = PR_TRUE; - } - } /* PKCS #11 object ID's are unique for all objects on a * token */ @@ -1255,9 +1355,16 @@ pk11_handleObject(PK11Object *object, PK11Session *session) switch (object->objclass) { case CKO_DATA: crv = pk11_handleDataObject(session,object); + break; case CKO_CERTIFICATE: crv = pk11_handleCertObject(session,object); break; + case CKO_NETSCAPE_TRUST: + crv = pk11_handleTrustObject(session,object); + break; + case CKO_NETSCAPE_CRL: + crv = pk11_handleCrlObject(session,object); + break; case CKO_PRIVATE_KEY: case CKO_PUBLIC_KEY: case CKO_SECRET_KEY: @@ -1275,649 +1382,14 @@ pk11_handleObject(PK11Object *object, PK11Session *session) } /* now link the object into the slot and session structures */ - object->slot = slot; - pk11_AddObject(session,object); - - return CKR_OK; -} - -/* import a private key as an object. We don't call handle object. - * because we the private key came from the key DB and we don't want to - * write back out again */ -static PK11Object * -pk11_importPrivateKey(PK11Slot *slot,NSSLOWKEYPrivateKey *lowPriv, - SECItem *dbKey) -{ - PK11Object *privateKey; - CK_KEY_TYPE key_type; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_BBOOL sign = CK_TRUE; - CK_BBOOL recover = CK_TRUE; - CK_BBOOL decrypt = CK_TRUE; - CK_BBOOL derive = CK_FALSE; - CK_RV crv = CKR_OK; - CK_OBJECT_CLASS privClass = CKO_PRIVATE_KEY; - unsigned char cka_id[SHA1_LENGTH]; - - /* - * now lets create an object to hang the attributes off of - */ - privateKey = pk11_NewObject(slot); /* fill in the handle later */ - if (privateKey == NULL) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* Netscape Private Attribute for dealing with database storeage */ - if (pk11_AddAttributeType(privateKey, CKA_NETSCAPE_DB, - pk11_item_expand(dbKey)) ) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* now force the CKA_ID */ - SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len); - if (pk11_AddAttributeType(privateKey, CKA_ID, cka_id, sizeof(cka_id))) { - pk11_FreeObject(privateKey); - return NULL; - } - - - /* Fill in the common Default values */ - if (pk11_AddAttributeType(privateKey,CKA_CLASS, &privClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_PRIVATE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_LABEL, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_START_DATE, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_END_DATE, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - /* local: well we really don't know for sure... it could have been an - * imported key, but it's not a useful attribute anyway. */ - if (pk11_AddAttributeType(privateKey,CKA_LOCAL, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SUBJECT, NULL, 0) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SENSITIVE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_EXTRACTABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - /* is this really true? Maybe we should just say false here? */ - if (pk11_AddAttributeType(privateKey,CKA_ALWAYS_SENSITIVE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_NEVER_EXTRACTABLE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - - /* Now Set up the parameters to generate the key (based on mechanism) */ - /* NOTE: for safety sake we *DO NOT* remember critical attributes. PKCS #11 - * will look them up again from the database when it needs them. - */ - switch (lowPriv->keyType) { - case NSSLOWKEYRSAKey: - /* format the keys */ - key_type = CKK_RSA; - sign = CK_TRUE; - recover = CK_TRUE; - decrypt = CK_TRUE; - derive = CK_FALSE; - /* now fill in the RSA dependent parameters in the public key */ - crv = pk11_AddAttributeType(privateKey,CKA_MODULUS, - pk11_item_expand(&lowPriv->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIVATE_EXPONENT,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&lowPriv->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME_1,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME_2,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_1,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_EXPONENT_2,NULL,0); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_COEFFICIENT,NULL,0); - break; - case NSSLOWKEYDSAKey: - key_type = CKK_DSA; - sign = CK_TRUE; - recover = CK_FALSE; - decrypt = CK_FALSE; - derive = CK_FALSE; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_SUBPRIME, - pk11_item_expand(&lowPriv->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_VALUE,NULL,0); - if (crv != CKR_OK) break; - break; - case NSSLOWKEYDHKey: - key_type = CKK_DH; - sign = CK_FALSE; - decrypt = CK_FALSE; - recover = CK_FALSE; - derive = CK_TRUE; - crv = pk11_AddAttributeType(privateKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dh.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dh.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(privateKey,CKA_VALUE,NULL,0); - if (crv != CKR_OK) break; - break; - default: - crv = CKR_MECHANISM_INVALID; - } - - if (crv != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - - - if (pk11_AddAttributeType(privateKey,CKA_SIGN, &sign, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_SIGN_RECOVER, &recover, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DECRYPT, &decrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_UNWRAP, &decrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_DERIVE, &derive, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - if (pk11_AddAttributeType(privateKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)) != CKR_OK) { - pk11_FreeObject(privateKey); - return NULL; - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - privateKey->handle = slot->tokenIDCount++; - privateKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - privateKey->objclass = privClass; - privateKey->slot = slot; - privateKey->inDB = PR_TRUE; - - return privateKey; -} - -/* import a private key or cert as a public key object.*/ -static PK11Object * -pk11_importPublicKey(PK11Slot *slot, - NSSLOWKEYPrivateKey *lowPriv, NSSLOWCERTCertificate *cert, SECItem *dbKey) -{ - PK11Object *publicKey = NULL; - CK_KEY_TYPE key_type; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_BBOOL verify = CK_TRUE; - CK_BBOOL recover = CK_TRUE; - CK_BBOOL encrypt = CK_TRUE; - CK_BBOOL derive = CK_FALSE; - CK_RV crv = CKR_OK; - CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY; - unsigned char cka_id[SHA1_LENGTH]; - NSSLOWKEYType keyType = NSSLOWKEYNullKey; - NSSLOWKEYPublicKey *pubKey = NULL; - CK_ATTRIBUTE theTemplate[2]; - PK11ObjectListElement *objectList = NULL; - - if (lowPriv == NULL) { - pubKey = nsslowcert_ExtractPublicKey(cert); - if (pubKey == NULL) { - goto failed; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. All callers - * should include this comment. - */ - dbKey = pk11_GetPubItem(pubKey); - if (dbKey == NULL) { - goto failed; - } - } - SHA1_HashBuf(cka_id, (unsigned char *)dbKey->data, (uint32)dbKey->len); - theTemplate[0].type = CKA_ID; - theTemplate[0].pValue = cka_id; - theTemplate[0].ulValueLen = sizeof(cka_id); - theTemplate[1].type = CKA_CLASS; - theTemplate[1].pValue = &pubClass; - theTemplate[1].ulValueLen = sizeof(CK_OBJECT_CLASS); - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, theTemplate, 2, slot->isLoggedIn); - if ((crv == CKR_OK) && (objectList != NULL)) { - goto failed; - } - /* - * now lets create an object to hang the attributes off of - */ - publicKey = pk11_NewObject(slot); /* fill in the handle later */ - if (publicKey == NULL) { - goto failed; - } - - /* now force the CKA_ID */ - if (pk11_AddAttributeType(publicKey, CKA_ID, cka_id, sizeof(cka_id))) { - goto failed; - } - - /* Fill in the common Default values */ - if (pk11_AddAttributeType(publicKey,CKA_CLASS,&pubClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_LABEL, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_START_DATE, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_END_DATE, NULL, 0) != CKR_OK) { - goto failed; - } - /* local: well we really don't know for sure... it could have been an - * imported key, but it's not a useful attribute anyway. */ - if (pk11_AddAttributeType(publicKey,CKA_LOCAL, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_SUBJECT, NULL, 0) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_SENSITIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_EXTRACTABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_ALWAYS_SENSITIVE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_NEVER_EXTRACTABLE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - - /* Now Set up the parameters to generate the key (based on mechanism) */ - if (lowPriv == NULL) { - keyType = pubKey->keyType; - } else { - keyType = lowPriv->keyType; - } - - - switch (keyType) { - case NSSLOWKEYRSAKey: - /* format the keys */ - key_type = CKK_RSA; - verify = CK_TRUE; - recover = CK_TRUE; - encrypt = CK_TRUE; - derive = CK_FALSE; - /* now fill in the RSA dependent parameters in the public key */ - if (lowPriv) { - crv = pk11_AddAttributeType(publicKey,CKA_MODULUS, - pk11_item_expand(&lowPriv->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&lowPriv->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - } else { - crv = pk11_AddAttributeType(publicKey,CKA_MODULUS, - pk11_item_expand(&pubKey->u.rsa.modulus)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_PUBLIC_EXPONENT, - pk11_item_expand(&pubKey->u.rsa.publicExponent)); - if (crv != CKR_OK) break; - } - break; - case NSSLOWKEYDSAKey: - key_type = CKK_DSA; - verify = CK_TRUE; - recover = CK_FALSE; - encrypt = CK_FALSE; - derive = CK_FALSE; - if (lowPriv) { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME, - pk11_item_expand(&lowPriv->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&lowPriv->u.dsa.publicValue)); - if (crv != CKR_OK) break; - } else { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&pubKey->u.dsa.params.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_SUBPRIME, - pk11_item_expand(&pubKey->u.dsa.params.subPrime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&pubKey->u.dsa.params.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&pubKey->u.dsa.publicValue)); - if (crv != CKR_OK) break; - } - break; - case NSSLOWKEYDHKey: - key_type = CKK_DH; - verify = CK_FALSE; - encrypt = CK_FALSE; - recover = CK_FALSE; - derive = CK_TRUE; - if (lowPriv) { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&lowPriv->u.dh.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&lowPriv->u.dh.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&lowPriv->u.dh.publicValue)); - if (crv != CKR_OK) break; - } else { - crv = pk11_AddAttributeType(publicKey,CKA_PRIME, - pk11_item_expand(&pubKey->u.dh.prime)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_BASE, - pk11_item_expand(&pubKey->u.dh.base)); - if (crv != CKR_OK) break; - crv = pk11_AddAttributeType(publicKey,CKA_VALUE, - pk11_item_expand(&pubKey->u.dh.publicValue)); - if (crv != CKR_OK) break; - } - break; - default: - crv = CKR_MECHANISM_INVALID; - } - - if (pubKey) { - nsslowkey_DestroyPublicKey(pubKey); - pubKey = NULL; - } - - if (crv != CKR_OK) { - goto failed; - } - - if (pk11_AddAttributeType(publicKey,CKA_VERIFY, &verify, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_VERIFY_RECOVER, &recover, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_ENCRYPT, &encrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_WRAP, &encrypt, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_DERIVE, &derive, - sizeof(CK_BBOOL)) != CKR_OK) { - goto failed; - } - if (pk11_AddAttributeType(publicKey,CKA_KEY_TYPE,&key_type, - sizeof(CK_KEY_TYPE)) != CKR_OK) { - goto failed; - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - publicKey->handle = slot->tokenIDCount++; - publicKey->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PUB); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - publicKey->objclass = pubClass; - publicKey->slot = slot; - publicKey->inDB = PR_FALSE; /* not really in the Database */ - - return publicKey; -failed: - if (pubKey) nsslowkey_DestroyPublicKey(pubKey); - if (publicKey) pk11_FreeObject(publicKey); - return NULL; -} - -/* - * Question.. Why doesn't import Cert call pk11_handleObject, or - * pk11 handleCertObject? Answer: because they will try to write - * this cert back out to the Database, even though it is already in - * the database. - */ -static PK11Object * -pk11_importCertificate(PK11Slot *slot, NSSLOWCERTCertificate *cert, - unsigned char *data, unsigned int size, PRBool needObject) -{ - PK11Object *certObject = NULL; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_CERTIFICATE_TYPE certType = CKC_X_509; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - unsigned char cka_id[SHA1_LENGTH]; - CK_ATTRIBUTE theTemplate; - PK11ObjectListElement *objectList = NULL; - CK_RV crv; - - - /* - * first make sure that no object for this cert already exists. - */ - theTemplate.type = CKA_VALUE; - theTemplate.pValue = cert->derCert.data; - theTemplate.ulValueLen = cert->derCert.len; - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, &theTemplate, 1, slot->isLoggedIn); - if ((crv == CKR_OK) && (objectList != NULL)) { - if (needObject) { - pk11_ReferenceObject(objectList->object); - certObject = objectList->object; - } - pk11_FreeObjectList(objectList); - return certObject; - } - - /* - * now lets create an object to hang the attributes off of - */ - certObject = pk11_NewObject(slot); /* fill in the handle later */ - if (certObject == NULL) { - return NULL; - } - - /* First set the CKA_ID */ - if (data == NULL) { - NSSLOWKEYPublicKey *pubKey = nsslowcert_ExtractPublicKey(cert); - SECItem *pubItem; - if (pubKey == NULL) { - pk11_FreeObject(certObject); - return NULL; - } - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. - */ - pubItem =pk11_GetPubItem(pubKey); - if (pubItem == NULL) { - nsslowkey_DestroyPublicKey(pubKey); - pk11_FreeObject(certObject); - return NULL; - } - SHA1_HashBuf(cka_id, (unsigned char *)pubItem->data, - (uint32)pubItem->len); - nsslowkey_DestroyPublicKey(pubKey); - } else { - SHA1_HashBuf(cka_id, (unsigned char *)data, (uint32)size); - } - if (pk11_AddAttributeType(certObject, CKA_ID, cka_id, sizeof(cka_id))) { - pk11_FreeObject(certObject); - return NULL; - } - - /* initalize the certificate attributes */ - if (pk11_AddAttributeType(certObject, CKA_CLASS, &certClass, - sizeof(CK_OBJECT_CLASS)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_TOKEN, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_LABEL, cert->nickname, - PORT_Strlen(cert->nickname)) - != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_MODIFIABLE, &cktrue, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_CERTIFICATE_TYPE, &certType, - sizeof(CK_CERTIFICATE_TYPE))!=CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_VALUE, - pk11_item_expand(&cert->derCert)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_ISSUER, - pk11_item_expand(&cert->derIssuer)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_SUBJECT, - pk11_item_expand(&cert->derSubject)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - if (pk11_AddAttributeType(certObject, CKA_SERIAL_NUMBER, - pk11_item_expand(&cert->serialNumber)) != CKR_OK) { - pk11_FreeObject(certObject); - return NULL; - } - - - certObject->objectInfo = NULL; - certObject->infoFree = (PK11Free) NULL; - - /* now just verify the required date fields */ - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - certObject->handle = slot->tokenIDCount++; - certObject->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_CERT); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - certObject->objclass = certClass; - certObject->slot = slot; - certObject->inDB = PR_TRUE; - pk11_AddSlotObject(slot, certObject); - if (needObject) { - pk11_ReferenceObject(certObject); + if (pk11_isToken(object->handle)) { + pk11_convertSessionToToken(object); } else { - certObject = NULL; + object->slot = slot; + pk11_AddObject(session,object); } - return certObject; + return CKR_OK; } /* @@ -1934,6 +1406,10 @@ NSSLOWKEYPublicKey *pk11_GetPubKey(PK11Object *object,CK_KEY_TYPE key_type) return NULL; } + if (pk11_isToken(object->handle)) { +/* ferret out the token object handle */ + } + /* If we already have a key, use it */ if (object->objectInfo) { return (NSSLOWKEYPublicKey *)object->objectInfo; @@ -2009,6 +1485,7 @@ pk11_mkPrivKey(PK11Object *object,CK_KEY_TYPE key_type) CK_RV crv = CKR_OK; SECStatus rv; + PORT_Assert(!pk11_isToken(object->handle)); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; @@ -2111,39 +1588,18 @@ pk11_GetPrivKey(PK11Object *object,CK_KEY_TYPE key_type) return (NSSLOWKEYPrivateKey *)object->objectInfo; } - if (pk11_isTrue(object,CKA_TOKEN)) { + if (pk11_isToken(object->handle)) { /* grab it from the data base */ - SECItem pubKey; + PK11TokenObject *to = pk11_narrowToTokenObject(object); CK_RV crv; - /* KEYID is the public KEY for DSA and DH, and the MODULUS for - * RSA */ - crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv != CKR_OK) return NULL; - + PORT_Assert(to); PORT_Assert(object->slot->keyDB); - priv=nsslowkey_FindKeyByPublicKey(object->slot->keyDB,&pubKey, - (NSSLOWKEYGetPasswordKey) pk11_givePass, - object->slot); - if (!priv && pubKey.data[0] == 0) { - /* Because of legacy code issues, sometimes the public key has - * a '0' prepended to it, forcing it to be unsigned. The database - * may not store that '0', so remove it and try again. - */ - SECItem tmpPubKey; - tmpPubKey.data = pubKey.data + 1; - tmpPubKey.len = pubKey.len - 1; - priv=nsslowkey_FindKeyByPublicKey(object->slot->keyDB, - &tmpPubKey, (NSSLOWKEYGetPasswordKey) pk11_givePass, - object->slot); - } - if (pubKey.data) PORT_Free(pubKey.data); - - /* don't 'cache' DB private keys */ - return priv; - } - - priv = pk11_mkPrivKey(object, key_type); + priv = nsslowkey_FindKeyByPublicKey(object->slot->keyDB, &to->dbKey, + object->slot->password); + } else { + priv = pk11_mkPrivKey(object, key_type); + } object->objectInfo = priv; object->infoFree = (PK11Free) nsslowkey_DestroyPrivateKey; return priv; @@ -2293,86 +1749,6 @@ isSecretKey(NSSLOWKEYPrivateKey *privKey) return PR_FALSE; } -/* Import a Secret Key */ -static PRBool -importSecretKey(PK11Slot *slot, NSSLOWKEYPrivateKey *priv) -{ - PK11Object *object; - CK_OBJECT_CLASS secretClass = CKO_SECRET_KEY; - CK_BBOOL cktrue = CK_TRUE; - CK_BBOOL ckfalse = CK_FALSE; - CK_KEY_TYPE key_type; - - /* Check for secret key representation, return if it isn't one */ - if (!isSecretKey(priv)) - return PR_FALSE; - - /* - * now lets create an object to hang the attributes off of - */ - object = pk11_NewObject(slot); /* fill in the handle later */ - if (object == NULL) { - goto loser; - } - - /* Set the ID value */ - if (pk11_AddAttributeType(object, CKA_ID, - priv->u.rsa.modulus.data, priv->u.rsa.modulus.len)) { - pk11_FreeObject(object); - goto loser; - } - - /* initalize the object attributes */ - if (pk11_AddAttributeType(object, CKA_CLASS, &secretClass, - sizeof(secretClass)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } - - if (pk11_AddAttributeType(object, CKA_TOKEN, &cktrue, - sizeof(cktrue)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } - - if (pk11_AddAttributeType(object, CKA_PRIVATE, &ckfalse, - sizeof(CK_BBOOL)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } - - if (pk11_AddAttributeType(object, CKA_VALUE, - pk11_item_expand(&priv->u.rsa.privateExponent)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } - - if (pk11_AddAttributeType(object, CKA_KEY_TYPE, - pk11_item_expand(&priv->u.rsa.coefficient)) != CKR_OK) { - pk11_FreeObject(object); - goto loser; - } - key_type = *(CK_KEY_TYPE*)priv->u.rsa.coefficient.data; - - /* Validate and add default attributes */ - validateSecretKey(object, key_type, (PRBool)(slot->slotID == FIPS_SLOT_ID)); - - /* now just verify the required date fields */ - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - object->handle = slot->tokenIDCount++; - object->handle |= (PK11_TOKEN_MAGIC | PK11_TOKEN_TYPE_PRIV); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - - object->objclass = secretClass; - object->slot = slot; - object->inDB = PR_TRUE; - pk11_AddSlotObject(slot, object); - -loser: - return PR_TRUE; -} - - /********************************************************************** * * Start of PKCS 11 functions @@ -2383,10 +1759,22 @@ loser: /* return the function list */ CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) { - *pFunctionList = &pk11_funcList; + *pFunctionList = (CK_FUNCTION_LIST_PTR) &pk11_funcList; return CKR_OK; } +/* return the function list */ +CK_RV C_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList) +{ + return NSC_GetFunctionList(pFunctionList); +} + +static PLHashNumber +pk11_HashNumber(const void *key) +{ + return (PLHashNumber) key; +} + /* * initialize one of the slot structures. figure out which by the ID */ @@ -2411,6 +1799,11 @@ PK11_SlotInit(CK_SLOT_ID slotID, PRBool needLogin, for(i=0; i < TOKEN_OBJECT_HASH_SIZE; i++) { slot->tokObjects[i] = NULL; } + slot->tokenHashTable = PL_NewHashTable(64,pk11_HashNumber,PL_CompareValues, + SECITEM_HashCompare, NULL, 0); + if (slot->tokenHashTable == NULL) { + return CKR_HOST_MEMORY; + } slot->password = NULL; slot->hasTokens = PR_FALSE; slot->sessionIDCount = 1; @@ -2447,7 +1840,8 @@ CK_RV PK11_LowInitialize(CK_VOID_PTR pReserved) */ /* initialize the key and cert db's */ - nsslowkey_SetDefaultKeyDBAlg(SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); + nsslowkey_SetDefaultKeyDBAlg + (SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC); if ((init_args && init_args->LibraryParameters)) { pk11_parameters paramStrings; @@ -2541,7 +1935,7 @@ CK_RV NSC_Finalize (CK_VOID_PTR pReserved) CK_RV NSC_GetInfo(CK_INFO_PTR pInfo) { pInfo->cryptokiVersion.major = 2; - pInfo->cryptokiVersion.minor = 1; + pInfo->cryptokiVersion.minor = 11; PORT_Memcpy(pInfo->manufacturerID,manufacturerID,32); pInfo->libraryVersion.major = 3; pInfo->libraryVersion.minor = 2; @@ -3506,439 +2900,311 @@ CK_RV NSC_SetAttributeValue (CK_SESSION_HANDLE hSession, return CKR_OK; } -/* stolen from keydb.c */ -#define KEYDB_PW_CHECK_STRING "password-check" -#define KEYDB_PW_CHECK_LEN 14 +/* + * find any certs that may match the template and load them. + */ +#define NSC_CERT 0x00000001 +#define NSC_TRUST 0x00000002 +#define NSC_CRL 0x00000004 +#define NSC_SMIME 0x00000008 +#define NSC_PRIVATE 0x00000010 +#define NSC_PUBLIC 0x00000020 +#define NSC_KEY 0x00000040 -NSSLOWKEYPrivateKey * nsslowkey_DecryptKey(DBT *key, SECItem *pwitem, - NSSLOWKEYDBHandle *handle); -typedef struct pk11keyNodeStr { - struct pk11keyNodeStr *next; - NSSLOWKEYPrivateKey *privKey; - NSSLOWCERTCertificate *cert; - SECItem *pubItem; -} pk11keyNode; +/* + * structure to collect key handles. + */ +typedef struct pk11KeyDataStr { + PK11Slot *slot; + PK11SearchResults *searchHandles; + SECItem *id; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; + unsigned long classFlags; + PRBool isLoggedIn; + PRBool strict; +} pk11KeyData; -typedef struct { - PLArenaPool *arena; - pk11keyNode *head; +/* + * structure to collect certs into + */ +typedef struct pk11CertDataStr { PK11Slot *slot; -} keyList; + int cert_count; + int max_cert_count; + NSSLOWCERTCertificate **certs; + CK_ATTRIBUTE *template; + CK_ULONG templ_count; + unsigned long classFlags; + PRBool strict; +} pk11CertData; static SECStatus -add_key_to_list(DBT *key, DBT *data, void *arg) +pk11_key_collect(DBT *key, DBT *data, void *arg) { - keyList *keylist; - pk11keyNode *node; - void *keydata; + pk11KeyData *keyData; NSSLOWKEYPrivateKey *privKey = NULL; + SECItem tmpDBKey; + PK11Slot *slot; - keylist = (keyList *)arg; + keyData = (pk11KeyData *)arg; + slot = keyData->slot; - PORT_Assert(keylist->slot->keyDB); - privKey = nsslowkey_DecryptKey(key, keylist->slot->password, - keylist->slot->keyDB); - if ( privKey == NULL ) { - goto loser; - } + tmpDBKey.data = key->data; + tmpDBKey.len = key->size; - /* allocate the node struct */ - node = (pk11keyNode*)PORT_ArenaZAlloc(keylist->arena, sizeof(pk11keyNode)); - if ( node == NULL ) { - goto loser; + PORT_Assert(slot->keyDB); + if (!keyData->strict && keyData->id) { + SECItem result; + unsigned char hashKey[SHA1_LENGTH]; + result.data = hashKey; + result.len = sizeof(hashKey); + + SHA1_HashBuf( hashKey, key->data, key->size ); + if (SECITEM_ItemsAreEqual(keyData->id,&result)) { + if (keyData->classFlags & NSC_PRIVATE) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV)); + } + if (keyData->classFlags & NSC_PUBLIC) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(slot,&tmpDBKey,PK11_TOKEN_TYPE_PUB)); + } + /* NSC_KEY Already handled */ + } + return SECSuccess; } - - /* allocate room for key data */ - keydata = PORT_ArenaZAlloc(keylist->arena, key->size); - if ( keydata == NULL ) { + + privKey = nsslowkey_FindKeyByPublicKey(keyData->slot->keyDB, &tmpDBKey, + keyData->slot->password); + if ( privKey == NULL ) { goto loser; } - /* link node into list */ - node->next = keylist->head; - keylist->head = node; - - node->privKey = privKey; - switch (privKey->keyType) { - case NSSLOWKEYRSAKey: - node->pubItem = &privKey->u.rsa.modulus; - break; - case NSSLOWKEYDSAKey: - node->pubItem = &privKey->u.dsa.publicValue; - break; - case NSSLOWKEYDHKey: - node->pubItem = &privKey->u.dh.publicValue; - break; - default: - break; + if (isSecretKey(privKey)) { + if ((keyData->classFlags & NSC_KEY) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_KEY)); + } + } else { + if ((keyData->classFlags & NSC_PRIVATE) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PRIV, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot,&tmpDBKey,PK11_TOKEN_TYPE_PRIV)); + } + if ((keyData->classFlags & NSC_PUBLIC) && + pk11_tokenMatch(keyData->slot, &tmpDBKey, PK11_TOKEN_TYPE_PUB, + keyData->template, keyData->templ_count)) { + pk11_addHandle(keyData->searchHandles, + pk11_mkHandle(keyData->slot, &tmpDBKey,PK11_TOKEN_TYPE_PUB)); + } } - - return(SECSuccess); + loser: if ( privKey ) { nsslowkey_DestroyPrivateKey(privKey); } return(SECSuccess); } - /* - * If the cert is a user cert, then try to match it to a key on the - * linked list of private keys built earlier. - * If the cert matches one on the list, then save it. - */ + * collect all the certs from the traverse call. + */ static SECStatus -add_cert_to_list(NSSLOWCERTCertificate *cert, SECItem *k, void *pdata) +pk11_cert_collect(NSSLOWCERTCertificate *cert,void *arg) { - keyList *keylist; - pk11keyNode *node; - NSSLOWKEYPublicKey *pubKey = NULL; - SECItem *pubItem; - NSSLOWCERTCertificate *oldcert; - - keylist = (keyList *)pdata; - - /* only if it is a user cert and has a nickname!! */ - if ( ( ( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER ) ) && - ( cert->nickname != NULL ) ) { - - /* get cert's public key */ - pubKey = nsslowcert_ExtractPublicKey(cert); - if ( pubKey == NULL ) { - goto done; - } + pk11CertData *cd = (pk11CertData *)arg; - /* pk11_GetPubItem returns data associated with the public key. - * one only needs to free the public key. This comment is here - * because this sematic would be non-obvious otherwise. - */ - pubItem = pk11_GetPubItem(pubKey); - if (pubItem == NULL) goto done; - - node = keylist->head; - while ( node ) { - /* if key type is different, then there is no match */ - if (node->privKey->keyType == pubKey->keyType) { - - /* compare public value from cert with public value from - * the key - */ - if ( SECITEM_CompareItem(pubItem, node->pubItem) == SECEqual ){ - /* this is a match */ - - /* if no cert has yet been found for this key, or this - * cert is newer, then save this cert - */ - if ( ( node->cert == NULL ) -#ifdef notdef - || CERT_IsNewer(cert, node->cert ) -#endif - ) { - - oldcert = node->cert; - - /* get a real DB copy of the cert, since the one - * passed in here is not properly recorded in the - * temp database - */ - - /* We need a better way to deal with this */ - PORT_Assert(keylist->slot->certDB); - node->cert = - nsslowcert_FindCertByKeyNoLocking( - keylist->slot->certDB, - &cert->certKey); - - /* free the old cert if there was one */ - if ( oldcert ) { - nsslowcert_DestroyCertificate(oldcert); - } - } - } - } - - node = node->next; + if (cd->certs == NULL) { + return SECFailure; + } + + if (cd->strict) { + if ((cd->classFlags & NSC_CERT) && !pk11_tokenMatch(cd->slot, + &cert->certKey, PK11_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) { + return SECSuccess; + } + if ((cd->classFlags & NSC_TRUST) && !pk11_tokenMatch(cd->slot, + &cert->certKey, PK11_TOKEN_TYPE_TRUST, + cd->template, cd->templ_count)) { + return SECSuccess; } } -done: - if ( pubKey ) { - nsslowkey_DestroyPublicKey(pubKey); + + /* allocate more space if we need it. This should only happen in + * the general traversal case */ + if (cd->cert_count >= cd->max_cert_count) { + int size; + cd->max_cert_count += NSC_CERT_BLOCK_SIZE; + size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *); + cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size); + if (cd->certs == NULL) { + return SECFailure; + } } - return(SECSuccess); + cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert); + return SECSuccess; } -#if 0 -/* This appears to be obsolete - TNH */ -static SECItem * -decodeKeyDBGlobalSalt(DBT *saltData) +/* provide impedence matching ... */ +static SECStatus +pk11_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg) { - SECItem *saltitem; - - saltitem = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if ( saltitem == NULL ) { - return(NULL); - } - - saltitem->data = (unsigned char *)PORT_ZAlloc(saltData->size); - if ( saltitem->data == NULL ) { - PORT_Free(saltitem); - return(NULL); - } - - saltitem->len = saltData->size; - PORT_Memcpy(saltitem->data, saltData->data, saltitem->len); - - return(saltitem); + return pk11_cert_collect(cert, arg); } -#endif - -#if 0 -/* - * Create a (fixed) DES3 key [ testing ] - */ -static unsigned char keyValue[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 -}; -static SECItem keyItem = { - 0, - keyValue, - sizeof keyValue -}; - -static unsigned char keyID[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static SECItem keyIDItem = { - 0, - keyID, - sizeof keyID -}; -/* +AAA */ -static CK_RV -pk11_createFixedDES3Key(PK11Slot *slot) +static void +pk11_searchSingleCert(pk11CertData *certData,NSSLOWCERTCertificate *cert) { - CK_RV rv = CKR_OK; - PK11Object *keyObject; - CK_BBOOL true = CK_TRUE; - CK_OBJECT_CLASS class = CKO_SECRET_KEY; - CK_KEY_TYPE keyType = CKK_DES3; - - /* - * Create the object - */ - keyObject = pk11_NewObject(slot); /* fill in the handle later */ - if (keyObject == NULL) { - return CKR_HOST_MEMORY; - } - - /* Add attributes to the object */ - rv = pk11_AddAttributeType(keyObject, CKA_ID, keyID, sizeof keyID); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + if (cert == NULL) { + return; } - - rv = pk11_AddAttributeType(keyObject, CKA_VALUE, keyValue, sizeof keyValue); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + if (certData->strict && + !pk11_tokenMatch(certData->slot, &cert->certKey, PK11_TOKEN_TYPE_CERT, + certData->template,certData->templ_count)) { + nsslowcert_DestroyCertificate(cert); + return; } - - rv = pk11_AddAttributeType(keyObject, CKA_TOKEN, &true, sizeof true); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + certData->certs = (NSSLOWCERTCertificate **) + PORT_Alloc(sizeof (NSSLOWCERTCertificate *)); + if (certData->certs == NULL) { + nsslowcert_DestroyCertificate(cert); + return; } + certData->certs[0] = cert; + certData->cert_count = 1; +} - rv = pk11_AddAttributeType(keyObject, CKA_CLASS, &class, sizeof class); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; - } +static void +pk11_CertSetupData(pk11CertData *certData,int count) +{ + certData->max_cert_count = count; - rv = pk11_AddAttributeType(keyObject, CKA_KEY_TYPE, &keyType, sizeof keyType); - if (rv != CKR_OK) { - pk11_FreeObject(keyObject); - return rv; + if (certData->max_cert_count <= 0) { + return; } - - pk11_handleSecretKeyObject(keyObject, keyType, PR_TRUE); - - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - keyObject->handle = slot->tokenIDCount++; - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) - keyObject->slot = slot; - keyObject->objclass = CKO_SECRET_KEY; - pk11_AddSlotObject(slot, keyObject); - - return rv; + certData->certs = (NSSLOWCERTCertificate **) + PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *)); + return; } -#endif /* Fixed DES key */ -/* - * load up our token database - */ -static CK_RV -pk11_importKeyDB(PK11Slot *slot) +static void +pk11_searchCertsAndTrust(PK11Slot *slot, SECItem *derCert, SECItem *name, + SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN, + unsigned long classFlags, PK11SearchResults *handles, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { - keyList keylist; - pk11keyNode *node; - CK_RV crv; - SECStatus rv; - PK11Object *privateKeyObject; - PK11Object *publicKeyObject; - PK11Object *certObject; + NSSLOWCERTCertDBHandle *certHandle = NULL; + pk11CertData certData; + int i; - /* traverse the database, collecting the index keys of all - * records into a linked list - */ - keylist.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if ( keylist.arena == NULL ) { - return CKR_HOST_MEMORY; - } - keylist.head = NULL; - keylist.slot = slot; - - /* collect all of the keys */ - PORT_Assert(slot->keyDB); - rv = nsslowkey_TraverseKeys(slot->keyDB, - add_key_to_list, (void *)&keylist); - if (rv != SECSuccess) { - PORT_FreeArena(keylist.arena, PR_FALSE); - return CKR_HOST_MEMORY; - } + certHandle = slot->certDB; + if (certHandle == NULL) return; + + certData.slot = slot; + certData.max_cert_count = 0; + certData.certs = NULL; + certData.cert_count = 0; + certData.template = pTemplate; + certData.templ_count = ulCount; + certData.classFlags = classFlags; + certData.strict = NSC_STRICT; - /* find certs that match any of the keys */ - PORT_Assert(slot->certDB); - crv = nsslowcert_TraversePermCerts(slot->certDB, - add_cert_to_list, (void *)&keylist); - if ( crv != SECSuccess ) { - PORT_FreeArena(keylist.arena, PR_FALSE); - return CKR_HOST_MEMORY; - } - /* now traverse the list and entry certs/keys into the - * pkcs11 world + /* + * Find the Cert. */ - for (node = keylist.head; node != NULL; node=node->next ) { - /* Check for "special" private key that wraps a symmetric key */ - if (isSecretKey(node->privKey)) { - importSecretKey(slot, node->privKey); - goto end_loop; - } - - /* create the private key object */ - privateKeyObject = pk11_importPrivateKey(slot, node->privKey, - node->pubItem); - if ( privateKeyObject == NULL ) { - goto end_loop; - } + if (derCert->data != NULL) { + NSSLOWCERTCertificate *cert = + nsslowcert_FindCertByDERCert(certHandle,derCert); + pk11_searchSingleCert(&certData,cert); + } else if (name->data != NULL) { + char *tmp_name = (char*)PORT_Alloc(name->len+1); + int count; - publicKeyObject = pk11_importPublicKey(slot, node->privKey, NULL, - node->pubItem); - if ( node->cert ) { - /* Now import the Cert */ - certObject = pk11_importCertificate(slot, node->cert, - node->pubItem->data, - node->pubItem->len, PR_TRUE); - - /* Copy the subject */ - if ( certObject ) { - /* NOTE: cert has been adopted */ - PK11Attribute *attribute; - - /* Copy the Subject */ - attribute = pk11_FindAttribute(certObject,CKA_SUBJECT); - if (attribute) { - pk11_forceAttribute(privateKeyObject, - pk11_attr_expand(&attribute->attrib)); - if (publicKeyObject) { - pk11_forceAttribute(publicKeyObject, - pk11_attr_expand(&attribute->attrib)); - } - pk11_FreeAttribute(attribute); - } - pk11_FreeObject(certObject); - } + if (tmp_name == NULL) { + return; } + PORT_Memcpy(tmp_name,name->data,name->len); + tmp_name[name->len] = 0; - if ( publicKeyObject != NULL ) { - pk11_AddSlotObject(slot, publicKeyObject); - } + count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name); + pk11_CertSetupData(&certData,count); + nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name, + pk11_cert_collect, &certData); + PORT_Free(tmp_name); + } else if (derSubject->data != NULL) { + int count; - pk11_AddSlotObject(slot, privateKeyObject); + count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject); + pk11_CertSetupData(&certData,count); + nsslowcert_TraversePermCertsForSubject(certHandle,derSubject, + pk11_cert_collect, &certData); + } else if ((issuerSN->derIssuer.data != NULL) && + (issuerSN->serialNumber.data != NULL)) { + NSSLOWCERTCertificate *cert = + nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN); -end_loop: - nsslowkey_DestroyPrivateKey(node->privKey); - if ( node->cert ) { - nsslowcert_DestroyCertificate(node->cert); - } - + pk11_searchSingleCert(&certData,cert); + } else { + /* we aren't filtering the certs, we are working on all, so turn + * on the strict filters. */ + certData.strict = PR_TRUE; + pk11_CertSetupData(&certData,NSC_CERT_BLOCK_SIZE); + nsslowcert_TraversePermCerts(certHandle, pk11_cert_collect2, &certData); } - PORT_FreeArena(keylist.arena, PR_FALSE); - - return CKR_OK; -} -/* - * structure to collect certs into - */ -typedef struct pk11CertDataStr { - int cert_count; - int max_cert_count; - NSSLOWCERTCertificate **certs; -} pk11CertData; - -/* - * collect all the certs from the traverse call. - */ -static SECStatus -pk11_cert_collect(NSSLOWCERTCertificate *cert,void *arg) { - pk11CertData *cd = (pk11CertData *)arg; + /* + * build the handles + */ + for (i=0 ; i < certData.cert_count ; i++) { + NSSLOWCERTCertificate *cert = certData.certs[i]; - /* shouldn't happen, but don't crash if it does */ - if (cd->cert_count >= cd->max_cert_count) { - PORT_Assert(0); - return SECFailure; + /* if we filtered it would have been on the stuff above */ + if (classFlags & NSC_CERT) { + pk11_addHandle(handles, + pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_CERT)); + } + if ((classFlags & NSC_TRUST) && nsslowcert_hasTrust(cert)) { + pk11_addHandle(handles, + pk11_mkHandle(slot,&cert->certKey,PK11_TOKEN_TYPE_TRUST)); + } + nsslowcert_DestroyCertificate(cert); } - cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert); - return SECSuccess; + if (certData.certs) PORT_Free(certData.certs); + return; } -/* - * find any certs that may match the template and load them. - */ -static void -pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { +static CK_RV +pk11_searchTokenList(PK11Slot *slot, PK11SearchResults *search, + CK_ATTRIBUTE *pTemplate, CK_LONG ulCount, + PRBool *tokenOnly, PRBool isLoggedIn) +{ int i; + PRBool isKrl = PR_FALSE; SECItem derCert = { siBuffer, NULL, 0 }; SECItem derSubject = { siBuffer, NULL, 0 }; SECItem name = { siBuffer, NULL, 0 }; + SECItem key_id = { siBuffer, NULL, 0 }; + SECItem cert_sha1_hash = { siBuffer, NULL, 0 }; + SECItem cert_md5_hash = { siBuffer, NULL, 0 }; NSSLOWCERTIssuerAndSN issuerSN = { { siBuffer, NULL, 0 }, { siBuffer, NULL, 0 } }; SECItem *copy = NULL; - NSSLOWCERTCertDBHandle *handle = NULL; - NSSLOWKEYDBHandle *keyHandle = NULL; - pk11CertData certData; + unsigned long classFlags = + NSC_CERT|NSC_TRUST|NSC_PRIVATE|NSC_PUBLIC|NSC_KEY|NSC_SMIME ; + /* if we aren't logged in, don't look for private or secret keys */ + if (!isLoggedIn) { + classFlags &= ~(NSC_PRIVATE|NSC_KEY); + } - /* - * These should be stored in the slot some day in the future - */ - handle = slot->certDB; - if (handle == NULL) return; - keyHandle = slot->keyDB; - if (keyHandle == NULL) return; /* * look for things to search on certs for. We only need one of these @@ -3946,139 +3212,216 @@ pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { * (as long as they are user certs). We'll let find objects filter out * the ones that don't apply. */ - for (i=0 ;i < (int)ulCount; i++) { + for (i=0 ;classFlags && i < (int)ulCount; i++) { switch (pTemplate[i].type) { - case CKA_SUBJECT: copy = &derSubject; break; - case CKA_ISSUER: copy = &issuerSN.derIssuer; break; - case CKA_SERIAL_NUMBER: copy = &issuerSN.serialNumber; break; - case CKA_VALUE: copy = &derCert; break; - case CKA_LABEL: copy = &name; break; + case CKA_SUBJECT: + copy = &derSubject; + classFlags &= (NSC_CERT|NSC_PRIVATE|NSC_PUBLIC); + break; + case CKA_ISSUER: + copy = &issuerSN.derIssuer; + classFlags &= (NSC_CERT|NSC_CRL|NSC_TRUST); + break; + case CKA_SERIAL_NUMBER: + copy = &issuerSN.serialNumber; + classFlags &= (NSC_CERT|NSC_TRUST); + break; + case CKA_VALUE: + copy = &derCert; + classFlags &= (NSC_CERT|NSC_CRL); + break; + case CKA_LABEL: + copy = &name; + break; case CKA_CLASS: if (pTemplate[i].ulValueLen != sizeof(CK_OBJECT_CLASS)) { - return; + classFlags = 0; + break;; } - if (*((CK_OBJECT_CLASS *)pTemplate[i].pValue) != CKO_CERTIFICATE) { - return; + switch (*((CK_OBJECT_CLASS *)pTemplate[i].pValue)) { + case CKO_CERTIFICATE: + classFlags &= NSC_CERT; + break; + case CKO_NETSCAPE_TRUST: + classFlags &= NSC_CERT; + break; + case CKO_NETSCAPE_CRL: + classFlags &= NSC_CERT; + break; + case CKO_PRIVATE_KEY: + classFlags &= NSC_PRIVATE; + break; + case CKO_PUBLIC_KEY: + classFlags &= NSC_PUBLIC; + break; + case CKO_SECRET_KEY: + classFlags &= NSC_KEY; + break; + default: + classFlags = 0; + break; } - copy = NULL; break; + break; case CKA_PRIVATE: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { - return; + classFlags = 0; + } + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + classFlags &= (NSC_PRIVATE|NSC_KEY); + } else { + classFlags &= ~(NSC_PRIVATE|NSC_KEY); + } + break; + case CKA_SENSITIVE: + if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { + classFlags = 0; } - if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_FALSE) { - return; + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + classFlags &= (NSC_PRIVATE|NSC_KEY); + } else { + classFlags = 0; } - copy = NULL; break; + break; case CKA_TOKEN: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { - return; + classFlags = 0; } - if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) { - return; + if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { + *tokenOnly = PR_TRUE; + } else { + classFlags = 0; } - copy = NULL; break; + break; + case CKA_CERT_SHA1_HASH: + classFlags &= NSC_TRUST; + copy = &cert_sha1_hash; break; + case CKA_CERT_MD5_HASH: + classFlags &= NSC_TRUST; + copy = &cert_md5_hash; break; case CKA_CERTIFICATE_TYPE: + if (pTemplate[i].ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) { + classFlags = 0; + } + classFlags &= NSC_CERT; + if (*((CK_CERTIFICATE_TYPE *)pTemplate[i].pValue) != CKC_X_509) { + classFlags = 0; + } + break; case CKA_ID: + copy = &key_id; break; + case CKA_NETSCAPE_KRL: + classFlags &= NSC_CRL; + isKrl = PR_TRUE; + break; case CKA_MODIFIABLE: - copy = NULL; break; + break; + case CKA_KEY_TYPE: + case CKA_DERIVE: + classFlags &= NSC_PUBLIC|NSC_PRIVATE|NSC_KEY; + break; + case CKA_VERIFY_RECOVER: + classFlags &= NSC_PUBLIC; + break; + case CKA_SIGN_RECOVER: + classFlags &= NSC_PRIVATE; + break; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_WRAP: + classFlags &= NSC_PUBLIC|NSC_KEY; + break; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_UNWRAP: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + case CKA_NEVER_EXTRACTABLE: + classFlags &= NSC_PRIVATE|NSC_KEY; + break; /* can't be a certificate if it doesn't match one of the above * attributes */ - default: return; + default: + classFlags = 0; + break; } if (copy) { copy->data = (unsigned char*)pTemplate[i].pValue; copy->len = pTemplate[i].ulValueLen; } + copy = NULL; } - certData.max_cert_count = 0; - certData.certs = NULL; - certData.cert_count = 0; - if (derCert.data != NULL) { - NSSLOWCERTCertificate *cert = nsslowcert_FindCertByDERCert(handle,&derCert); - if (cert != NULL) { - certData.certs = - (NSSLOWCERTCertificate **) PORT_Alloc(sizeof (NSSLOWCERTCertificate *)); - if (certData.certs) { - certData.certs[0] = cert; - certData.cert_count = 1; - } else nsslowcert_DestroyCertificate(cert); - } - } else if (name.data != NULL) { - char *tmp_name = (char*)PORT_Alloc(name.len+1); + /* certs */ + if (classFlags & (NSC_CERT|NSC_TRUST)) { + pk11_searchCertsAndTrust(slot,&derCert,&name,&derSubject, + &issuerSN,classFlags,search, + pTemplate, ulCount); + } - if (tmp_name == NULL) { - return; - } - PORT_Memcpy(tmp_name,name.data,name.len); - tmp_name[name.len] = 0; - - certData.max_cert_count=nsslowcert_NumPermCertsForNickname(handle,tmp_name); - if (certData.max_cert_count > 0) { - certData.certs = (NSSLOWCERTCertificate **) - PORT_Alloc(certData.max_cert_count *sizeof(NSSLOWCERTCertificate *)); - if (certData.certs) { - nsslowcert_TraversePermCertsForNickname(handle,tmp_name, - pk11_cert_collect, &certData); - } - + /* 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; } - PORT_Free(tmp_name); - } else if (derSubject.data != NULL) { - certData.max_cert_count=nsslowcert_NumPermCertsForSubject(handle,&derSubject); - if (certData.max_cert_count > 0) { - certData.certs = (NSSLOWCERTCertificate **) - PORT_Alloc(certData.max_cert_count *sizeof(NSSLOWCERTCertificate *)); - if (certData.certs) { - nsslowcert_TraversePermCertsForSubject(handle,&derSubject, - pk11_cert_collect, &certData); + 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; } } - } else if ((issuerSN.derIssuer.data != NULL) && - (issuerSN.serialNumber.data != NULL)) { - NSSLOWCERTCertificate *cert = nsslowcert_FindCertByIssuerAndSN(handle,&issuerSN); - - if (cert != NULL) { - certData.certs = - (NSSLOWCERTCertificate **) PORT_Alloc(sizeof (NSSLOWCERTCertificate *)); - if (certData.certs) { - certData.certs[0] = cert; - certData.cert_count = 1; - } else nsslowcert_DestroyCertificate(cert); - } - } else { - /* PORT_Assert(0); may get called when not looking for certs */ - /* look up all the certs sometime, and get rid of the assert */; + 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; -/* we need to search on email address and S/MIME data */ -/* we also need to add CRL searching code */ -/* we also need to add TRUST searching code */ + nsslowkey_TraverseKeys(keyHandle, pk11_key_collect, &keyData); } +key_loser: + /* crl's */ + if (classFlags & NSC_CRL) { + NSSLOWCERTCertDBHandle *certHandle = NULL; - for (i=0 ; i < certData.cert_count ; i++) { - NSSLOWCERTCertificate *cert = certData.certs[i]; - - /* we are only interested in permanment user certs here */ - if ((cert->trust) && - (( cert->trust->sslFlags & CERTDB_USER ) || - ( cert->trust->emailFlags & CERTDB_USER ) || - ( cert->trust->objectSigningFlags & CERTDB_USER )) && - ( cert->nickname != NULL ) && - (nsslowkey_KeyForCertExists(keyHandle, cert) == SECSuccess)) { - PK11Object *obj; - pk11_importCertificate(slot, cert, NULL, 0, PR_FALSE); - obj = pk11_importPublicKey(slot, NULL, cert, NULL); - if (obj) pk11_AddSlotObject(slot, obj); + certHandle = slot->certDB; + if (certHandle == NULL) { + goto crl_loser; } - nsslowcert_DestroyCertificate(cert); + 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); + } } - if (certData.certs) PORT_Free(certData.certs); +crl_loser: + /* Add S/MIME entry stuff */ - return; + return CKR_OK; } @@ -4087,74 +3430,51 @@ pk11_searchCerts(PK11Slot *slot, CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) { CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount) { - PK11ObjectListElement *objectList = NULL; - PK11ObjectListElement *olp; PK11SearchResults *search,*freeSearch; - PK11Session *session; + PK11Session *session = NULL; PK11Slot *slot = pk11_SlotFromSessionHandle(hSession); + PRBool tokenOnly = PR_FALSE; int count, i; - CK_RV crv; + CK_RV crv = CKR_OK; + PRBool isLoggedIn; session = pk11_SessionFromHandle(hSession); if (session == NULL) { - return CKR_SESSION_HANDLE_INVALID; - } - - /* resync token objects with the data base */ - if ((session->info.slotID == PRIVATE_KEY_SLOT_ID) || - (session->info.slotID == FIPS_SLOT_ID)) { - if (slot->DB_loaded == PR_FALSE) { - /* if we aren't logged in, we can't unload all key keys - * and certs. Just unload those certs we need for this search - */ - if ((!slot->isLoggedIn) && (slot->needLogin)) { - pk11_searchCerts(slot,pTemplate,ulCount); - } else { - pk11_importKeyDB(slot); - slot->DB_loaded = PR_TRUE; - } - } - } - - - /* build list of found objects in the session */ - crv = pk11_searchObjectList(&objectList,slot->tokObjects, - slot->objectLock, pTemplate, ulCount, (PRBool)((!slot->needLogin) || - slot->isLoggedIn)); - if (crv != CKR_OK) { - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return crv; - } - - - /* copy list to session */ - count = 0; - for (olp = objectList; olp != NULL; olp = olp->next) { - count++; + crv = CKR_SESSION_HANDLE_INVALID; + goto loser; } + search = (PK11SearchResults *)PORT_Alloc(sizeof(PK11SearchResults)); if (search == NULL) { - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto loser; } search->handles = (CK_OBJECT_HANDLE *) - PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * count); + PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * NSC_SEARCH_BLOCK_SIZE); if (search->handles == NULL) { - PORT_Free(search); - pk11_FreeObjectList(objectList); - pk11_FreeSession(session); - return CKR_HOST_MEMORY; + crv = CKR_HOST_MEMORY; + goto loser; + } + search->index = 0; + search->size = 0; + search->array_size = NSC_SEARCH_BLOCK_SIZE; + isLoggedIn = (PRBool)((!slot->needLogin) || slot->isLoggedIn); + + crv = pk11_searchTokenList(slot, search, pTemplate, ulCount, &tokenOnly, + isLoggedIn); + if (crv != CKR_OK) { + goto loser; } - for (i=0; i < count; i++) { - search->handles[i] = objectList->object->handle; - objectList = pk11_FreeObjectListElement(objectList); + + /* build list of found objects in the session */ + if (!tokenOnly) { + crv = pk11_searchObjectList(search, slot->tokObjects, + slot->objectLock, pTemplate, ulCount, isLoggedIn); + } + if (crv != CKR_OK) { + goto loser; } - /* store the search info */ - search->index = 0; - search->size = count; if ((freeSearch = session->search) != NULL) { session->search = NULL; pk11_FreeSearch(freeSearch); @@ -4162,6 +3482,15 @@ CK_RV NSC_FindObjectsInit(CK_SESSION_HANDLE hSession, session->search = search; pk11_FreeSession(session); return CKR_OK; + +loser: + if (freeSearch) { + pk11_FreeSearch(freeSearch); + } + if (session) { + pk11_FreeSession(session); + } + return crv; } diff --git a/security/nss/lib/softoken/pkcs11.h b/security/nss/lib/softoken/pkcs11.h index 9ada2625e..9b54421e7 100644 --- a/security/nss/lib/softoken/pkcs11.h +++ b/security/nss/lib/softoken/pkcs11.h @@ -16,7 +16,7 @@ * Copyright (C) 1994-2000 Netscape Communications Corporation. All * Rights Reserved. * - * Contributor(s): + * Contributor(s): RSA Labs * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -35,6 +35,9 @@ * is granted provided that it is identified as "RSA Security In.c Public-Key * Cryptography Standards (PKCS)" in all material mentioning or referencing * this document. + * + * The latest version of this header can be found at: + * http://www.rsalabs.com/pkcs/pkcs-11/index.html */ #ifndef _PKCS11_H_ #define _PKCS11_H_ 1 @@ -313,12 +316,4 @@ struct CK_FUNCTION_LIST { } #endif -/* -** Functions called directly by applications to configure the FIPS token. -*/ -extern void PK11_ConfigurePKCS11(char *man, char *libdes, char *tokdes, - char *ptokdes, char *slotdes, char *pslotdes, char *fslotdes, - char *fpslotdes, int minPwd, int pwdRequired); -extern void PK11_ConfigureFIPS(char *slotdes, char *pslotdes); - #endif diff --git a/security/nss/lib/softoken/pkcs11c.c b/security/nss/lib/softoken/pkcs11c.c index d702c1452..f1ab1df0c 100644 --- a/security/nss/lib/softoken/pkcs11c.c +++ b/security/nss/lib/softoken/pkcs11c.c @@ -1448,17 +1448,19 @@ pk11_HMACCmp(CK_ULONG *copyLen,unsigned char *sig,unsigned int sigLen, * common HMAC initalization routine */ static CK_RV -pk11_doHMACInit(PK11SessionContext *context,SECOidTag oid, +pk11_doHMACInit(PK11SessionContext *context,HASH_HashType hash, PK11Object *key, CK_ULONG mac_size) { PK11Attribute *keyval; HMACContext *HMACcontext; CK_ULONG *intpointer; + const SECHashObject *hashObj = &SECRawHashObjects[hash]; keyval = pk11_FindAttribute(key,CKA_VALUE); if (keyval == NULL) return CKR_KEY_SIZE_RANGE; - HMACcontext = HMAC_Create(oid, (const unsigned char*)keyval->attrib.pValue, + HMACcontext = HMAC_Create(hashObj, + (const unsigned char*)keyval->attrib.pValue, keyval->attrib.ulValueLen); context->hashInfo = HMACcontext; context->multi = PR_TRUE; @@ -2103,25 +2105,25 @@ finish_rsa: break; case CKM_MD2_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key, + crv = pk11_doHMACInit(context,HASH_AlgMD2,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD2_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH); break; case CKM_MD5_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key, + crv = pk11_doHMACInit(context,HASH_AlgMD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD5_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH); break; case CKM_SHA_1_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key, + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SHA_1_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); break; case CKM_SSL3_MD5_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key, @@ -2508,25 +2510,25 @@ finish_rsa: break; case CKM_MD2_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key, + crv = pk11_doHMACInit(context,HASH_AlgMD2,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD2_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD2,key,MD2_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD2,key,MD2_LENGTH); break; case CKM_MD5_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key, + crv = pk11_doHMACInit(context,HASH_AlgMD5,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_MD5_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_MD5,key,MD5_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgMD5,key,MD5_LENGTH); break; case CKM_SHA_1_HMAC_GENERAL: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key, + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key, *(CK_ULONG *)pMechanism->pParameter); break; case CKM_SHA_1_HMAC: - crv = pk11_doHMACInit(context,SEC_OID_SHA1,key,SHA1_LENGTH); + crv = pk11_doHMACInit(context,HASH_AlgSHA1,key,SHA1_LENGTH); break; case CKM_SSL3_MD5_MAC: crv = pk11_doSSLMACInit(context,SEC_OID_MD5,key, @@ -2755,105 +2757,52 @@ CK_RV NSC_GenerateRandom(CK_SESSION_HANDLE hSession, **************************** Key Functions: ************************ */ -CK_RV -pk11_pbe_hmac_key_gen(CK_MECHANISM_PTR pMechanism, char *buf, - unsigned long *len, PRBool faultyPBE3DES) -{ - PBEBitGenContext *pbeCx; - SECItem pwd, salt, *key; - SECOidTag hashAlg; - unsigned long keylenbits; - CK_PBE_PARAMS *pbe_params = NULL; - pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - pwd.data = (unsigned char *)pbe_params->pPassword; - pwd.len = (unsigned int)pbe_params->ulPasswordLen; - salt.data = (unsigned char *)pbe_params->pSalt; - salt.len = (unsigned int)pbe_params->ulSaltLen; - switch (pMechanism->mechanism) { - case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: - hashAlg = SEC_OID_SHA1; keylenbits = 160; break; - case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: - hashAlg = SEC_OID_MD5; keylenbits = 128; break; - case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - hashAlg = SEC_OID_MD2; keylenbits = 128; break; - default: - return CKR_MECHANISM_INVALID; - } - pbeCx = PBE_CreateContext(hashAlg, pbeBitGenIntegrityKey, &pwd, - &salt, keylenbits, pbe_params->ulIteration); - key = PBE_GenerateBits(pbeCx); - PORT_Memcpy(buf, key->data, key->len); - *len = key->len; - PBE_DestroyContext(pbeCx); - SECITEM_ZfreeItem(key, PR_TRUE); - return CKR_OK; -} /* * generate a password based encryption key. This code uses - * PKCS5 to do the work. Note that it calls PBE_PK11ParamToAlgid, which is - * a utility function in secpkcs5.c. This function is used in here - * and in PK11_ParamToAlgid. + * PKCS5 to do the work. */ -CK_RV -pk11_pbe_key_gen(SECOidTag algtag,CK_MECHANISM_PTR pMechanism, - char *buf,CK_ULONG *key_length, PRBool faulty3DES) +static CK_RV +nsc_pbe_key_gen(NSSPKCS5PBEParameter *pkcs5_pbe, CK_MECHANISM_PTR pMechanism, + char *buf, CK_ULONG *key_length, PRBool faulty3DES) { SECAlgorithmID algid; - SECItem *pbe_key = NULL, mech; + SECItem *pbe_key = NULL, iv, pwitem; CK_PBE_PARAMS *pbe_params = NULL; SECStatus pbe_rv; *key_length = 0; + iv.data = NULL; iv.len = 0; - mech.data = (unsigned char *)pMechanism->pParameter; - mech.len = (unsigned int)pMechanism->ulParameterLen; - - /* A common routine to map from Params to AlgIDs for PBE - * algorithms was created in secpkcs5.c. This function is - * called both by PK11_ParamToAlgid and this function. - */ - pbe_rv = PBE_PK11ParamToAlgid(algtag, &mech, NULL, &algid); - if (pbe_rv != SECSuccess) { - return CKR_DATA_INVALID; - } pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; - mech.data = (unsigned char *)pbe_params->pPassword; - mech.len = (unsigned int)pbe_params->ulPasswordLen; - pbe_key = SEC_PKCS5GetKey(&algid, &mech, faulty3DES); + + pwitem.data = (unsigned char *)pbe_params->pPassword; + pwitem.len = (unsigned int)pbe_params->ulPasswordLen; + pbe_key = nsspkcs5_ComputeKeyAndIV(pkcs5_pbe, &pwitem, &iv, faulty3DES); if (pbe_key == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); return CKR_HOST_MEMORY; } + PORT_Memcpy(buf, pbe_key->data, pbe_key->len); *key_length = pbe_key->len; SECITEM_ZfreeItem(pbe_key, PR_TRUE); pbe_key = NULL; - if (pbe_params->pInitVector == NULL) { - pbe_key = SEC_PKCS5GetIV(&algid, &mech, faulty3DES); - if (pbe_key == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); - SECITEM_ZfreeItem(pbe_key, PR_TRUE); - return CKR_HOST_MEMORY; - } + if (iv.data && pbe_params->pInitVector == NULL) { pbe_params->pInitVector = (CK_CHAR_PTR)PORT_ZAlloc(pbe_key->len); if (pbe_params->pInitVector == NULL) { - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); - SECITEM_ZfreeItem(pbe_key, PR_TRUE); return CKR_HOST_MEMORY; } - PORT_Memcpy(pbe_params->pInitVector, pbe_key->data, pbe_key->len); + PORT_Memcpy(pbe_params->pInitVector, iv.data, iv.len); } - SECITEM_ZfreeItem(pbe_key, PR_TRUE); - SECOID_DestroyAlgorithmID(&algid, PR_FALSE); return CKR_OK; } static CK_RV -nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, - CK_KEY_TYPE *key_type,CK_ULONG *key_length) { +nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, CK_KEY_TYPE *key_type, + CK_ULONG *key_length) +{ CK_RV crv = CKR_OK; switch (mechanism) { @@ -2904,81 +2853,112 @@ nsc_SetupBulkKeyGen(CK_MECHANISM_TYPE mechanism, return crv; } +CK_RV +nsc_SetupHMACKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe) +{ + SECItem pwd, salt, *key; + HASH_HashType hashType; + unsigned long keylenbits; + CK_PBE_PARAMS *pbe_params = NULL; + NSSPKCS5PBEParameter *params; + PRArenaPool *arena = NULL; + SECStatus rv; + + *pbe == NULL; + + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) { + return CKR_HOST_MEMORY; + } + + params = (NSSPKCS5PBEParameter *) PORT_ArenaZAlloc(arena, + sizeof(NSSPKCS5PBEParameter)); + if (params == NULL) { + PORT_FreeArena(arena,PR_TRUE); + return CKR_HOST_MEMORY; + } + + params->ivLen = 0; + params->pbeType = NSSPKCS5_PKCS12_V2; + params->hashType = HASH_AlgSHA1; + params->encAlg = SEC_OID_SHA1; /* any invalid value */ + params->is2KeyDES = PR_FALSE; + params->keyID = pbeBitGenIntegrityKey; + params->iter = pbe_params->ulIteration; + + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + salt.data = (unsigned char *)pbe_params->pSalt; + salt.len = (unsigned int)pbe_params->ulSaltLen; + rv = SECITEM_CopyItem(arena,¶ms->salt,&salt); + if (rv != SECSuccess) { + PORT_FreeArena(arena,PR_TRUE); + return CKR_HOST_MEMORY; + } + switch (pMechanism->mechanism) { + case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: + params->hashType = HASH_AlgSHA1; + params->keyLen = 20; + break; + case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD5; + params->keyLen = 16; + break; + case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: + params->hashType = HASH_AlgMD2; + params->keyLen = 16; + break; + default: + PORT_FreeArena(arena,PR_TRUE); + return CKR_MECHANISM_INVALID; + } + *pbe = params; + return CKR_OK; +} +/* maybe this should be table driven? */ static CK_RV -nsc_SetupPBEKeyGen(CK_MECHANISM_TYPE mechanism,SECOidTag *algtag, - CK_KEY_TYPE *key_type,CK_ULONG *key_length) { +nsc_SetupPBEKeyGen(CK_MECHANISM_PTR pMechanism, NSSPKCS5PBEParameter **pbe, + CK_KEY_TYPE *key_type) +{ CK_RV crv = CKR_OK; + SECOidData *oid; + CK_PBE_PARAMS *pbe_params; + NSSPKCS5PBEParameter *params; + SECItem salt; - switch (mechanism) { - case CKM_PBE_MD2_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC; + oid = SECOID_FindOIDByMechanism(pMechanism->mechanism); + if (oid == NULL) { + return CKR_MECHANISM_INVALID; + } + + pbe_params = (CK_PBE_PARAMS *)pMechanism->pParameter; + salt.data = (unsigned char *)pbe_params->pSalt; + salt.len = (unsigned int)pbe_params->ulSaltLen; + + params=nsspkcs5_NewParam(oid->offset, &salt, pbe_params->ulIteration); + if (params == NULL) { + return CKR_MECHANISM_INVALID; + } + + + switch (params->encAlg) { + case SEC_OID_DES_CBC: *key_type = CKK_DES; break; + case SEC_OID_DES_EDE3_CBC: + *key_type = params->is2KeyDES ? CKK_DES2 : CKK_DES3; case CKM_PBE_MD5_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC; *key_type = CKK_DES; break; - case CKM_PBE_SHA1_RC4_40: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; - *key_length = 5; + case SEC_OID_RC2_CBC: *key_type = CKK_RC4; break; - case CKM_PBE_SHA1_RC4_128: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; - *key_length = 16; - *key_type = CKK_RC4; - break; - case CKM_PBE_SHA1_RC2_40_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - *key_length = 5; - *key_type = CKK_RC2; - break; - case CKM_PBE_SHA1_RC2_128_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - *key_length = 16; - *key_type = CKK_RC2; - break; - case CKM_PBE_SHA1_DES3_EDE_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; - *key_length = 24; - *key_type = CKK_DES3; - break; - case CKM_PBE_SHA1_DES2_EDE_CBC: - *algtag = SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; - *key_length = 16; - *key_type = CKK_DES2; - break; - case CKM_NETSCAPE_PBE_SHA1_DES_CBC: - *algtag = SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; - *key_type = CKK_DES; - break; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC; - *key_type = CKK_DES3; - break; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - *key_type = CKK_RC2; - break; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - *key_type = CKK_RC2; - break; - case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4; - *key_type = CKK_RC4; - break; - case CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4: - *algtag = SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4; + case SEC_OID_RC4: *key_type = CKK_RC4; break; default: - PORT_Assert(0); crv = CKR_MECHANISM_INVALID; break; } - return crv; } @@ -2998,8 +2978,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, int i; PK11Slot *slot = pk11_SlotFromSessionHandle(hSession); char buf[MAX_KEY_LEN]; - enum {pk11_pbe, pk11_pbe_hmac, pk11_ssl, pk11_bulk} key_gen_type; - SECOidTag algtag = SEC_OID_UNKNOWN; + enum {nsc_pbe, nsc_ssl, nsc_bulk} key_gen_type; + NSSPKCS5PBEParameter *pbe_param; SSL3RSAPreMasterSecret *rsa_pms; CK_VERSION *version; /* in very old versions of NSS, there were implementation errors with key @@ -3040,7 +3020,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, pk11_DeleteAttributeType(key,CKA_VALUE); /* Now Set up the parameters to generate the key (based on mechanism) */ - key_gen_type = pk11_bulk; /* bulk key by default */ + key_gen_type = nsc_bulk; /* bulk key by default */ switch (pMechanism->mechanism) { case CKM_CDMF_KEY_GEN: case CKM_DES_KEY_GEN: @@ -3059,16 +3039,17 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, case CKM_SSL3_PRE_MASTER_KEY_GEN: key_type = CKK_GENERIC_SECRET; key_length = 48; - key_gen_type = pk11_ssl; + key_gen_type = nsc_ssl; break; - case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: - faultyPBE3DES = PR_TRUE; case CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN: case CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN: - key_gen_type = pk11_pbe_hmac; + key_gen_type = nsc_pbe; key_type = CKK_GENERIC_SECRET; + crv = nsc_SetupHMACKeyGen(pMechanism, &pbe_param); break; + case CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC: + faultyPBE3DES = PR_TRUE; case CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC: case CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC: case CKM_NETSCAPE_PBE_SHA1_DES_CBC: @@ -3083,9 +3064,8 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, case CKM_PBE_SHA1_RC4_40: case CKM_PBE_MD5_DES_CBC: case CKM_PBE_MD2_DES_CBC: - key_gen_type = pk11_pbe; - crv = nsc_SetupPBEKeyGen(pMechanism->mechanism,&algtag, - &key_type,&key_length); + key_gen_type = nsc_pbe; + crv = nsc_SetupPBEKeyGen(pMechanism,&pbe_param, &key_type); break; default: crv = CKR_MECHANISM_INVALID; @@ -3109,15 +3089,11 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, * now to the actual key gen. */ switch (key_gen_type) { - case pk11_pbe_hmac: - crv = pk11_pbe_hmac_key_gen(pMechanism, buf, &key_length, - faultyPBE3DES); - break; - case pk11_pbe: - crv = pk11_pbe_key_gen(algtag, pMechanism, buf, &key_length, + case nsc_pbe: + crv = nsc_pbe_key_gen(pbe_param, pMechanism, buf, &key_length, faultyPBE3DES); break; - case pk11_ssl: + case nsc_ssl: rsa_pms = (SSL3RSAPreMasterSecret *)buf; version = (CK_VERSION *)pMechanism->pParameter; rsa_pms->client_version[0] = version->major; @@ -3125,7 +3101,7 @@ CK_RV NSC_GenerateKey(CK_SESSION_HANDLE hSession, crv = NSC_GenerateRandom(0,&rsa_pms->random[0], sizeof(rsa_pms->random)); break; - case pk11_bulk: + case nsc_bulk: /* get the key, check for weak keys and repeat if found */ do { crv = NSC_GenerateRandom(0, (unsigned char *)buf, key_length); @@ -3609,7 +3585,7 @@ static SECItem *pk11_PackagePrivateKey(PK11Object *key) } dummy = SEC_ASN1EncodeInteger(arena, &pki->version, - SEC_PRIVATE_KEY_INFO_VERSION); + NSSLOWKEY_PRIVATE_KEY_INFO_VERSION); if(!dummy) { rv = SECFailure; goto loser; @@ -4080,10 +4056,10 @@ pk11_buildSSLKey(CK_SESSION_HANDLE hSession, PK11Object *baseKey, /* * now lets create an object to hang the attributes off of */ - *keyHandle = CK_INVALID_KEY; + *keyHandle = CK_INVALID_HANDLE; key = pk11_NewObject(baseKey->slot); if (key == NULL) return CKR_HOST_MEMORY; - key->wasDerived = PR_TRUE; + pk11_narrowToSessionObject(key)->wasDerived = PR_TRUE; crv = pk11_CopyObject(key,baseKey); if (crv != CKR_OK) goto loser; @@ -4131,16 +4107,16 @@ loser: static void pk11_freeSSLKeys(CK_SESSION_HANDLE session, CK_SSL3_KEY_MAT_OUT *returnedMaterial ) { - if (returnedMaterial->hClientMacSecret != CK_INVALID_KEY) { + if (returnedMaterial->hClientMacSecret != CK_INVALID_HANDLE) { NSC_DestroyObject(session,returnedMaterial->hClientMacSecret); } - if (returnedMaterial->hServerMacSecret != CK_INVALID_KEY) { + if (returnedMaterial->hServerMacSecret != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hServerMacSecret); } - if (returnedMaterial->hClientKey != CK_INVALID_KEY) { + if (returnedMaterial->hClientKey != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hClientKey); } - if (returnedMaterial->hServerKey != CK_INVALID_KEY) { + if (returnedMaterial->hServerKey != CK_INVALID_HANDLE) { NSC_DestroyObject(session, returnedMaterial->hServerKey); } } @@ -4233,7 +4209,7 @@ pk11_MapKeySize(CK_KEY_TYPE keyType) { /* TLS P_hash function */ static SECStatus -pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, +pk11_P_hash(HASH_HashType hashType, const SECItem *secret, const char *label, SECItem *seed, SECItem *result) { unsigned char state[PHASH_STATE_MAX_LEN]; @@ -4244,6 +4220,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, SECStatus status; HMACContext *cx; SECStatus rv = SECFailure; + const SECHashObject *hashObj = &SECRawHashObjects[hashType]; PORT_Assert((secret != NULL) && (secret->data != NULL || !secret->len)); PORT_Assert((seed != NULL) && (seed->data != NULL)); @@ -4255,7 +4232,7 @@ pk11_P_hash(SECOidTag alg, const SECItem *secret, const char *label, if (label != NULL) label_len = PORT_Strlen(label); - cx = HMAC_Create(alg, secret->data, secret->len); + cx = HMAC_Create(hashObj, secret->data, secret->len); if (cx == NULL) goto loser; @@ -4330,11 +4307,11 @@ pk11_PRF(const SECItem *secret, const char *label, SECItem *seed, goto loser; tmp.len = result->len; - status = pk11_P_hash(SEC_OID_MD5, &S1, label, seed, result); + status = pk11_P_hash(HASH_AlgMD5, &S1, label, seed, result); if (status != SECSuccess) goto loser; - status = pk11_P_hash(SEC_OID_SHA1, &S2, label, seed, &tmp); + status = pk11_P_hash(HASH_AlgSHA1, &S2, label, seed, &tmp); if (status != SECSuccess) goto loser; @@ -4404,7 +4381,7 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, /* * now lets create an object to hang the attributes off of */ - if (phKey) *phKey = CK_INVALID_KEY; + if (phKey) *phKey = CK_INVALID_HANDLE; key = pk11_NewObject(slot); /* fill in the handle later */ if (key == NULL) { @@ -4513,9 +4490,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, ssl3_master = (CK_SSL3_MASTER_KEY_DERIVE_PARAMS *) pMechanism->pParameter; if (ssl3_master->pVersion) { + PK11SessionObject *sessKey = pk11_narrowToSessionObject(key); rsa_pms = (SSL3RSAPreMasterSecret *) att->attrib.pValue; /* don't leak more key material then necessary for SSL to work */ - if (key->wasDerived) { + if ((sessKey == NULL) || sessKey->wasDerived) { ssl3_master->pVersion->major = 0xff; ssl3_master->pVersion->minor = 0xff; } else { @@ -4652,10 +4630,10 @@ CK_RV NSC_DeriveKey( CK_SESSION_HANDLE hSession, * clear out our returned keys so we can recover on failure */ ssl3_keys_out = ssl3_keys->pReturnedKeyMaterial; - ssl3_keys_out->hClientMacSecret = CK_INVALID_KEY; - ssl3_keys_out->hServerMacSecret = CK_INVALID_KEY; - ssl3_keys_out->hClientKey = CK_INVALID_KEY; - ssl3_keys_out->hServerKey = CK_INVALID_KEY; + ssl3_keys_out->hClientMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hServerMacSecret = CK_INVALID_HANDLE; + ssl3_keys_out->hClientKey = CK_INVALID_HANDLE; + ssl3_keys_out->hServerKey = CK_INVALID_HANDLE; /* * generate the key material: This looks amazingly similar to the @@ -5222,8 +5200,10 @@ key_and_mac_derive_fail: /* link the key object into the list */ if (key) { + PK11SessionObject *sessKey = pk11_narrowToSessionObject(key); + PORT_Assert(sessKey); /* get the session */ - key->wasDerived = PR_TRUE; + sessKey->wasDerived = PR_TRUE; session = pk11_SessionFromHandle(hSession); if (session == NULL) { pk11_FreeObject(key); diff --git a/security/nss/lib/softoken/pkcs11f.h b/security/nss/lib/softoken/pkcs11f.h index 71ee2676a..70d34da5e 100644 --- a/security/nss/lib/softoken/pkcs11f.h +++ b/security/nss/lib/softoken/pkcs11f.h @@ -150,10 +150,11 @@ CK_PKCS11_FUNCTION_INFO(C_GetMechanismInfo) CK_PKCS11_FUNCTION_INFO(C_InitToken) #ifdef CK_NEED_ARG_LIST ( - CK_SLOT_ID slotID, /* ID of the token's slot */ - CK_CHAR_PTR pPin, /* the SO's initial PIN */ - CK_ULONG ulPinLen, /* length in bytes of the PIN */ - CK_CHAR_PTR pLabel /* 32-byte token label (blank padded) */ +/* pLabel changed from CK_CHAR_PTR to CK_UTF8CHAR_PTR for v2.10 */ + CK_SLOT_ID slotID, /* ID of the token's slot */ + CK_CHAR_PTR pPin, /* the SO's initial PIN */ + CK_ULONG ulPinLen, /* length in bytes of the PIN */ + CK_UTF8CHAR_PTR pLabel /* 32-byte token label (blank padded) */ ); #endif diff --git a/security/nss/lib/softoken/pkcs11i.h b/security/nss/lib/softoken/pkcs11i.h index bada687f7..102fb5738 100644 --- a/security/nss/lib/softoken/pkcs11i.h +++ b/security/nss/lib/softoken/pkcs11i.h @@ -43,11 +43,61 @@ #include "pkcs11t.h" #include "pcertt.h" -#define PKCS11_USE_THREADS -#define NO_ARENA -#define MAX_OBJS_ATTRS 45 -#define ATTR_SPACE 50 /* hold up to a SSL premaster secret */ +/* + * Configuration Defines + * + * The following defines affect the space verse speed trade offs of + * the PKCS #11 module. For the most part the current settings are optimized + * for web servers, where we want faster speed and lower lock contention at + * the expense of space. + */ + +#define PKCS11_USE_THREADS /* set to true of you are need threads */ +/* + * Attribute Allocation strategy: + * + * 1) static allocation (PKCS11_STATIC_ATTRIBUTES set + * PKCS11_REF_COUNT_ATTRIBUTES not set) + * Attributes are pre-allocated as part of the session object and used from + * the object array. + * + * 2) heap allocation with ref counting (PKCS11_STATIC_ATTRIBUTES not set + * PKCS11_REF_COUNT_ATTRIBUTES set) + * Attributes are allocated from the heap when needed and freed when their + * reference count goes to zero. + * + * 3) arena allocation (PKCS11_STATIC_ATTRIBUTES not set + * PKCS11_REF_COUNT_ATTRIBUTE not set) + * Attributes are allocated from the arena when needed and freed only when + * the object goes away. + */ +#define PKCS11_STATIC_ATTRIBUTES +/*#define PKCS11_REF_COUNT_ATTRIBUTES */ +/* the next two are only active if PKCS11_STATIC_ATTRIBUTES is set */ +#define MAX_OBJS_ATTRS 45 /* number of attributes to preallocate in + * the object (must me the absolute max) */ +#define ATTR_SPACE 50 /* Maximum size of attribute data before extra + * data needs to be allocated. This is set to + * enough space to hold an SSL MASTER secret */ + +#define NSC_STRICT PR_FALSE /* forces the code to do strict template + * matching when doing C_FindObject on token + * objects. This will slow down search in + * NSS. */ +/* default search block allocations and increments */ +#define NSC_CERT_BLOCK_SIZE 50 +#define NSC_SEARCH_BLOCK_SIZE 5 +/* 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 +#define SESSION_OBJECT_HASH_SIZE 32 +#define TOKEN_OBJECT_HASH_SIZE 1024 +#define SESSION_HASH_SIZE 512 +#define MAX_OBJECT_LIST_SIZE 800 /* how many objects to keep on the free list + * before we start freeing them */ +#define MAX_KEY_LEN 256 + #ifdef PKCS11_USE_THREADS @@ -61,6 +111,8 @@ typedef struct PK11AttributeStr PK11Attribute; typedef struct PK11ObjectListStr PK11ObjectList; typedef struct PK11ObjectListElementStr PK11ObjectListElement; typedef struct PK11ObjectStr PK11Object; +typedef struct PK11SessionObjectStr PK11SessionObject; +typedef struct PK11TokenObjectStr PK11TokenObject; typedef struct PK11SessionStr PK11Session; typedef struct PK11SlotStr PK11Slot; typedef struct PK11SessionContextStr PK11SessionContext; @@ -79,17 +131,6 @@ typedef void (*PK11Hash)(void *,void *,unsigned int); typedef void (*PK11End)(void *,void *,unsigned int *,unsigned int); typedef void (*PK11Free)(void *); -/* - * 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 -#define SESSION_OBJECT_HASH_SIZE 32 -#define TOKEN_OBJECT_HASH_SIZE 1024 -#define SESSION_HASH_SIZE 512 -#define MAX_KEY_LEN 256 -#define MAX_OBJECT_LIST_SIZE 800 - /* Value to tell if an attribute is modifiable or not. * NEVER: attribute is only set on creation. * ONCOPY: attribute is set on creation and can only be changed on copy. @@ -119,14 +160,16 @@ typedef enum { struct PK11AttributeStr { PK11Attribute *next; PK11Attribute *prev; -#ifdef REF_COUNT_ATTRIBUTE + PRBool freeAttr; + PRBool freeData; +#ifdef PKCS11_REF_COUNT_ATTRIBUTES int refCount; PZLock *refLock; #endif /*must be called handle to make pk11queue_find work */ CK_ATTRIBUTE_TYPE handle; CK_ATTRIBUTE attrib; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES unsigned char space[ATTR_SPACE]; #endif }; @@ -146,27 +189,33 @@ struct PK11ObjectListStr { */ struct PK11ObjectStr { PK11Object *next; - PK11Object *prev; - PK11ObjectList sessionList; - CK_OBJECT_HANDLE handle; -#ifdef NO_ARENA - int nextAttr; -#else - PLArenaPool *arena; -#endif - int refCount; + PK11Object *prev; + CK_OBJECT_CLASS objclass; + CK_OBJECT_HANDLE handle; + int refCount; PZLock *refLock; - PZLock *attributeLock; - PK11Session *session; PK11Slot *slot; - CK_OBJECT_CLASS objclass; void *objectInfo; PK11Free infoFree; - char *label; - PRBool inDB; +#ifndef PKCS11_STATIC_ATTRIBUTES + PLArenaPool *arena; +#endif +}; + +struct PK11TokenObjectStr { + PK11Object obj; + SECItem dbKey; +}; + +struct PK11SessionObjectStr { + PK11Object obj; + PK11ObjectList sessionList; + PZLock *attributeLock; + PK11Session *session; PRBool wasDerived; PK11Attribute *head[ATTRIBUTE_HASH_SIZE]; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES + int nextAttr; PK11Attribute attrList[MAX_OBJS_ATTRS]; #endif }; @@ -186,6 +235,7 @@ struct PK11SearchResultsStr { CK_OBJECT_HANDLE *handles; int size; int index; + int array_size; }; @@ -271,6 +321,7 @@ struct PK11SlotStr { int sessionCount; int rwSessionCount; int tokenIDCount; + PLHashTable *tokenHashTable; PK11Object *tokObjects[TOKEN_OBJECT_HASH_SIZE]; PK11Session *head[SESSION_HASH_SIZE]; }; @@ -312,9 +363,15 @@ struct PK11SSLMACInfoStr { #define PK11_TOKEN_MASK 0x80000000L #define PK11_TOKEN_MAGIC 0x80000000L #define PK11_TOKEN_TYPE_MASK 0x70000000L -#define PK11_TOKEN_TYPE_CERT 0x00000000L +/* keydb (high bit == 0) */ #define PK11_TOKEN_TYPE_PRIV 0x10000000L #define PK11_TOKEN_TYPE_PUB 0x20000000L +#define PK11_TOKEN_TYPE_KEY 0x30000000L +/* certdb (high bit == 1) */ +#define PK11_TOKEN_TYPE_TRUST 0x40000000L +#define PK11_TOKEN_TYPE_CRL 0x50000000L +#define PK11_TOKEN_TYPE_SMIME 0x60000000L +#define PK11_TOKEN_TYPE_CERT 0x70000000L /* how big a password/pin we can deal with */ #define PK11_MAX_PIN 255 @@ -426,14 +483,14 @@ extern CK_RV pk11_defaultAttribute(PK11Object *object, CK_ATTRIBUTE_TYPE type, extern PK11Object *pk11_NewObject(PK11Slot *slot); extern CK_RV pk11_CopyObject(PK11Object *destObject, PK11Object *srcObject); extern PK11FreeStatus pk11_FreeObject(PK11Object *object); -extern void pk11_DeleteObject(PK11Session *session, PK11Object *object); +extern CK_RV pk11_DeleteObject(PK11Session *session, PK11Object *object); extern void pk11_ReferenceObject(PK11Object *object); extern PK11Object *pk11_ObjectFromHandle(CK_OBJECT_HANDLE handle, PK11Session *session); extern void pk11_AddSlotObject(PK11Slot *slot, PK11Object *object); extern void pk11_AddObject(PK11Session *session, PK11Object *object); -extern CK_RV pk11_searchObjectList(PK11ObjectListElement **objectList, +extern CK_RV pk11_searchObjectList(PK11SearchResults *search, PK11Object **head, PZLock *lock, CK_ATTRIBUTE_PTR inTemplate, int count, PRBool isLoggedIn); @@ -488,7 +545,22 @@ CK_RV pk11_DBInit(const char *configdir, const char *certPrefix, const char *keyPrefix, const char *secmodName, PRBool readOnly, PRBool noCertDB, PRBool noModDB, PRBool forceOpen); +/* + * narrow objects + */ +PK11SessionObject * pk11_narrowToSessionObject(PK11Object *); +PK11TokenObject * pk11_narrowToTokenObject(PK11Object *); +/* + * token object utilities + */ +void pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle); +PRBool pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class, + CK_ATTRIBUTE_PTR theTemplate,int count); +CK_OBJECT_HANDLE pk11_mkHandle(PK11Slot *slot, + SECItem *dbKey, CK_OBJECT_HANDLE class); +PK11Object * pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, + CK_OBJECT_HANDLE handle); SEC_END_PROTOS #endif /* _PKCS11I_H_ */ diff --git a/security/nss/lib/softoken/pkcs11t.h b/security/nss/lib/softoken/pkcs11t.h index aa3d70496..124a1bb27 100644 --- a/security/nss/lib/softoken/pkcs11t.h +++ b/security/nss/lib/softoken/pkcs11t.h @@ -17,7 +17,6 @@ * Rights Reserved. * * Contributor(s): - * Dr Stephen Henson <stephen.henson@gemplus.com> * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the @@ -61,12 +60,17 @@ #define CK_DECLARE_FUNCTION(rv,func) PR_EXTERN(rv) func #define CK_DECLARE_FUNCTION_POINTER(rv,func) rv (PR_CALLBACK * func) +#define CK_INVALID_SESSION 0 + /* an unsigned 8-bit value */ typedef unsigned char CK_BYTE; /* an unsigned 8-bit character */ typedef CK_BYTE CK_CHAR; +/* an unsigned 8-bit character */ +typedef CK_BYTE CK_UTF8CHAR; + /* a BYTE-sized Boolean flag */ typedef CK_BYTE CK_BBOOL; @@ -88,6 +92,7 @@ typedef CK_ULONG CK_FLAGS; typedef CK_BYTE CK_PTR CK_BYTE_PTR; typedef CK_CHAR CK_PTR CK_CHAR_PTR; +typedef CK_UTF8CHAR CK_PTR CK_UTF8CHAR_PTR; typedef CK_ULONG CK_PTR CK_ULONG_PTR; typedef void CK_PTR CK_VOID_PTR; @@ -112,12 +117,14 @@ typedef CK_VERSION CK_PTR CK_VERSION_PTR; typedef struct CK_INFO { + /* manufacturerID and libraryDecription have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ CK_VERSION cryptokiVersion; /* PKCS #11 interface ver */ - CK_CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* must be zero */ /* libraryDescription and libraryVersion are new for v2.0 */ - CK_CHAR libraryDescription[32]; /* blank padded */ + CK_UTF8CHAR libraryDescription[32]; /* blank padded */ CK_VERSION libraryVersion; /* version of library */ } CK_INFO; @@ -139,8 +146,10 @@ typedef CK_SLOT_ID CK_PTR CK_SLOT_ID_PTR; /* CK_SLOT_INFO provides information about a slot */ typedef struct CK_SLOT_INFO { - CK_CHAR slotDescription[64]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ + /* slotDescription and manufacturerID have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR slotDescription[64]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ CK_FLAGS flags; /* hardwareVersion and firmwareVersion are new for v2.0 */ @@ -160,9 +169,11 @@ typedef CK_SLOT_INFO CK_PTR CK_SLOT_INFO_PTR; /* CK_TOKEN_INFO provides information about a token */ typedef struct CK_TOKEN_INFO { - CK_CHAR label[32]; /* blank padded */ - CK_CHAR manufacturerID[32]; /* blank padded */ - CK_CHAR model[16]; /* blank padded */ + /* label, manufacturerID, and model have been changed from + * CK_CHAR to CK_UTF8CHAR for v2.10 */ + CK_UTF8CHAR label[32]; /* blank padded */ + CK_UTF8CHAR manufacturerID[32]; /* blank padded */ + CK_UTF8CHAR model[16]; /* blank padded */ CK_CHAR serialNumber[16]; /* blank padded */ CK_FLAGS flags; /* see below */ @@ -223,6 +234,57 @@ typedef struct CK_TOKEN_INFO { * and sign) */ #define CKF_DUAL_CRYPTO_OPERATIONS 0x00000200 +/* CKF_TOKEN_INITIALIZED if new for v2.10. If it is true, the + * token has been initialized using C_InitializeToken or an + * equivalent mechanism outside the scope of PKCS #11. + * Calling C_InitializeToken when this flag is set will cause + * the token to be reinitialized. */ +#define CKF_TOKEN_INITIALIZED 0x00000400 + +/* CKF_SECONDARY_AUTHENTICATION if new for v2.10. If it is + * true, the token supports secondary authentication for + * private key objects. */ +/* DEPRICATED in v2.11 */ +#define CKF_SECONDARY_AUTHENTICATION 0x00000800 + +/* CKF_USER_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect user login PIN has been entered at least once + * since the last successful authentication. */ +#define CKF_USER_PIN_COUNT_LOW 0x00010000 + +/* CKF_USER_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect user PIN will it to become locked. */ +#define CKF_USER_PIN_FINAL_TRY 0x00020000 + +/* CKF_USER_PIN_LOCKED if new for v2.10. If it is true, the + * user PIN has been locked. User login to the token is not + * possible. */ +#define CKF_USER_PIN_LOCKED 0x00040000 + +/* CKF_USER_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the user PIN value is the default value set by token + * initialization or manufacturing. */ +#define CKF_USER_PIN_TO_BE_CHANGED 0x00080000 + +/* CKF_SO_PIN_COUNT_LOW if new for v2.10. If it is true, an + * incorrect SO login PIN has been entered at least once since + * the last successful authentication. */ +#define CKF_SO_PIN_COUNT_LOW 0x00100000 + +/* CKF_SO_PIN_FINAL_TRY if new for v2.10. If it is true, + * supplying an incorrect SO PIN will it to become locked. */ +#define CKF_SO_PIN_FINAL_TRY 0x00200000 + +/* CKF_SO_PIN_LOCKED if new for v2.10. If it is true, the SO + * PIN has been locked. SO login to the token is not possible. + */ +#define CKF_SO_PIN_LOCKED 0x00400000 + +/* CKF_SO_PIN_TO_BE_CHANGED if new for v2.10. If it is true, + * the SO PIN value is the default value set by token + * initialization or manufacturing. */ +#define CKF_SO_PIN_TO_BE_CHANGED 0x00800000 + typedef CK_TOKEN_INFO CK_PTR CK_TOKEN_INFO_PTR; @@ -289,15 +351,28 @@ typedef CK_OBJECT_HANDLE CK_PTR CK_OBJECT_HANDLE_PTR; typedef CK_ULONG CK_OBJECT_CLASS; /* The following classes of objects are defined: */ -#define CKO_DATA 0x00000000 -#define CKO_CERTIFICATE 0x00000001 -#define CKO_PUBLIC_KEY 0x00000002 -#define CKO_PRIVATE_KEY 0x00000003 -#define CKO_SECRET_KEY 0x00000004 -#define CKO_VENDOR_DEFINED 0x80000000 +/* CKO_HW_FEATURE is new for v2.10 */ +/* CKO_DOMAIN_PARAMETERS is new for v2.11 */ +#define CKO_DATA 0x00000000 +#define CKO_CERTIFICATE 0x00000001 +#define CKO_PUBLIC_KEY 0x00000002 +#define CKO_PRIVATE_KEY 0x00000003 +#define CKO_SECRET_KEY 0x00000004 +#define CKO_HW_FEATURE 0x00000005 +#define CKO_DOMAIN_PARAMETERS 0x00000006 +#define CKO_VENDOR_DEFINED 0x80000000 typedef CK_OBJECT_CLASS CK_PTR CK_OBJECT_CLASS_PTR; +/* CK_HW_FEATURE_TYPE is new for v2.10. CK_HW_FEATURE_TYPE is a + * value that identifies the hardware feature type of an object + * with CK_OBJECT_CLASS equal to CKO_HW_FEATURE. */ +typedef CK_ULONG CK_HW_FEATURE_TYPE; + +/* The following hardware feature types are defined */ +#define CKH_MONOTONIC_COUNTER 0x00000001 +#define CKH_CLOCK 0x00000002 +#define CKH_VENDOR_DEFINED 0x80000000 /* CK_KEY_TYPE is a value that identifies a key type */ /* CK_KEY_TYPE was changed from CK_USHORT to CK_ULONG for v2.0 */ @@ -309,10 +384,10 @@ typedef CK_ULONG CK_KEY_TYPE; #define CKK_DH 0x00000002 /* CKK_ECDSA and CKK_KEA are new for v2.0 */ - -/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKK_ECDSA 0x00000003 - +/* CKK_X9_42_DH is new for v2.11 */ +#define CKK_ECDSA 0x00000003 /* deprecated in v2.11 */ +#define CKK_EC 0x00000003 +#define CKK_X9_42_DH 0x00000004 #define CKK_KEA 0x00000005 #define CKK_GENERIC_SECRET 0x00000010 @@ -325,8 +400,8 @@ typedef CK_ULONG CK_KEY_TYPE; /* all these key types are new for v2.0 */ #define CKK_CAST 0x00000016 #define CKK_CAST3 0x00000017 -#define CKK_CAST5 0x00000018 -#define CKK_CAST128 0x00000018 /* CAST128=CAST5 */ +#define CKK_CAST5 0x00000018 /* deprecated in v2.11 */ +#define CKK_CAST128 0x00000018 #define CKK_RC5 0x00000019 #define CKK_IDEA 0x0000001A #define CKK_SKIPJACK 0x0000001B @@ -348,7 +423,9 @@ typedef CK_ULONG CK_KEY_TYPE; typedef CK_ULONG CK_CERTIFICATE_TYPE; /* The following certificate types are defined: */ +/* CKC_X_509_ATTR_CERT is new for v2.10 */ #define CKC_X_509 0x00000000 +#define CKC_X_509_ATTR_CERT 0x00000001 #define CKC_VENDOR_DEFINED 0x80000000 @@ -365,9 +442,22 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_LABEL 0x00000003 #define CKA_APPLICATION 0x00000010 #define CKA_VALUE 0x00000011 + +/* CKA_OBJECT_ID is new for v2.10 */ +#define CKA_OBJECT_ID 0x00000012 + #define CKA_CERTIFICATE_TYPE 0x00000080 #define CKA_ISSUER 0x00000081 #define CKA_SERIAL_NUMBER 0x00000082 + +/* CKA_AC_ISSUER, CKA_OWNER, and CKA_ATTR_TYPES are new + * for v2.10 */ +#define CKA_AC_ISSUER 0x00000083 +#define CKA_OWNER 0x00000084 +#define CKA_ATTR_TYPES 0x00000085 +/* CKA_TRUSTED is new for v2.11 */ +#define CKA_TRUSTED 0x00000086 + #define CKA_KEY_TYPE 0x00000100 #define CKA_SUBJECT 0x00000101 #define CKA_ID 0x00000102 @@ -395,16 +485,34 @@ typedef CK_ULONG CK_ATTRIBUTE_TYPE; #define CKA_PRIME 0x00000130 #define CKA_SUBPRIME 0x00000131 #define CKA_BASE 0x00000132 +/* CKA_PRIME_BITS and CKA_SUB_PRIME_BITS are new for v2.11 */ +#define CKA_PRIME_BITS 0x00000133 +#define CKA_SUB_PRIME_BITS 0x00000134 #define CKA_VALUE_BITS 0x00000160 #define CKA_VALUE_LEN 0x00000161 /* CKA_EXTRACTABLE, CKA_LOCAL, CKA_NEVER_EXTRACTABLE, - * CKA_ALWAYS_SENSITIVE, and CKA_MODIFIABLE are new for v2.0 */ + * CKA_ALWAYS_SENSITIVE, CKA_MODIFIABLE, CKA_ECDSA_PARAMS, + * and CKA_EC_POINT are new for v2.0 */ #define CKA_EXTRACTABLE 0x00000162 #define CKA_LOCAL 0x00000163 #define CKA_NEVER_EXTRACTABLE 0x00000164 #define CKA_ALWAYS_SENSITIVE 0x00000165 +/* CKA_KEY_GEN_MECHANISM is new for v2.11 */ +#define CKA_KEY_GEN_MECHANISM 0x00000166 #define CKA_MODIFIABLE 0x00000170 +#define CKA_ECDSA_PARAMS 0x00000180 /* depricated v2.11 */ +#define CKA_EC_PARAMS 0x00000180 +#define CKA_EC_POINT 0x00000181 + +/* CKA_SECONDARY_AUTH, CKA_AUTH_PIN_FLAGS, + * CKA_HW_FEATURE_TYPE, CKA_RESET_ON_INIT, and CKA_HAS_RESET + * are new for v2.10 */ +#define CKA_SECONDARY_AUTH 0x00000200 /* depricated v2.11 */ +#define CKA_AUTH_PIN_FLAGS 0x00000201 /* depricated v2.11 */ +#define CKA_HW_FEATURE_TYPE 0x00000300 +#define CKA_RESET_ON_INIT 0x00000301 +#define CKA_HAS_RESET 0x00000302 #define CKA_VENDOR_DEFINED 0x80000000 @@ -448,11 +556,32 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_MD5_RSA_PKCS 0x00000005 #define CKM_SHA1_RSA_PKCS 0x00000006 +/* CKM_RIPEMD128_RSA_PKCS, CKM_RIPEMD160_RSA_PKCS & CKM_RSA_OAEP + * are new for 2.10 */ +#define CKM_RIPEMD128_RSA_PKCS 0x00000007 +#define CKM_RIPEMD160_RSA_PKCS 0x00000008 +#define CKM_RSA_PKCS_OAEP 0x00000009 + +/* CKM_RSA_X9_31, CKM_SHA1_RSA_X9_31 & CKM_RSA_X9_31_KEY_PAIR_GEN + * are new for 2.11 */ +#define CKM_RSA_X9_31_KEY_PAIR_GEN 0x0000000A +#define CKM_RSA_X9_31 0x0000000B +#define CKM_SHA1_RSA_X9_31 0x0000000C + #define CKM_DSA_KEY_PAIR_GEN 0x00000010 #define CKM_DSA 0x00000011 #define CKM_DSA_SHA1 0x00000012 #define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020 #define CKM_DH_PKCS_DERIVE 0x00000021 + +/* CKM_X9_42_DH_PKCS_KEY_PAIR_GEN, CKM_X9_42_DH_DERIVE, + * CKM_X9_42_DH_HYBRID_DERIVE, & CKM_X9_42_MQV_DERIVE + * are new for v2.11 */ +#define CKM_X9_42_DH_PKCS_KEY_PAIR_GEN 0x00000030 +#define CKM_X9_42_DH_DERIVE 0x00000031 +#define CKM_X9_42_DH_HYBRID_DERIVE 0x00000032 +#define CKM_X9_42_MQV_DERIVE 0x00000033 + #define CKM_RC2_KEY_GEN 0x00000100 #define CKM_RC2_ECB 0x00000101 #define CKM_RC2_CBC 0x00000102 @@ -509,6 +638,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SHA_1_HMAC 0x00000221 #define CKM_SHA_1_HMAC_GENERAL 0x00000222 +/* CKM_RIPEMD128, CKM_RIPEMD128_HMAC, + * CKM_RIPEMD128_HMAC_GENERAL, CKM_RIPEMD160, CKM_RIPEMD160_HMAC, + * and CKM_RIPEMD160_HMAC_GENERAL are new for v2.10 */ +#define CKM_RIPEMD128 0x00000230 +#define CKM_RIPEMD128_HMAC 0x00000231 +#define CKM_RIPEMD128_HMAC_GENERAL 0x00000232 +#define CKM_RIPEMD160 0x00000240 +#define CKM_RIPEMD160_HMAC 0x00000241 +#define CKM_RIPEMD160_HMAC_GENERAL 0x00000242 + /* All of the following mechanisms are new for v2.0 */ /* Note that CAST128 and CAST5 are the same algorithm */ #define CKM_CAST_KEY_GEN 0x00000300 @@ -556,6 +695,17 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_SSL3_PRE_MASTER_KEY_GEN 0x00000370 #define CKM_SSL3_MASTER_KEY_DERIVE 0x00000371 #define CKM_SSL3_KEY_AND_MAC_DERIVE 0x00000372 + +/* CKM_SSL3_MASTER_KEY_DERIVE_DH, CKM_TLS_PRE_MASTER_KEY_GEN, + * CKM_TLS_MASTER_KEY_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE, + * CKM_TLS_MASTER_KEY_DERIVE_DH, & CKM_SSL3_MASTER_KEY_DERIVE_DH + * are new for v2.11. */ +#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x00000373 +#define CKM_TLS_PRE_MASTER_KEY_GEN 0x00000374 +#define CKM_TLS_MASTER_KEY_DERIVE 0x00000375 +#define CKM_TLS_KEY_AND_MAC_DERIVE 0x00000376 +#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x00000377 + #define CKM_SSL3_MD5_MAC 0x00000380 #define CKM_SSL3_SHA1_MAC 0x00000381 #define CKM_MD5_KEY_DERIVATION 0x00000390 @@ -575,6 +725,10 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_PBE_SHA1_DES2_EDE_CBC 0x000003A9 #define CKM_PBE_SHA1_RC2_128_CBC 0x000003AA #define CKM_PBE_SHA1_RC2_40_CBC 0x000003AB + +/* CKM_PKCS5_PBKD2 is new for v2.10 */ +#define CKM_PKCS5_PBKD2 0x000003B0 + #define CKM_PBA_SHA1_WITH_SHA1_HMAC 0x000003C0 #define CKM_KEY_WRAP_LYNKS 0x00000400 #define CKM_KEY_WRAP_SET_OAEP 0x00000401 @@ -601,12 +755,16 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_BATON_COUNTER 0x00001034 #define CKM_BATON_SHUFFLE 0x00001035 #define CKM_BATON_WRAP 0x00001036 - -/* PKCS #11 V2.01 probably won't actually have ECDSA in it */ -#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 +#define CKM_ECDSA_KEY_PAIR_GEN 0x00001040 /* depricated in v2.11 */ +#define CKM_EC_KEY_PAIR_GEN 0x00001040 #define CKM_ECDSA 0x00001041 #define CKM_ECDSA_SHA1 0x00001042 +/* ECDH1 is new for 2.11 */ +#define CKM_ECDH1_DERIVE 0x00001043 +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001044 +#define CKM_ECMQV_DERIVE 0x00001045 + #define CKM_JUNIPER_KEY_GEN 0x00001060 #define CKM_JUNIPER_ECB128 0x00001061 #define CKM_JUNIPER_CBC128 0x00001062 @@ -615,6 +773,7 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_JUNIPER_WRAP 0x00001065 #define CKM_FASTHASH 0x00001070 +/* AES is new for 2.11 */ #define CKM_AES_KEY_GEN 0x00001080 #define CKM_AES_ECB 0x00001081 #define CKM_AES_CBC 0x00001082 @@ -622,6 +781,12 @@ typedef CK_ULONG CK_MECHANISM_TYPE; #define CKM_AES_MAC_GENERAL 0x00001084 #define CKM_AES_CBC_PAD 0x00001085 +/* CKM_DSA_PARAMETER_GEN, CKM_DH_PKCS_PARAMETER_GEN, + * and CKM_DH_X9_42_PARAMETER_GEN are new for 2.11 */ +#define CKM_DSA_PARAMETER_GEN 0x00002000 +#define CKM_DH_PKCS_PARAMETER_GEN 0x00002001 +#define CKM_DH_X9_42_PARAMETER_GEN 0x00002002 + #define CKM_VENDOR_DEFINED 0x80000000 typedef CK_MECHANISM_TYPE CK_PTR CK_MECHANISM_TYPE_PTR; @@ -658,6 +823,8 @@ typedef struct CK_MECHANISM_INFO { * CKF_GENERATE, CKF_GENERATE_KEY_PAIR, CKF_WRAP, CKF_UNWRAP, * and CKF_DERIVE are new for v2.0. They specify whether or not * a mechanism can be used for a particular task */ +/* The flags CKF_EC_FP, CKF_EC_F_2M, CKF_EC_ECPARAMETERS, CKF_EC_NAMEDCURVE, + * CKF_EC_UNCOMPRESS, and CKF_EC_COMPRESS are new for v2.11 */ #define CKF_ENCRYPT 0x00000100 #define CKF_DECRYPT 0x00000200 #define CKF_DIGEST 0x00000400 @@ -670,6 +837,12 @@ typedef struct CK_MECHANISM_INFO { #define CKF_WRAP 0x00020000 #define CKF_UNWRAP 0x00040000 #define CKF_DERIVE 0x00080000 +#define CKF_EC_FP 0x00100000 +#define CKF_EC_F_2M 0x00200000 +#define CKF_EC_ECPARAMETERS 0x00400000 +#define CKF_EC_NAMEDCURVE 0x00800000 +#define CKF_EC_UNCOMPRESS 0x01000000 +#define CKF_EC_COMPRESS 0x02000000 #define CKF_EXTENSION 0x80000000 /* FALSE for 2.01 */ @@ -735,6 +908,9 @@ typedef CK_ULONG CK_RV; #define CKR_KEY_NOT_WRAPPABLE 0x00000069 #define CKR_KEY_UNEXTRACTABLE 0x0000006A +/* CKR_KEY_PARAMS_INVALID is new for v2.11 */ +#define CKR_KEY_PARAMS_INVALID 0x0000006B + #define CKR_MECHANISM_INVALID 0x00000070 #define CKR_MECHANISM_PARAM_INVALID 0x00000071 @@ -790,8 +966,13 @@ typedef CK_ULONG CK_RV; #define CKR_WRAPPING_KEY_TYPE_INCONSISTENT 0x00000115 #define CKR_RANDOM_SEED_NOT_SUPPORTED 0x00000120 -/* These are new to v2.0 */ +/* New for v2.0 */ #define CKR_RANDOM_NO_RNG 0x00000121 + +/* New for v2.11 */ +#define CKR_DOMAIN_PARAMS_INVALID 0x00000130 + +/* These are new to v2.0 */ #define CKR_BUFFER_TOO_SMALL 0x00000150 #define CKR_SAVED_STATE_INVALID 0x00000160 #define CKR_INFORMATION_SENSITIVE 0x00000170 @@ -878,6 +1059,41 @@ typedef CK_C_INITIALIZE_ARGS CK_PTR CK_C_INITIALIZE_ARGS_PTR; /* CKF_DONT_BLOCK is for the function C_WaitForSlotEvent */ #define CKF_DONT_BLOCK 1 +/* CK_RSA_PKCS_OAEP_MGF_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_MGF_TYPE is used to indicate the Message + * Generation Function (MGF) applied to a message block when + * formatting a message block for the PKCS #1 OAEP encryption + * scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_MGF_TYPE; + +typedef CK_RSA_PKCS_OAEP_MGF_TYPE CK_PTR CK_RSA_PKCS_OAEP_MGF_TYPE_PTR; + +/* The following MGFs are defined */ +#define CKG_MGF1_SHA1 0x00000001 + +/* CK_RSA_PKCS_OAEP_SOURCE_TYPE is new for v2.10. + * CK_RSA_PKCS_OAEP_SOURCE_TYPE is used to indicate the source + * of the encoding parameter when formatting a message block + * for the PKCS #1 OAEP encryption scheme. */ +typedef CK_ULONG CK_RSA_PKCS_OAEP_SOURCE_TYPE; + +typedef CK_RSA_PKCS_OAEP_SOURCE_TYPE CK_PTR CK_RSA_PKCS_OAEP_SOURCE_TYPE_PTR; + +/* The following encoding parameter sources are defined */ +#define CKZ_DATA_SPECIFIED 0x00000001 + +/* CK_RSA_PKCS_OAEP_PARAMS is new for v2.10. + * CK_RSA_PKCS_OAEP_PARAMS provides the parameters to the + * CKM_RSA_PKCS_OAEP mechanism. */ +typedef struct CK_RSA_PKCS_OAEP_PARAMS { + CK_MECHANISM_TYPE hashAlg; + CK_RSA_PKCS_OAEP_MGF_TYPE mgf; + CK_RSA_PKCS_OAEP_SOURCE_TYPE source; + CK_VOID_PTR pSourceData; + CK_ULONG ulSourceDataLen; +} CK_RSA_PKCS_OAEP_PARAMS; + +typedef CK_RSA_PKCS_OAEP_PARAMS CK_PTR CK_RSA_PKCS_OAEP_PARAMS_PTR; /* CK_KEA_DERIVE_PARAMS provides the parameters to the * CKM_KEA_DERIVE mechanism */ @@ -1102,36 +1318,46 @@ typedef CK_ULONG CK_EXTRACT_PARAMS; typedef CK_EXTRACT_PARAMS CK_PTR CK_EXTRACT_PARAMS_PTR; -/* Do not attempt to use these. They are only used by NETSCAPE's internal - * PKCS #11 interface. Most of these are place holders for other mechanism - * and will change in the future. - */ -#define CKM_NETSCAPE_PBE_KEY_GEN 0x80000001L -#define CKM_NETSCAPE_PBE_SHA1_DES_CBC 0x80000002L -#define CKM_NETSCAPE_PBE_SHA1_TRIPLE_DES_CBC 0x80000003L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC2_CBC 0x80000004L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC2_CBC 0x80000005L -#define CKM_NETSCAPE_PBE_SHA1_40_BIT_RC4 0x80000006L -#define CKM_NETSCAPE_PBE_SHA1_128_BIT_RC4 0x80000007L -#define CKM_NETSCAPE_PBE_SHA1_FAULTY_3DES_CBC 0x80000008L -#define CKM_NETSCAPE_PBE_SHA1_HMAC_KEY_GEN 0x80000009L -#define CKM_NETSCAPE_PBE_MD5_HMAC_KEY_GEN 0x8000000aL -#define CKM_NETSCAPE_PBE_MD2_HMAC_KEY_GEN 0x8000000bL -#define CKM_TLS_MASTER_KEY_DERIVE 0x80000371L -#define CKM_TLS_KEY_AND_MAC_DERIVE 0x80000372L -#define CKM_TLS_PRF_GENERAL 0x80000373L -#define CKM_SSL3_MASTER_KEY_DERIVE_DH 0x80000374L -#define CKM_TLS_MASTER_KEY_DERIVE_DH 0x80000375L - -/* define used to pass in the database key for DSA private keys */ -#define CKA_NETSCAPE_DB 0xD5A0DB00L -#define CKA_NETSCAPE_TRUST 0x80000001L - -#define SECMOD_MODULE_DB_FUNCTION_FIND 0 -#define SECMOD_MODULE_DB_FUNCTION_ADD 1 -#define SECMOD_MODULE_DB_FUNCTION_DEL 2 -typedef char ** (PR_CALLBACK *SECMODModuleDBFunc)(unsigned long function, - char *parameters, char *moduleSpec); +/* CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE is used to + * indicate the Pseudo-Random Function (PRF) used to generate + * key bits using PKCS #5 PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE; + +typedef CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE CK_PTR CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE_PTR; + +/* The following PRFs are defined in PKCS #5 v2.0. */ +#define CKP_PKCS5_PBKD2_HMAC_SHA1 0x00000001 + + +/* CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is new for v2.10. + * CK_PKCS5_PBKD2_SALT_SOURCE_TYPE is used to indicate the + * source of the salt value when deriving a key using PKCS #5 + * PBKDF2. */ +typedef CK_ULONG CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE; + +typedef CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE CK_PTR CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE_PTR; + +/* The following salt value sources are defined in PKCS #5 v2.0. */ +#define CKZ_SALT_SPECIFIED 0x00000001 + +/* CK_PKCS5_PBKD2_PARAMS is new for v2.10. + * CK_PKCS5_PBKD2_PARAMS is a structure that provides the + * parameters to the CKM_PKCS5_PBKD2 mechanism. */ +typedef struct CK_PKCS5_PBKD2_PARAMS { + CK_PKCS5_PBKDF2_SALT_SOURCE_TYPE saltSource; + CK_VOID_PTR pSaltSourceData; + CK_ULONG ulSaltSourceDataLen; + CK_ULONG iterations; + CK_PKCS5_PBKD2_PSEUDO_RANDOM_FUNCTION_TYPE prf; + CK_VOID_PTR pPrfData; + CK_ULONG ulPrfDataLen; +} CK_PKCS5_PBKD2_PARAMS; + +typedef CK_PKCS5_PBKD2_PARAMS CK_PTR CK_PKCS5_PBKD2_PARAMS_PTR; + +/* Netscape Specific defines */ +#include "pkcs11n.h" /* undo packing */ #include "pkcs11u.h" diff --git a/security/nss/lib/softoken/pkcs11u.c b/security/nss/lib/softoken/pkcs11u.c index 536d938a0..cbd5b371c 100644 --- a/security/nss/lib/softoken/pkcs11u.c +++ b/security/nss/lib/softoken/pkcs11u.c @@ -38,6 +38,7 @@ #include "pcertt.h" #include "lowkeyi.h" #include "pcert.h" +#include "secasn1.h" /* declare the internal pkcs11 slot structures: @@ -62,27 +63,36 @@ pk11_NewAttribute(PK11Object *object, { PK11Attribute *attribute; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES + PK11SessionObject *so = pk11_narrowToSessionObject(object); int index; + + if (so == NULL) { + /* allocate new attribute in a buffer */ + PORT_Assert(0); + } /* - * NO_ARENA attempts to keep down contention on Malloc and Arena locks + * PKCS11_STATIC_ATTRIBUTES attempts to keep down contention on Malloc and Arena locks * by limiting the number of these calls on high traversed paths. this * is done for attributes by 'allocating' them from a pool already allocated * by the parent object. */ - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - index = object->nextAttr++; - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Lock(so->attributeLock);) + index = so->nextAttr++; + PK11_USE_THREADS(PZ_Unlock(so->attributeLock);) PORT_Assert(index < MAX_OBJS_ATTRS); if (index >= MAX_OBJS_ATTRS) return NULL; - attribute = &object->attrList[index]; + attribute = &so->attrList[index]; attribute->attrib.type = type; + attribute->freeAttr = PR_FALSE; + attribute->freeData = PR_FALSE; if (value) { if (len <= ATTR_SPACE) { attribute->attrib.pValue = attribute->space; } else { attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; } if (attribute->attrib.pValue == NULL) { return NULL; @@ -94,23 +104,27 @@ pk11_NewAttribute(PK11Object *object, attribute->attrib.ulValueLen = 0; } #else -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute)); + attribute->freeAttr = PR_TRUE; #else attribute = (PK11Attribute*)PORT_ArenaAlloc(object->arena,sizeof(PK11Attribute)); -#endif /* REF_COUNT_ATTRIBUTE */ + attribute->freeAttr = PR_FALSE; +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ if (attribute == NULL) return NULL; + attribute->freeData = PR_FALSE; if (value) { -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; #else attribute->attrib.pValue = PORT_ArenaAlloc(object->arena,len); -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ if (attribute->attrib.pValue == NULL) { -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES PORT_Free(attribute); -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ return NULL; } PORT_Memcpy(attribute->attrib.pValue,value,len); @@ -119,11 +133,11 @@ pk11_NewAttribute(PK11Object *object, attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } -#endif /* NO_ARENA */ +#endif /* PKCS11_STATIC_ATTRIBUTES */ attribute->attrib.type = type; attribute->handle = type; attribute->next = attribute->prev = NULL; -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES attribute->refCount = 1; #ifdef PKCS11_USE_THREADS attribute->refLock = PZ_NewLock(nssILockRefLock); @@ -135,31 +149,751 @@ pk11_NewAttribute(PK11Object *object, #else attribute->refLock = NULL; #endif -#endif /* REF_COUNT_ATTRIBUTE */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ return attribute; } +static PK11Attribute * +pk11_NewTokenAttribute(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, + CK_ULONG len, PRBool copy) +{ + PK11Attribute *attribute; + + attribute = (PK11Attribute*)PORT_Alloc(sizeof(PK11Attribute)); + + if (attribute == NULL) return NULL; + attribute->attrib.type = type; + attribute->handle = type; + attribute->next = attribute->prev = NULL; + attribute->freeAttr = PR_TRUE; + attribute->freeData = PR_FALSE; +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + attribute->refCount = 1; +#ifdef PKCS11_USE_THREADS + attribute->refLock = PZ_NewLock(nssILockRefLock); + if (attribute->refLock == NULL) { + PORT_Free(attribute); + return NULL; + } +#else + attribute->refLock = NULL; +#endif +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ + attribute->attrib.type = type; + if (!copy) { + attribute->attrib.pValue = value; + attribute->attrib.ulValueLen = len; + return attribute; + } + + if (value) { +#ifdef PKCS11_STATIC_ATTRIBUTES + if (len <= ATTR_SPACE) { + attribute->attrib.pValue = attribute->space; + } else { + attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; + } +#else + attribute->attrib.pValue = PORT_Alloc(len); + attribute->freeData = PR_TRUE; +#endif + if (attribute->attrib.pValue == NULL) { +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + if (attribute->refLock) { + PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);) + } +#endif + PORT_Free(attribute); + return NULL; + } + PORT_Memcpy(attribute->attrib.pValue,value,len); + attribute->attrib.ulValueLen = len; + } else { + attribute->attrib.pValue = NULL; + attribute->attrib.ulValueLen = 0; + } + return attribute; +} + +static PK11Attribute * +pk11_NewTokenAttributeSigned(CK_ATTRIBUTE_TYPE type, CK_VOID_PTR value, + CK_ULONG len, PRBool copy) +{ + unsigned char * dval = (unsigned char *)value; + if (*dval == 0) { + dval++; + len--; + } + return pk11_NewTokenAttribute(type,dval,len,copy); +} + /* * Free up all the memory associated with an attribute. Reference count * must be zero to call this. */ -#ifdef REF_COUNT_ATTRIBUTE static void pk11_DestroyAttribute(PK11Attribute *attribute) { +#ifdef PKCS11_REF_COUNT_ATTRIBUTES PORT_Assert(attribute->refCount == 0); PK11_USE_THREADS(PZ_DestroyLock(attribute->refLock);) +#endif if (attribute->attrib.pValue) { /* clear out the data in the attribute value... it may have been * sensitive data */ PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); + } + if (attribute->freeData) { PORT_Free(attribute->attrib.pValue); } PORT_Free(attribute); } + +/* + * release a reference to an attribute structure + */ +void +pk11_FreeAttribute(PK11Attribute *attribute) +{ + PRBool destroy = PR_FALSE; + + if (attribute->freeAttr) { + pk11_DestroyAttribute(attribute); + return; + } + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + PK11_USE_THREADS(PZ_Lock(attribute->refLock);) + if (attribute->refCount == 1) destroy = PR_TRUE; + attribute->refCount--; + PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) + + if (destroy) pk11_DestroyAttribute(attribute); #endif +} + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES +#define PK11_DEF_ATTRIBUTE(value,len) \ + { NULL, NULL, PR_FALSE, PR_FALSE, 1, NULL, 0, { 0, value, len } } + +#else +#define PK11_DEF_ATTRIBUTE(value,len) \ + { NULL, NULL, PR_FALSE, PR_FALSE, 0, { 0, value, len } } +#endif + +CK_BBOOL pk11_staticTrueValue = CK_TRUE; +CK_BBOOL pk11_staticFalseValue = CK_FALSE; +static const PK11Attribute pk11_StaticTrueAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticTrueValue,sizeof(pk11_staticTrueValue)); +static const PK11Attribute pk11_StaticFalseAttr = + PK11_DEF_ATTRIBUTE(&pk11_staticFalseValue,sizeof(pk11_staticFalseValue)); +static const PK11Attribute pk11_StaticNullAttr = PK11_DEF_ATTRIBUTE(NULL,0); + +SECItem * +pk11_getCrl(PK11TokenObject *object) +{ + SECItem *crl; + + if (object->obj.objclass != CKO_NETSCAPE_CRL) { + return NULL; + } + if (object->obj.objectInfo) { + return (SECItem *)object->obj.objectInfo; + } + crl = nsslowcert_FindCrlByKey(object->obj.slot->certDB,&object->dbKey, + NULL,PR_FALSE); + object->obj.objectInfo = (void *)crl; + object->obj.infoFree = (PK11Free) SECITEM_FreeItem; + return crl; +} + +NSSLOWCERTCertificate * +pk11_getCert(PK11TokenObject *object) +{ + NSSLOWCERTCertificate *cert; + + if ((object->obj.objclass != CKO_CERTIFICATE) && + (object->obj.objclass != CKO_NETSCAPE_TRUST)) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWCERTCertificate *)object->obj.objectInfo; + } + cert = nsslowcert_FindCertByKey(object->obj.slot->certDB,&object->dbKey); + object->obj.objectInfo = (void *)cert; + object->obj.infoFree = (PK11Free) nsslowcert_DestroyCertificate ; + return cert; +} + +NSSLOWKEYPublicKey * +pk11_GetPublicKey(PK11TokenObject *object) +{ + NSSLOWKEYPublicKey *pubKey; + NSSLOWKEYPrivateKey *privKey; + + if (object->obj.objclass != CKO_PUBLIC_KEY) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWKEYPublicKey *)object->obj.objectInfo; + } + privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, + &object->dbKey, object->obj.slot->password); + pubKey = nsslowkey_ConvertToPublicKey(privKey); + nsslowkey_DestroyPrivateKey(privKey); + object->obj.objectInfo = (void *) pubKey; + object->obj.infoFree = (PK11Free) nsslowkey_DestroyPublicKey ; + return pubKey; +} + +NSSLOWKEYPrivateKey * +pk11_GetPrivateKey(PK11TokenObject *object) +{ + NSSLOWKEYPrivateKey *privKey; + + if (object->obj.objclass != CKO_PUBLIC_KEY) { + return NULL; + } + if (object->obj.objectInfo) { + return (NSSLOWKEYPrivateKey *)object->obj.objectInfo; + } + privKey = nsslowkey_FindKeyByPublicKey(object->obj.slot->keyDB, + &object->dbKey, object->obj.slot->password); + object->obj.objectInfo = (void *) privKey; + object->obj.infoFree = (PK11Free) nsslowkey_DestroyPrivateKey ; + return privKey; +} + +/* pk11_GetPubItem returns data associated with the public key. + * one only needs to free the public key. This comment is here + * because this sematic would be non-obvious otherwise. All callers + * should include this comment. + */ +static SECItem * +pk11_GetPubItem(NSSLOWKEYPublicKey *pubKey) { + SECItem *pubItem = NULL; + /* get value to compare from the cert's public key */ + switch ( pubKey->keyType ) { + case NSSLOWKEYRSAKey: + pubItem = &pubKey->u.rsa.modulus; + break; + case NSSLOWKEYDSAKey: + pubItem = &pubKey->u.dsa.publicValue; + break; + case NSSLOWKEYDHKey: + pubItem = &pubKey->u.dh.publicValue; + break; + default: + break; + } + return pubItem; +} + +static const SEC_ASN1Template pk11_SerialTemplate[] = { + { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) }, + { 0 } +}; + +PK11Attribute * +pk11_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_RSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + case CKA_MODULUS: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, + key->u.rsa.modulus.len, PR_FALSE); + case CKA_PUBLIC_EXPONENT: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data, + key->u.rsa.publicExponent.len, PR_FALSE); + break; + } + return NULL; +} +PK11Attribute * +pk11_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_ENCRYPT: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VERIFY: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_VALUE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len, PR_FALSE); + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data, + key->u.dsa.params.prime.len, PR_FALSE); + case CKA_SUBPRIME: + return pk11_NewTokenAttributeSigned(type, + key->u.dsa.params.subPrime.data, + key->u.dsa.params.subPrime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data, + key->u.dsa.params.base.len, PR_FALSE); + default: + break; + } + return NULL; +} +PK11Attribute * +pk11_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DH; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_ENCRYPT: + case CKA_VERIFY: + case CKA_VERIFY_RECOVER: + case CKA_WRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.publicValue.data, + key->u.dh.publicValue.len, PR_FALSE); + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data, + key->u.dh.prime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data, + key->u.dh.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindPublicKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPublicKey *key; + + switch (type) { + case CKA_PRIVATE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + default: + break; + } + + key = pk11_GetPublicKey(object); + if (key == NULL) { + return NULL; + } + switch (key->keyType) { + case NSSLOWKEYRSAKey: + return pk11_FindRSAPublicKeyAttribute(key,type); + case NSSLOWKEYDSAKey: + return pk11_FindDSAPublicKeyAttribute(key,type); + case NSSLOWKEYDHKey: + return pk11_FindDHPublicKeyAttribute(key,type); + default: + break; + } + + return NULL; +} +PK11Attribute * +pk11_FindSecretKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPrivateKey *key; + switch (type) { + case CKA_PRIVATE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + case CKA_DERIVE: + case CKA_ENCRYPT: + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_VERIFY: + case CKA_WRAP: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_NEVER_EXTRACTABLE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + default: + break; + } + + key = pk11_GetPrivateKey(object); + if (key == NULL) { + return NULL; + } + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,key->u.rsa.coefficient.data, + key->u.rsa.coefficient.len, PR_FALSE); + case CKA_VALUE: + return pk11_NewTokenAttribute(type,key->u.rsa.privateExponent.data, + key->u.rsa.privateExponent.len, PR_FALSE); + } + + return NULL; +} + +PK11Attribute * +pk11_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, + CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_RSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_MODULUS: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.modulus.data, + key->u.rsa.modulus.len, PR_FALSE); + case CKA_PUBLIC_EXPONENT: + return pk11_NewTokenAttributeSigned(type,key->u.rsa.publicExponent.data, + key->u.rsa.publicExponent.len, PR_FALSE); + case CKA_PRIVATE_EXPONENT: + case CKA_PRIME_1: + case CKA_PRIME_2: + case CKA_EXPONENT_1: + case CKA_EXPONENT_2: + case CKA_COEFFICIENT: + return (PK11Attribute *) &pk11_StaticNullAttr; + default: + break; + } + return NULL; +} +PK11Attribute * +pk11_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, + CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DSA; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dsa.publicValue.data, + key->u.dsa.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + case CKA_DECRYPT: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_SIGN: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.prime.data, + key->u.dsa.params.prime.len, PR_FALSE); + case CKA_SUBPRIME: + return pk11_NewTokenAttributeSigned(type, + key->u.dsa.params.subPrime.data, + key->u.dsa.params.subPrime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dsa.params.base.data, + key->u.dsa.params.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type) +{ + unsigned char hash[SHA1_LENGTH]; + CK_KEY_TYPE keyType = CKK_DH; + + switch (type) { + case CKA_KEY_TYPE: + return pk11_NewTokenAttribute(type,&keyType,sizeof(keyType), PR_TRUE); + case CKA_ID: + SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_DERIVE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_DECRYPT: + case CKA_SIGN: + case CKA_SIGN_RECOVER: + case CKA_UNWRAP: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + return (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_PRIME: + return pk11_NewTokenAttributeSigned(type,key->u.dh.prime.data, + key->u.dh.prime.len, PR_FALSE); + case CKA_BASE: + return pk11_NewTokenAttributeSigned(type,key->u.dh.base.data, + key->u.dh.base.len, PR_FALSE); + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindPrivateKeyAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWKEYPrivateKey *key; + switch (type) { + case CKA_PRIVATE: + case CKA_SENSITIVE: + case CKA_ALWAYS_SENSITIVE: + case CKA_EXTRACTABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_NEVER_EXTRACTABLE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + default: + break; + } + key = pk11_GetPrivateKey(object); + if (key == NULL) { + return NULL; + } + switch (key->keyType) { + case NSSLOWKEYRSAKey: + return pk11_FindRSAPrivateKeyAttribute(key,type); + case NSSLOWKEYDSAKey: + return pk11_FindDSAPrivateKeyAttribute(key,type); + case NSSLOWKEYDHKey: + return pk11_FindDHPrivateKeyAttribute(key,type); + default: + break; + } + + return NULL; +} + +PK11Attribute * +pk11_FindSMIMEAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWCERTCertificate *cert; + switch (type) { + case CKA_PRIVATE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindTrustAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWCERTCertificate *cert; + unsigned char hash[SHA1_LENGTH]; + SECItem *item; + PK11Attribute *attr; + + switch (type) { + case CKA_PRIVATE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + break; + } + cert = pk11_getCert(object); + if (cert == NULL) { + return NULL; + } + switch (type) { + case CKA_CERT_SHA1_HASH: + SHA1_HashBuf(hash,cert->derCert.data,cert->derCert.len); + return pk11_NewTokenAttribute(type,hash,SHA1_LENGTH, PR_TRUE); + case CKA_CERT_MD5_HASH: + MD5_HashBuf(hash,cert->derCert.data,cert->derCert.len); + return pk11_NewTokenAttribute(type,hash,MD5_LENGTH, PR_TRUE); + case CKA_ISSUER: + return pk11_NewTokenAttribute(type,cert->derIssuer.data, + cert->derIssuer.len, PR_FALSE); + case CKA_SERIAL_NUMBER: + item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate); + if (item == NULL) break; + attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE); + SECITEM_FreeItem(item,PR_TRUE); + return attr; + case CKA_TRUST_SERVER_AUTH: + case CKA_TRUST_CLIENT_AUTH: + case CKA_TRUST_EMAIL_PROTECTION: + case CKA_TRUST_CODE_SIGNING: + /* XXXXXX */ + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindCrlAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + SECItem *crl; + + switch (type) { + case CKA_PRIVATE: + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_VALUE: + crl = pk11_getCrl(object); + if (crl == NULL) break; + return pk11_NewTokenAttribute(type, crl->data, crl->len, PR_FALSE); + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,object->dbKey.data, + object->dbKey.len, PR_FALSE); + default: + break; + } + return NULL; +} + +PK11Attribute * +pk11_FindCertAttribute(PK11TokenObject *object, CK_ATTRIBUTE_TYPE type) +{ + NSSLOWCERTCertificate *cert; + NSSLOWKEYPublicKey *pubKey; + unsigned char hash[SHA1_LENGTH]; + SECItem *item; + PK11Attribute *attr; + + switch (type) { + case CKA_PRIVATE: + return (PK11Attribute *) &pk11_StaticFalseAttr; + case CKA_MODIFIABLE: + return (PK11Attribute *) &pk11_StaticTrueAttr; + default: + break; + } + cert = pk11_getCert(object); + if (cert == NULL) { + return NULL; + } + switch (type) { + case CKA_VALUE: + return pk11_NewTokenAttribute(type,cert->derCert.data, + cert->derCert.len,PR_FALSE); + case CKA_ID: + pubKey = nsslowcert_ExtractPublicKey(cert); + if (pubKey == NULL) break; + item = pk11_GetPubItem(pubKey); + if (item == NULL) { + nsslowkey_DestroyPublicKey(pubKey); + break; + } + SHA1_Hash(hash,item->data,item->len); + /* item is imbedded in pubKey, just free the key */ + nsslowkey_DestroyPublicKey(pubKey); + return pk11_NewTokenAttribute(type, hash, SHA1_LENGTH, PR_TRUE); + case CKA_LABEL: + return cert->nickname ? pk11_NewTokenAttribute(type, cert->nickname, + PORT_Strlen(cert->nickname)+1, PR_FALSE) : + (PK11Attribute *) &pk11_StaticNullAttr; + case CKA_SUBJECT: + return pk11_NewTokenAttribute(type,cert->derSubject.data, + cert->derSubject.len, PR_FALSE); + case CKA_ISSUER: + return pk11_NewTokenAttribute(type,cert->derIssuer.data, + cert->derIssuer.len, PR_FALSE); + case CKA_SERIAL_NUMBER: + item = SEC_ASN1EncodeItem(NULL,NULL,cert,pk11_SerialTemplate); + if (item == NULL) break; + attr = pk11_NewTokenAttribute(type, item->data, item->len, PR_TRUE); + SECITEM_FreeItem(item,PR_TRUE); + return attr; + default: + break; + } + return NULL; +} - +PK11Attribute * +pk11_FindTokenAttribute(PK11TokenObject *object,CK_ATTRIBUTE_TYPE type) +{ + /* handle the common ones */ + switch (type) { + case CKA_CLASS: + return pk11_NewTokenAttribute(type,&object->obj.objclass, + sizeof(object->obj.objclass),PR_FALSE); + case CKA_TOKEN: + return (PK11Attribute *) &pk11_StaticTrueAttr; + case CKA_LABEL: + return (object->obj.objclass != CKO_CERTIFICATE) ? + (PK11Attribute *) &pk11_StaticNullAttr : + pk11_FindCertAttribute(object,type); + default: + break; + } + switch (object->obj.objclass) { + case CKO_CERTIFICATE: + return pk11_FindCertAttribute(object,type); + case CKO_NETSCAPE_CRL: + return pk11_FindCrlAttribute(object,type); + case CKO_NETSCAPE_TRUST: + return pk11_FindTrustAttribute(object,type); + case CKO_NETSCAPE_SMIME: + return pk11_FindSMIMEAttribute(object,type); + case CKO_PUBLIC_KEY: + return pk11_FindPublicKeyAttribute(object,type); + case CKO_PRIVATE_KEY: + return pk11_FindPrivateKeyAttribute(object,type); + case CKO_SECRET_KEY: + return pk11_FindSecretKeyAttribute(object,type); + default: + break; + } + PORT_Assert(0); + return NULL; +} + /* * look up and attribute structure from a type and Object structure. * The returned attribute is referenced and needs to be freed when @@ -169,10 +903,15 @@ PK11Attribute * pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) { PK11Attribute *attribute; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE); -#ifdef REF_COUNT_ATTRIBUTE + if (sessObject == NULL) { + return pk11_FindTokenAttribute(pk11_narrowToTokenObject(object),type); + } + + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE); +#ifdef PKCS11_REF_COUNT_ATTRIBUTES if (attribute) { /* atomic increment would be nice here */ PK11_USE_THREADS(PZ_Lock(attribute->refLock);) @@ -180,31 +919,18 @@ pk11_FindAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) } #endif - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) return(attribute); } -/* - * release a reference to an attribute structure - */ -void -pk11_FreeAttribute(PK11Attribute *attribute) -{ -#ifdef REF_COUNT_ATTRIBUTE - PRBool destroy = PR_FALSE; - - PK11_USE_THREADS(PZ_Lock(attribute->refLock);) - if (attribute->refCount == 1) destroy = PR_TRUE; - attribute->refCount--; - PK11_USE_THREADS(PZ_Unlock(attribute->refLock);) - if (destroy) pk11_DestroyAttribute(attribute); -#endif +PRBool +pk11_hasAttributeToken(PK11TokenObject *object) +{ + return PR_FALSE; } - - /* * return true if object has attribute */ @@ -212,10 +938,15 @@ PRBool pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) { PK11Attribute *attribute; + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) { + return pk11_hasAttributeToken(pk11_narrowToTokenObject(object)); + } - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_find(attribute,type,object->head,ATTRIBUTE_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_find(attribute,type,sessObject->head,ATTRIBUTE_HASH_SIZE); + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) return (PRBool)(attribute != NULL); } @@ -223,12 +954,16 @@ pk11_hasAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) /* * add an attribute to an object */ -static -void pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute) +static void +pk11_AddAttribute(PK11Object *object,PK11Attribute *attribute) { - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) - pk11queue_add(attribute,attribute->handle,object->head,ATTRIBUTE_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) return; + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) + pk11queue_add(attribute,attribute->handle, + sessObject->head,ATTRIBUTE_HASH_SIZE); + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) } /* @@ -277,13 +1012,18 @@ pk11_Attribute2SSecItem(PLArenaPool *arena,SECItem *item,PK11Object *object, static void pk11_DeleteAttribute(PK11Object *object, PK11Attribute *attribute) { - PK11_USE_THREADS(PZ_Lock(object->attributeLock);) + PK11SessionObject *sessObject = pk11_narrowToSessionObject(object); + + if (sessObject == NULL) { + return ; + } + PK11_USE_THREADS(PZ_Lock(sessObject->attributeLock);) if (pk11queue_is_queued(attribute,attribute->handle, - object->head,ATTRIBUTE_HASH_SIZE)) { + sessObject->head,ATTRIBUTE_HASH_SIZE)) { pk11queue_delete(attribute,attribute->handle, - object->head,ATTRIBUTE_HASH_SIZE); + sessObject->head,ATTRIBUTE_HASH_SIZE); } - PK11_USE_THREADS(PZ_Unlock(object->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(sessObject->attributeLock);) pk11_FreeAttribute(attribute); } @@ -320,14 +1060,10 @@ pk11_nullAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type) if (attribute->attrib.pValue != NULL) { PORT_Memset(attribute->attrib.pValue,0,attribute->attrib.ulValueLen); -#ifdef REF_COUNT_ATTRIBUTE - PORT_Free(attribute->attrib.pValue); -#endif /* REF_COUNT_ATTRIBUTE */ -#ifdef NO_ARENA - if (attribute->attrib.pValue != attribute->space) { + if (attribute->freeData) { PORT_Free(attribute->attrib.pValue); } -#endif /* NO_ARENA */ + attribute->freeData = PR_FALSE; attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } @@ -343,25 +1079,28 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, { PK11Attribute *attribute; void *att_val = NULL; + PRBool freeData = PR_FALSE; attribute=pk11_FindAttribute(object,type); if (attribute == NULL) return pk11_AddAttributeType(object,type,value,len); if (value) { -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES if (len <= ATTR_SPACE) { att_val = attribute->space; } else { att_val = PORT_Alloc(len); + freeData = PR_TRUE; } #else -#ifdef REF_COUNT_ATTRIBUTE +#ifdef PKCS11_REF_COUNT_ATTRIBUTES att_val = PORT_Alloc(len); + freeData = PR_TRUE; #else att_val = PORT_ArenaAlloc(object->arena,len); -#endif /* REF_COUNT_ATTRIBUTE */ -#endif /* NO_ARENA */ +#endif /* PKCS11_REF_COUNT_ATTRIBUTES */ +#endif /* PKCS11_STATIC_ATTRIBUTES */ if (att_val == NULL) { return CKR_HOST_MEMORY; } @@ -376,20 +1115,17 @@ pk11_forceAttribute(PK11Object *object,CK_ATTRIBUTE_TYPE type, void *value, PORT_Memset(attribute->attrib.pValue,0, attribute->attrib.ulValueLen); } -#ifdef REF_COUNT_ATTRIBUTE - PORT_Free(attribute->attrib.pValue); -#endif /* REF_COUNT_ATTRIBUTE */ -#ifdef NO_ARENA - if (attribute->attrib.pValue != attribute->space) { + if (attribute->freeData) { PORT_Free(attribute->attrib.pValue); } -#endif /* NO_ARENA */ + attribute->freeData = PR_FALSE; attribute->attrib.pValue = NULL; attribute->attrib.ulValueLen = 0; } if (att_val) { attribute->attrib.pValue = att_val; attribute->attrib.ulValueLen = len; + attribute->freeData = freeData; } return CKR_OK; } @@ -591,6 +1327,62 @@ pk11_AddAttributeType(PK11Object *object,CK_ATTRIBUTE_TYPE type,void *valPtr, * ******************** Object Utilities ******************************* */ +static SECStatus +pk11_deleteTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle) +{ + SECItem *item; + PRBool rem; + + item = (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable, + (void *)handle); + if (item) { + SECITEM_FreeItem(item,PR_TRUE); + } + rem = PL_HashTableRemove(slot->tokenHashTable,(void *)handle) ; + return rem ? SECSuccess : SECFailure; +} + +static SECStatus +pk11_addTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle, SECItem *key) +{ + PLHashEntry *entry; + SECItem *item; + + item = SECITEM_DupItem(key); + if (item == NULL) { + return SECFailure; + } + entry = PL_HashTableAdd(slot->tokenHashTable,(void *)handle,item); + if (entry == NULL) { + SECITEM_FreeItem(item,PR_TRUE); + return SECFailure; + } + return SECSuccess; +} + +static SECItem * +pk11_lookupTokenKeyByHandle(PK11Slot *slot, CK_OBJECT_HANDLE handle) +{ + return (SECItem *)PL_HashTableLookupConst(slot->tokenHashTable, + (void *)handle); +} + +/* + * use the refLock. This operations should be very rare, so the added + * contention on the ref lock should be lower than the overhead of adding + * a new lock. We use separate functions for this just in case I'm wrong. + */ +static void +pk11_tokenKeyLock(PK11Slot *slot) { + PK11_USE_THREADS(PZ_Lock(slot->objectLock);) +} + +static void +pk11_tokenKeyUnlock(PK11Slot *slot) { + PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) +} + + /* allocation hooks that allow us to recycle old object structures */ #ifdef MAX_OBJECT_LIST_SIZE static PK11Object * objectFreeList = NULL; @@ -620,26 +1412,26 @@ pk11_GetObjectFromList(PRBool *hasLocks) { } #endif - object = (PK11Object*)PORT_ZAlloc(sizeof(PK11Object)); + object = (PK11Object*)PORT_ZAlloc(sizeof(PK11SessionObject)); *hasLocks = PR_FALSE; return object; } static void -pk11_PutObjectToList(PK11Object *object) { +pk11_PutObjectToList(PK11SessionObject *object) { #ifdef MAX_OBJECT_LIST_SIZE if (object_count < MAX_OBJECT_LIST_SIZE) { PK11_USE_THREADS(PZ_Lock(objectLock)); - object->next = objectFreeList; - objectFreeList = object; + object->obj.next = objectFreeList; + objectFreeList = &object->obj; object_count++; PK11_USE_THREADS(PZ_Unlock(objectLock)); return; } #endif PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);) - PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) - object->attributeLock = object->refLock = NULL; + PK11_USE_THREADS(PZ_DestroyLock(object->obj.refLock);) + object->attributeLock = object->obj.refLock = NULL; PORT_Free(object); } @@ -651,58 +1443,63 @@ PK11Object * pk11_NewObject(PK11Slot *slot) { PK11Object *object; + PK11SessionObject *sessObject; PRBool hasLocks = PR_FALSE; int i; -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES object = pk11_GetObjectFromList(&hasLocks); if (object == NULL) { return NULL; } - object->nextAttr = 0; + sessObject = (PK11SessionObject *)object; + sessObject->nextAttr = 0; + + for (i=0; i < MAX_OBJS_ATTRS; i++) { + sessObject->attrList[i].attrib.pValue = NULL; + sessObject->attrList[i].freeData = PR_FALSE; + } #else + PRArenaPool *arena; + arena = PORT_NewArena(2048); if (arena == NULL) return NULL; - object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11Object)); + object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11SessionObject)); if (object == NULL) { PORT_FreeArena(arena,PR_FALSE); return NULL; } object->arena = arena; - for (i=0; i < MAX_OBJS_ATTRS; i++) { - object->attrList[i].attrib.pValue = NULL; - } + sessObject = (PK11SessionObject *)object; #endif object->handle = 0; object->next = object->prev = NULL; - object->sessionList.next = NULL; - object->sessionList.prev = NULL; - object->sessionList.parent = object; - object->inDB = PR_FALSE; - object->label = NULL; - object->refCount = 1; - object->session = NULL; object->slot = slot; object->objclass = 0xffff; - object->wasDerived = PR_FALSE; + object->refCount = 1; + sessObject->sessionList.next = NULL; + sessObject->sessionList.prev = NULL; + sessObject->sessionList.parent = object; + sessObject->session = NULL; + sessObject->wasDerived = PR_FALSE; #ifdef PKCS11_USE_THREADS if (!hasLocks) object->refLock = PZ_NewLock(nssILockRefLock); if (object->refLock == NULL) { -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES PORT_Free(object); #else PORT_FreeArena(arena,PR_FALSE); #endif return NULL; } - if (!hasLocks) object->attributeLock = PZ_NewLock(nssILockAttribute); - if (object->attributeLock == NULL) { + if (!hasLocks) sessObject->attributeLock = PZ_NewLock(nssILockAttribute); + if (sessObject->attributeLock == NULL) { PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) -#ifdef NO_ARENA +#ifdef PKCS11_STATIC_ATTRIBUTES PORT_Free(object); #else PORT_FreeArena(arena,PR_FALSE); @@ -710,17 +1507,55 @@ pk11_NewObject(PK11Slot *slot) return NULL; } #else - object->attributeLock = NULL; + sessObject->attributeLock = NULL; object->refLock = NULL; #endif for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - object->head[i] = NULL; + sessObject->head[i] = NULL; } object->objectInfo = NULL; object->infoFree = NULL; return object; } +static CK_RV +pk11_DestroySessionObjectData(PK11SessionObject *so) +{ + int i; + +#ifdef PKCS11_STATIC_ATTRIBUTES + for (i=0; i < MAX_OBJS_ATTRS; i++) { + unsigned char *value = so->attrList[i].attrib.pValue; + if (value) { + PORT_Memset(value,0,so->attrList[i].attrib.ulValueLen); + if (so->attrList[i].freeData) { + PORT_Free(value); + } + so->attrList[i].attrib.pValue = NULL; + so->attrList[i].freeData = PR_FALSE; + } + } +#endif + +#ifdef PKCS11_REF_COUNT_ATTRIBUTES + /* clean out the attributes */ + /* since no one is referencing us, it's safe to walk the chain + * without a lock */ + for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { + PK11Attribute *ap,*next; + for (ap = so->head[i]; ap != NULL; ap = next) { + next = ap->next; + /* paranoia */ + ap->next = ap->prev = NULL; + pk11_FreeAttribute(ap); + } + so->head[i] = NULL; + } +#endif + PK11_USE_THREADS(PZ_DestroyLock(so->attributeLock)); + return CKR_OK; +} + /* * free all the data associated with an object. Object reference count must * be 'zero'. @@ -728,88 +1563,38 @@ pk11_NewObject(PK11Slot *slot) static CK_RV pk11_DestroyObject(PK11Object *object) { -#if defined(REF_COUNT_ATTRIBUTE) || defined(NO_ARENA) +#if defined(PKCS11_REF_COUNT_ATTRIBUTES) || defined(PKCS11_STATIC_ATTRIBUTES) int i; #endif SECItem pubKey; CK_RV crv = CKR_OK; SECStatus rv; + PK11SessionObject *so = pk11_narrowToSessionObject(object); + PK11TokenObject *to = pk11_narrowToTokenObject(object); PORT_Assert(object->refCount == 0); /* delete the database value */ - if (object->inDB) { - if (pk11_isToken(object->handle)) { - /* remove the objects from the real data base */ - switch (object->handle & PK11_TOKEN_TYPE_MASK) { - case PK11_TOKEN_TYPE_PRIV: - /* KEYID is the public KEY for DSA and DH, and the MODULUS for - * RSA */ - crv=pk11_Attribute2SecItem(NULL,&pubKey,object,CKA_NETSCAPE_DB); - if (crv != CKR_OK) break; - rv = nsslowkey_DeleteKey(nsslowkey_GetDefaultKeyDB(), &pubKey); - if (rv != SECSuccess && pubKey.data[0] == 0) { - /* Because of legacy code issues, sometimes the public key - * has a '0' prepended to it, forcing it to be unsigned. - * The database may not store that '0', so remove it and - * try again. - */ - SECItem tmpPubKey; - tmpPubKey.data = pubKey.data + 1; - tmpPubKey.len = pubKey.len - 1; - rv = nsslowkey_DeleteKey(nsslowkey_GetDefaultKeyDB(), &tmpPubKey); - } - if (rv != SECSuccess) crv= CKR_DEVICE_ERROR; - break; - case PK11_TOKEN_TYPE_CERT: - - /* USE THE DER CERT To LOOK THINGS UP XXXX */ - rv = nsslowcert_DeletePermCertificate((NSSLOWCERTCertificate *)object->objectInfo); - if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; - break; - } + if (to) { + if (to->dbKey.data) { + PORT_Free(to->dbKey.data); + to->dbKey.data = NULL; } } - if (object->label) PORT_Free(object->label); - - object->inDB = PR_FALSE; - object->label = NULL; - -#ifdef NO_ARENA - for (i=0; i < MAX_OBJS_ATTRS; i++) { - unsigned char *value = object->attrList[i].attrib.pValue; - if (value) { - PORT_Memset(value,0,object->attrList[i].attrib.ulValueLen); - if (value != object->attrList[i].space) { - PORT_Free(value); - } - object->attrList[i].attrib.pValue = NULL; - } - } -#endif - -#ifdef REF_COUNT_ATTRIBUTE - /* clean out the attributes */ - /* since no one is referencing us, it's safe to walk the chain - * without a lock */ - for (i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - PK11Attribute *ap,*next; - for (ap = object->head[i]; ap != NULL; ap = next) { - next = ap->next; - /* paranoia */ - ap->next = ap->prev = NULL; - pk11_FreeAttribute(ap); - } - object->head[i] = NULL; + if (so) { + pk11_DestroySessionObjectData(so); } -#endif if (object->objectInfo) { (*object->infoFree)(object->objectInfo); } -#ifdef NO_ARENA - pk11_PutObjectToList(object); +#ifdef PKCS11_STATIC_ATTRIBUTES + if (so) { + pk11_PutObjectToList(so); + } else { + PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) + PORT_Free(to);; + } #else - PK11_USE_THREADS(PZ_DestroyLock(object->attributeLock);) PK11_USE_THREADS(PZ_DestroyLock(object->refLock);) arena = object->arena; PORT_FreeArena(arena,PR_FALSE); @@ -832,6 +1617,10 @@ pk11_ObjectFromHandleOnSlot(CK_OBJECT_HANDLE handle, PK11Slot *slot) PZLock *lock; PK11Object *object; + if (pk11_isToken(handle)) { + return pk11_NewTokenObject(slot, NULL, handle); + } + head = slot->tokObjects; lock = slot->objectLock; @@ -890,7 +1679,8 @@ void pk11_AddSlotObject(PK11Slot *slot, PK11Object *object) { PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - pk11queue_add(object,object->handle,slot->tokObjects,TOKEN_OBJECT_HASH_SIZE); + pk11queue_add(object,object->handle,slot->tokObjects, + TOKEN_OBJECT_HASH_SIZE); PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) } @@ -898,11 +1688,12 @@ void pk11_AddObject(PK11Session *session, PK11Object *object) { PK11Slot *slot = pk11_SlotFromSession(session); + PK11SessionObject *so = pk11_narrowToSessionObject(object); - if (!pk11_isToken(object->handle)) { + if (so) { PK11_USE_THREADS(PZ_Lock(session->objectLock);) - pk11queue_add(&object->sessionList,0,session->objects,0); - object->session = session; + pk11queue_add(&so->sessionList,0,session->objects,0); + so->session = session; PK11_USE_THREADS(PZ_Unlock(session->objectLock);) } pk11_AddSlotObject(slot,object); @@ -911,21 +1702,83 @@ pk11_AddObject(PK11Session *session, PK11Object *object) /* * add an object to a slot andsession queue */ -void +CK_RV pk11_DeleteObject(PK11Session *session, PK11Object *object) { PK11Slot *slot = pk11_SlotFromSession(session); + PK11SessionObject *so = pk11_narrowToSessionObject(object); + PK11TokenObject *to = pk11_narrowToTokenObject(object); + CK_RV crv = CKR_OK; + SECStatus rv; + NSSLOWCERTCertificate *cert; + NSSLOWCERTCertTrust tmptrust; - if (object->session) { - PK11Session *session = object->session; + /* Handle Token case */ + if (so && so->session) { + PK11Session *session = so->session; PK11_USE_THREADS(PZ_Lock(session->objectLock);) - pk11queue_delete(&object->sessionList,0,session->objects,0); + pk11queue_delete(&so->sessionList,0,session->objects,0); PK11_USE_THREADS(PZ_Unlock(session->objectLock);) - } - PK11_USE_THREADS(PZ_Lock(slot->objectLock);) - pk11queue_delete(object,object->handle,slot->tokObjects, + PK11_USE_THREADS(PZ_Lock(slot->objectLock);) + pk11queue_delete(object,object->handle,slot->tokObjects, TOKEN_OBJECT_HASH_SIZE); - PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) + PK11_USE_THREADS(PZ_Unlock(slot->objectLock);) + } else { + PORT_Assert(to); + /* remove the objects from the real data base */ + switch (object->handle & PK11_TOKEN_TYPE_MASK) { + case PK11_TOKEN_TYPE_PRIV: + case PK11_TOKEN_TYPE_KEY: + /* KEYID is the public KEY for DSA and DH, and the MODULUS for + * RSA */ + PORT_Assert(slot->keyDB); + rv = nsslowkey_DeleteKey(slot->keyDB, &to->dbKey); + if (rv != SECSuccess) crv= CKR_DEVICE_ERROR; + break; + case PK11_TOKEN_TYPE_PUB: + break; /* public keys only exist at the behest of the priv key */ + case PK11_TOKEN_TYPE_CERT: + cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + if (cert == NULL) { + crv = CKR_DEVICE_ERROR; + break; + } + rv = nsslowcert_DeletePermCertificate(cert); + if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; + 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; + } + break; + case PK11_TOKEN_TYPE_TRUST: + cert = nsslowcert_FindCertByKey(slot->certDB,&to->dbKey); + if (cert == NULL) { + crv = CKR_DEVICE_ERROR; + break; + } + tmptrust = *cert->trust; + tmptrust.sslFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.emailFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.objectSigningFlags &= CERTDB_PRESERVE_TRUST_BITS; + tmptrust.sslFlags |= CERTDB_TRUSTED_UNKNOWN; + tmptrust.emailFlags |= CERTDB_TRUSTED_UNKNOWN; + tmptrust.objectSigningFlags |= CERTDB_TRUSTED_UNKNOWN; + rv = nsslowcert_ChangeCertTrust(slot->certDB,cert,&tmptrust); + if (rv != SECSuccess) crv = CKR_DEVICE_ERROR; + nsslowcert_DestroyCertificate(cert); + break; + default: + break; + } + pk11_tokenKeyLock(object->slot); + pk11_deleteTokenKeyByHandle(object->slot,object->handle); + pk11_tokenKeyUnlock(object->slot); + } pk11_FreeObject(object); } @@ -938,11 +1791,16 @@ CK_RV pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) { PK11Attribute *attribute; + PK11SessionObject *src_so = pk11_narrowToSessionObject(srcObject); int i; - PK11_USE_THREADS(PZ_Lock(srcObject->attributeLock);) + if (src_so == NULL) { + return CKR_DEVICE_ERROR; /* can't copy token objects yet */ + } + + PK11_USE_THREADS(PZ_Lock(src_so->attributeLock);) for(i=0; i < ATTRIBUTE_HASH_SIZE; i++) { - attribute = srcObject->head[i]; + attribute = src_so->head[i]; do { if (attribute) { if (!pk11_hasAttribute(destObject,attribute->handle)) { @@ -951,7 +1809,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) PK11Attribute *newAttribute = pk11_NewAttribute( destObject,pk11_attr_expand(&attribute->attrib)); if (newAttribute == NULL) { - PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);) return CKR_HOST_MEMORY; } pk11_AddAttribute(destObject,newAttribute); @@ -960,7 +1818,7 @@ pk11_CopyObject(PK11Object *destObject,PK11Object *srcObject) } } while (attribute != NULL); } - PK11_USE_THREADS(PZ_Unlock(srcObject->attributeLock);) + PK11_USE_THREADS(PZ_Unlock(src_so->attributeLock);) return CKR_OK; } @@ -1014,7 +1872,7 @@ pk11_objectMatch(PK11Object *object,CK_ATTRIBUTE_PTR theTemplate,int count) * in the object list. */ CK_RV -pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head, +pk11_searchObjectList(PK11SearchResults *search,PK11Object **head, PZLock *lock, CK_ATTRIBUTE_PTR theTemplate, int count, PRBool isLoggedIn) { int i; @@ -1029,10 +1887,7 @@ pk11_searchObjectList(PK11ObjectListElement **objectList,PK11Object **head, if (pk11_objectMatch(object,theTemplate,count)) { /* don't return objects that aren't yet visible */ if ((!isLoggedIn) && pk11_isTrue(object,CKA_PRIVATE)) continue; - crv = AddToList(objectList,object); - if (crv != CKR_OK) { - break; - } + pk11_addHandle(search,object->handle); } } PK11_USE_THREADS(PZ_Unlock(lock);) @@ -1280,3 +2135,177 @@ pk11_FreeSession(PK11Session *session) if (destroy) pk11_DestroySession(session); } +/* + * handle Token Object stuff + */ + +/* Make a token handle for an object and record it so we can find it again */ +CK_OBJECT_HANDLE +pk11_mkHandle(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class) +{ + unsigned char hashBuf[SHA1_LENGTH]; + CK_OBJECT_HANDLE handle; + SECItem *key; + + SHA1_HashBuf(hashBuf,dbKey->data,dbKey->len); + handle = PK11_TOKEN_MASK | class | (hashBuf[0] << 24) | hashBuf[1] << 16 + | hashBuf[2] << 8 ; + + pk11_tokenKeyLock(slot); + while (key = pk11_lookupTokenKeyByHandle(slot,handle)) { + if (SECITEM_ItemsAreEqual(key,dbKey)) { + pk11_tokenKeyUnlock(slot); + return handle; + } + handle++; + } + pk11_addTokenKeyByHandle(slot,handle,dbKey); + pk11_tokenKeyUnlock(slot); +} + +void +pk11_addHandle(PK11SearchResults *search, CK_OBJECT_HANDLE handle) +{ + if (search->handles == NULL) { + return; + } + if (search->size >= search->array_size) { + search->array_size += NSC_SEARCH_BLOCK_SIZE; + search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles, + sizeof(CK_OBJECT_HANDLE)* search->array_size); + if (search->handles == NULL) { + return; + } + } + search->handles[search->size] = handle; + search->size++; +} + +static const CK_OBJECT_HANDLE pk11_classArray[] = { + 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY, + CKO_NETSCAPE_TRUST, CKO_NETSCAPE_CRL, CKO_NETSCAPE_SMIME, + CKO_CERTIFICATE }; + +#define handleToClass(handle) \ + pk11_classArray[((handle & PK11_TOKEN_TYPE_MASK))>>24] + +PK11Object * +pk11_NewTokenObject(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE handle) +{ + PK11Object *object = NULL; + PK11TokenObject *tokObject = NULL; + SECStatus rv; + +#ifdef PKCS11_STATIC_ATTRIBUTES + object = (PK11Object *) PORT_ZAlloc(sizeof(PK11TokenObject)); + if (object == NULL) { + return NULL; + } +#else + PRArenaPool *arena; + + arena = PORT_NewArena(2048); + if (arena == NULL) return NULL; + + object = (PK11Object*)PORT_ArenaAlloc(arena,sizeof(PK11TokenObject)); + if (object == NULL) { + PORT_FreeArena(arena,PR_FALSE); + return NULL; + } + object->arena = arena; +#endif + tokObject = (PK11TokenObject *) object; + + object->objclass = handleToClass(handle); + object->handle = handle; + object->refCount = 1; + object->slot = slot; + object->objectInfo = NULL; + object->infoFree = NULL; + if (dbKey == NULL) { + pk11_tokenKeyLock(slot); + dbKey = pk11_lookupTokenKeyByHandle(slot,handle); + if (dbKey == NULL) { + pk11_tokenKeyUnlock(slot); + goto loser; + } + rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey); + pk11_tokenKeyUnlock(slot); + } else { + rv = SECITEM_CopyItem(NULL,&tokObject->dbKey,dbKey); + } + if (rv != SECSuccess) { + goto loser; + } +#ifdef PKCS11_USE_THREADS + object->refLock = PZ_NewLock(nssILockRefLock); + if (object->refLock == NULL) { + goto loser; + } +#endif + + return object; +loser: + if (object) { + pk11_FreeObject(object); + } + return NULL; + +} + +PRBool +pk11_tokenMatch(PK11Slot *slot, SECItem *dbKey, CK_OBJECT_HANDLE class, + CK_ATTRIBUTE_PTR theTemplate,int count) +{ + PK11Object *object; + PRBool ret; + + object = pk11_NewTokenObject(slot,dbKey,PK11_TOKEN_MASK|class); + if (object == NULL) { + return PR_FALSE; + } + + ret = pk11_objectMatch(object,theTemplate,count); + pk11_FreeObject(object); + return ret; +} + +PK11TokenObject * +pk11_convertSessionToToken(PK11SessionObject *so) +{ + SECItem *key; + PK11TokenObject *to = pk11_narrowToTokenObject(&so->obj); + SECStatus rv; + + pk11_DestroySessionObjectData(so); + if (to == NULL) { + return NULL; + } + pk11_tokenKeyLock(so->obj.slot); + key = pk11_lookupTokenKeyByHandle(so->obj.slot,so->obj.handle); + if (key == NULL) { + pk11_tokenKeyUnlock(so->obj.slot); + return NULL; + } + rv = SECITEM_CopyItem(NULL,&to->dbKey,key); + pk11_tokenKeyUnlock(so->obj.slot); + if (rv == SECFailure) { + return NULL; + } + + return to; + +} + +PK11SessionObject * +pk11_narrowToSessionObject(PK11Object *obj) +{ + return !pk11_isToken(obj->handle) ? (PK11SessionObject *)obj : NULL; +} + +PK11TokenObject * +pk11_narrowToTokenObject(PK11Object *obj) +{ + return pk11_isToken(obj->handle) ? (PK11TokenObject *)obj : NULL; +} + diff --git a/security/nss/lib/softoken/secpkcs5.c b/security/nss/lib/softoken/secpkcs5.c index 1cfa37206..126184ef3 100644 --- a/security/nss/lib/softoken/secpkcs5.c +++ b/security/nss/lib/softoken/secpkcs5.c @@ -39,7 +39,7 @@ #include "hasht.h" #include "pkcs11t.h" #include "blapi.h" -#include "sechash.h" +#include "hasht.h" #include "secasn1.h" #include "secder.h" #include "secpkcs5.h" @@ -48,385 +48,52 @@ #include "softoken.h" #include "secerr.h" -#define DES_IV_LENGTH 8 -#define RC2_IV_LENGTH 8 -#define MD2_LENGTH 16 -#define MD5_LENGTH 16 -#define SHA1_LENGTH 20 -#define SEED_LENGTH 16 -#define SALT_LENGTH 8 -#define PBE_SALT_LENGTH 16 - /* template for PKCS 5 PBE Parameter. This template has been expanded * based upon the additions in PKCS 12. This should eventually be moved * if RSA updates PKCS 5. */ -const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[] = +static const SEC_ASN1Template NSSPKCS5PBEParameterTemplate[] = { { SEC_ASN1_SEQUENCE, - 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, + 0, NULL, sizeof(NSSPKCS5PBEParameter) }, { SEC_ASN1_OCTET_STRING, - offsetof(SEC_PKCS5PBEParameter, salt) }, + offsetof(NSSPKCS5PBEParameter, salt) }, { SEC_ASN1_INTEGER, - offsetof(SEC_PKCS5PBEParameter, iteration) }, + offsetof(NSSPKCS5PBEParameter, iteration) }, { 0 } }; -const SEC_ASN1Template SEC_V2PKCS12PBEParameterTemplate[] = +static const SEC_ASN1Template NSSPKCS5PKCS12V2PBEParameterTemplate[] = { - { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SEC_PKCS5PBEParameter) }, - { SEC_ASN1_OCTET_STRING, offsetof(SEC_PKCS5PBEParameter, salt) }, - { SEC_ASN1_INTEGER, offsetof(SEC_PKCS5PBEParameter, iteration) }, + { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSPKCS5PBEParameter) }, + { SEC_ASN1_OCTET_STRING, offsetof(NSSPKCS5PBEParameter, salt) }, + { SEC_ASN1_INTEGER, offsetof(NSSPKCS5PBEParameter, iteration) }, { 0 } }; -pbeBitGenParameters pbeHashAlgorithmParams[] = { - { 0, 0, SEC_OID_UNKNOWN }, - { 128, 512, SEC_OID_MD2 }, - { 128, 512, SEC_OID_MD5 }, - { 160, 512, SEC_OID_SHA1 }, -}; - -/* generate some random bytes. this is used to generate the - * salt if it is not specified. - */ -static SECStatus -sec_pkcs5_generate_random_bytes(PRArenaPool *poolp, - SECItem *dest, int len) -{ - SECStatus rv = SECFailure; - - if(dest != NULL) - { - void *mark = PORT_ArenaMark(poolp); - dest->data = (unsigned char *)PORT_ArenaZAlloc(poolp, len); - if(dest->data != NULL) - { - dest->len = len; - RNG_GenerateGlobalRandomBytes(dest->data, dest->len); - PORT_ArenaUnmark(poolp, mark); - rv = SECSuccess; - } else - PORT_ArenaRelease(poolp, mark); - } - - return rv; -} - -/* maps hash algorithm from PBE algorithm. - */ -static SECOidTag -sec_pkcs5_hash_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_SHA1; - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return SEC_OID_MD5; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - return SEC_OID_MD2; - default: - break; - } - return SEC_OID_UNKNOWN; -} - -/* get the iv length needed for the PBE algorithm - */ -static int -sec_pkcs5_iv_length(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - return DES_IV_LENGTH; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - return RC2_IV_LENGTH; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return 0; - default: - break; - } - return -1; -} - -/* get the key length needed for the PBE algorithm - */ -static int -sec_pkcs5_key_length(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - return 24; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return 8; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return 5; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - return 16; - default: - break; - } - return -1; -} - -/* the V2 algorithms only encode the salt, there is no iteration - * count so we need a check for V2 algorithm parameters. - */ -static PRBool -sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return PR_TRUE; - default: - break; - } - - return PR_FALSE; -} - -/* creates a PBE parameter based on the PBE algorithm. the only required - * parameters are algorithm and interation. the return is a PBE parameter - * which conforms to PKCS 5 parameter unless an extended parameter is needed. - * this is primarily if keyLen and a variable key length algorithm are - * specified. - * salt - if null, a salt will be generated from random bytes. - * iteration - number of iterations to perform hashing. - * keyLen - only used in variable key length algorithms - * iv - if null, the IV will be generated based on PKCS 5 when needed. - * params - optional, currently unsupported additional parameters. - * once a parameter is allocated, it should be destroyed calling - * sec_pkcs5_destroy_pbe_parameter or SEC_PKCS5DestroyPBEParameter. - */ -static SEC_PKCS5PBEParameter * -sec_pkcs5_create_pbe_parameter(SECOidTag algorithm, - SECItem *salt, - int iteration) -{ - PRArenaPool *poolp = NULL; - SEC_PKCS5PBEParameter *pbe_param = NULL; - SECStatus rv; - void *dummy = NULL; - - if(iteration < 0) { - return NULL; - } - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(poolp == NULL) - return NULL; - - pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS5PBEParameter)); - if(!pbe_param) { - PORT_FreeArena(poolp, PR_TRUE); - return NULL; - } - - pbe_param->poolp = poolp; - pbe_param->algorithm = algorithm; - - /* should we generate the salt? */ - if(!salt || !salt->data) { - rv = sec_pkcs5_generate_random_bytes(poolp, &pbe_param->salt, - SALT_LENGTH); - } else { - rv = SECITEM_CopyItem(poolp, &pbe_param->salt, salt); - } - - if(rv != SECSuccess) { - PORT_FreeArena(poolp, PR_TRUE); - return NULL; - } - - /* encode the integer */ - dummy = SEC_ASN1EncodeInteger(poolp, &pbe_param->iteration, - iteration); - rv = (dummy) ? SECSuccess : SECFailure; - - if(rv != SECSuccess) { - PORT_FreeArena(poolp, PR_FALSE); - return NULL; - } - - return pbe_param; -} - -/* generate bits for key and iv using MD5 hashing - */ -static SECItem * -sec_pkcs5_compute_md5_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool dummy) -{ - SECItem *hash = NULL, *pre_hash = NULL; - SECStatus rv = SECFailure; - - if((salt == NULL) || (pwd == NULL) || (iter < 0)) { - return NULL; - } - - hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if((hash != NULL) && (pre_hash != NULL)) { - unsigned int i, ph_len; - - ph_len = MD5_LENGTH; - if(ph_len < (salt->len + pwd->len)) { - ph_len = salt->len + pwd->len; - } - - rv = SECFailure; - hash->data = (unsigned char *)PORT_ZAlloc(MD5_LENGTH); - hash->len = MD5_LENGTH; - pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); - pre_hash->len = salt->len + pwd->len; - - if((hash->data != NULL) && (pre_hash->data != NULL)) { - rv = SECSuccess; - /* handle 0 length password */ - if(pwd->len > 0) { - PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); - } - if(salt->len > 0) { - PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); - } - for(i = 0; ((i < (unsigned int)iter) && (rv == SECSuccess)); i++) { - rv = MD5_HashBuf(hash->data, pre_hash->data, pre_hash->len); - if(rv != SECFailure) { - PORT_Memcpy(pre_hash->data, hash->data, MD5_LENGTH); - pre_hash->len = MD5_LENGTH; - } - } - } - } - - if(pre_hash != NULL) - SECITEM_FreeItem(pre_hash, PR_TRUE); - - if((rv == SECFailure) && (hash)) { - SECITEM_FreeItem(hash, PR_TRUE); - hash = NULL; - } - - return hash; -} - -/* generate bits for key and iv using MD2 hashing - */ -static SECItem * -sec_pkcs5_compute_md2_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool dummy) +SECStatus +nsspkcs5_HashBuf(const SECHashObject *hashObj, unsigned char *dest, + unsigned char *src, int len) { - SECItem *hash = NULL, *pre_hash = NULL; - SECStatus rv = SECFailure; - - if((salt == NULL) || (pwd == NULL) || (iter < 0)) - return NULL; - - hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - pre_hash = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if((hash != NULL) && (pre_hash != NULL)) - { - int i, ph_len; - - ph_len = MD2_LENGTH; - if((salt->len + pwd->len) > MD2_LENGTH) - ph_len = salt->len+pwd->len; - - rv = SECFailure; - hash->data = (unsigned char *)PORT_ZAlloc(MD2_LENGTH); - hash->len = MD2_LENGTH; - pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); - pre_hash->len = salt->len + pwd->len; - - if((hash->data != NULL) && (pre_hash->data != NULL)) - { - MD2Context *ctxt; - - rv = SECSuccess; - if(pwd->len > 0) { - PORT_Memcpy(pre_hash->data, pwd->data, pwd->len); - } - if(salt->len > 0) { - PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); - } + void *ctx; + unsigned int retLen; - for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) - { - ctxt = MD2_NewContext(); - if(ctxt == NULL) - rv = SECFailure; - else - { - MD2_Update(ctxt, pre_hash->data, pre_hash->len); - MD2_End(ctxt, hash->data, &hash->len, hash->len); - PORT_Memcpy(pre_hash->data, hash->data, MD2_LENGTH); - pre_hash->len = MD2_LENGTH; - MD2_DestroyContext(ctxt, PR_TRUE); - } - } - } + ctx = hashObj->create(); + if(ctx == NULL) { + return SECFailure; } - - if(pre_hash != NULL) - SECITEM_FreeItem(pre_hash, PR_TRUE); - - if(rv != SECSuccess) - if(hash != NULL) - { - SECITEM_FreeItem(hash, PR_TRUE); - hash = NULL; - } - - return hash; + hashObj->begin(ctx); + hashObj->update(ctx, src, len); + hashObj->end(ctx, dest, &retLen, hashObj->length); + hashObj->destroy(ctx, PR_TRUE); + return SECSuccess; } -/* generate bits using SHA1 hash +/* generate bits using any hash */ static SECItem * -sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, - PRBool faulty3DES) +nsspkcs5_PBKDF1(const SECHashObject *hashObj, SECItem *salt, SECItem *pwd, + int iter, PRBool faulty3DES) { SECItem *hash = NULL, *pre_hash = NULL; SECStatus rv = SECFailure; @@ -441,8 +108,8 @@ sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, if((hash != NULL) && (pre_hash != NULL)) { int i, ph_len; - ph_len = SHA1_LENGTH; - if((salt->len + pwd->len) > SHA1_LENGTH) { + ph_len = hashObj->length; + if((salt->len + pwd->len) > hashObj->length) { ph_len = salt->len + pwd->len; } @@ -450,21 +117,21 @@ sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, /* allocate buffers */ hash->data = (unsigned char *)PORT_ZAlloc(SHA1_LENGTH); - hash->len = SHA1_LENGTH; + hash->len = hashObj->length; pre_hash->data = (unsigned char *)PORT_ZAlloc(ph_len); /* in pbeSHA1TripleDESCBC there was an allocation error that made * it into the caller. We do not want to propagate those errors * further, so we are doing it correctly, but reading the old method. */ - if(faulty3DES) { + if (faulty3DES) { pre_hash->len = ph_len; } else { pre_hash->len = salt->len + pwd->len; } /* preform hash */ - if((hash->data != NULL) && (pre_hash->data != NULL)) { + if ((hash->data != NULL) && (pre_hash->data != NULL)) { rv = SECSuccess; /* check for 0 length password */ if(pwd->len > 0) { @@ -474,10 +141,11 @@ sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, PORT_Memcpy((pre_hash->data+pwd->len), salt->data, salt->len); } for(i = 0; ((i < iter) && (rv == SECSuccess)); i++) { - rv = SHA1_HashBuf(hash->data, pre_hash->data, pre_hash->len); + rv = nsspkcs5_HashBuf(hashObj, hash->data, + pre_hash->data, pre_hash->len); if(rv != SECFailure) { - pre_hash->len = SHA1_LENGTH; - PORT_Memcpy(pre_hash->data, hash->data, SHA1_LENGTH); + pre_hash->len = hashObj->length; + PORT_Memcpy(pre_hash->data, hash->data, hashObj->length); } } } @@ -495,101 +163,6 @@ sec_pkcs5_compute_sha1_hash(SECItem *salt, SECItem *pwd, int iter, return hash; } -/* bit generation/key and iv generation routines. */ -typedef SECItem *(* sec_pkcs5_hash_func)(SECItem *s, SECItem *p, - int iter, PRBool faulty3DES); - -/* generates bits needed for the key and iv based on PKCS 5, - * be concatenating the password and salt and using the appropriate - * hash algorithm. This function serves as a front end to the - * specific hash functions above. a return of NULL indicates an - * error. - */ -static SECItem * -sec_pkcs5_compute_hash(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) -{ - sec_pkcs5_hash_func hash_func; - SECOidTag hash_alg; - SECItem *hash = NULL; - SECItem *salt = NULL; - - hash_alg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - salt = &(pbe_param->salt); - switch(hash_alg) - { - case SEC_OID_SHA1: - hash_func = sec_pkcs5_compute_sha1_hash; - break; - case SEC_OID_MD2: - hash_func = sec_pkcs5_compute_md2_hash; - break; - case SEC_OID_MD5: - hash_func = sec_pkcs5_compute_md5_hash; - break; - default: - hash_func = NULL; - } - - if(hash_func) { - hash = (* hash_func)(salt, pwitem, pbe_param->iter, faulty3DES); - } - - return hash; -} - -/* determines the number of bits needed for key and iv generation - * based upon the algorithm identifier. if a number of - * bits greater than the hash algorithm can produce are needed, - * the bits will be generated based upon the extended PKCS 5 - * described in PKCS 12. - * - * a return of -1 indicates an error. - */ -static int -sec_pkcs5_bits_needed(SEC_PKCS5PBEParameter *pbe_param) -{ - int iv_bits; - int key_bits; - - if(pbe_param == NULL) { - return -1; - } - - iv_bits = sec_pkcs5_iv_length(pbe_param->algorithm) * 8; - key_bits = sec_pkcs5_key_length(pbe_param->algorithm) * 8; - - if(key_bits != 0) { - return iv_bits + key_bits; - } - - return -1; -} - -/* determines the number of bits generated by each hash algorithm. - * in case of an error, -1 is returned. - */ -static int -sec_pkcs5_hash_bits_generated(SEC_PKCS5PBEParameter *pbe_param) -{ - if(pbe_param == NULL) { - return -1; - } - - switch(sec_pkcs5_hash_algorithm(pbe_param->algorithm)) { - case SEC_OID_SHA1: - return SHA1_LENGTH * 8; - case SEC_OID_MD2: - return MD2_LENGTH * 8; - case SEC_OID_MD5: - return MD5_LENGTH * 8; - default: - break; - } - - return -1; -} - /* this bit generation routine is described in PKCS 12 and the proposed * extensions to PKCS 5. an initial hash is generated following the * instructions laid out in PKCS 5. If the number of bits generated is @@ -598,9 +171,8 @@ sec_pkcs5_hash_bits_generated(SEC_PKCS5PBEParameter *pbe_param) * function. And the P_Hash function from the TLS standard. */ static SECItem * -sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param, - SECItem *init_hash, - unsigned int bits_needed) +nsspkcs5_PFXPBE(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, + SECItem *init_hash, unsigned int bytes_needed) { SECItem *ret_bits = NULL; int hash_size = 0; @@ -612,12 +184,8 @@ sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param, unsigned int state_len; HMACContext *cx = NULL; - hash_size = sec_pkcs5_hash_bits_generated(pbe_param); - if(hash_size == -1) - return NULL; - - hash_iter = (bits_needed + (unsigned int)hash_size - 1) / hash_size; - hash_size /= 8; + hash_size = hashObj->length; + hash_iter = (bytes_needed + (unsigned int)hash_size - 1) / hash_size; /* allocate return buffer */ ret_bits = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); @@ -648,8 +216,7 @@ sec_pkcs5_bit_generator(SEC_PKCS5PBEParameter *pbe_param, PORT_Memcpy(state, pbe_param->salt.data, pbe_param->salt.len); } - cx = HMAC_Create(sec_pkcs5_hash_algorithm(pbe_param->algorithm), - init_hash->data, init_hash->len); + cx = HMAC_Create(hashObj, init_hash->data, init_hash->len); if (cx == NULL) { rv = SECFailure; goto loser; @@ -694,151 +261,371 @@ loser: * based on the extension proposed in PKCS 12 */ static SECItem * -sec_pkcs5_generate_bits(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) +nsspkcs5_PBKDF1Extended(const SECHashObject *hashObj, + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, PRBool faulty3DES) { SECItem * hash = NULL; SECItem * newHash = NULL; - int bits_needed; - int bits_available; + int bytes_needed; + int bytes_available; - bits_needed = sec_pkcs5_bits_needed(pbe_param); - bits_available = sec_pkcs5_hash_bits_generated(pbe_param); - - if((bits_needed == -1) || (bits_available == -1)) { - return NULL; - } + bytes_needed = pbe_param->ivLen + pbe_param->keyLen; + bytes_available = hashObj->length; + + hash = nsspkcs5_PBKDF1(hashObj, &pbe_param->salt, pwitem, + pbe_param->iter, faulty3DES); - hash = sec_pkcs5_compute_hash(pbe_param, pwitem, faulty3DES); if(hash == NULL) { return NULL; } - if(bits_needed <= bits_available) { + if(bytes_needed <= bytes_available) { return hash; } - newHash = sec_pkcs5_bit_generator(pbe_param, hash, bits_needed); + newHash = nsspkcs5_PFXPBE(hashObj, pbe_param, hash, bytes_needed); if (hash != newHash) SECITEM_FreeItem(hash, PR_TRUE); return newHash; } -/* compute the IV as per PKCS 5 +#ifdef PBKDF2 + +/* + * PBDKDF2 is PKCS #5 v2.0 it's currently not used by NSS */ -static SECItem * -sec_pkcs5_compute_iv(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) +/* + * We This is safe because hLen for all our + * HMAC algorithms are multiples of 4. + */ +static void +xorbytes(unsigned char *dest, unsigned char *src, int len) { - SECItem *hash = NULL, *iv = NULL; +#ifdef PARANOIA + while (len--) { + *dest = *dest ^ *src; + dest++; + src++; + } +#else + PRUInt32 dest32 = (PRUInt32 *)dest; + PRUInt32 src32 = (PRUInt32 *)dest; + while (len -= sizeof(PRUInt32)) { + *dest32 = *dest32 ^ *src32; + dest++; + src++; + } +#endif +} - if((pbe_param == NULL) || (pwitem == NULL)) { - return NULL; +static SECStatus +nsspkcs5_PBKFD2_F(const SECHashObject *hashobj, SECItem *pwitem, SECItem *salt, + int iterations, unsigned int i, unsigned char *T) +{ + int j; + HMACContext *cx = NULL; + unsigned int hLen = hashObject->length + SECStatus rv = SECFailure; + unsigned char *last = NULL; + int lastLength = salt->len + 4; + + cx=HMAC_Create(hashobj,pwitem->data,pwitem->len); + if (cx == NULL) { + goto loser; + } + PORT_Memset(T,0,hLen); + realLastLength= MAX(lastLength,hLen); + last = PORT_Alloc(realLastLength); + if (last == NULL) { + goto loser; + } + PORT_Memcpy(last,salt.data,salt.len); + last[salt->len ] = (i >> 24) & 0xff; + last[salt->len+1] = (i >> 16) & 0xff; + last[salt->len+2] = (i >> 8) & 0xff; + last[salt->len+3] = i & 0xff; + + /* NOTE: we need at least one iteration to return success! */ + for (j=0; j < interations; j++) { + rv =HMAC_Begin(cx); + if (rv !=SECSuccess) { + break; + } + HMAC_Update(cx,last,lastLength); + rv =HMAC_Finish(cx,last,&lastLength,hLen); + if (rv !=SECSuccess) { + break; + } + do_xor(T,last,hLen); + } +loser: + if (cx) { + HMAC_DestroyContext(cx); } + if (last) { + PORT_ZFree(last,reaLastLength); + } + return rv; +} - /* generate iv */ - iv = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!iv) { +static SECItem * +nsspkcs5_PBKFD2(const SECHashObject *hashObj, NSSPKCS5PBEParameter *pbe_param, + SECItem *pwitem) +{ + unsigned int dkLen = bytesNeeded; + unsigned int hLen = hashObject->length + unsigned int l = (dkLen+hLen-1) / hLen; + unsigned char *rp; + SECItem *result; + SECItem *salt = pbe_param->salt; + int interations = pbe_param->iter; + int bytesNeeded = pbe_param->keyLen; + + result = SECITEM_AllocItem(NULL,NULL,l*hLen); + if (result == NULL) { return NULL; } - iv->len = sec_pkcs5_iv_length(pbe_param->algorithm); - if(iv->len == -1) { - PORT_Free(iv); - return NULL; + T = PORT_Alloc(hLen); + if (T == NULL) { + goto loser; + } + + for (i=0,rp=results->data; i < l ; i++, rp +=hLen) { + rv = nsspkcs5_PBKFD2_F(hashobj,pwitem,salt,iterations,i,T); + if (rv != SECSuccess) { + break; + } + PORT_Memcpy(rp,T,hLen); + } + +loser: + if (T) { + PORT_ZFree(T); } + if (rv != SECSuccess) { + SECITEM_FreeITEM(result,PR_TRUE); + result = NULL; + } else { + result->len = dkLen; + } + + return result; +} +#endif - iv->data = (unsigned char *)PORT_ZAlloc(iv->len); - if(iv->data == NULL) { - PORT_Free(iv); +#define HMAC_BUFFER 64 +#define ROUNDUP(x,y) ((((x)+((y)-1))/(y))*(y)) +/* + * This is the extended PBE function defined by the final PKCS #12 spec. + */ +static SECItem * +nsspkcs5_PKCS12PBE(const SECHashObject *hashObject, + NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + PBEBitGenID bitGenPurpose, unsigned int bytesNeeded) +{ + PRArenaPool *arena = NULL; + unsigned int SLen,PLen; + unsigned int hashLength = hashObject->length; + unsigned char *S, *P; + SECItem *A = NULL, B, D, I; + SECItem *salt = &pbe_param->salt; + unsigned int c,i = 0; + unsigned int hashLen, n, iter; + unsigned char *iterBuf; + void *hash = NULL; + + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if(!arena) { return NULL; } - if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) { - SECOidTag hashAlg; - PBEBitGenContext *ctxt; - hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherIV, - pwitem, &pbe_param->salt, - iv->len * 8, pbe_param->iter); - if(!ctxt) { - SECITEM_FreeItem(iv, PR_TRUE); - return NULL; + /* how many hash object lengths are needed */ + c = (bytesNeeded + (hashLength-1))/hashLength; + + /* initialize our buffers */ + D.len = HMAC_BUFFER; + /* B and D are the same length, use one alloc go get both */ + D.data = (unsigned char*)PORT_ArenaZAlloc(arena, D.len*2); + B.len = D.len; + B.data = D.data + D.len; + + /* if all goes well, A will be returned, so don't use our temp arena */ + A = SECITEM_AllocItem(NULL,NULL,c*hashLength); + if (A == NULL) { + goto loser; + } + + SLen = ROUNDUP(salt->len,HMAC_BUFFER); + PLen = ROUNDUP(pwitem->len,HMAC_BUFFER); + I.len = SLen+PLen; + I.data = (unsigned char*)PORT_ArenaZAlloc(arena, I.len); + if (I.data == NULL) { + goto loser; + } + + /* S & P are only used to initialize I */ + S = I.data; + P = S + SLen; + + PORT_Memset(D.data, (char)bitGenPurpose, D.len); + if (SLen) { + PORT_Memcpy(S, salt->data, salt->len); + if (salt->len != SLen) { + PORT_Memcpy(S+salt->len, salt->data, SLen-(salt->len)); + } + } + if (PLen) { + PORT_Memcpy(P, salt->data, salt->len); + if (salt->len != PLen) { + PORT_Memcpy(P+salt->len, salt->data, PLen-salt->len); } + } - hash = PBE_GenerateBits(ctxt); - PBE_DestroyContext(ctxt); - } else { - hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES); + iterBuf = (unsigned char*)PORT_ArenaZAlloc(arena,hashLength); + if (iterBuf == NULL) { + goto loser; } + hash = hashObject->create(); if(!hash) { - SECITEM_FreeItem(iv, PR_TRUE); - return NULL; + goto loser; } + /* calculate the PBE now */ + for(i = 0; i < c; i++) { + int Bidx; /* must be signed or the for loop won't terminate */ + unsigned int k, j; + unsigned char *Ai = A->data+i*hashLength; - PORT_Memcpy(iv->data, (hash->data+(hash->len - iv->len)), iv->len); - SECITEM_FreeItem(hash, PR_TRUE); - return iv; + for(iter = 0; iter < pbe_param->iter; iter++) { + hashObject->begin(hash); + + if (iter) { + hashObject->update(hash, iterBuf, hashLen); + } else { + hashObject->update(hash, D.data, D.len); + hashObject->update(hash, I.data, I.len); + } + + hashObject->end(hash, iterBuf, &hashLen, hashObject->length); + if(hashLen != hashObject->length) { + break; + } + } + + PORT_Memcpy(&(A->data[i*hashLength]), iterBuf, hashLength); + for (Bidx = 0; Bidx < B.len; B.len += hashLength) { + PORT_Memcpy(B.data +Bidx, iterBuf, + (((Bidx + hashLength) > B.len) ? (B.len - Bidx) : + hashLength)); + } + + k = I.len/B.len; + for(j = 0; j < k; j++) { + unsigned int q, carryBit; + unsigned char *Ij = I.data + j*B.len; + + /* (Ij = Ij+B+1) */ + for (Bidx = (B.len-1), q=1, carryBit=0; Bidx >= 0; Bidx--,q=0) { + q += (unsigned int)Ij[Bidx]; + q += (unsigned int)B.data[Bidx]; + q += carryBit; + + carryBit = (q > 0xff); + Ij[Bidx] = (unsigned char)(q & 0xff); + } + } + } +loser: + if (hash) { + hashObject->destroy(hash, PR_TRUE); + } + if(arena) { + PORT_FreeArena(arena, PR_TRUE); + } + + /* if i != c, then we didn't complete the loop above and must of failed + * somwhere along the way */ + if (i != c) { + SECITEM_ZfreeItem(A,PR_TRUE); + A = NULL; + } else { + A->len = bytesNeeded; + } + + return A; } -/* generate key as per PKCS 5 +/* + * generate key as per PKCS 5 */ -static SECItem * -sec_pkcs5_compute_key(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, - PRBool faulty3DES) +SECItem * +nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + SECItem *iv, PRBool faulty3DES) { SECItem *hash = NULL, *key = NULL; + const SECHashObject *hashObj; + PRBool getIV = PR_FALSE; if((pbe_param == NULL) || (pwitem == NULL)) { return NULL; } - key = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); - if(!key) { + key = SECITEM_AllocItem(NULL,NULL,pbe_param->keyLen); + if (key == NULL) { return NULL; } - key->len = sec_pkcs5_key_length(pbe_param->algorithm); - if(key->len == -1) { - PORT_Free(key); - return NULL; - } - - key->data = (unsigned char *)PORT_ZAlloc(sizeof(unsigned char) * - key->len); - if(!key->data) { - PORT_Free(key); - return NULL; + if ((pbe_param->ivLen) && (iv->data == NULL)) { + getIV = PR_TRUE; + iv->data = (unsigned char *)PORT_Alloc(pbe_param->ivLen); + if (iv->data == NULL) { + goto loser; + } + iv->len = pbe_param->ivLen; } - - if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(pbe_param->algorithm)) { - SECOidTag hashAlg; - PBEBitGenContext *ctxt; - hashAlg = sec_pkcs5_hash_algorithm(pbe_param->algorithm); - ctxt = PBE_CreateContext(hashAlg, pbeBitGenCipherKey, - pwitem, &pbe_param->salt, - key->len * 8, pbe_param->iter); - if(!ctxt) { - SECITEM_FreeItem(key, PR_TRUE); - return NULL; + hashObj = &SECRawHashObjects[pbe_param->hashType]; + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + hash = nsspkcs5_PBKDF1Extended(hashObj,pbe_param,pwitem,faulty3DES); + if (hash == NULL) { + goto loser; } - - hash = PBE_GenerateBits(ctxt); - PBE_DestroyContext(ctxt); - } else { - hash = sec_pkcs5_generate_bits(pbe_param, pwitem, faulty3DES); + PORT_Assert(hash->len >= key->len+iv->len); + if (getIV) { + PORT_Memcpy(iv->data, hash->data+(hash->len - iv->len),iv->len); + } + break; +#ifdef PBKDF2 + case NSSPKCS5_PBKDF2: + hash = nsspkcs5_PBKDF2(hashObj,pbe_param,pwitem); + PORT_Assert(!getIV); + break; +#endif + case NSSPKCS5_PKCS12_V2: + if (getIV) { + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, + pbeBitGenCipherIV,iv->len); + if (hash == NULL) { + goto loser; + } + PORT_Memcpy(iv->data,hash->data,iv->len); + SECITEM_ZfreeItem(hash,PR_TRUE); + hash = NULL; + } + hash = nsspkcs5_PKCS12PBE(hashObj,pbe_param,pwitem, + pbeBitGenCipherKey,key->len); + default: + break; } - - if(!hash) { - SECITEM_FreeItem(key, PR_TRUE); - return NULL; + + if (hash == NULL) { + goto loser; } - if(pbe_param->algorithm == - SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC) { + if (pbe_param->is2KeyDES) { PORT_Memcpy(key->data, hash->data, (key->len * 2) / 3); PORT_Memcpy(&(key->data[(key->len * 2) / 3]), key->data, key->len / 3); @@ -848,58 +635,174 @@ sec_pkcs5_compute_key(SEC_PKCS5PBEParameter *pbe_param, SECItem *pwitem, SECITEM_FreeItem(hash, PR_TRUE); return key; + +loser: + if (getIV && iv->data) { + PORT_ZFree(iv->data,iv->len); + iv->data = NULL; + } + + SECITEM_ZfreeItem(key, PR_TRUE); + return NULL; +} + +static SECStatus +nsspkcs5_FillInParam(SECOidTag algorithm, NSSPKCS5PBEParameter *pbe_param) +{ + PRBool skipType = PR_FALSE; + + pbe_param->keyLen = 5; + pbe_param->ivLen = 8; + pbe_param->hashType = HASH_AlgSHA1; + pbe_param->pbeType = NSSPKCS5_PBKDF1; + pbe_param->encAlg = SEC_OID_RC2_CBC; + pbe_param->is2KeyDES = PR_FALSE; + switch(algorithm) { + /* DES3 Algorithms */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: + pbe_param->is2KeyDES = PR_TRUE; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: + pbe_param->keyLen = 24; + pbe_param->encAlg = SEC_OID_DES_EDE3_CBC; + break; + + /* DES Algorithms */ + case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: + pbe_param->hashType = HASH_AlgMD2; + goto finish_des; + case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: + pbe_param->hashType = HASH_AlgMD5; + /* fall through */ + case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: +finish_des: + pbe_param->keyLen = 8; + pbe_param->encAlg = SEC_OID_DES_CBC; + break; + + /* RC2 Algorithms */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + break; + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: + break; + + /* RC4 algorithms */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: + skipType = PR_TRUE; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: + pbe_param->keyLen = 16; + /* fall through */ + case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: + if (!skipType) { + pbe_param->pbeType = NSSPKCS5_PKCS12_V2; + } + /* fall through */ + case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: + pbe_param->ivLen = 0; + pbe_param->encAlg = SEC_OID_RC4; + break; + default: + return SECFailure; + } + + return SECSuccess; } /* decode the algid and generate a PKCS 5 parameter from it */ -static SEC_PKCS5PBEParameter * -sec_pkcs5_convert_algid(SECAlgorithmID *algid) +NSSPKCS5PBEParameter * +nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator) { - PRArenaPool *poolp; - SEC_PKCS5PBEParameter *pbe_param = NULL; + PRArenaPool *arena = NULL; + NSSPKCS5PBEParameter *pbe_param = NULL; SECOidTag algorithm; SECStatus rv = SECFailure; - if(algid == NULL) + arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); + if (arena == NULL) return NULL; - algorithm = SECOID_GetAlgorithmTag(algid); - - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) - return NULL; + /* allocate memory for the parameter */ + pbe_param = (NSSPKCS5PBEParameter *)PORT_ArenaZAlloc(arena, + sizeof(NSSPKCS5PBEParameter)); + + if (pbe_param == NULL) { + goto loser; + } + + pbe_param->poolp = arena; + + rv = nsspkcs5_FillInParam(alg, pbe_param); + if (rv != SECSuccess) { + goto loser; + } + + pbe_param->iter = iterator; + if (salt) { + rv = SECITEM_CopyItem(arena,&pbe_param->salt,salt); + } + +loser: + if (rv != SECSuccess) { + PORT_FreeArena(arena, PR_TRUE); + pbe_param = NULL; + } + + return pbe_param; +} + +/* decode the algid and generate a PKCS 5 parameter from it + */ +NSSPKCS5PBEParameter * +nsspkcs5_AlgidToParam(SECAlgorithmID *algid) +{ + NSSPKCS5PBEParameter *pbe_param = NULL; + SECOidTag algorithm; + SECStatus rv = SECFailure; - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(poolp == NULL) + if (algid == NULL) { return NULL; + } - /* allocate memory for the parameter */ - pbe_param = (SEC_PKCS5PBEParameter *)PORT_ArenaZAlloc(poolp, - sizeof(SEC_PKCS5PBEParameter)); + algorithm = SECOID_GetAlgorithmTag(algid); + if (algorithm == SEC_OID_UNKNOWN) { + goto loser; + } + + pbe_param = nsspkcs5_NewParam(algorithm, NULL, 1); + if (pbe_param == NULL) { + goto loser; + } /* decode parameter */ - if(pbe_param && !sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - pbe_param->poolp = poolp; - rv = SEC_ASN1DecodeItem(poolp, pbe_param, - SEC_PKCS5PBEParameterTemplate, &algid->parameters); - if(rv != SECSuccess) { - goto loser; - } - pbe_param->algorithm = algorithm; - pbe_param->iter = DER_GetInteger(&pbe_param->iteration); - } else if(sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - pbe_param->algorithm = algorithm; - pbe_param->poolp = poolp; - rv = SEC_ASN1DecodeItem(poolp, pbe_param, SEC_V2PKCS12PBEParameterTemplate, - &algid->parameters); - if(rv != SECSuccess) { - goto loser; - } - pbe_param->iter = DER_GetInteger(&pbe_param->iteration); + rv = SECFailure; + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, + NSSPKCS5PBEParameterTemplate, &algid->parameters); + case NSSPKCS5_PKCS12_V2: + rv = SEC_ASN1DecodeItem(pbe_param->poolp, pbe_param, + NSSPKCS5PKCS12V2PBEParameterTemplate, &algid->parameters); + case NSSPKCS5_PBKDF2: + break; } loser: - if((pbe_param == NULL) || (rv != SECSuccess)) { - PORT_FreeArena(poolp, PR_TRUE); + if (rv == SECSuccess) { + pbe_param->iter = DER_GetInteger(&pbe_param->iteration); + } else { + nsspkcs5_DestroyPBEParameter(pbe_param); pbe_param = NULL; } @@ -910,59 +813,22 @@ loser: * generated using the appropriate create function and therefor * contains an arena pool. */ -static void -sec_pkcs5_destroy_pbe_param(SEC_PKCS5PBEParameter *pbe_param) +void +nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *pbe_param) { - if(pbe_param != NULL) + if (pbe_param != NULL) { PORT_FreeArena(pbe_param->poolp, PR_TRUE); + } } /* crypto routines */ - -/* function pointer template for crypto functions */ -typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, - SECItem *src, PRBool op1, PRBool op2); - -/* map PBE algorithm to crypto algorithm */ -static SECOidTag -sec_pkcs5_encryption_algorithm(SECOidTag algorithm) -{ - switch(algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - return SEC_OID_DES_EDE3_CBC; - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - return SEC_OID_DES_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_RC2_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return SEC_OID_RC4; - default: - break; - } - return SEC_OID_UNKNOWN; -} - /* perform DES encryption and decryption. these routines are called - * by SEC_PKCS5CipherData. In the case of an error, NULL is returned. + * by nsspkcs5_CipherData. In the case of an error, NULL is returned. */ static SECItem * -sec_pkcs5_des(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool triple_des, - PRBool encrypt) +sec_pkcs5_des(SECItem *key, SECItem *iv, SECItem *src, PRBool triple_des, + PRBool encrypt) { SECItem *dest; SECItem *dup_src; @@ -1041,11 +907,8 @@ sec_pkcs5_des(SECItem *key, /* perform rc2 encryption/decryption if an error occurs, NULL is returned */ static SECItem * -sec_pkcs5_rc2(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool cbc_mode, - PRBool encrypt) +sec_pkcs5_rc2(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy, + PRBool encrypt) { SECItem *dest; SECItem *dup_src; @@ -1079,9 +942,8 @@ sec_pkcs5_rc2(SECItem *key, if(dest->data != NULL) { RC2Context *ctxt; - ctxt = RC2_CreateContext(key->data, key->len, iv->data, - ((cbc_mode != PR_TRUE) ? NSS_RC2 : NSS_RC2_CBC), - key->len); + ctxt = RC2_CreateContext(key->data, key->len, iv->data, + NSS_RC2_CBC, key->len); if(ctxt != NULL) { rv = ((encrypt != PR_TRUE) ? RC2_Decrypt : RC2_Encrypt)( @@ -1089,8 +951,7 @@ sec_pkcs5_rc2(SECItem *key, dup_src->len + 64, dup_src->data, dup_src->len); /* assumes 8 byte blocks -- remove padding */ - if((rv == SECSuccess) && (encrypt != PR_TRUE) && - (cbc_mode == PR_TRUE)) { + if((rv == SECSuccess) && (encrypt != PR_TRUE)) { pad = dest->data[dest->len-1]; if((pad > 0) && (pad <= 8)) { if(dest->data[dest->len-pad] != pad) { @@ -1123,11 +984,8 @@ sec_pkcs5_rc2(SECItem *key, /* perform rc4 encryption and decryption */ static SECItem * -sec_pkcs5_rc4(SECItem *key, - SECItem *iv, - SECItem *src, - PRBool dummy_op, - PRBool encrypt) +sec_pkcs5_rc4(SECItem *key, SECItem *iv, SECItem *src, PRBool dummy_op, + PRBool encrypt) { SECItem *dest; SECStatus rv = SECFailure; @@ -1160,6 +1018,9 @@ sec_pkcs5_rc4(SECItem *key, return dest; } +/* function pointer template for crypto functions */ +typedef SECItem *(* pkcs5_crypto_func)(SECItem *key, SECItem *iv, + SECItem *src, PRBool op1, PRBool op2); /* performs the cipher operation on the src and returns the result. * if an error occurs, NULL is returned. @@ -1169,88 +1030,75 @@ sec_pkcs5_rc4(SECItem *key, */ /* change this to use PKCS 11? */ SECItem * -SEC_PKCS5CipherData(SECAlgorithmID *algid, - SECItem *pwitem, - SECItem *src, - PRBool encrypt, PRBool *update) +nsspkcs5_CipherData(NSSPKCS5PBEParameter *pbe_param, SECItem *pwitem, + SECItem *src, PRBool encrypt, PRBool *update) { - SEC_PKCS5PBEParameter *pbe_param; - SECOidTag enc_alg; - SECItem *key = NULL, *iv = NULL; + SECItem *key = NULL, iv; SECItem *dest = NULL; - int iv_len; + PRBool tripleDES = PR_TRUE; + pkcs5_crypto_func cryptof; + + iv.data = NULL; if (update) { *update = PR_FALSE; } - if((algid == NULL) || (pwitem == NULL) || (src == NULL)) { + if ((pwitem == NULL) || (src == NULL)) { return NULL; } - /* convert algid to pbe parameter */ - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) { + /* get key, and iv */ + key = nsspkcs5_ComputeKeyAndIV(pbe_param, pwitem, &iv, PR_FALSE); + if(key == NULL) { return NULL; } - /* get algorithm, key, and iv */ - enc_alg = sec_pkcs5_encryption_algorithm(pbe_param->algorithm); - key = sec_pkcs5_compute_key(pbe_param, pwitem, PR_FALSE); - if(key != NULL) { - iv_len = sec_pkcs5_iv_length(pbe_param->algorithm); - iv = sec_pkcs5_compute_iv(pbe_param, pwitem, PR_FALSE); - - if((iv != NULL) || (iv_len == 0)) { - /*perform encryption / decryption */ - PRBool op1 = PR_TRUE; - pkcs5_crypto_func cryptof; - - switch(enc_alg) { - case SEC_OID_DES_EDE3_CBC: - cryptof = sec_pkcs5_des; - break; - case SEC_OID_DES_CBC: - cryptof = sec_pkcs5_des; - op1 = PR_FALSE; - break; - case SEC_OID_RC2_CBC: - cryptof = sec_pkcs5_rc2; - break; - case SEC_OID_RC4: - cryptof = sec_pkcs5_rc4; - break; - default: - cryptof = NULL; - break; - } - - if(cryptof) { - dest = (*cryptof)(key, iv, src, op1, encrypt); - /* - * it's possible for some keys and keydb's to claim to - * be triple des when they're really des. In this case - * we simply try des. If des works we set the update flag - * so the key db knows it needs to update all it's entries. - * The case can only happen on decrypted of a - * SEC_OID_DES_EDE3_CBD. - */ - if ((dest == NULL) && (encrypt == PR_FALSE) && - (enc_alg == SEC_OID_DES_EDE3_CBC)) { - dest = (*cryptof)(key, iv, src, PR_FALSE, encrypt); - if (update && (dest != NULL)) *update = PR_TRUE; - } - } - } + switch(pbe_param->encAlg) { + case SEC_OID_DES_EDE3_CBC: + cryptof = sec_pkcs5_des; + tripleDES = PR_TRUE; + break; + case SEC_OID_DES_CBC: + cryptof = sec_pkcs5_des; + tripleDES = PR_FALSE; + break; + case SEC_OID_RC2_CBC: + cryptof = sec_pkcs5_rc2; + break; + case SEC_OID_RC4: + cryptof = sec_pkcs5_rc4; + break; + default: + cryptof = NULL; + break; + } + + if(cryptof) { + goto loser; } - sec_pkcs5_destroy_pbe_param(pbe_param); + dest = (*cryptof)(key, &iv, src, tripleDES, encrypt); + /* + * it's possible for some keys and keydb's to claim to + * be triple des when they're really des. In this case + * we simply try des. If des works we set the update flag + * so the key db knows it needs to update all it's entries. + * The case can only happen on decrypted of a + * SEC_OID_DES_EDE3_CBD. + */ + if ((dest == NULL) && (encrypt == PR_FALSE) && + (pbe_param->encAlg == SEC_OID_DES_EDE3_CBC)) { + dest = (*cryptof)(key, &iv, src, PR_FALSE, encrypt); + if (update && (dest != NULL)) *update = PR_TRUE; + } - if(key != NULL) { +loser: + if (key != NULL) { SECITEM_ZfreeItem(key, PR_TRUE); } - if(iv != NULL) { - SECITEM_ZfreeItem(iv, PR_TRUE); + if (iv.data != NULL) { + SECITEM_ZfreeItem(&iv, PR_FALSE); } return dest; @@ -1265,585 +1113,60 @@ SEC_PKCS5CipherData(SECAlgorithmID *algid, * SECOID_DestroyAlgorithmID */ SECAlgorithmID * -SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, - SECItem *salt, - int iteration) +nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm, + NSSPKCS5PBEParameter *pbe_param) { - PRArenaPool *poolp = NULL; SECAlgorithmID *algid, *ret_algid; SECItem der_param; SECStatus rv = SECFailure; - SEC_PKCS5PBEParameter *pbe_param; - - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) - return NULL; + void *dummy = NULL; - if(iteration <= 0) { + if (arena == NULL) { return NULL; } der_param.data = NULL; der_param.len = 0; - /* generate the parameter */ - pbe_param = sec_pkcs5_create_pbe_parameter(algorithm, salt, iteration); - if(!pbe_param) { - return NULL; - } - - poolp = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); - if(!poolp) { - sec_pkcs5_destroy_pbe_param(pbe_param); - return NULL; - } - /* generate the algorithm id */ - algid = (SECAlgorithmID *)PORT_ArenaZAlloc(poolp, sizeof(SECAlgorithmID)); - if(algid != NULL) { - void *dummy; - if(!sec_pkcs5_is_algorithm_v2_pkcs12_algorithm(algorithm)) { - dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, - SEC_PKCS5PBEParameterTemplate); - } else { - dummy = SEC_ASN1EncodeItem(poolp, &der_param, pbe_param, - SEC_V2PKCS12PBEParameterTemplate); - } - - if(dummy) { - rv = SECOID_SetAlgorithmID(poolp, algid, algorithm, &der_param); - } - } - - ret_algid = NULL; - if(algid != NULL) { - ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); - if(ret_algid != NULL) { - rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); - if(rv != SECSuccess) { - SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); - ret_algid = NULL; - } - } - } - - if(poolp != NULL) { - PORT_FreeArena(poolp, PR_TRUE); - algid = NULL; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return ret_algid; -} - -/* wrapper for converting the algid to a pbe parameter. - */ -SEC_PKCS5PBEParameter * -SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid) -{ - if(algid) { - return sec_pkcs5_convert_algid(algid); - } - - return NULL; -} - -/* destroy a pbe parameter */ -void -SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *pbe_param) -{ - sec_pkcs5_destroy_pbe_param(pbe_param); -} - -/* return the initialization vector either the preset one if it - * exists or generated based on pkcs 5. - * - * a null length password is allowed...but not a null password - * secitem. - */ -SECItem * -SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) -{ - SECItem *iv; - SEC_PKCS5PBEParameter *pbe_param; - - if((algid == NULL) || (pwitem == NULL)) { - return NULL; - } - - pbe_param = sec_pkcs5_convert_algid(algid); - if(!pbe_param) { - return NULL; - } - - iv = sec_pkcs5_compute_iv(pbe_param, pwitem, faulty3DES); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return iv; -} - -/* generate the key - * a 0 length password is allowed. corresponds to a key generated - * from just the salt. - */ -SECItem * -SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES) -{ - SECItem *key; - SEC_PKCS5PBEParameter *pbe_param; - - if((algid == NULL) || (pwitem == NULL)) { - return NULL; - } - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) { - return NULL; - } - - key = sec_pkcs5_compute_key(pbe_param, pwitem, faulty3DES); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return key; -} - -/* retrieve the salt */ -SECItem * -SEC_PKCS5GetSalt(SECAlgorithmID *algid) -{ - SECItem *salt; - SEC_PKCS5PBEParameter *pbe_param; - - if(algid == NULL) - return NULL; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return NULL; - - if(pbe_param->salt.data) { - salt = SECITEM_DupItem(&pbe_param->salt); - } else { - salt = NULL; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return salt; -} - -/* check to see if an oid is a pbe algorithm - */ -PRBool -SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid) -{ - SECOidTag algorithm; - - algorithm = SECOID_GetAlgorithmTag(algid); - if(sec_pkcs5_hash_algorithm(algorithm) == SEC_OID_UNKNOWN) { - return PR_FALSE; - } - - return PR_TRUE; -} - -int -SEC_PKCS5GetKeyLength(SECAlgorithmID *algid) -{ - SEC_PKCS5PBEParameter *pbe_param; - int keyLen = -1; - - if(algid == NULL) - return -1; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return -1; - - keyLen = sec_pkcs5_key_length(pbe_param->algorithm); - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return keyLen; -} - -/* maps crypto algorithm from PBE algorithm. - */ -SECOidTag -SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid) -{ - SEC_PKCS5PBEParameter *pbe_param; - - if(algid == NULL) - return SEC_OID_UNKNOWN; - - pbe_param = sec_pkcs5_convert_algid(algid); - if(pbe_param == NULL) - return SEC_OID_UNKNOWN; - - switch(pbe_param->algorithm) - { - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC: - return SEC_OID_DES_EDE3_CBC; - case SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC: - case SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC: - return SEC_OID_DES_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC: - return SEC_OID_RC2_CBC; - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_40_BIT_RC4: - case SEC_OID_PKCS12_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4: - case SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4: - return SEC_OID_RC4; - default: - break; - } - - sec_pkcs5_destroy_pbe_param(pbe_param); - - return SEC_OID_UNKNOWN; -} - -/* maps PBE algorithm from crypto algorithm, assumes SHA1 hashing. - */ -SECOidTag -SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen) -{ - switch(algTag) - { - case SEC_OID_DES_EDE3_CBC: - switch(keyLen) { - case 168: - case 192: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC; - case 128: - case 92: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_2KEY_TRIPLE_DES_CBC; - default: - break; - } - break; - case SEC_OID_DES_CBC: - return SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC; - case SEC_OID_RC2_CBC: - switch(keyLen) { - case 40: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC; - case 128: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC; - default: - break; - } - break; - case SEC_OID_RC4: - switch(keyLen) { - case 40: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4; - case 128: - return SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4; - default: - break; - } - break; - default: - break; - } - - return SEC_OID_UNKNOWN; -} - -/* zero length password and salts are allowed. however, the items - * containing the salt and password must be non-null. - */ -PBEBitGenContext * -__PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int iterations) -{ - PRArenaPool *arena = NULL; - PBEBitGenContext *pbeCtxt = NULL; - HASH_HashType pbeHash; - int vbytes, ubytes; - - unsigned int c; - - if(!pwitem || !salt) { - return NULL; - } - - arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); - if(!arena) { - return NULL; - } - - pbeCtxt = (PBEBitGenContext*)PORT_ArenaZAlloc(arena, sizeof(PBEBitGenContext)); - if(!pbeCtxt) { + algid = (SECAlgorithmID *)PORT_ArenaZAlloc(arena, sizeof(SECAlgorithmID)); + if (algid == NULL) { goto loser; } - - switch(hashAlgorithm) { - case SEC_OID_MD2: - pbeHash = HASH_AlgMD2; - break; - case SEC_OID_MD5: - pbeHash = HASH_AlgMD5; - break; - case SEC_OID_SHA1: - pbeHash = HASH_AlgSHA1; - break; - default: - goto loser; + switch (pbe_param->pbeType) { + case NSSPKCS5_PBKDF1: + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, + NSSPKCS5PBEParameterTemplate); + break; + case NSSPKCS5_PKCS12_V2: + dummy = SEC_ASN1EncodeItem(arena, &der_param, pbe_param, + NSSPKCS5PKCS12V2PBEParameterTemplate); + break; + default: + break; } - pbeCtxt->hashObject = &SECRawHashObjects[pbeHash]; - PORT_Memcpy(&pbeCtxt->pbeParams, &pbeHashAlgorithmParams[pbeHash], - sizeof(pbeBitGenParameters)); - PORT_Assert(pbeCtxt->pbeParams.hashAlgorithm == hashAlgorithm); - - vbytes = pbeCtxt->pbeParams.v / 8; - ubytes = pbeCtxt->pbeParams.u / 8; - - c = (bitsNeeded / pbeCtxt->pbeParams.u); - c += ((bitsNeeded - (pbeCtxt->pbeParams.u * c)) > 0) ? 1 : 0; - pbeCtxt->c = c; - pbeCtxt->n = bitsNeeded; - pbeCtxt->iterations = iterations; - - /* allocate buffers */ - pbeCtxt->D.len = vbytes; - pbeCtxt->S.len = (((salt->len * 8) / pbeCtxt->pbeParams.v) + - ((((salt->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) * - vbytes; - pbeCtxt->P.len = (((pwitem->len * 8) / pbeCtxt->pbeParams.v) + - ((((pwitem->len * 8) % pbeCtxt->pbeParams.v) > 0) ? 1 : 0)) * - vbytes; - pbeCtxt->I.len = pbeCtxt->S.len + pbeCtxt->P.len; - pbeCtxt->A.len = c * ubytes; - pbeCtxt->B.len = pbeCtxt->D.len; - - pbeCtxt->D.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->D.len); - if(pbeCtxt->S.len) { - pbeCtxt->S.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->S.len); - } - if(pbeCtxt->P.len) { - pbeCtxt->P.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->P.len); - } - if(pbeCtxt->I.len) { - pbeCtxt->I.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->I.len); - } - pbeCtxt->A.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->A.len); - pbeCtxt->B.data = (unsigned char*)PORT_ArenaZAlloc(arena, pbeCtxt->B.len); - - if(!pbeCtxt->D.data || !pbeCtxt->A.data || !pbeCtxt->B.data || - (!pbeCtxt->S.data && pbeCtxt->S.len) || - (!pbeCtxt->P.data && pbeCtxt->P.len) || - (!pbeCtxt->I.data && pbeCtxt->I.len)) { + if (dummy == NULL) { goto loser; } - - PORT_Memset(pbeCtxt->D.data, (char)bitGenPurpose, pbeCtxt->D.len); - if(pbeCtxt->P.len) { - unsigned int z = 0; - while(z < pbeCtxt->P.len) { - PORT_Memcpy(&(pbeCtxt->P.data[z]), pwitem->data, - ((z + pwitem->len > pbeCtxt->P.len) ? (pbeCtxt->P.len - z) : - (pwitem->len))); - z += pwitem->len; - } - } - if(pbeCtxt->S.len) { - unsigned int z = 0; - while(z < pbeCtxt->S.len) { - PORT_Memcpy(&(pbeCtxt->S.data[z]), salt->data, - ((z + salt->len > pbeCtxt->S.len) ? (pbeCtxt->S.len - z) : - (salt->len))); - z += salt->len; - } - } - if(pbeCtxt->I.len) { - if(pbeCtxt->S.len) { - PORT_Memcpy(pbeCtxt->I.data, pbeCtxt->S.data, pbeCtxt->S.len); - } - if(pbeCtxt->P.len) { - PORT_Memcpy(&(pbeCtxt->I.data[pbeCtxt->S.len]), pbeCtxt->P.data, - pbeCtxt->P.len); - } - } - - pbeCtxt->arena = arena; - - return pbeCtxt; - -loser: - if(arena) { - PORT_FreeArena(arena, PR_TRUE); - } - - return NULL; -} - -PBEBitGenContext * -PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int iterations) -{ - return __PBE_CreateContext(hashAlgorithm, bitGenPurpose, pwitem, - salt, bitsNeeded, iterations); -} - -SECItem * -__PBE_GenerateBits(PBEBitGenContext *pbeCtxt) -{ - unsigned int i; - SECItem *A, *D, *I, *B, *S, *P; - unsigned int u, v, c, z, hashLen, n, iter; - unsigned int vbyte, ubyte; - unsigned char *iterBuf; - void *hash = NULL; - - if(!pbeCtxt) { - return NULL; - } - - A = &pbeCtxt->A; - B = &pbeCtxt->B; - I = &pbeCtxt->I; - D = &pbeCtxt->D; - S = &pbeCtxt->S; - P = &pbeCtxt->P; - u = pbeCtxt->pbeParams.u; - v = pbeCtxt->pbeParams.v; - vbyte = v / 8; - ubyte = u / 8; - c = pbeCtxt->c; - n = pbeCtxt->n; - z = 0; - - iterBuf = (unsigned char*)PORT_Alloc(ubyte); - if(!iterBuf) { + + rv = SECOID_SetAlgorithmID(arena, algid, algorithm, &der_param); + if (rv != SECSuccess) { goto loser; } - for(i = 1; i <= c; i++) { - unsigned int Bidx; - unsigned int k, j; - - - for(iter = 1; iter <= pbeCtxt->iterations; iter++) { - hash = pbeCtxt->hashObject->create(); - if(!hash) { - goto loser; - } - - pbeCtxt->hashObject->begin(hash); - - if(iter == 1) { - pbeCtxt->hashObject->update(hash, D->data, D->len); - pbeCtxt->hashObject->update(hash, I->data, I->len); - } else { - pbeCtxt->hashObject->update(hash, iterBuf, hashLen); - } - - pbeCtxt->hashObject->end(hash, iterBuf, &hashLen, (ubyte)); - pbeCtxt->hashObject->destroy(hash, PR_TRUE); - if(hashLen != (ubyte)) { - goto loser; - } - } - - PORT_Memcpy(&(A->data[z]), iterBuf, (ubyte)); - - Bidx = 0; - while(Bidx < B->len) { - PORT_Memcpy(&(B->data[Bidx]), &(A->data[z]), - (((Bidx + (ubyte)) > B->len) ? (B->len - Bidx) : - (ubyte))); - Bidx += (ubyte); - } - - k = (S->len / (vbyte)) + (P->len / (vbyte)); - for(j = 0; j < k; j++) { - unsigned int byteIdx = (vbyte); - unsigned int q, carryBit = 0; - - while(byteIdx > 0) { - q = (unsigned int)I->data[(j * (vbyte)) + byteIdx - 1]; - q += (unsigned int)B->data[byteIdx - 1]; - q += carryBit; - if(byteIdx == (vbyte)) { - q += 1; - } - - carryBit = ((q > 255) ? 1 : 0); - - I->data[(j * (vbyte)) + byteIdx - 1] = (unsigned char)(q & 255); - - byteIdx--; - } - } - - z += (ubyte); - } - - A->len = (n / 8); - - return SECITEM_DupItem(A); - -loser: - return NULL; -} - -SECItem * -PBE_GenerateBits(PBEBitGenContext *pbeCtxt) -{ - return __PBE_GenerateBits(pbeCtxt); -} - -void -__PBE_DestroyContext(PBEBitGenContext *pbeCtxt) -{ - if(pbeCtxt) { - PORT_FreeArena(pbeCtxt->arena, PR_TRUE); + ret_algid = (SECAlgorithmID *)PORT_ZAlloc(sizeof(SECAlgorithmID)); + if (ret_algid == NULL) { + goto loser; } -} - -void -PBE_DestroyContext(PBEBitGenContext *pbeCtxt) -{ - __PBE_DestroyContext(pbeCtxt); -} -SECStatus -PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, PRArenaPool *arena, - SECAlgorithmID *algId) -{ - CK_PBE_PARAMS *pbe_param; - SECItem pbeSalt; - SECAlgorithmID *pbeAlgID = NULL; - SECStatus rv; - - if(!param || !algId) { - return SECFailure; + rv = SECOID_CopyAlgorithmID(NULL, ret_algid, algid); + if (rv != SECSuccess) { + SECOID_DestroyAlgorithmID(ret_algid, PR_TRUE); + ret_algid = NULL; } - pbe_param = (CK_PBE_PARAMS *)param->data; - pbeSalt.data = (unsigned char *)pbe_param->pSalt; - pbeSalt.len = pbe_param->ulSaltLen; - pbeAlgID = SEC_PKCS5CreateAlgorithmID(algTag, &pbeSalt, - (int)pbe_param->ulIteration); - if(!pbeAlgID) { - return SECFailure; - } +loser: - rv = SECOID_CopyAlgorithmID(arena, algId, pbeAlgID); - SECOID_DestroyAlgorithmID(pbeAlgID, PR_TRUE); - return rv; + return ret_algid; } diff --git a/security/nss/lib/softoken/secpkcs5.h b/security/nss/lib/softoken/secpkcs5.h index d538450dd..8ddee11a6 100644 --- a/security/nss/lib/softoken/secpkcs5.h +++ b/security/nss/lib/softoken/secpkcs5.h @@ -50,36 +50,28 @@ typedef enum { pbeBitGenIntegrityKey = 0x03 } PBEBitGenID; -typedef struct _pbeBitGenParameters { - unsigned int u, v; - SECOidTag hashAlgorithm; -} pbeBitGenParameters; - -typedef struct _PBEBitGenContext { - PRArenaPool *arena; - - /* hash algorithm information */ - pbeBitGenParameters pbeParams; - const SECHashObject *hashObject; - void *hash; - - /* buffers used in generation of bits */ - SECItem D, S, P, I, A, B; - unsigned int c, n; - unsigned int iterations; -} PBEBitGenContext; +typedef enum { + NSSPKCS5_PBKDF1 = 0, + NSSPKCS5_PBKDF2 = 1, + NSSPKCS5_PKCS12_V2 = 2 +} NSSPKCS5PBEType; -extern const SEC_ASN1Template SEC_PKCS5PBEParameterTemplate[]; -typedef struct SEC_PKCS5PBEParameterStr SEC_PKCS5PBEParameter; +typedef struct NSSPKCS5PBEParameterStr NSSPKCS5PBEParameter; -struct SEC_PKCS5PBEParameterStr { +struct NSSPKCS5PBEParameterStr { PRArenaPool *poolp; SECItem salt; /* octet string */ SECItem iteration; /* integer */ /* used locally */ - SECOidTag algorithm; int iter; + int keyLen; + int ivLen; + HASH_HashType hashType; + NSSPKCS5PBEType pbeType; + PBEBitGenID keyID; + SECOidTag encAlg; + PRBool is2KeyDES; }; @@ -87,46 +79,32 @@ SEC_BEGIN_PROTOS /* Create a PKCS5 Algorithm ID * The algorithm ID is set up using the PKCS #5 parameter structure * algorithm is the PBE algorithm ID for the desired algorithm - * salt can be specified or can be NULL, if salt is NULL then the - * salt is generated from random bytes - * iteration is the number of iterations for which to perform the - * hash prior to key and iv generation. + * pbe is a pbe param block with all the info needed to create the + * algorithm id. * If an error occurs or the algorithm specified is not supported * or is not a password based encryption algorithm, NULL is returned. * Otherwise, a pointer to the algorithm id is returned. */ extern SECAlgorithmID * -SEC_PKCS5CreateAlgorithmID(SECOidTag algorithm, - SECItem *salt, - int iteration); - -/* Get the initialization vector. The password is passed in, hashing - * is performed, and the initialization vector is returned. - * algid is a pointer to a PBE algorithm ID - * pwitem is the password - * If an error occurs or the algorithm id is not a PBE algrithm, - * NULL is returned. Otherwise, the iv is returned in a secitem. - */ -extern SECItem * -SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES); - -/* Get the key. The password is passed in, hashing is performed, - * and the key is returned. - * algid is a pointer to a PBE algorithm ID - * pwitem is the password - * If an error occurs or the algorithm id is not a PBE algrithm, - * NULL is returned. Otherwise, the key is returned in a secitem. +nsspkcs5_CreateAlgorithmID(PRArenaPool *arena, SECOidTag algorithm, + NSSPKCS5PBEParameter *pbe); + +/* + * Convert an Algorithm ID to a PBE Param. + * NOTE: this does not suppport PKCS 5 v2 because it's only used for the + * keyDB which only support PKCS 5 v1, PFX, and PKCS 12. */ -extern SECItem * -SEC_PKCS5GetKey(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES); +NSSPKCS5PBEParameter * +nsspkcs5_AlgidToParam(SECAlgorithmID *algid); -/* Get PBE salt. The salt for the password based algorithm is returned. - * algid is the PBE algorithm identifier - * If an error occurs NULL is returned, otherwise the salt is returned - * in a SECItem. +/* + * Convert an Algorithm ID to a PBE Param. + * NOTE: this does not suppport PKCS 5 v2 because it's only used for the + * keyDB which only support PKCS 5 v1, PFX, and PKCS 12. */ -extern SECItem * -SEC_PKCS5GetSalt(SECAlgorithmID *algid); +NSSPKCS5PBEParameter * +nsspkcs5_NewParam(SECOidTag alg, SECItem *salt, int iterator); + /* Encrypt/Decrypt data using password based encryption. * algid is the PBE algorithm identifier, @@ -138,48 +116,17 @@ SEC_PKCS5GetSalt(SECAlgorithmID *algid); * is returned, otherwise the ciphered contents is returned. */ extern SECItem * -SEC_PKCS5CipherData(SECAlgorithmID *algid, SECItem *pwitem, +nsspkcs5_CipherData(NSSPKCS5PBEParameter *, SECItem *pwitem, SECItem *src, PRBool encrypt, PRBool *update); -/* Checks to see if algid algorithm is a PBE algorithm. If - * so, PR_TRUE is returned, otherwise PR_FALSE is returned. - */ -extern PRBool -SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid); +extern SECItem * +nsspkcs5_ComputeKeyAndIV(NSSPKCS5PBEParameter *, SECItem *pwitem, + SECItem *iv, PRBool faulty3DES); /* Destroys PBE parameter */ extern void -SEC_PKCS5DestroyPBEParameter(SEC_PKCS5PBEParameter *param); - -/* Convert Algorithm ID to PBE parameter */ -extern SEC_PKCS5PBEParameter * -SEC_PKCS5GetPBEParameter(SECAlgorithmID *algid); - -/* Determine how large the key generated is */ -extern int -SEC_PKCS5GetKeyLength(SECAlgorithmID *algid); - -/* map crypto algorithm to pbe algorithm, assume sha 1 hashing for DES - */ -extern SECOidTag -SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen); - -/* return the underlying crypto algorithm */ -extern SECOidTag -SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid); - -extern PBEBitGenContext * -PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose, - SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded, - unsigned int interations); - -extern SECItem * -PBE_GenerateBits(PBEBitGenContext *pbeCtxt); - -extern void PBE_DestroyContext(PBEBitGenContext *pbeCtxt); +nsspkcs5_DestroyPBEParameter(NSSPKCS5PBEParameter *param); -extern SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param, - PRArenaPool *arena, SECAlgorithmID *algId); SEC_END_PROTOS #endif diff --git a/security/nss/lib/ssl/ssl3con.c b/security/nss/lib/ssl/ssl3con.c index 98867bb0b..86f5638d9 100644 --- a/security/nss/lib/ssl/ssl3con.c +++ b/security/nss/lib/ssl/ssl3con.c @@ -65,7 +65,8 @@ #endif static PK11SymKey *ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, - PK11SlotInfo * serverKeySlot); + PK11SlotInfo * serverKeySlot, + PRBool isTls); static SECStatus ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms); static SECStatus ssl3_HandshakeFailure( sslSocket *ss); static SECStatus ssl3_InitState( sslSocket *ss); @@ -2023,7 +2024,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) if (pwSpec->master_secret == NULL) { /* Generate a faux master secret in the same slot as the old one. */ PK11SlotInfo * slot = PK11_GetSlotFromKey((PK11SymKey *)pms); - PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); + PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot, isTLS); PK11_FreeSlot(slot); if (fpms != NULL) { @@ -2037,7 +2038,7 @@ ssl3_GenerateSessionKeys(sslSocket *ss, const PK11SymKey *pms) if (pwSpec->master_secret == NULL) { /* Generate a faux master secret from the internal slot. */ PK11SlotInfo * slot = PK11_GetInternalSlot(); - PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot); + PK11SymKey * fpms = ssl3_GenerateRSAPMS(ss, pwSpec, slot, isTLS); PK11_FreeSlot(slot); if (fpms != NULL) { @@ -3183,7 +3184,7 @@ sendRSAClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey) ssl_GetSpecWriteLock(ss); isTLS = (PRBool)(ss->ssl3->pwSpec->version > SSL_LIBRARY_VERSION_3_0); - pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->pwSpec, NULL); + pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->pwSpec, NULL, isTLS); ssl_ReleaseSpecWriteLock(ss); if (pms == NULL) { ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE); @@ -4267,7 +4268,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) peerKey->arena = arena; peerKey->keyType = rsaKey; peerKey->pkcs11Slot = NULL; - peerKey->pkcs11ID = CK_INVALID_KEY; + peerKey->pkcs11ID = CK_INVALID_HANDLE; if (SECITEM_CopyItem(arena, &peerKey->u.rsa.modulus, &modulus) || SECITEM_CopyItem(arena, &peerKey->u.rsa.publicExponent, &exponent)) { @@ -4349,7 +4350,7 @@ ssl3_HandleServerKeyExchange(sslSocket *ss, SSL3Opaque *b, PRUint32 length) peerKey->arena = arena; peerKey->keyType = dhKey; peerKey->pkcs11Slot = NULL; - peerKey->pkcs11ID = CK_INVALID_KEY; + peerKey->pkcs11ID = CK_INVALID_HANDLE; if (SECITEM_CopyItem(arena, &peerKey->u.dh.prime, &dh_p) || SECITEM_CopyItem(arena, &peerKey->u.dh.base, &dh_g) || @@ -6059,7 +6060,7 @@ fortezza_loser: */ static PK11SymKey * ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, - PK11SlotInfo * serverKeySlot) + PK11SlotInfo * serverKeySlot, PRBool isTLS) { PK11SymKey * pms = NULL; PK11SlotInfo * slot = serverKeySlot; @@ -6067,9 +6068,12 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, SECItem param; CK_VERSION version; CK_MECHANISM_TYPE mechanism_array[3]; + CK_MECHANISM_TYPE keygen; PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); + keygen = isTLS ? CKM_TLS_PRE_MASTER_KEY_GEN: CKM_SSL3_PRE_MASTER_KEY_GEN; + if (slot == NULL) { SSLCipherAlgorithm calg; /* The specReadLock would suffice here, but we cannot assert on @@ -6083,7 +6087,7 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, PORT_Assert(alg2Mech[calg].calg == calg); /* First get an appropriate slot. */ - mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN; + mechanism_array[0] = keygen; mechanism_array[1] = CKM_RSA_PKCS; mechanism_array[2] = alg2Mech[calg].cmech; @@ -6105,7 +6109,7 @@ ssl3_GenerateRSAPMS(sslSocket *ss, ssl3CipherSpec *spec, param.data = (unsigned char *)&version; param.len = sizeof version; - pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, ¶m, 0, pwArg); + pms = PK11_KeyGen(slot, keygen, ¶m, 0, pwArg); if (!serverKeySlot) PK11_FreeSlot(slot); if (pms == NULL) { @@ -6135,6 +6139,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, PK11SymKey * pms; SECStatus rv; SECItem enc_pms; + PRBool isTLS = PR_FALSE; PORT_Assert( ssl_HaveRecvBufLock(ss) ); PORT_Assert( ssl_HaveSSL3HandshakeLock(ss) ); @@ -6152,6 +6157,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, if ((unsigned)kLen < enc_pms.len) { enc_pms.len = kLen; } + isTLS = PR_TRUE; } /* * decrypt pms out of the incoming buffer @@ -6170,7 +6176,7 @@ ssl3_HandleRSAClientKeyExchange(sslSocket *ss, PK11SlotInfo * slot = PK11_GetSlotFromPrivateKey(serverKey); ssl_GetSpecWriteLock(ss); - pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->prSpec, slot); + pms = ssl3_GenerateRSAPMS(ss, ss->ssl3->prSpec, slot, isTLS); ssl_ReleaseSpecWriteLock(ss); PK11_FreeSlot(slot); @@ -6447,8 +6453,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) if (rv != SECSuccess) goto loser; /* fatal alert already sent by ConsumeHandshake. */ - sec->peerCert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, - PR_FALSE, PR_TRUE); + sec->peerCert = CERT_DecodeDERCertificate(&certItem, NULL, PR_FALSE); if (sec->peerCert == NULL) { /* We should report an alert if the cert was bad, but not if the * problem was just some local problem, like memory error. @@ -6486,8 +6491,7 @@ ssl3_HandleCertificate(sslSocket *ss, SSL3Opaque *b, PRUint32 length) goto loser; /* don't send alerts on memory errors */ } - c->cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, - PR_FALSE, PR_TRUE); + c->cert = CERT_DecodeDERCertificate(&certItem, NULL, PR_FALSE); if (c->cert == NULL) { goto ambiguous_err; } diff --git a/security/nss/lib/ssl/sslcon.c b/security/nss/lib/ssl/sslcon.c index cc9d48b09..cf24c1198 100644 --- a/security/nss/lib/ssl/sslcon.c +++ b/security/nss/lib/ssl/sslcon.c @@ -1964,8 +1964,7 @@ ssl2_ClientHandleServerCert(sslSocket *ss, PRUint8 *certData, int certLen) certItem.len = certLen; /* decode the certificate */ - cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(&certItem, NULL, PR_FALSE); if (cert == NULL) { SSL_DBG(("%d: SSL[%d]: decode of server certificate fails", @@ -2472,8 +2471,7 @@ ssl2_HandleClientCertificate(sslSocket * ss, certItem.data = cd; certItem.len = cdLen; - cert = CERT_NewTempCertificate(ss->dbHandle, &certItem, NULL, - PR_FALSE, PR_TRUE); + cert = CERT_DecodeDERCertificate(&certItem, NULL, PR_FALSE); if (cert == NULL) { goto loser; } diff --git a/security/nss/lib/ssl/sslsnce.c b/security/nss/lib/ssl/sslsnce.c index 9eca3b22b..7515a57f8 100644 --- a/security/nss/lib/ssl/sslsnce.c +++ b/security/nss/lib/ssl/sslsnce.c @@ -548,8 +548,7 @@ ConvertToSID(sidCacheEntry *from, certCacheEntry *pcce, derCert.len = pcce->certLength; derCert.data = pcce->cert; - to->peerCert = CERT_NewTempCertificate(dbHandle, &derCert, NULL, - PR_FALSE, PR_TRUE); + to->peerCert = CERT_DecodeDERCertificate(&derCert, NULL, PR_FALSE); if (to->peerCert == NULL) goto loser; } diff --git a/security/nss/lib/util/secitem.c b/security/nss/lib/util/secitem.c index fd7e83464..ded548a00 100644 --- a/security/nss/lib/util/secitem.c +++ b/security/nss/lib/util/secitem.c @@ -240,3 +240,45 @@ SECITEM_ZfreeItem(SECItem *zap, PRBool freeit) } } } +/* these reroutines were taken from pkix oid.c, which is supposed to + * replace this file some day */ +/* + * This is the hash function. We simply XOR the encoded form with + * itself in sizeof(PLHashNumber)-byte chunks. Improving this + * routine is left as an excercise for the more mathematically + * inclined student. + */ +PLHashNumber PR_CALLBACK +SECITEM_Hash ( const void *key) +{ + const SECItem *item = (const SECItem *)key; + PLHashNumber rv = 0; + + PRUint8 *data = (PRUint8 *)item->data; + PRUint32 i; + PRUint8 *rvc = (PRUint8 *)&rv; + + for( i = 0; i < item->len; i++ ) { + rvc[ i % sizeof(rv) ] ^= *data; + data++; + } + + return rv; +} + +/* + * This is the key-compare function. It simply does a lexical + * comparison on the item data. This does not result in + * quite the same ordering as the "sequence of numbers" order, + * but heck it's only used internally by the hash table anyway. + */ +PRIntn PR_CALLBACK +SECITEM_HashCompare ( const void *k1, const void *k2) +{ + PRIntn rv; + + const SECItem *i1 = (const SECItem *)k1; + const SECItem *i2 = (const SECItem *)k2; + + return SECITEM_ItemsAreEqual(i1,i2); +} diff --git a/security/nss/lib/util/secitem.h b/security/nss/lib/util/secitem.h index 3928cad98..76a5d16fb 100644 --- a/security/nss/lib/util/secitem.h +++ b/security/nss/lib/util/secitem.h @@ -41,6 +41,7 @@ */ #include "plarena.h" +#include "plhash.h" #include "seccomon.h" SEC_BEGIN_PROTOS @@ -101,6 +102,11 @@ extern void SECITEM_FreeItem(SECItem *zap, PRBool freeit); */ extern void SECITEM_ZfreeItem(SECItem *zap, PRBool freeit); +PLHashNumber PR_CALLBACK SECITEM_Hash ( const void *key); + +PRIntn PR_CALLBACK SECITEM_HashCompare ( const void *k1, const void *k2); + + SEC_END_PROTOS #endif /* _SECITEM_H_ */ diff --git a/security/nss/lib/util/secoid.c b/security/nss/lib/util/secoid.c index 0044c83f0..baebc5322 100644 --- a/security/nss/lib/util/secoid.c +++ b/security/nss/lib/util/secoid.c @@ -32,11 +32,11 @@ */ #include "secoid.h" -#include "mcom_db.h" #include "pkcs11t.h" #include "secmodt.h" #include "secitem.h" #include "secerr.h" +#include "plhash.h" /* MISSI Mosaic Object ID space */ #define MISSI 0x60, 0x86, 0x48, 0x01, 0x65, 0x02, 0x01, 0x01 @@ -1222,7 +1222,7 @@ static SECOidData oids[] = { * and gets modified if the user loads new crypto modules. */ -static DB *oid_d_hash = 0; +static PLHashTable *oid_d_hash = 0; static SECOidData **secoidDynamicTable = NULL; static int secoidDynamicTableSize = 0; static int secoidLastDynamicEntry = 0; @@ -1231,15 +1231,14 @@ static int secoidLastHashEntry = 0; static SECStatus secoid_DynamicRehash(void) { - DBT key; - DBT data; - int rv; SECOidData *oid; + PLHashEntry *entry; int i; int last = secoidLastDynamicEntry; if (!oid_d_hash) { - oid_d_hash = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, 0 ); + oid_d_hash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, + PL_CompareValues, NULL, NULL); } @@ -1251,18 +1250,8 @@ secoid_DynamicRehash(void) for ( i = secoidLastHashEntry; i < last; i++ ) { oid = secoidDynamicTable[i]; - /* invalid assert ... guarrenteed not to be true */ - /* PORT_Assert ( oid->offset == i ); */ - - key.data = oid->oid.data; - key.size = oid->oid.len; - - data.data = &oid; - data.size = sizeof(oid); - - rv = (* oid_d_hash->put)( oid_d_hash, &key, &data, R_NOOVERWRITE ); - if ( rv ) { - PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); + entry = PL_HashTableAdd( oid_d_hash, &oid->oid.data, oid ); + if ( entry == NULL ) { return(SECFailure); } } @@ -1270,24 +1259,29 @@ secoid_DynamicRehash(void) return(SECSuccess); } + + /* * Lookup a Dynamic OID. Dynamic OID's still change slowly, so it's * cheaper to rehash the table when it changes than it is to do the loop * each time. Worry: what about thread safety here? Global Static data with * no locks.... (sigh). */ -static SECStatus -secoid_FindDynamic(DBT *key, DBT *data) { +static SECOidData * +secoid_FindDynamic(SECItem *key) { + SECOidData *ret = NULL; if (secoidDynamicTable == NULL) { - return SECFailure; + /* PORT_SetError! */ + return NULL; } if (secoidLastHashEntry != secoidLastDynamicEntry) { SECStatus rv = secoid_DynamicRehash(); if ( rv != SECSuccess ) { - return rv; + return NULL; } } - return (SECStatus)(* oid_d_hash->get)( oid_d_hash, key, data, 0 ); + ret = (SECOidData *)PL_HashTableLookup (oid_d_hash, key); + return ret; } @@ -1364,20 +1358,22 @@ SECOID_AddEntry(SECItem *oid, char *description, unsigned long mech) { /* normal static table processing */ -static DB *oidhash = NULL; -static DB *oidmechhash = NULL; +static PLHashTable *oidhash = NULL; +static PLHashTable *oidmechhash = NULL; static SECStatus InitOIDHash(void) { - DBT key; - DBT data; + SECItem key; + PLHashEntry *entry; int rv; SECOidData *oid; int i; - oidhash = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, 0 ); - oidmechhash = dbopen( 0, O_RDWR | O_CREAT, 0600, DB_HASH, 0 ); + oidhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, + PL_CompareValues, NULL, NULL); + oidmechhash = PL_NewHashTable(0, SECITEM_Hash, SECITEM_HashCompare, + PL_CompareValues, NULL, NULL); if ( !oidhash || !oidmechhash) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); @@ -1390,29 +1386,19 @@ InitOIDHash(void) PORT_Assert ( oid->offset == i ); - key.data = oid->oid.data; - key.size = oid->oid.len; - - data.data = &oid; - data.size = sizeof(oid); - - rv = (* oidhash->put)( oidhash, &key, &data, R_NOOVERWRITE ); - if ( rv ) { + entry = PL_HashTableAdd( oidhash, &oid->oid.data, oid ); + if ( entry == NULL ) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_Assert(0); /*This function should never fail. */ return(SECFailure); } if ( oid->mechanism != CKM_INVALID_MECHANISM ) { - key.data = &oid->mechanism; - key.size = sizeof(oid->mechanism); - - rv = (* oidmechhash->put)( oidmechhash, &key, &data, R_NOOVERWRITE); - /* Only error out if the error value returned is not - * RET_SPECIAL, ie the mechanism already has a registered - * OID. - */ - if ( rv && rv != RET_SPECIAL) { + key.data = (unsigned char *)&oid->mechanism; + key.len = sizeof(oid->mechanism); + + entry = PL_HashTableAdd( oidmechhash, &key, oid ); + if ( entry ) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); PORT_Assert(0); /* This function should never fail. */ return(SECFailure); @@ -1428,8 +1414,7 @@ InitOIDHash(void) SECOidData * SECOID_FindOIDByMechanism(unsigned long mechanism) { - DBT key; - DBT data; + SECItem key; SECOidData *ret; int rv; @@ -1440,15 +1425,13 @@ SECOID_FindOIDByMechanism(unsigned long mechanism) return NULL; } } - key.data = &mechanism; - key.size = sizeof(mechanism); + key.data = (unsigned char *)&mechanism; + key.len = sizeof(mechanism); - rv = (* oidmechhash->get)( oidmechhash, &key, &data, 0 ); - if ( rv || ( data.size != sizeof(unsigned long) ) ) { + ret = PL_HashTableLookup ( oidmechhash, &key); + if ( ret == NULL ) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return NULL; } - PORT_Memcpy(&ret, data.data, data.size); return (ret); } @@ -1456,8 +1439,6 @@ SECOID_FindOIDByMechanism(unsigned long mechanism) SECOidData * SECOID_FindOID(SECItem *oid) { - DBT key; - DBT data; SECOidData *ret; int rv; @@ -1469,20 +1450,14 @@ SECOID_FindOID(SECItem *oid) } } - key.data = oid->data; - key.size = oid->len; - - rv = (* oidhash->get)( oidhash, &key, &data, 0 ); - if ( rv || ( data.size != sizeof(SECOidData*) ) ) { - rv = secoid_FindDynamic(&key, &data); - if (rv != SECSuccess) { + ret = PL_HashTableLookup ( oidhash, oid ); + if ( ret == NULL ) { + ret = secoid_FindDynamic(oid); + if (ret == NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); - return(0); } } - PORT_Memcpy(&ret, data.data, data.size); - return(ret); } @@ -1538,13 +1513,29 @@ SECOID_FindOIDTagDescription(SECOidTag tagnum) SECStatus SECOID_Shutdown(void) { + int i; + if (oidhash) { - (oidhash->close)(oidhash); + PL_HashTableDestroy(oidhash); oidhash = NULL; } if (oidmechhash) { - (oidmechhash->close)(oidmechhash); + PL_HashTableDestroy(oidmechhash); oidmechhash = NULL; } + if (oid_d_hash) { + PL_HashTableDestroy(oid_d_hash); + oid_d_hash = NULL; + } + if (secoidDynamicTable) { + for (i=0; i < secoidLastDynamicEntry; i++) { + PORT_Free(secoidDynamicTable[i]); + } + PORT_Free(secoidDynamicTable); + secoidDynamicTable = NULL; + secoidDynamicTableSize = 0; + secoidLastDynamicEntry = 0; + secoidLastHashEntry = 0; + } return SECSuccess; } |